feat: interfaz clara unificada en Centro de Mando

Shell con nav agrupada y activa, PageHeader común, tipografía y tokens.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-24 09:32:35 +02:00
parent 8c11291396
commit bf9a504c40
17 changed files with 577 additions and 372 deletions

View File

@@ -25,6 +25,7 @@ import {
formatNum,
resolveKpiDayRange,
} from '@/lib/metrics';
import { PageHeader } from '@/components/ui';
type RangeKey = KpiRangeKey;
@@ -95,44 +96,39 @@ export default function CrmDashboard({
return (
<div className="space-y-8">
<div className="flex flex-col md:flex-row md:items-end md:justify-between gap-3">
<div>
<h2 className="text-2xl font-bold tracking-tight text-white">
CRM · Clientify
</h2>
<p className="text-sm text-gray-400 mt-1">
{label}
{portfolioWide ? ' · portafolio' : ' · zoom cliente'}. Funnel y % a
cliente (ganado) por canal · {rangeHint}.
</p>
</div>
<div className="flex items-center gap-2">
<CalendarRange className="w-4 h-4 text-gray-500" />
<div className="flex gap-1 rounded-lg border border-gray-800 p-0.5 bg-black/20">
{(
[
['7d', '7d'],
['30d', '30d'],
['month', 'Mes'],
['all', 'Todo'],
] as [RangeKey, string][]
).map(([k, lbl]) => (
<button
key={k}
type="button"
onClick={() => setRange(k)}
className={`px-2.5 py-1 text-xs rounded-md ${
range === k
? 'bg-brand-500/20 text-brand-300'
: 'text-gray-400 hover:text-white'
}`}
>
{lbl}
</button>
))}
<PageHeader
eyebrow="Rendimiento"
title="CRM"
description={`${label}${portfolioWide ? ' · portafolio' : ''}. Funnel y % a cliente por canal · ${rangeHint}.`}
actions={
<div className="flex items-center gap-2">
<CalendarRange className="w-4 h-4 text-gray-500" />
<div className="flex gap-1 rounded-lg border border-white/[0.08] p-0.5 bg-black/20">
{(
[
['7d', '7d'],
['30d', '30d'],
['month', 'Mes'],
['all', 'Todo'],
] as [RangeKey, string][]
).map(([k, lbl]) => (
<button
key={k}
type="button"
onClick={() => setRange(k)}
className={`px-2.5 py-1 text-xs rounded-md ${
range === k
? 'bg-brand-500/20 text-brand-300'
: 'text-gray-400 hover:text-white'
}`}
>
{lbl}
</button>
))}
</div>
</div>
</div>
</div>
}
/>
{!crmLeads.length ? (
<p className="text-sm text-amber-400/90 border border-amber-500/20 rounded-lg px-4 py-3">