diff --git a/src/app/shared/components/hero-banner/hero-banner.component.html b/src/app/shared/components/hero-banner/hero-banner.component.html index 79aea97..e3a20bd 100644 --- a/src/app/shared/components/hero-banner/hero-banner.component.html +++ b/src/app/shared/components/hero-banner/hero-banner.component.html @@ -1,13 +1,15 @@
-
+
- + @if (heroConfig) {
} @if (heroConfig.button_text) { - + {{ heroConfig.button_text }} @@ -29,37 +34,78 @@
} - - @if (eventConfig) { -
-
- @if (eventConfig.title) { -

{{ eventConfig.title }}

- } - -
- @if (eventConfig.dates && eventConfig.dates.length > 0) { -
- - {{ formattedDates }} -
- } - @if (eventConfig.location) { -
- - {{ eventConfig.location }} -
- } -
- - -
-
- }
+ + @if (eventConfig) { +
+
+ @if (eventConfig.title) { +

{{ eventConfig.title }}

+ } + +
+ @if (eventConfig.dates && eventConfig.dates.length > 0) { +
+ + {{ formattedDates }} +
+ } + @if (eventConfig.location) { +
+ + {{ eventConfig.location }} +
+ } +
+ + @if (eventConfig.dates && eventConfig.dates.length > 0) { + + + @if (schedulesExpanded) { +
+ + + @for (eventDate of eventConfig.dates; track eventDate.id ?? eventDate.date) { + + + + + } + +
+ + + {{ formatScheduleDate(eventDate.date) }} + + + + + + {{ formatScheduleTime(eventDate.start_time) }} - + {{ formatScheduleTime(eventDate.end_time) }} + + +
+
+ } + } +
+
+ } diff --git a/src/app/shared/components/hero-banner/hero-banner.component.scss b/src/app/shared/components/hero-banner/hero-banner.component.scss index 52a25cd..a030b6a 100644 --- a/src/app/shared/components/hero-banner/hero-banner.component.scss +++ b/src/app/shared/components/hero-banner/hero-banner.component.scss @@ -1,5 +1,4 @@ .hero-banner-container { - padding-bottom: 4rem; /* Spacing to accommodate the overlapping card */ margin-bottom: 1rem; } @@ -19,10 +18,15 @@ border-radius: inherit; &::after { - content: ""; + content: ''; position: absolute; inset: 0; - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0.95) 100%); + background: linear-gradient( + to right, + rgba(255, 255, 255, 0) 0%, + rgba(255, 255, 255, 0.7) 50%, + rgba(255, 255, 255, 0.95) 100% + ); border-radius: inherit; } } @@ -39,8 +43,8 @@ flex-grow: 1; } - -::ng-deep .hero-title, .hero-title { +::ng-deep .hero-title, +.hero-title { color: #666666; font-size: 1.5rem; margin-bottom: 1rem; @@ -49,7 +53,8 @@ } } -::ng-deep .hero-description, .hero-description { +::ng-deep .hero-description, +.hero-description { color: #666666; font-size: 1.1rem; line-height: 1.5; @@ -59,8 +64,8 @@ } .event-card-container { - bottom: -40px; /* Negative margin to pull it down and overlap */ - left: 0; + position: relative; + margin-top: -40px; z-index: 10; } @@ -70,12 +75,13 @@ } .event-title { - font-size: 1.4rem; + font-size: 25px; + font-weight: 700; letter-spacing: 0.5px; } .event-details { - font-size: 1.1rem; + font-size: 21px; } .event-icon { @@ -85,11 +91,55 @@ .event-info-text { color: #8a8a8a; - font-weight: 500; + font-weight: 400; } -.event-schedule-label { - display: none; +.event-schedule-toggle { + display: inline-flex; + justify-content: center; + align-items: center; + gap: 0.55rem; + margin-top: 1.75rem; + padding: 0; + border: 0; + background: transparent; + color: var(--tenant-primary, #009d4f); + font-size: 15px; + font-weight: 700; + + &:focus-visible { + outline: 2px solid currentColor; + outline-offset: 0.25rem; + } + + i { + font-size: 0.7rem; + } +} + +.event-schedules { + margin-top: 1.25rem; + + td { + width: 50%; + padding: 0.65rem 1rem; + border-radius: 0.5rem; + vertical-align: middle; + } +} + +.event-schedule-value { + display: inline-flex; + align-items: center; + gap: 0.75rem; + color: #8a8a8a; + font-size: 19px; + font-weight: 400; + + i { + width: 1rem; + color: #c9ccce; + } } @media (max-width: 767.98px) { @@ -175,9 +225,7 @@ } .event-card-container { - position: relative !important; - bottom: auto; - left: auto; + margin-top: 0; padding: 0 1.25rem 1.2rem; } @@ -193,14 +241,12 @@ .event-title { max-width: 16rem; margin: 0 auto 0.85rem !important; - font-size: 1rem; line-height: 1.1; letter-spacing: 0; } .event-details { gap: 0.45rem !important; - font-size: 0.7rem; line-height: 1.25; } @@ -213,22 +259,23 @@ font-size: 0.85rem; } - .event-info-text { - font-weight: 400; - } - - .event-schedule-label { - display: flex; - justify-content: center; - align-items: center; - gap: 0.55rem; + .event-schedule-toggle { margin-top: 1.9rem; - color: var(--tenant-primary, #009d4f); - font-size: 0.625rem; - font-weight: 700; } - .event-schedule-label i { + .event-schedule-toggle i { font-size: 0.65rem; } + + .event-schedules { + margin-top: 1rem; + + td { + padding: 0.55rem 0.4rem; + } + } + + .event-schedule-value { + gap: 0.4rem; + } } diff --git a/src/app/shared/components/hero-banner/hero-banner.component.spec.ts b/src/app/shared/components/hero-banner/hero-banner.component.spec.ts new file mode 100644 index 0000000..235e236 --- /dev/null +++ b/src/app/shared/components/hero-banner/hero-banner.component.spec.ts @@ -0,0 +1,50 @@ +import { TestBed } from '@angular/core/testing'; +import { HeroBannerComponent } from './hero-banner.component'; + +describe('HeroBannerComponent', () => { + it('expands and collapses the event schedules', async () => { + await TestBed.configureTestingModule({ imports: [HeroBannerComponent] }).compileComponents(); + + const fixture = TestBed.createComponent(HeroBannerComponent); + fixture.componentRef.setInput('eventConfig', { + title: 'Fiesta Nacional del FĂștbol Infantil', + location: 'Sunchales, Santa Fe', + dates: [ + { + id: 1, + date: '2026-10-09', + start_time: '10:00:00', + end_time: '20:30:00', + }, + { + id: 2, + date: '2026-10-10', + start_time: '10:00:00', + end_time: '22:00:00', + }, + ], + }); + fixture.detectChanges(); + + const element = fixture.nativeElement as HTMLElement; + const toggle = element.querySelector('.event-schedule-toggle'); + + expect(toggle?.textContent).toContain('Ver horarios'); + expect(toggle?.getAttribute('aria-expanded')).toBe('false'); + expect(element.querySelector('.event-schedules')).toBeNull(); + + toggle?.click(); + fixture.detectChanges(); + + expect(toggle?.textContent).toContain('Ocultar horarios'); + expect(toggle?.getAttribute('aria-expanded')).toBe('true'); + expect(element.querySelectorAll('.event-schedules tbody tr')).toHaveLength(2); + expect(element.querySelector('.event-schedules')?.textContent).toContain('9 de Octubre 2026'); + expect(element.querySelector('.event-schedules')?.textContent).toContain('10:00 - 20:30'); + + toggle?.click(); + fixture.detectChanges(); + + expect(element.querySelector('.event-schedules')).toBeNull(); + }); +}); diff --git a/src/app/shared/components/hero-banner/hero-banner.component.ts b/src/app/shared/components/hero-banner/hero-banner.component.ts index 2a32e6b..e3385c6 100644 --- a/src/app/shared/components/hero-banner/hero-banner.component.ts +++ b/src/app/shared/components/hero-banner/hero-banner.component.ts @@ -16,6 +16,8 @@ export class HeroBannerComponent { @Input() heroConfig?: HeroConfig | null; @Input() eventConfig?: EventConfig | null; + protected schedulesExpanded = false; + get formattedDates(): string { if (this.eventConfig?.dates_text) { return this.eventConfig.dates_text; @@ -27,4 +29,28 @@ export class HeroBannerComponent { return this.eventConfig.dates.map(({ date }) => date).join(', '); } + + protected toggleSchedules(): void { + this.schedulesExpanded = !this.schedulesExpanded; + } + + protected formatScheduleDate(date: string): string { + const [year, month, day] = date.split('-').map(Number); + + if (!year || !month || !day) { + return date; + } + + const monthName = new Intl.DateTimeFormat('es-AR', { + month: 'long', + timeZone: 'UTC', + }).format(new Date(Date.UTC(year, month - 1, day))); + const capitalizedMonth = `${monthName.charAt(0).toUpperCase()}${monthName.slice(1)}`; + + return `${day} de ${capitalizedMonth} ${year}`; + } + + protected formatScheduleTime(time: string): string { + return time.match(/^\d{2}:\d{2}/)?.[0] ?? time; + } } diff --git a/src/styles.scss b/src/styles.scss index 75a4605..63dd8cc 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,13 +1,14 @@ -@use "./fonts"; +@use './fonts'; -@import "@fortawesome/fontawesome-free/css/all.min.css"; +@import '@fortawesome/fontawesome-free/css/all.min.css'; -@import "./theme"; +@import './theme'; -@import "../node_modules/bootstrap/scss/bootstrap"; +@import '../node_modules/bootstrap/scss/bootstrap'; -:root, app-root { - --bs-body-font-family: "Gotham", sans-serif; +:root, +app-root { + --bs-body-font-family: 'Gotham', sans-serif; --color-primary: var(--tenant-primary); --color-primary-rgb: var(--tenant-primary-rgb); --color-secondary: var(--tenant-secondary); @@ -57,3 +58,18 @@ label { color: var(--color-danger, #dc3545); } } + +.table-striped { + --bs-table-bg: transparent; + --bs-table-color: #8a8a8a; + --bs-table-color-state: #8a8a8a; + --bs-table-color-type: #8a8a8a; + --bs-table-striped-bg: transparent; + --bs-table-striped-color: #8a8a8a; + + color: #8a8a8a; + + > tbody > tr:nth-of-type(odd) { + background-color: rgba(221, 221, 221, 0.25); + } +}