- agruparPorZona (lib/funnel/fotos.ts): helper puro que agrupa fotos (antes/después) y notas por zona, con fallback al tipo del lead. 5 tests. - getLead trae también lead_notas. - LeadFotosGaleria: galería por zona (Antes/Después + notas) que sustituye el grid plano de la ficha del panel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
82 lines
2.4 KiB
TypeScript
82 lines
2.4 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { agruparPorZona } from '@/lib/funnel/fotos';
|
|
import type { LeadFoto, LeadNota } from '@/db/schema';
|
|
|
|
function foto(p: Partial<LeadFoto>): LeadFoto {
|
|
return {
|
|
id: Math.random().toString(36).slice(2),
|
|
leadId: 'lead-1',
|
|
url: 'data:img',
|
|
momento: 'antes',
|
|
zona: null,
|
|
orden: 0,
|
|
createdAt: new Date(),
|
|
...p,
|
|
} as LeadFoto;
|
|
}
|
|
|
|
function nota(p: Partial<LeadNota>): LeadNota {
|
|
return {
|
|
id: Math.random().toString(36).slice(2),
|
|
leadId: 'lead-1',
|
|
zona: null,
|
|
texto: 'x',
|
|
origen: 'ep',
|
|
createdAt: new Date(),
|
|
...p,
|
|
} as LeadNota;
|
|
}
|
|
|
|
describe('agruparPorZona', () => {
|
|
it('separa antes y después dentro de cada zona', () => {
|
|
const grupos = agruparPorZona(
|
|
[
|
|
foto({ zona: 'bano', momento: 'antes' }),
|
|
foto({ zona: 'bano', momento: 'despues' }),
|
|
foto({ zona: 'bano', momento: 'antes' }),
|
|
],
|
|
[],
|
|
'otro',
|
|
);
|
|
expect(grupos).toHaveLength(1);
|
|
expect(grupos[0].zona).toBe('bano');
|
|
expect(grupos[0].antes).toHaveLength(2);
|
|
expect(grupos[0].despues).toHaveLength(1);
|
|
});
|
|
|
|
it('agrupa por zona distintas y mantiene el orden de aparición', () => {
|
|
const grupos = agruparPorZona(
|
|
[foto({ zona: 'cocina' }), foto({ zona: 'bano' }), foto({ zona: 'cocina' })],
|
|
[],
|
|
'otro',
|
|
);
|
|
expect(grupos.map((g) => g.zona)).toEqual(['cocina', 'bano']);
|
|
expect(grupos[0].antes).toHaveLength(2);
|
|
});
|
|
|
|
it('usa el tipo del lead como fallback cuando la zona es null', () => {
|
|
const grupos = agruparPorZona([foto({ zona: null })], [nota({ zona: null })], 'salon');
|
|
expect(grupos).toHaveLength(1);
|
|
expect(grupos[0].zona).toBe('salon');
|
|
expect(grupos[0].antes).toHaveLength(1);
|
|
expect(grupos[0].notas).toHaveLength(1);
|
|
});
|
|
|
|
it('asocia las notas a su zona', () => {
|
|
const grupos = agruparPorZona(
|
|
[foto({ zona: 'cocina' })],
|
|
[nota({ zona: 'cocina', texto: 'encimera de cuarzo' }), nota({ zona: 'bano', texto: 'ducha' })],
|
|
'otro',
|
|
);
|
|
const cocina = grupos.find((g) => g.zona === 'cocina');
|
|
const bano = grupos.find((g) => g.zona === 'bano');
|
|
expect(cocina?.notas.map((n) => n.texto)).toEqual(['encimera de cuarzo']);
|
|
expect(bano?.notas.map((n) => n.texto)).toEqual(['ducha']);
|
|
expect(bano?.antes).toHaveLength(0);
|
|
});
|
|
|
|
it('devuelve vacío sin fotos ni notas', () => {
|
|
expect(agruparPorZona([], [], 'cocina')).toEqual([]);
|
|
});
|
|
});
|