diff --git a/src/app/core/services/tenant.interface.ts b/src/app/core/services/tenant.interface.ts
index 8dbdfd6..6f8bff5 100644
--- a/src/app/core/services/tenant.interface.ts
+++ b/src/app/core/services/tenant.interface.ts
@@ -51,6 +51,8 @@ export interface EventDate {
date: string;
start_time: string;
end_time: string;
+ info_text: string | null;
+ isCanceled: boolean;
}
export interface EventConfig {
@@ -67,6 +69,8 @@ export interface ActiveEventDate {
date: string;
time_start: string;
time_end: string;
+ info_text: string | null;
+ isCanceled: boolean;
}
export type TenantEventDateChangeType = 'rescheduled' | 'suspended';
diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.spec.ts b/src/app/features/store/pages/store-home-page/store-home-page.component.spec.ts
index 60367d9..47e3c14 100644
--- a/src/app/features/store/pages/store-home-page/store-home-page.component.spec.ts
+++ b/src/app/features/store/pages/store-home-page/store-home-page.component.spec.ts
@@ -233,12 +233,16 @@ describe('StoreHomePageComponent', () => {
date: '2026-12-05',
time_start: '09:00:00',
time_end: '18:00:00',
+ info_text: null,
+ isCanceled: false,
},
{
id: 21,
date: '2026-12-06',
time_start: '09:00:00',
time_end: '18:00:00',
+ info_text: null,
+ isCanceled: false,
},
],
};
@@ -369,6 +373,8 @@ describe('StoreHomePageComponent', () => {
date: '2026-10-09',
time_start: '09:00:00',
time_end: '18:00:00',
+ info_text: null,
+ isCanceled: false,
},
],
};
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 3092cd0..45e9c93 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
@@ -89,6 +89,8 @@ export class StoreHomePageComponent implements OnInit, OnDestroy {
date: eventDate.date,
start_time: eventDate.time_start,
end_time: eventDate.time_end,
+ info_text: eventDate.info_text,
+ isCanceled: eventDate.isCanceled,
})),
contact,
};
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 0fcf6db..c46dff9 100644
--- a/src/app/shared/components/hero-banner/hero-banner.component.html
+++ b/src/app/shared/components/hero-banner/hero-banner.component.html
@@ -88,7 +88,12 @@
- {{ formatScheduleDate(eventDate.date) }}
+
+ {{ formatScheduleDate(eventDate.date) }}
+
+ @if (eventDate.info_text) {
+
+ }
|
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 1b42b53..25223a1 100644
--- a/src/app/shared/components/hero-banner/hero-banner.component.scss
+++ b/src/app/shared/components/hero-banner/hero-banner.component.scss
@@ -164,6 +164,10 @@
}
}
+.event-schedule-date--canceled {
+ text-decoration: line-through;
+}
+
@media (max-width: 767.98px) {
.hero-banner-container {
padding-bottom: 0;
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
index 6d11bbe..8d7fd88 100644
--- a/src/app/shared/components/hero-banner/hero-banner.component.spec.ts
+++ b/src/app/shared/components/hero-banner/hero-banner.component.spec.ts
@@ -22,9 +22,7 @@ describe('HeroBannerComponent', () => {
expect(element.querySelector('img')?.getAttribute('src')).toBe(
'https://example.com/desktop.jpg',
);
- expect(element.querySelector('.hero-banner')?.classList).toContain(
- 'hero-banner--with-media',
- );
+ expect(element.querySelector('.hero-banner')?.classList).toContain('hero-banner--with-media');
});
it('keeps the fallback banner sizing when there is no image', async () => {
@@ -52,12 +50,16 @@ describe('HeroBannerComponent', () => {
date: '2026-10-09',
start_time: '10:00:00',
end_time: '20:30:00',
+ info_text: 'Esta fecha fue cancelada.',
+ isCanceled: true,
},
{
id: 2,
date: '2026-10-10',
start_time: '10:00:00',
end_time: '22:00:00',
+ info_text: null,
+ isCanceled: false,
},
],
});
@@ -78,6 +80,10 @@ describe('HeroBannerComponent', () => {
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');
+ expect(element.querySelector('.event-schedule-date--canceled')).not.toBeNull();
+ expect(element.querySelector('app-tooltip')?.textContent).toContain(
+ 'Esta fecha fue cancelada.',
+ );
toggle?.click();
fixture.detectChanges();
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 4859c54..7509445 100644
--- a/src/app/shared/components/hero-banner/hero-banner.component.ts
+++ b/src/app/shared/components/hero-banner/hero-banner.component.ts
@@ -3,11 +3,12 @@ import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { EventConfig, HeroConfig } from '../../../core/services/tenant.interface';
import { ButtonComponent } from '../button/button.component';
+import { TooltipComponent } from '../tooltip/tooltip.component';
@Component({
selector: 'app-hero-banner',
standalone: true,
- imports: [CommonModule, RouterModule, ButtonComponent],
+ imports: [CommonModule, RouterModule, ButtonComponent, TooltipComponent],
templateUrl: './hero-banner.component.html',
styleUrl: './hero-banner.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
diff --git a/src/app/shared/components/tooltip/tooltip.component.html b/src/app/shared/components/tooltip/tooltip.component.html
index 35788c8..f3c2475 100644
--- a/src/app/shared/components/tooltip/tooltip.component.html
+++ b/src/app/shared/components/tooltip/tooltip.component.html
@@ -3,9 +3,21 @@
class="tooltip-trigger"
[attr.aria-describedby]="tooltipId"
[attr.aria-label]="message()"
+ (mouseenter)="showTooltip($event)"
+ (mouseleave)="hideTooltip()"
+ (focus)="showTooltip($event)"
+ (blur)="hideTooltip()"
>
-
+
{{ message() }}
diff --git a/src/app/shared/components/tooltip/tooltip.component.scss b/src/app/shared/components/tooltip/tooltip.component.scss
index c195b68..e77d912 100644
--- a/src/app/shared/components/tooltip/tooltip.component.scss
+++ b/src/app/shared/components/tooltip/tooltip.component.scss
@@ -22,22 +22,15 @@
outline: 2px solid currentColor;
outline-offset: 2px;
}
-
- &:hover .tooltip-message,
- &:focus-visible .tooltip-message {
- visibility: visible;
- opacity: 1;
- transform: translate(-50%, -0.25rem);
- }
}
.tooltip-message {
- position: absolute;
- z-index: 1100;
- bottom: calc(100% + 0.625rem);
- left: 50%;
+ position: fixed;
+ inset: auto;
+ z-index: 2000;
width: max-content;
max-width: min(16rem, 75vw);
+ margin: 0;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
border: 1px solid var(--tenant-primary, var(--color-primary, #0d6efd));
@@ -54,9 +47,13 @@
visibility: hidden;
opacity: 0;
pointer-events: none;
- transform: translate(-50%, 0);
+ transform: translateX(-50%);
transition:
opacity 0.15s ease,
- transform 0.15s ease,
visibility 0.15s ease;
}
+
+.tooltip-message--visible {
+ visibility: visible;
+ opacity: 1;
+}
diff --git a/src/app/shared/components/tooltip/tooltip.component.spec.ts b/src/app/shared/components/tooltip/tooltip.component.spec.ts
index 1702ac7..c78b05a 100644
--- a/src/app/shared/components/tooltip/tooltip.component.spec.ts
+++ b/src/app/shared/components/tooltip/tooltip.component.spec.ts
@@ -28,5 +28,15 @@ describe('TooltipComponent', () => {
expect(trigger?.querySelector('i.fa-solid.fa-circle-info')).not.toBeNull();
expect(message?.textContent?.trim()).toBe('Este producto no tiene stock disponible.');
expect(trigger?.getAttribute('aria-describedby')).toBe(message?.id);
+
+ trigger?.dispatchEvent(new MouseEvent('mouseenter'));
+ fixture.detectChanges();
+
+ expect(message?.classList).toContain('tooltip-message--visible');
+
+ trigger?.dispatchEvent(new MouseEvent('mouseleave'));
+ fixture.detectChanges();
+
+ expect(message?.classList).not.toContain('tooltip-message--visible');
});
});
diff --git a/src/app/shared/components/tooltip/tooltip.component.ts b/src/app/shared/components/tooltip/tooltip.component.ts
index 9f70c23..68786f8 100644
--- a/src/app/shared/components/tooltip/tooltip.component.ts
+++ b/src/app/shared/components/tooltip/tooltip.component.ts
@@ -11,4 +11,40 @@ let nextTooltipId = 0;
export class TooltipComponent {
readonly message = input.required();
protected readonly tooltipId = `app-tooltip-${nextTooltipId++}`;
+ protected tooltipVisible = false;
+ protected tooltipLeft = 0;
+ protected tooltipTop = 0;
+ private activeTooltip: HTMLElement | null = null;
+
+ protected showTooltip(event: MouseEvent | FocusEvent): void {
+ const trigger = event.currentTarget as HTMLElement;
+ const rect = trigger.getBoundingClientRect();
+
+ this.tooltipLeft = rect.left + rect.width / 2;
+ this.tooltipTop = rect.bottom + 10;
+ this.tooltipVisible = true;
+ this.activeTooltip = trigger.querySelector('.tooltip-message');
+
+ if (
+ this.activeTooltip &&
+ typeof this.activeTooltip.showPopover === 'function' &&
+ !this.activeTooltip.matches(':popover-open')
+ ) {
+ this.activeTooltip.showPopover();
+ }
+ }
+
+ protected hideTooltip(): void {
+ this.tooltipVisible = false;
+
+ if (
+ this.activeTooltip &&
+ typeof this.activeTooltip.hidePopover === 'function' &&
+ this.activeTooltip.matches(':popover-open')
+ ) {
+ this.activeTooltip.hidePopover();
+ }
+
+ this.activeTooltip = null;
+ }
}
|