Muestra fotos y notas por zona en la ficha del lead
- 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>
This commit is contained in:
81
mvp/b2c/tests/panel/agrupar-zonas.test.ts
Normal file
81
mvp/b2c/tests/panel/agrupar-zonas.test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
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([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user