feat: update social media handling across components to prioritize tenant-specific links and add banner support in category items
This commit is contained in:
@@ -69,7 +69,7 @@
|
|||||||
<app-store-footer
|
<app-store-footer
|
||||||
[currentYear]="currentYear"
|
[currentYear]="currentYear"
|
||||||
[footerSections]="footerSections()"
|
[footerSections]="footerSections()"
|
||||||
[socialMedia]="tenant()?.social_media ?? []"
|
[socialMedia]="tenant()?.tenant_social_media ?? tenant()?.social_media ?? []"
|
||||||
[logoUrl]="tenant()?.footer_logo ?? null"
|
[logoUrl]="tenant()?.footer_logo ?? null"
|
||||||
[backgroundImageUrl]="tenant()?.footer_bg_image ?? null"
|
[backgroundImageUrl]="tenant()?.footer_bg_image ?? null"
|
||||||
[storeName]="tenant()?.nombre ?? null"
|
[storeName]="tenant()?.nombre ?? null"
|
||||||
|
|||||||
@@ -580,6 +580,20 @@ describe('StoreLayoutComponent', () => {
|
|||||||
expect(footer.textContent).not.toContain(tenant.address);
|
expect(footer.textContent).not.toContain(tenant.address);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses commerce social networks in the footer and respects an empty collection', () => {
|
||||||
|
tenantState.set({ ...tenant, tenant_social_media: [
|
||||||
|
{ ...tenant.social_media![0], url: 'https://instagram.com/commerce-contact' },
|
||||||
|
] });
|
||||||
|
const fixture = TestBed.createComponent(StoreLayoutComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const footer = fixture.nativeElement.querySelector('app-store-footer') as HTMLElement;
|
||||||
|
expect(footer.querySelector('a[href="https://instagram.com/commerce-contact"]')).not.toBeNull();
|
||||||
|
tenantState.set({ ...tenant, tenant_social_media: [] });
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(footer.querySelector('a[href="https://instagram.com/commerce-contact"]')).toBeNull();
|
||||||
|
expect(footer.querySelector('a[href="' + tenant.social_media![0].url + '"]')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('uses only the main phone number in the footer', () => {
|
it('uses only the main phone number in the footer', () => {
|
||||||
tenantState.set({ ...tenant, main_phone_number: {
|
tenantState.set({ ...tenant, main_phone_number: {
|
||||||
id: 10, label: 'Principal', number: '3411234567', tel_url: 'tel:3411234567',
|
id: 10, label: 'Principal', number: '3411234567', tel_url: 'tel:3411234567',
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ export interface CatalogCategory {
|
|||||||
id: number;
|
id: number;
|
||||||
nombre: string;
|
nombre: string;
|
||||||
categoria_id: number | null;
|
categoria_id: number | null;
|
||||||
|
banner_url?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CategoryItemsResponse extends ApiPaginatedResponse<CatalogFeaturedItem[]> {
|
export interface CategoryItemsResponse extends ApiPaginatedResponse<CatalogFeaturedItem[]> {
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ export interface Tenant {
|
|||||||
allow_ticket_partial_refund?: boolean;
|
allow_ticket_partial_refund?: boolean;
|
||||||
ticket_partial_refund_percentage?: string;
|
ticket_partial_refund_percentage?: string;
|
||||||
social_media?: SocialMedia[];
|
social_media?: SocialMedia[];
|
||||||
|
tenant_social_media?: SocialMedia[];
|
||||||
menues?: Menu[];
|
menues?: Menu[];
|
||||||
categories?: Category[];
|
categories?: Category[];
|
||||||
event_categories?: Category[];
|
event_categories?: Category[];
|
||||||
|
|||||||
@@ -2,7 +2,14 @@
|
|||||||
@if (error()) {
|
@if (error()) {
|
||||||
<p class="alert text-center mb-0 category-items__alert-error">{{ error() }}</p>
|
<p class="alert text-center mb-0 category-items__alert-error">{{ error() }}</p>
|
||||||
} @else if (results(); as categoryResults) {
|
} @else if (results(); as categoryResults) {
|
||||||
<header class="category-items__header mb-5">
|
@if (categoryResults.category.banner_url; as bannerUrl) {
|
||||||
|
<img
|
||||||
|
class="category-items__banner"
|
||||||
|
[src]="bannerUrl"
|
||||||
|
[alt]="'Banner de ' + categoryResults.category.nombre"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<header class="category-items__header">
|
||||||
<h1 id="category-items-title" class="category-items__title mb-0">
|
<h1 id="category-items-title" class="category-items__title mb-0">
|
||||||
{{ categoryResults.category.nombre }}
|
{{ categoryResults.category.nombre }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
|
.category-items__banner {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 170px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
.category-items__header {
|
.category-items__header {
|
||||||
display: flex;
|
margin: 16px 0;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 16px 28px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-items__title {
|
.category-items__title {
|
||||||
font-size: 24px;
|
font-size: 15px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
color:var(--bs-primary)
|
text-transform: uppercase;
|
||||||
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-items__alert-error {
|
.category-items__alert-error {
|
||||||
|
|||||||
@@ -106,6 +106,30 @@ describe('CategoryItemsPageComponent', () => {
|
|||||||
expect(productList.layout()).toBe('row');
|
expect(productList.layout()).toBe('row');
|
||||||
expect(productList.groupLayout()).toBe('paginated');
|
expect(productList.groupLayout()).toBe('paginated');
|
||||||
expect(Array.isArray(productList.items())).toBe(false);
|
expect(Array.isArray(productList.items())).toBe(false);
|
||||||
|
expect(fixture.nativeElement.querySelector('.category-items__banner')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the category banner above the title when the API returns its URL', () => {
|
||||||
|
getCategoryItems.mockReturnValue(
|
||||||
|
of({
|
||||||
|
category: {
|
||||||
|
id: 7,
|
||||||
|
nombre: 'Remeras',
|
||||||
|
categoria_id: null,
|
||||||
|
banner_url: 'https://example.com/banner.jpg',
|
||||||
|
},
|
||||||
|
data: [],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(CategoryItemsPageComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
|
const banner = element.querySelector<HTMLImageElement>('.category-items__banner');
|
||||||
|
expect(banner?.getAttribute('src')).toBe('https://example.com/banner.jpg');
|
||||||
|
expect(banner?.alt).toBe('Banner de Remeras');
|
||||||
|
expect(banner?.nextElementSibling?.querySelector('h1')?.textContent).toContain('Remeras');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reloads the current category page when catalog availability changes', () => {
|
it('reloads the current category page when catalog availability changes', () => {
|
||||||
|
|||||||
@@ -138,6 +138,24 @@ describe('ContactPage', () => {
|
|||||||
expect(element.textContent).toContain('San Martín 2450');
|
expect(element.textContent).toContain('San Martín 2450');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses commerce networks even when the active event has different networks', () => {
|
||||||
|
tenantState.set({
|
||||||
|
...tenant,
|
||||||
|
tenant_social_media: [{ ...tenant.social_media![0], url: 'https://wa.me/commerce' }],
|
||||||
|
social_media: [{ ...tenant.social_media![0], url: 'https://wa.me/event' }],
|
||||||
|
});
|
||||||
|
fixture.detectChanges();
|
||||||
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(element.querySelector('a[href="https://wa.me/commerce"]')).not.toBeNull();
|
||||||
|
expect(element.querySelector('a[href="https://wa.me/event"]')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not restore event networks after all commerce networks are removed', () => {
|
||||||
|
tenantState.set({ ...tenant, tenant_social_media: [] });
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect((fixture.nativeElement as HTMLElement).querySelector('a[href="https://wa.me/543412602222"]')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('passes the tenant map coordinates to the reusable map component', () => {
|
it('passes the tenant map coordinates to the reusable map component', () => {
|
||||||
const element = fixture.nativeElement as HTMLElement;
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
const map = element.querySelector('app-location-map');
|
const map = element.querySelector('app-location-map');
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class ContactPage {
|
|||||||
|
|
||||||
private buildContactContent(): ContactContent {
|
private buildContactContent(): ContactContent {
|
||||||
const tenant = this.tenantService.tenant();
|
const tenant = this.tenantService.tenant();
|
||||||
const socialMedia = (tenant?.social_media ?? []).filter((social) => social.url.trim());
|
const socialMedia = (tenant?.tenant_social_media ?? tenant?.social_media ?? []).filter((social) => social.url.trim());
|
||||||
const addresses = [...(tenant?.addresses ?? [])].sort(
|
const addresses = [...(tenant?.addresses ?? [])].sort(
|
||||||
(a, b) => Number(b.is_main) - Number(a.is_main),
|
(a, b) => Number(b.is_main) - Number(a.is_main),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user