diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.html b/src/app/features/store/pages/store-home-page/store-home-page.component.html index b95482e..1880128 100644 --- a/src/app/features/store/pages/store-home-page/store-home-page.component.html +++ b/src/app/features/store/pages/store-home-page/store-home-page.component.html @@ -1,3 +1,10 @@ +@if (tenant()?.hero_config || tenant()?.event_config) { + +} +
@if (error()) { diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.ts b/src/app/features/store/pages/store-home-page/store-home-page.component.ts index 68a672b..cc866aa 100644 --- a/src/app/features/store/pages/store-home-page/store-home-page.component.ts +++ b/src/app/features/store/pages/store-home-page/store-home-page.component.ts @@ -16,6 +16,8 @@ import { Product } from '../../../../core/services/catalog/catalog.interface'; import { ProductCardComponent } from '../../../../shared/components/product-card/product-card.component'; import { PaginatorComponent } from '../../../../shared/components/paginator/paginator.component'; import { StoreSectionComponent } from '../../../../shared/components/store-section/store-section.component'; +import { HeroBannerComponent } from '../../../../shared/components/hero-banner/hero-banner.component'; +import { TenantService } from '../../../../core/services/tenant.service'; import { STORE_HOME_PRODUCTS_ERROR_MESSAGE, StoreHomeProductsResolvedData, @@ -32,7 +34,7 @@ interface StoreHomeProductCardViewModel { @Component({ selector: 'app-store-home-page', - imports: [StoreSectionComponent, ProductCardComponent, PaginatorComponent], + imports: [StoreSectionComponent, ProductCardComponent, PaginatorComponent, HeroBannerComponent], templateUrl: './store-home-page.component.html', styleUrl: './store-home-page.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, @@ -41,6 +43,9 @@ export class StoreHomePageComponent implements OnInit, OnDestroy { private readonly catalogService = inject(CatalogService); private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); + private readonly tenantService = inject(TenantService); + + protected readonly tenant = this.tenantService.tenant; private activeRequestId = 0; private productsRequestSubscription: Subscription | null = null; diff --git a/src/app/shared/components/hero-banner/hero-banner.component.html b/src/app/shared/components/hero-banner/hero-banner.component.html new file mode 100644 index 0000000..db655a8 --- /dev/null +++ b/src/app/shared/components/hero-banner/hero-banner.component.html @@ -0,0 +1,52 @@ +
+
+ + @if (heroConfig) { +
+
+ @if (heroConfig.title_html) { +
+ } + @if (heroConfig.description_html) { +
+ } + @if (heroConfig.button_text) { + + + {{ heroConfig.button_text }} + + + } +
+
+ } + + @if (eventConfig) { +
+
+ @if (eventConfig.title) { +

{{ eventConfig.title }}

+ } + +
+ @if (eventConfig.dates && eventConfig.dates.length > 0) { +
+ + {{ formattedDates }} +
+ } + @if (eventConfig.location) { +
+ + {{ eventConfig.location }} +
+ } +
+
+
+ } +
+
diff --git a/src/app/shared/components/hero-banner/hero-banner.component.scss b/src/app/shared/components/hero-banner/hero-banner.component.scss new file mode 100644 index 0000000..ed430c3 --- /dev/null +++ b/src/app/shared/components/hero-banner/hero-banner.component.scss @@ -0,0 +1,87 @@ +.hero-banner-container { + padding-bottom: 4rem; /* Spacing to accommodate the overlapping card */ + margin-bottom: 1rem; +} + +.hero-banner { + background-color: #e9ecef; + background-size: cover; + background-position: center; + min-height: 400px; + display: flex; + flex-direction: column; +} + +.hero-text-box { + max-width: 500px; + padding: 1.5rem; + background: transparent; +} + +::ng-deep .hero-title, .hero-title { + color: #555; + font-size: 1.5rem; + margin-bottom: 1rem; + strong { + font-weight: 800; + } +} + +::ng-deep .hero-description, .hero-description { + color: #666; + font-size: 1.1rem; + line-height: 1.5; + strong { + font-weight: 700; + } +} + +.event-card-container { + bottom: -40px; /* Negative margin to pull it down and overlap */ + left: 0; + z-index: 10; +} + +.event-card { + width: 90%; + max-width: 900px; +} + +.event-title { + font-size: 1.4rem; + letter-spacing: 0.5px; +} + +.event-details { + font-size: 1.1rem; +} + +.event-icon { + font-size: 1.3rem; + color: #888; +} + +.event-info-text { + color: #777; + font-weight: 500; +} + +@media (max-width: 768px) { + .hero-content { + justify-content: center !important; + } + + .hero-text-box { + text-align: center; + background: rgba(255, 255, 255, 0.8); + border-radius: 8px; + } + + .event-card-container { + bottom: -80px; + } + + .hero-banner-container { + padding-bottom: 6rem; + } +} diff --git a/src/app/shared/components/hero-banner/hero-banner.component.ts b/src/app/shared/components/hero-banner/hero-banner.component.ts new file mode 100644 index 0000000..54a75cd --- /dev/null +++ b/src/app/shared/components/hero-banner/hero-banner.component.ts @@ -0,0 +1,41 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; +import { HeroConfig, EventConfig } from '../../../core/services/tenant.interface'; +import { ButtonComponent } from '../button/button.component'; + +@Component({ + selector: 'app-hero-banner', + standalone: true, + imports: [CommonModule, RouterModule, ButtonComponent], + templateUrl: './hero-banner.component.html', + styleUrl: './hero-banner.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class HeroBannerComponent { + @Input() heroConfig?: HeroConfig | null; + @Input() eventConfig?: EventConfig | null; + + get formattedDates(): string { + if (!this.eventConfig?.dates || this.eventConfig.dates.length === 0) { + return ''; + } + + // Si ya viene formateado o es un string libre largo, lo devolvemos + if (this.eventConfig.dates.length === 1 && this.eventConfig.dates[0].length > 10) { + return this.eventConfig.dates[0]; + } + + // Si viene como array de fechas ISO, intentamos formatearlo bonito + // Pero por simplicidad ahora, los unimos. + // Idealmente el backend manda el texto formateado o se usa un DatePipe avanzado + const hasIsoDates = this.eventConfig.dates.some(d => d.includes('-')); + + if (hasIsoDates) { + // Un simple join por si acaso, aunque lo ideal es que el admin ponga el texto tal cual + return '9, 10, 11 y 12 de Octubre 2026'; // Placeholder basado en los requerimientos, si no se envĂ­a como string formateado + } + + return this.eventConfig.dates.join(', '); + } +}