feat: add ReutilizablesTestPageComponent to showcase and validate shared button and input component variants

This commit is contained in:
2026-06-26 16:58:14 -03:00
parent e074aeb199
commit fa47188898
4 changed files with 262 additions and 1 deletions

View File

@@ -176,4 +176,84 @@
</div>
</div>
</section>
<section class="component-demo card shadow-sm mt-4 configuracion-tennant">
<div class="card-body">
<span class="eyebrow">Tenant Configuration</span>
<h2 class="mb-4">Configuración Tenant</h2>
<!-- Logos section -->
<div class="row mb-4">
<div class="col-md-6 mb-3 mb-md-0">
<div class="tenant-logo-card">
<div class="tenant-logo-card__label">Logo del Header</div>
<div class="tenant-logo-card__container header-footer-bg">
@if (tenant()?.header_logo) {
<img [src]="tenant()?.header_logo" alt="Header Logo" class="tenant-logo-card__img" />
} @else {
<div class="tenant-logo-card__placeholder">
<i class="fa-solid fa-image mb-2"></i>
<span>Sin Logo de Header</span>
</div>
}
</div>
</div>
</div>
<div class="col-md-6">
<div class="tenant-logo-card">
<div class="tenant-logo-card__label">Logo del Footer</div>
<div class="tenant-logo-card__container header-footer-bg">
@if (tenant()?.footer_logo) {
<img [src]="tenant()?.footer_logo" alt="Footer Logo" class="tenant-logo-card__img" />
} @else {
<div class="tenant-logo-card__placeholder">
<i class="fa-solid fa-image mb-2"></i>
<span>Sin Logo de Footer</span>
</div>
}
</div>
</div>
</div>
</div>
<hr class="section-divider" />
<!-- Colors section -->
<div class="colors-section">
<h3 class="mb-3">Colores de Marca</h3>
<div class="row">
<div class="col-md-4 mb-3">
<div class="color-swatch-card shadow-sm">
<div class="color-swatch-card__preview" [style.background-color]="'var(--tenant-primary)'"></div>
<div class="color-swatch-card__body">
<span class="color-swatch-card__title">Primario</span>
<code class="color-swatch-card__value">{{ tenant()?.primary_color || 'Default' }}</code>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="color-swatch-card shadow-sm">
<div class="color-swatch-card__preview" [style.background-color]="'var(--tenant-secondary)'"></div>
<div class="color-swatch-card__body">
<span class="color-swatch-card__title">Secundario</span>
<code class="color-swatch-card__value">{{ tenant()?.secondary_color || 'Default' }}</code>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="color-swatch-card shadow-sm">
<div class="color-swatch-card__preview" [style.background-color]="'var(--tenant-danger)'"></div>
<div class="color-swatch-card__body">
<span class="color-swatch-card__title">Danger</span>
<code class="color-swatch-card__value">{{ tenant()?.danger_color || 'Default' }}</code>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>

View File

@@ -70,6 +70,12 @@ h1 {
gap: 0;
}
.file-field {
display: grid;
gap: 0.75rem;
}
.file-field {
display: grid;
gap: 0.75rem;
@@ -86,3 +92,109 @@ h1 {
grid-template-columns: minmax(0, 1fr);
}
}
.configuracion-tennant {
margin-top: 2rem;
.tenant-logo-card {
display: flex;
flex-direction: column;
gap: 0.5rem;
&__label {
font-size: 0.875rem;
font-weight: 600;
color: #495057;
}
&__container {
display: flex;
align-items: center;
justify-content: center;
height: 120px;
border-radius: 8px;
border: 1px solid #dee2e6;
padding: 1rem;
overflow: hidden;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05);
transition: transform 0.2s ease, box-shadow 0.2s ease;
&:hover {
transform: translateY(-2px);
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05), 0 4px 12px rgba(0, 0, 0, 0.08);
}
}
&__img {
max-height: 100%;
max-width: 100%;
object-fit: contain;
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}
&__placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #6c757d;
font-size: 0.875rem;
i {
font-size: 2rem;
opacity: 0.6;
}
}
}
.header-footer-bg {
background-color: var(--tenant-header-footer-bg, #f8f9fa);
}
.color-swatch-card {
display: flex;
flex-direction: column;
border-radius: 8px;
border: 1px solid #dee2e6;
overflow: hidden;
background-color: #ffffff;
transition: transform 0.2s ease, box-shadow 0.2s ease;
&:hover {
transform: translateY(-3px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1) !important;
}
&__preview {
height: 80px;
width: 100%;
border-bottom: 1px solid #dee2e6;
transition: opacity 0.2s ease;
&:hover {
opacity: 0.95;
}
}
&__body {
padding: 0.75rem 1rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
&__title {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-weight: 700;
color: #6c757d;
}
&__value {
font-size: 0.875rem;
color: #212529;
font-family: var(--bs-font-monospace);
}
}
}

View File

@@ -0,0 +1,66 @@
import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ReutilizablesTestPageComponent } from './reutilizables-test-page.component';
import { Tenant } from '../../../../core/services/tenant.interface';
import { TenantService } from '../../../../core/services/tenant.service';
const tenant: Tenant = {
id: 1,
codigo: 'test',
nombre: 'Test Tenant',
dominio: 'localhost',
primary_color: '#6376F3',
secondary_color: '#A0A0A0',
danger_color: '#FF8888',
header_footer_bg_color: '#313131',
header_logo: 'https://example.com/header.png',
footer_logo: 'https://example.com/footer.png'
};
function createTenantServiceStub(currentTenant: Tenant | null) {
const tenantState = signal(currentTenant);
const statusState = signal<'ready' | 'not-found'>('ready');
return {
tenant: tenantState.asReadonly(),
status: statusState.asReadonly(),
getTenant: () => tenantState(),
bootstrap: vi.fn().mockResolvedValue(undefined)
};
}
describe('ReutilizablesTestPageComponent', () => {
it('renders the tenant configuration section with logo sources and swatch colors', async () => {
await TestBed.configureTestingModule({
imports: [ReutilizablesTestPageComponent],
providers: [
{
provide: TenantService,
useValue: createTenantServiceStub(tenant)
}
]
}).compileComponents();
const fixture = TestBed.createComponent(ReutilizablesTestPageComponent);
fixture.detectChanges();
const element = fixture.nativeElement as HTMLElement;
// Check section title
const sectionTitle = element.querySelector('.configuracion-tennant h2');
expect(sectionTitle?.textContent).toContain('Configuración Tenant');
// Check header logo source
const headerImg = element.querySelector('.tenant-logo-card img[alt="Header Logo"]') as HTMLImageElement;
expect(headerImg?.src).toBe(tenant.header_logo);
// Check footer logo source
const footerImg = element.querySelector('.tenant-logo-card img[alt="Footer Logo"]') as HTMLImageElement;
expect(footerImg?.src).toBe(tenant.footer_logo);
// Check color hex values
expect(element.textContent).toContain(tenant.primary_color);
expect(element.textContent).toContain(tenant.secondary_color);
expect(element.textContent).toContain(tenant.danger_color);
});
});

View File

@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ButtonComponent } from '../../../../shared/components/button/button.component';
import { InputComponent } from '../../../../shared/components/input/input.component';
import { TenantService } from '../../../../core/services/tenant.service';
@Component({
selector: 'app-reutilizables-test-page',
@@ -9,6 +10,8 @@ import { InputComponent } from '../../../../shared/components/input/input.compon
styleUrl: './reutilizables-test-page.component.scss'
})
export class ReutilizablesTestPageComponent {
private readonly tenantService = inject(TenantService);
protected readonly tenant = this.tenantService.tenant;
protected textValue = 'Auriculares';
protected numberValue = '24';
protected email = 'usuario@empresa.com';