feat: add menu content section component for improved layout and responsiveness across help and FAQ pages
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
<section class="menu-content-section" [attr.aria-labelledby]="titleId()">
|
||||||
|
<h2 class="menu-content-section__title" [id]="titleId()">{{ title() }}</h2>
|
||||||
|
|
||||||
|
<div class="menu-content-section__body">
|
||||||
|
<ng-content />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content-section {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content-section__title {
|
||||||
|
margin: 0 0 1.25rem;
|
||||||
|
color: #888888;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content-section__body {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.menu-content-section {
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content-section__title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { MenuContentSectionComponent } from './menu-content-section.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
imports: [MenuContentSectionComponent],
|
||||||
|
template: `
|
||||||
|
<app-menu-content-section title="Contacto" titleId="contact-title">
|
||||||
|
<p>Contenido proyectado</p>
|
||||||
|
</app-menu-content-section>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class TestHostComponent {}
|
||||||
|
|
||||||
|
describe('MenuContentSectionComponent', () => {
|
||||||
|
it('renders an accessible title and projects its content', async () => {
|
||||||
|
await TestBed.configureTestingModule({ imports: [TestHostComponent] }).compileComponents();
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(TestHostComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
|
const section = element.querySelector('section');
|
||||||
|
|
||||||
|
expect(section?.getAttribute('aria-labelledby')).toBe('contact-title');
|
||||||
|
expect(element.querySelector('#contact-title')?.textContent?.trim()).toBe('Contacto');
|
||||||
|
expect(element.querySelector('.menu-content-section__body')?.textContent).toContain(
|
||||||
|
'Contenido proyectado',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component, input } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-menu-content-section',
|
||||||
|
templateUrl: './menu-content-section.component.html',
|
||||||
|
styleUrl: './menu-content-section.component.scss',
|
||||||
|
})
|
||||||
|
export class MenuContentSectionComponent {
|
||||||
|
readonly title = input.required<string>();
|
||||||
|
readonly titleId = input.required<string>();
|
||||||
|
}
|
||||||
@@ -80,5 +80,9 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.75rem 1.25rem;
|
gap: 0.75rem 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
<section class="contact-page" aria-labelledby="contact-page-title">
|
<app-menu-content-section title="CONTACTO" titleId="contact-page-title">
|
||||||
<div class="contact-page__details">
|
<div class="contact-page">
|
||||||
<h2 id="contact-page-title" class="contact-page__title">CONTACTO</h2>
|
<div class="contact-page__details">
|
||||||
|
@if (contact().whatsappUrl && contact().whatsappLabel) {
|
||||||
|
<a
|
||||||
|
class="contact-page__contact-link"
|
||||||
|
[href]="contact().whatsappUrl"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<i class="fa-brands fa-whatsapp" aria-hidden="true"></i>
|
||||||
|
<span>{{ contact().whatsappLabel }}</span>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
|
||||||
@if (contact().whatsappUrl && contact().whatsappLabel) {
|
@if (contact().phone; as phone) {
|
||||||
<a
|
<a class="contact-page__contact-link" [href]="phoneUrl(phone)">
|
||||||
class="contact-page__contact-link"
|
<i class="fa-solid fa-phone" aria-hidden="true"></i>
|
||||||
[href]="contact().whatsappUrl"
|
<span>{{ phone }}</span>
|
||||||
target="_blank"
|
</a>
|
||||||
rel="noopener noreferrer"
|
}
|
||||||
>
|
|
||||||
<i class="fa-brands fa-whatsapp" aria-hidden="true"></i>
|
|
||||||
<span>{{ contact().whatsappLabel }}</span>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (contact().phone; as phone) {
|
@for (location of contact().locations; track location.id) {
|
||||||
<a class="contact-page__contact-link" [href]="phoneUrl(phone)">
|
<article class="contact-page__location">
|
||||||
<i class="fa-solid fa-phone" aria-hidden="true"></i>
|
<h3 class="contact-page__location-title">
|
||||||
<span>{{ phone }}</span>
|
<i class="fa-solid fa-location-dot" aria-hidden="true"></i>
|
||||||
</a>
|
<span>{{ location.label }}</span>
|
||||||
}
|
</h3>
|
||||||
|
|
||||||
@for (location of contact().locations; track location.id) {
|
<ul class="contact-page__addresses">
|
||||||
<article class="contact-page__location">
|
@for (address of location.addresses; track address.id) {
|
||||||
<h3 class="contact-page__location-title">
|
<li>{{ address.address }}</li>
|
||||||
<i class="fa-solid fa-location-dot" aria-hidden="true"></i>
|
}
|
||||||
<span>{{ location.label }}</span>
|
</ul>
|
||||||
</h3>
|
</article>
|
||||||
|
}
|
||||||
|
|
||||||
<ul class="contact-page__addresses">
|
@if (!contact().whatsappUrl && !contact().phone && contact().locations.length === 0) {
|
||||||
@for (address of location.addresses; track address.id) {
|
<p class="contact-page__empty">No hay datos de contacto disponibles.</p>
|
||||||
<li>{{ address.address }}</li>
|
}
|
||||||
}
|
</div>
|
||||||
</ul>
|
|
||||||
</article>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!contact().whatsappUrl && !contact().phone && contact().locations.length === 0) {
|
@if (contact().mapLocations.length > 0) {
|
||||||
<p class="contact-page__empty">No hay datos de contacto disponibles.</p>
|
<app-location-map
|
||||||
|
class="contact-page__map"
|
||||||
|
[locations]="contact().mapLocations"
|
||||||
|
[markerColor]="markerColor()"
|
||||||
|
mapStyle="minimal-light"
|
||||||
|
ariaLabel="Mapa de sucursales y puntos de atención"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</app-menu-content-section>
|
||||||
@if (contact().mapLocations.length > 0) {
|
|
||||||
<app-location-map
|
|
||||||
class="contact-page__map"
|
|
||||||
[locations]="contact().mapLocations"
|
|
||||||
[markerColor]="markerColor()"
|
|
||||||
mapStyle="minimal-light"
|
|
||||||
ariaLabel="Mapa de sucursales y puntos de atención"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</section>
|
|
||||||
|
|||||||
@@ -20,14 +20,6 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-page__title {
|
|
||||||
margin: 0 0 1.25rem;
|
|
||||||
color: inherit;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-page__contact-link {
|
.contact-page__contact-link {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -128,10 +120,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-page__title {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contact-page__location {
|
.contact-page__location {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Component, computed, inject } from '@angular/core';
|
|||||||
|
|
||||||
import { findMenu } from '../../../../../../core/services/menu.utils';
|
import { findMenu } from '../../../../../../core/services/menu.utils';
|
||||||
import { TenantService } from '../../../../../../core/services/tenant.service';
|
import { TenantService } from '../../../../../../core/services/tenant.service';
|
||||||
|
import { MenuContentSectionComponent } from '../../../../components/menu-content-section/menu-content-section.component';
|
||||||
import {
|
import {
|
||||||
LocationMapComponent,
|
LocationMapComponent,
|
||||||
MapLocation,
|
MapLocation,
|
||||||
@@ -30,7 +31,7 @@ type ContactContent = {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact-page',
|
selector: 'app-contact-page',
|
||||||
imports: [LocationMapComponent],
|
imports: [LocationMapComponent, MenuContentSectionComponent],
|
||||||
templateUrl: './contact-page.html',
|
templateUrl: './contact-page.html',
|
||||||
styleUrl: './contact-page.scss',
|
styleUrl: './contact-page.scss',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
<section class="faq-page" aria-labelledby="faq-page-title">
|
<app-menu-content-section class="faq-page" title="PREGUNTAS FRECUENTES" titleId="faq-page-title">
|
||||||
<h2 id="faq-page-title" class="faq-page__title">PREGUNTAS FRECUENTES</h2>
|
|
||||||
|
|
||||||
@if (faqs().length > 0) {
|
@if (faqs().length > 0) {
|
||||||
<app-accordion [flush]="true">
|
<app-accordion [flush]="true">
|
||||||
@for (faq of faqs(); track $index; let last = $last) {
|
@for (faq of faqs(); track $index; let last = $last) {
|
||||||
<app-accordion-item
|
<app-accordion-item [title]="faq.question" [headingLevel]="3" [open]="last">
|
||||||
[title]="faq.question"
|
|
||||||
[headingLevel]="3"
|
|
||||||
[open]="last"
|
|
||||||
>
|
|
||||||
<p>{{ faq.answer }}</p>
|
<p>{{ faq.answer }}</p>
|
||||||
</app-accordion-item>
|
</app-accordion-item>
|
||||||
}
|
}
|
||||||
@@ -16,4 +10,4 @@
|
|||||||
} @else {
|
} @else {
|
||||||
<p class="faq-page__empty">No hay preguntas frecuentes disponibles.</p>
|
<p class="faq-page__empty">No hay preguntas frecuentes disponibles.</p>
|
||||||
}
|
}
|
||||||
</section>
|
</app-menu-content-section>
|
||||||
|
|||||||
@@ -4,18 +4,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.faq-page {
|
.faq-page {
|
||||||
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 760px;
|
max-width: 760px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.faq-page__title {
|
|
||||||
margin: 0 0 0.5rem;
|
|
||||||
color: #a0a0a0;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.faq-page p {
|
.faq-page p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -26,9 +19,3 @@
|
|||||||
color: #888888;
|
color: #888888;
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
|
||||||
.faq-page__title {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { findMenu } from '../../../../../../core/services/menu.utils';
|
|||||||
import { TenantService } from '../../../../../../core/services/tenant.service';
|
import { TenantService } from '../../../../../../core/services/tenant.service';
|
||||||
import { AccordionItemComponent } from '../../../../../../shared/components/accordion/accordion-item.component';
|
import { AccordionItemComponent } from '../../../../../../shared/components/accordion/accordion-item.component';
|
||||||
import { AccordionComponent } from '../../../../../../shared/components/accordion/accordion.component';
|
import { AccordionComponent } from '../../../../../../shared/components/accordion/accordion.component';
|
||||||
|
import { MenuContentSectionComponent } from '../../../../components/menu-content-section/menu-content-section.component';
|
||||||
|
|
||||||
type Faq = {
|
type Faq = {
|
||||||
question: string;
|
question: string;
|
||||||
@@ -12,7 +13,7 @@ type Faq = {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-faq-page',
|
selector: 'app-faq-page',
|
||||||
imports: [AccordionComponent, AccordionItemComponent],
|
imports: [AccordionComponent, AccordionItemComponent, MenuContentSectionComponent],
|
||||||
templateUrl: './faq-page.html',
|
templateUrl: './faq-page.html',
|
||||||
styleUrl: './faq-page.scss',
|
styleUrl: './faq-page.scss',
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user