feat: implement store layout and home page components with routing
This commit is contained in:
44
src/app/app.routes.spec.ts
Normal file
44
src/app/app.routes.spec.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { provideRouter, Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { App } from './app';
|
||||||
|
import { routes } from './app.routes';
|
||||||
|
|
||||||
|
async function renderAppAt(url: string) {
|
||||||
|
TestBed.resetTestingModule();
|
||||||
|
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [App],
|
||||||
|
providers: [provideRouter(routes)]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
const router = TestBed.inject(Router);
|
||||||
|
const fixture = TestBed.createComponent(App);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
await router.navigateByUrl(url);
|
||||||
|
await fixture.whenStable();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
return { fixture, router };
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('app routes', () => {
|
||||||
|
it('loads the store layout at /store', async () => {
|
||||||
|
const { fixture, router } = await renderAppAt('/store');
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
|
||||||
|
expect(router.url).toBe('/store');
|
||||||
|
expect(compiled.querySelector('.store-layout')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.store-home')).not.toBeNull();
|
||||||
|
expect(compiled.textContent).toContain('Tienda en construccion');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps the root redirect under componentes-test', async () => {
|
||||||
|
const { fixture, router } = await renderAppAt('/');
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
|
||||||
|
expect(router.url).toBe('/componentes-test/reutilizables');
|
||||||
|
expect(compiled.textContent).toContain('Componentes reutilizables');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -6,6 +6,10 @@ export const routes: Routes = [
|
|||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./features/componentes-test/componentes-test.routes').then((m) => m.routes)
|
import('./features/componentes-test/componentes-test.routes').then((m) => m.routes)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'store',
|
||||||
|
loadChildren: () => import('./features/store/store.routes').then((m) => m.routes)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
|
|||||||
110
src/app/core/layout/store-layout/store-layout.component.html
Normal file
110
src/app/core/layout/store-layout/store-layout.component.html
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<div class="store-layout">
|
||||||
|
<header class="store-layout__header">
|
||||||
|
<div class="store-layout__top-bar">
|
||||||
|
<div class="store-layout__container store-layout__top-content">
|
||||||
|
<div
|
||||||
|
class="store-layout__brand-slot"
|
||||||
|
data-testid="store-header-brand-slot"
|
||||||
|
aria-label="Espacio reservado para logo de Sonder"
|
||||||
|
>
|
||||||
|
<span class="store-layout__brand-mark" aria-hidden="true">S</span>
|
||||||
|
<span class="store-layout__brand-text">SONDER</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="store-layout__tools">
|
||||||
|
<div class="store-layout__search" role="search">
|
||||||
|
<label class="visually-hidden" for="store-search-input">Buscar productos</label>
|
||||||
|
<input
|
||||||
|
id="store-search-input"
|
||||||
|
type="search"
|
||||||
|
class="store-layout__search-input"
|
||||||
|
placeholder="Buscar productos"
|
||||||
|
/>
|
||||||
|
<button type="button" class="store-layout__search-button" aria-label="Buscar">
|
||||||
|
<i class="fa-solid fa-magnifying-glass" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="store-layout__actions" aria-label="Acciones de usuario">
|
||||||
|
@for (action of headerActions; track action.label) {
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="store-layout__header-action"
|
||||||
|
[attr.aria-label]="action.label"
|
||||||
|
[attr.title]="action.label"
|
||||||
|
>
|
||||||
|
<i [class]="action.iconClass" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="store-layout__category-bar">
|
||||||
|
<div class="store-layout__container">
|
||||||
|
<button type="button" class="store-layout__category-trigger" aria-label="Categorias">
|
||||||
|
<span>Categorias</span>
|
||||||
|
<i class="fa-solid fa-chevron-down" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="store-layout__main">
|
||||||
|
<router-outlet />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="store-layout__footer">
|
||||||
|
<div class="store-layout__container store-layout__footer-content">
|
||||||
|
<div class="store-layout__footer-brand-group">
|
||||||
|
<div
|
||||||
|
class="store-layout__brand-slot store-layout__brand-slot--footer"
|
||||||
|
data-testid="store-footer-brand-slot"
|
||||||
|
aria-label="Espacio reservado para logo de Sonder"
|
||||||
|
>
|
||||||
|
<span class="store-layout__brand-mark store-layout__brand-mark--footer" aria-hidden="true">
|
||||||
|
S
|
||||||
|
</span>
|
||||||
|
<span class="store-layout__brand-text store-layout__brand-text--footer">SONDER</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="store-layout__contact-list">
|
||||||
|
<div class="store-layout__contact-item">
|
||||||
|
<i class="fa-solid fa-location-dot" aria-hidden="true"></i>
|
||||||
|
<span>Av. San Lorenzo 1542, Rosario</span>
|
||||||
|
</div>
|
||||||
|
<div class="store-layout__contact-item">
|
||||||
|
<i class="fa-solid fa-phone" aria-hidden="true"></i>
|
||||||
|
<span>54 9 (0341) 6658247</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="store-layout__copyright">Copyright © {{ currentYear }} - Sonder</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@for (section of footerSections; track section.heading) {
|
||||||
|
<div class="store-layout__footer-section">
|
||||||
|
<h2 class="store-layout__footer-heading">{{ section.heading }}</h2>
|
||||||
|
<div class="store-layout__footer-links">
|
||||||
|
@for (link of section.links; track link) {
|
||||||
|
<span class="store-layout__footer-link">{{ link }}</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="store-layout__social-group">
|
||||||
|
<h2 class="store-layout__footer-heading">Seguinos:</h2>
|
||||||
|
<div class="store-layout__social-links">
|
||||||
|
@for (social of socialLinks; track social.label) {
|
||||||
|
<span class="store-layout__social-link">
|
||||||
|
<i [class]="social.iconClass" aria-hidden="true"></i>
|
||||||
|
<span class="visually-hidden">{{ social.label }}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
288
src/app/core/layout/store-layout/store-layout.component.scss
Normal file
288
src/app/core/layout/store-layout/store-layout.component.scss
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100dvh;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
color: #202020;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__container {
|
||||||
|
width: min(100% - 3rem, 75rem);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__header {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-bottom: 1px solid #e9e9e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__top-bar {
|
||||||
|
border-bottom: 1px solid #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__top-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1.5rem;
|
||||||
|
min-height: 5.5rem;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-slot {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
min-width: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-mark {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 2.75rem;
|
||||||
|
height: 2.75rem;
|
||||||
|
border: 1px dashed #bbbbbb;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
color: #373737;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-text {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.08em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__tools {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: min(100%, 24rem);
|
||||||
|
min-width: 18rem;
|
||||||
|
border: 1px solid #313131;
|
||||||
|
border-radius: 0.35rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0.7rem 0.85rem;
|
||||||
|
border: 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search-button,
|
||||||
|
.store-layout__header-action,
|
||||||
|
.store-layout__category-trigger {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search-button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2.75rem;
|
||||||
|
height: 2.75rem;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__header-action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__category-bar {
|
||||||
|
min-height: 2.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__category-trigger {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
min-height: 2.35rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #202020;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__main {
|
||||||
|
flex: 1;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer {
|
||||||
|
margin-top: auto;
|
||||||
|
background-color: #323232;
|
||||||
|
color: #f3f3f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-content {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(16rem, 1.6fr) repeat(2, minmax(10rem, 1fr)) auto;
|
||||||
|
gap: 2rem;
|
||||||
|
padding: 2.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-brand-group,
|
||||||
|
.store-layout__footer-section,
|
||||||
|
.store-layout__social-group {
|
||||||
|
display: grid;
|
||||||
|
align-content: start;
|
||||||
|
gap: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-slot--footer {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-mark--footer {
|
||||||
|
border-color: rgba(255, 255, 255, 0.35);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-text--footer {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__contact-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__contact-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__copyright {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #d3d3d3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-heading {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-links {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.55rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-link {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__social-group {
|
||||||
|
justify-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__social-links {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.85rem;
|
||||||
|
padding-top: 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__social-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
.store-layout__top-content {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__tools {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-content {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.store-layout__container {
|
||||||
|
width: min(100% - 1.5rem, 75rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-slot {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__brand-text {
|
||||||
|
font-size: 1.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__tools {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__search {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__actions {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-layout__footer-content {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 2rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
|
import { StoreLayoutComponent } from './store-layout.component';
|
||||||
|
|
||||||
|
describe('StoreLayoutComponent', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [StoreLayoutComponent],
|
||||||
|
providers: [provideRouter([])]
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the main layout sections', () => {
|
||||||
|
const fixture = TestBed.createComponent(StoreLayoutComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
|
||||||
|
expect(compiled.querySelector('.store-layout__header')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.store-layout__category-trigger')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('router-outlet')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.store-layout__footer')).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the placeholder branding and action icons', () => {
|
||||||
|
const fixture = TestBed.createComponent(StoreLayoutComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
|
||||||
|
expect(compiled.querySelector('[data-testid="store-header-brand-slot"]')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('[data-testid="store-footer-brand-slot"]')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-cart-shopping')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-circle-user')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-instagram')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-whatsapp')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-facebook')).not.toBeNull();
|
||||||
|
expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
68
src/app/core/layout/store-layout/store-layout.component.ts
Normal file
68
src/app/core/layout/store-layout/store-layout.component.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
|
||||||
|
type StoreHeaderAction = {
|
||||||
|
label: string;
|
||||||
|
iconClass: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StoreFooterSection = {
|
||||||
|
heading: string;
|
||||||
|
links: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type StoreSocialLink = {
|
||||||
|
label: string;
|
||||||
|
iconClass: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-store-layout',
|
||||||
|
imports: [RouterOutlet],
|
||||||
|
templateUrl: './store-layout.component.html',
|
||||||
|
styleUrl: './store-layout.component.scss'
|
||||||
|
})
|
||||||
|
export class StoreLayoutComponent {
|
||||||
|
protected readonly currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
|
protected readonly headerActions: StoreHeaderAction[] = [
|
||||||
|
{
|
||||||
|
label: 'Carrito',
|
||||||
|
iconClass: 'fa-solid fa-cart-shopping'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Mi cuenta',
|
||||||
|
iconClass: 'fa-solid fa-circle-user'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
protected readonly footerSections: StoreFooterSection[] = [
|
||||||
|
{
|
||||||
|
heading: 'Cuenta',
|
||||||
|
links: ['Mi cuenta', 'Mis compras', 'Cerrar sesion']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
heading: 'Ayuda',
|
||||||
|
links: ['Contacto', 'Ayuda', 'Preguntas frecuentes']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
protected readonly socialLinks: StoreSocialLink[] = [
|
||||||
|
{
|
||||||
|
label: 'Instagram',
|
||||||
|
iconClass: 'fa-brands fa-instagram'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'WhatsApp',
|
||||||
|
iconClass: 'fa-brands fa-whatsapp'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Facebook',
|
||||||
|
iconClass: 'fa-brands fa-facebook'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'LinkedIn',
|
||||||
|
iconClass: 'fa-brands fa-linkedin-in'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<section class="store-home">
|
||||||
|
<div class="store-home__inner">
|
||||||
|
<div class="store-home__hero">
|
||||||
|
<span class="store-home__eyebrow">Store Layout</span>
|
||||||
|
<h1>Tienda en construccion</h1>
|
||||||
|
<p class="store-home__lead">
|
||||||
|
Esta pagina placeholder deja visible el shell del store mientras se conectan categorias,
|
||||||
|
catalogo y acciones reales.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="store-home__highlights">
|
||||||
|
@for (highlight of highlights; track highlight) {
|
||||||
|
<article class="store-home__card">
|
||||||
|
<span class="store-home__card-index" aria-hidden="true">0{{ $index + 1 }}</span>
|
||||||
|
<p>{{ highlight }}</p>
|
||||||
|
</article>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home {
|
||||||
|
padding: 3rem 0 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__inner {
|
||||||
|
width: min(100% - 3rem, 75rem);
|
||||||
|
margin: 0 auto;
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__hero {
|
||||||
|
padding: clamp(2rem, 4vw, 3rem);
|
||||||
|
border: 1px solid #e4e4e4;
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
|
||||||
|
box-shadow: 0 1.2rem 2.2rem rgba(17, 17, 17, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__eyebrow {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-size: clamp(2rem, 4vw, 3.25rem);
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__lead {
|
||||||
|
max-width: 42rem;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__highlights {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__card {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.9rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border: 1px solid #e4e4e4;
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 0.75rem 1.5rem rgba(17, 17, 17, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__card-index {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: #707070;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__card p {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
.store-home__highlights {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.store-home {
|
||||||
|
padding: 2rem 0 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__inner {
|
||||||
|
width: min(100% - 1.5rem, 75rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-home__highlights {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-store-home-page',
|
||||||
|
templateUrl: './store-home-page.component.html',
|
||||||
|
styleUrl: './store-home-page.component.scss'
|
||||||
|
})
|
||||||
|
export class StoreHomePageComponent {
|
||||||
|
protected readonly highlights = [
|
||||||
|
'Header y footer listos para conectar con datos reales.',
|
||||||
|
'Barra de categorias reservada para sumar dropdown despues.',
|
||||||
|
'Placeholder inicial para validar layout, espaciados y responsive.'
|
||||||
|
];
|
||||||
|
}
|
||||||
17
src/app/features/store/store.routes.ts
Normal file
17
src/app/features/store/store.routes.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { StoreLayoutComponent } from '../../core/layout/store-layout/store-layout.component';
|
||||||
|
import { StoreHomePageComponent } from './pages/store-home-page/store-home-page.component';
|
||||||
|
|
||||||
|
export const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: StoreLayoutComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: StoreHomePageComponent
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
6
src/environments/environment.local.ts
Normal file
6
src/environments/environment.local.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const environment = {
|
||||||
|
production: false,
|
||||||
|
nombre:"Desarrollo - activo",
|
||||||
|
url:"http://localhost:8000/api/",
|
||||||
|
urlDescarga:"url/"
|
||||||
|
};
|
||||||
6
src/environments/environment.ts
Normal file
6
src/environments/environment.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const environment = {
|
||||||
|
production: false,
|
||||||
|
nombre:"Desarrollo - activo",
|
||||||
|
url:"url/api/",
|
||||||
|
urlDescarga:"url/"
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user