Sustituye la paleta negra/azul B2C del panel del reformista por el verde de marca, neutros cálidos y titulares en Instrument Serif de la landing B2B. Añade tokens --color-primary-*, --color-stone-50 y --font-display al @theme. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
126 lines
5.0 KiB
TypeScript
126 lines
5.0 KiB
TypeScript
import { getTestimoniosPanel, type TestimonioPanel } from '@/db/tenant-queries';
|
|
import { formatFecha } from '@/lib/funnel';
|
|
import { publicarTestimonio, ocultarTestimonio, eliminarTestimonio } from './actions';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
const ESTADO_BADGE: Record<TestimonioPanel['estado'], { label: string; className: string }> = {
|
|
pendiente: { label: 'Pendiente', className: 'bg-amber-100 text-amber-700' },
|
|
publicado: { label: 'Publicado', className: 'bg-green-100 text-green-700' },
|
|
oculto: { label: 'Oculto', className: 'bg-gray-100 text-gray-500' },
|
|
};
|
|
|
|
function Estrellas({ rating }: { rating: number }) {
|
|
return (
|
|
<div className="flex gap-0.5" aria-label={`${rating} de 5 estrellas`}>
|
|
{[1, 2, 3, 4, 5].map((n) => (
|
|
<svg
|
|
key={n}
|
|
viewBox="0 0 24 24"
|
|
className={`w-4 h-4 ${n <= rating ? 'fill-yellow-400' : 'fill-gray-200'}`}
|
|
aria-hidden="true"
|
|
>
|
|
<path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
|
</svg>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default async function OpinionesPage() {
|
|
const testimonios = await getTestimoniosPanel();
|
|
|
|
return (
|
|
<div className="space-y-8 max-w-3xl">
|
|
<div>
|
|
<h1 className="font-display text-3xl tracking-tight text-black">Opiniones</h1>
|
|
<p className="text-sm text-gray-500 mt-1">
|
|
Las opiniones que te dejan tus clientes. Aprueba las que quieras mostrar en tu funnel; solo
|
|
las publicadas aparecen en tu página.
|
|
</p>
|
|
</div>
|
|
|
|
{testimonios.length === 0 ? (
|
|
<div className="bg-white rounded-xl border border-gray-200 p-8 text-center text-sm text-gray-400">
|
|
Aún no tienes opiniones. Solicítalas a tus clientes desde la ficha de un lead ganado.
|
|
</div>
|
|
) : (
|
|
<ul className="flex flex-col gap-4">
|
|
{testimonios.map((t) => {
|
|
const badge = ESTADO_BADGE[t.estado];
|
|
return (
|
|
<li
|
|
key={t.id}
|
|
className="bg-white rounded-xl border border-gray-200 p-5 flex flex-col gap-3"
|
|
>
|
|
<div className="flex items-start justify-between gap-4">
|
|
<div className="flex flex-col gap-1">
|
|
<div className="flex items-center gap-2">
|
|
<span className="font-bold text-black">{t.nombre}</span>
|
|
<span
|
|
className={`px-2 py-0.5 rounded-full text-xs font-semibold ${badge.className}`}
|
|
>
|
|
{badge.label}
|
|
</span>
|
|
</div>
|
|
{t.contexto && <span className="text-xs text-gray-500">{t.contexto}</span>}
|
|
</div>
|
|
<Estrellas rating={t.rating} />
|
|
</div>
|
|
|
|
<p className="text-sm text-gray-700 leading-relaxed italic">{t.texto}</p>
|
|
|
|
{t.fotos.length > 0 && (
|
|
<div className="flex flex-wrap gap-2">
|
|
{t.fotos.map((url, i) => (
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
<img
|
|
key={i}
|
|
src={url}
|
|
alt=""
|
|
className="w-20 h-20 object-cover rounded-lg border border-gray-200"
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex flex-wrap items-center gap-2 pt-2 border-t border-gray-100">
|
|
<span className="text-xs text-gray-400 mr-auto">{formatFecha(t.createdAt)}</span>
|
|
{t.estado !== 'publicado' && (
|
|
<form action={publicarTestimonio.bind(null, t.id)}>
|
|
<button
|
|
type="submit"
|
|
className="px-3 py-1.5 rounded-lg bg-green-600 text-white text-xs font-semibold hover:bg-green-700"
|
|
>
|
|
Publicar
|
|
</button>
|
|
</form>
|
|
)}
|
|
{t.estado === 'publicado' && (
|
|
<form action={ocultarTestimonio.bind(null, t.id)}>
|
|
<button
|
|
type="submit"
|
|
className="px-3 py-1.5 rounded-lg border border-gray-300 text-gray-700 text-xs font-semibold hover:border-gray-500"
|
|
>
|
|
Ocultar
|
|
</button>
|
|
</form>
|
|
)}
|
|
<form action={eliminarTestimonio.bind(null, t.id)}>
|
|
<button
|
|
type="submit"
|
|
className="px-3 py-1.5 rounded-lg text-red-500 text-xs font-semibold hover:underline"
|
|
>
|
|
Eliminar
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|