fix: tema claro blanco, logo 4Ventures y menú original
Fondo blanco en la app; menú con labels/iconos originales; logo en sidebar y login. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -33,7 +33,7 @@ export default async function AdTrackerPage() {
|
||||
|
||||
if (ctx.portfolioWide) {
|
||||
return (
|
||||
<p className="text-sm text-gray-500 border border-gray-800 rounded-xl p-6 bg-[#111827]">
|
||||
<p className="text-sm text-gray-500 border border-gray-200 rounded-xl p-6 bg-white">
|
||||
Selecciona un cliente en Contexto para abrir su Ad Tracker (privado por
|
||||
tenant).
|
||||
</p>
|
||||
|
||||
@@ -82,41 +82,41 @@ export default async function AgencyPage() {
|
||||
|
||||
{/* Global Agency KPI Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-5">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-5">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs text-gray-400 font-medium">Clientes / Tenants</span>
|
||||
<Building2 className="w-4 h-4 text-brand-400" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">{tenants.length}</p>
|
||||
<p className="text-2xl font-extrabold text-gray-900">{tenants.length}</p>
|
||||
<p className="text-[11px] text-emerald-400 mt-1">100% aislados vía RLS</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-5">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-5">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs text-gray-400 font-medium">Inversión Gestionada</span>
|
||||
<DollarSign className="w-4 h-4 text-blue-400" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">
|
||||
<p className="text-2xl font-extrabold text-gray-900">
|
||||
{totalSpend.toLocaleString('es-ES', { minimumFractionDigits: 2 })} €
|
||||
</p>
|
||||
<p className="text-[11px] text-gray-400 mt-1">Vía Windsor.ai pipeline</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-5">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-5">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs text-gray-400 font-medium">Leads Captados</span>
|
||||
<Users className="w-4 h-4 text-purple-400" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">{totalLeads}</p>
|
||||
<p className="text-2xl font-extrabold text-gray-900">{totalLeads}</p>
|
||||
<p className="text-[11px] text-gray-400 mt-1">{totalWonDeals} cerrados ganados</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-5">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-5">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<span className="text-xs text-gray-400 font-medium">ROAS Blended Agencia</span>
|
||||
<TrendingUp className="w-4 h-4 text-emerald-400" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">{blendedRoas}x</p>
|
||||
<p className="text-2xl font-extrabold text-gray-900">{blendedRoas}x</p>
|
||||
<p className="text-[11px] text-emerald-400 mt-1">
|
||||
{totalRevenue.toLocaleString('es-ES', { minimumFractionDigits: 2 })} € generados
|
||||
</p>
|
||||
|
||||
@@ -19,19 +19,19 @@ function FormattedMessage({ content }: { content: string }) {
|
||||
const matchStr = match[0];
|
||||
if (matchStr.startsWith('**') && matchStr.endsWith('**')) {
|
||||
parts.push(
|
||||
<strong key={match.index} className="font-bold text-white tracking-wide">
|
||||
<strong key={match.index} className="font-bold text-gray-900 tracking-wide">
|
||||
{matchStr.slice(2, -2)}
|
||||
</strong>
|
||||
);
|
||||
} else if (matchStr.startsWith('*') && matchStr.endsWith('*')) {
|
||||
parts.push(
|
||||
<em key={match.index} className="italic text-gray-300">
|
||||
<em key={match.index} className="italic text-gray-600">
|
||||
{matchStr.slice(1, -1)}
|
||||
</em>
|
||||
);
|
||||
} else if (matchStr.startsWith('`') && matchStr.endsWith('`')) {
|
||||
parts.push(
|
||||
<code key={match.index} className="bg-gray-900/80 text-brand-400 font-mono text-[11px] px-1.5 py-0.5 rounded border border-gray-700/60">
|
||||
<code key={match.index} className="bg-gray-50 text-brand-400 font-mono text-[11px] px-1.5 py-0.5 rounded border border-gray-200">
|
||||
{matchStr.slice(1, -1)}
|
||||
</code>
|
||||
);
|
||||
@@ -85,7 +85,7 @@ function FormattedMessage({ content }: { content: string }) {
|
||||
|
||||
if (isQuote) {
|
||||
return (
|
||||
<blockquote key={lineIdx} className="border-l-2 border-brand-500/80 pl-3 italic text-gray-300 my-1 bg-gray-850/40 py-1 rounded-r">
|
||||
<blockquote key={lineIdx} className="border-l-2 border-brand-500/80 pl-3 italic text-gray-600 my-1 bg-gray-850/40 py-1 rounded-r">
|
||||
{renderInline(displayText)}
|
||||
</blockquote>
|
||||
);
|
||||
@@ -164,15 +164,15 @@ export default function AsistentePage() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-[calc(100vh-10rem)] bg-[#111827] border border-gray-800 rounded-xl overflow-hidden shadow-sm">
|
||||
<div className="flex flex-col h-[calc(100vh-10rem)] bg-white border border-gray-200 rounded-xl overflow-hidden shadow-sm">
|
||||
{/* Header */}
|
||||
<div className="p-4 border-b border-gray-800 flex items-center justify-between bg-[#0D121F]">
|
||||
<div className="p-4 border-b border-gray-200 flex items-center justify-between bg-white">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-8 h-8 rounded-lg bg-brand-500/20 text-brand-500 flex items-center justify-center">
|
||||
<Bot className="w-5 h-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-bold text-sm text-white">Asistente IA Financiero & KPIs</h3>
|
||||
<h3 className="font-bold text-sm text-gray-900">Asistente IA Financiero & KPIs</h3>
|
||||
<p className="text-[11px] text-gray-400">Temperatura 0.0 · Verificación Numérica Estricta · Supabase RPC</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -189,7 +189,7 @@ export default function AsistentePage() {
|
||||
className={`max-w-2xl px-5 py-3.5 rounded-2xl ${
|
||||
m.role === 'user'
|
||||
? 'bg-gradient-to-r from-brand-500 to-amber-600 text-white font-medium shadow-md shadow-brand-500/10'
|
||||
: 'bg-[#1a2333] text-gray-200 border border-gray-800/80 shadow-lg shadow-black/20'
|
||||
: 'bg-[#1a2333] text-gray-800 border border-gray-200 shadow-lg shadow-black/20'
|
||||
}`}
|
||||
>
|
||||
<FormattedMessage content={m.content} />
|
||||
@@ -199,7 +199,7 @@ export default function AsistentePage() {
|
||||
|
||||
{loading && (
|
||||
<div className="flex justify-start">
|
||||
<div className="bg-[#1a2333] text-gray-300 px-5 py-3 rounded-2xl text-sm border border-gray-800/80 flex items-center gap-2">
|
||||
<div className="bg-[#1a2333] text-gray-600 px-5 py-3 rounded-2xl text-sm border border-gray-200 flex items-center gap-2">
|
||||
<Sparkles className="w-4 h-4 animate-spin text-brand-500" />
|
||||
Calculando métricas sin alucinaciones...
|
||||
</div>
|
||||
@@ -209,7 +209,7 @@ export default function AsistentePage() {
|
||||
</div>
|
||||
|
||||
{/* Quick Prompts Chips */}
|
||||
<div className="px-6 py-2.5 bg-[#0D121F]/80 border-t border-gray-800/80 flex gap-2 overflow-x-auto text-xs text-gray-300">
|
||||
<div className="px-6 py-2.5 bg-white/80 border-t border-gray-200 flex gap-2 overflow-x-auto text-xs text-gray-600">
|
||||
<button
|
||||
onClick={() => sendMessage('¿Qué puedo preguntar?')}
|
||||
className="px-3 py-1.5 rounded-full bg-brand-500/20 text-brand-400 hover:bg-brand-500/30 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-brand-500/40"
|
||||
@@ -219,35 +219,35 @@ export default function AsistentePage() {
|
||||
</button>
|
||||
<button
|
||||
onClick={() => sendMessage('¿Qué pasa si invierto 1.000 € en Meta?')}
|
||||
className="px-3 py-1.5 rounded-full bg-gray-800 hover:bg-gray-700 hover:text-white whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-700/50"
|
||||
className="px-3 py-1.5 rounded-full bg-gray-100 hover:bg-gray-700 hover:text-gray-900 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-200/50"
|
||||
>
|
||||
<DollarSign className="w-3.5 h-3.5 text-brand-400" />
|
||||
🔮 Simular 1.000 € en Meta
|
||||
</button>
|
||||
<button
|
||||
onClick={() => sendMessage('¿Cómo va el cumplimiento de objetivos de este mes?')}
|
||||
className="px-3 py-1.5 rounded-full bg-gray-800 hover:bg-gray-700 hover:text-white whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-700/50"
|
||||
className="px-3 py-1.5 rounded-full bg-gray-100 hover:bg-gray-700 hover:text-gray-900 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-200/50"
|
||||
>
|
||||
<Target className="w-3.5 h-3.5 text-emerald-400" />
|
||||
🎯 Objetivos de este mes
|
||||
</button>
|
||||
<button
|
||||
onClick={() => sendMessage('Muéstrame el embudo comercial')}
|
||||
className="px-3 py-1.5 rounded-full bg-gray-800 hover:bg-gray-700 hover:text-white whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-700/50"
|
||||
className="px-3 py-1.5 rounded-full bg-gray-100 hover:bg-gray-700 hover:text-gray-900 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-200/50"
|
||||
>
|
||||
<Filter className="w-3.5 h-3.5 text-blue-400" />
|
||||
🔄 Embudo comercial
|
||||
</button>
|
||||
<button
|
||||
onClick={() => sendMessage('¿Cuál es el CAC y ROAS por canal de los últimos 30 días?')}
|
||||
className="px-3 py-1.5 rounded-full bg-gray-800 hover:bg-gray-700 hover:text-white whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-700/50"
|
||||
className="px-3 py-1.5 rounded-full bg-gray-100 hover:bg-gray-700 hover:text-gray-900 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-200/50"
|
||||
>
|
||||
<TrendingUp className="w-3.5 h-3.5 text-purple-400" />
|
||||
📊 CAC & ROAS por canal
|
||||
</button>
|
||||
<button
|
||||
onClick={() => sendMessage('Explícame la metodología 4Ventures y cómo calculáis el CAC de cohorte')}
|
||||
className="px-3 py-1.5 rounded-full bg-gray-800 hover:bg-gray-700 hover:text-white whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-700/50"
|
||||
className="px-3 py-1.5 rounded-full bg-gray-100 hover:bg-gray-700 hover:text-gray-900 whitespace-nowrap transition-colors flex items-center gap-1.5 cursor-pointer border border-gray-200/50"
|
||||
>
|
||||
<BookOpen className="w-3.5 h-3.5 text-amber-400" />
|
||||
📖 Metodología y atribución
|
||||
@@ -255,7 +255,7 @@ export default function AsistentePage() {
|
||||
</div>
|
||||
|
||||
{/* Input Box */}
|
||||
<div className="p-4 border-t border-gray-800 bg-[#0D121F]">
|
||||
<div className="p-4 border-t border-gray-200 bg-white">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
@@ -268,7 +268,7 @@ export default function AsistentePage() {
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
placeholder="Pregunta sobre inversión, metas, CAC, o escribe «¿Qué puedo preguntar?»..."
|
||||
className="flex-1 bg-[#111827] border border-gray-700 rounded-xl px-4 py-2.5 text-sm text-white placeholder-gray-500 focus:outline-none focus:border-brand-500 transition-all"
|
||||
className="flex-1 bg-white border border-gray-200 rounded-xl px-4 py-2.5 text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:border-brand-500 transition-all"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
|
||||
@@ -74,7 +74,7 @@ function platformMeta(p: string) {
|
||||
function DualBadge({ dual }: { dual?: Dual }) {
|
||||
if (!dual) {
|
||||
return (
|
||||
<span className="text-[10px] uppercase tracking-wider px-2 py-0.5 rounded-full border border-gray-700 text-gray-500">
|
||||
<span className="text-[10px] uppercase tracking-wider px-2 py-0.5 rounded-full border border-gray-200 text-gray-500">
|
||||
Sin checks
|
||||
</span>
|
||||
);
|
||||
@@ -245,7 +245,7 @@ export default function CalendarClient({
|
||||
{calendarTitle} · privado (sin publicación pública) · doble check
|
||||
agencia/cliente
|
||||
</p>
|
||||
<div className="flex gap-1 rounded-lg border border-gray-800 p-0.5 bg-black/20">
|
||||
<div className="flex gap-1 rounded-lg border border-gray-200 p-0.5 bg-gray-50">
|
||||
{(
|
||||
[
|
||||
['month', 'Mes'],
|
||||
@@ -267,12 +267,12 @@ export default function CalendarClient({
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3.5">
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-4">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between text-gray-400 text-xs mb-1">
|
||||
<span>Total piezas</span>
|
||||
<CalendarDays className="w-4 h-4 text-brand-400" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">{totalPosts}</p>
|
||||
<p className="text-2xl font-extrabold text-gray-900">{totalPosts}</p>
|
||||
</div>
|
||||
{platforms
|
||||
.filter((p) => p !== 'all')
|
||||
@@ -281,16 +281,16 @@ export default function CalendarClient({
|
||||
const meta = platformMeta(p);
|
||||
const n = initialPosts.filter((x) => x.platform === p).length;
|
||||
return (
|
||||
<div key={p} className="bg-[#111827] border border-gray-800 rounded-xl p-4">
|
||||
<div key={p} className="bg-white border border-gray-200 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between text-gray-400 text-xs mb-1">
|
||||
<span>{meta.label}</span>
|
||||
<meta.Icon className="w-4 h-4" />
|
||||
</div>
|
||||
<p className="text-2xl font-extrabold text-white">{n}</p>
|
||||
<p className="text-2xl font-extrabold text-gray-900">{n}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-4">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-4">
|
||||
<div className="flex items-center justify-between text-gray-400 text-xs mb-1">
|
||||
<span>Doble OK</span>
|
||||
<CheckCircle2 className="w-4 h-4 text-emerald-400" />
|
||||
@@ -303,7 +303,7 @@ export default function CalendarClient({
|
||||
</div>
|
||||
|
||||
{/* Unified + per-network tabs */}
|
||||
<div className="bg-[#111827] border border-gray-800 rounded-xl p-4 flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
<div className="bg-white border border-gray-200 rounded-xl p-4 flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-1.5 overflow-x-auto pb-1 md:pb-0">
|
||||
{platforms.map((p) => {
|
||||
const count =
|
||||
@@ -324,7 +324,7 @@ export default function CalendarClient({
|
||||
: p === 'instagram'
|
||||
? 'bg-gradient-to-r from-pink-500 to-purple-600 text-white'
|
||||
: `${meta?.color || 'bg-gray-700'} text-white`
|
||||
: 'bg-gray-800/60 text-gray-300 hover:text-white'
|
||||
: 'bg-gray-100 text-gray-600 hover:text-white'
|
||||
}`}
|
||||
>
|
||||
{meta && <meta.Icon className="w-3.5 h-3.5" />}
|
||||
@@ -338,7 +338,7 @@ export default function CalendarClient({
|
||||
<select
|
||||
value={statusFilter}
|
||||
onChange={(e) => setStatusFilter(e.target.value as typeof statusFilter)}
|
||||
className="bg-gray-900 border border-gray-700 text-xs text-white rounded-lg px-2.5 py-1.5 focus:outline-none focus:border-brand-500"
|
||||
className="bg-gray-900 border border-gray-200 text-xs text-gray-900 rounded-lg px-2.5 py-1.5 focus:outline-none focus:border-brand-500"
|
||||
>
|
||||
<option value="all">Todos</option>
|
||||
<option value="approved">Aprobados</option>
|
||||
@@ -356,7 +356,7 @@ export default function CalendarClient({
|
||||
byDay.map(([day, posts]) => (
|
||||
<div
|
||||
key={day}
|
||||
className="rounded-xl border border-gray-800 bg-[#111827] p-4"
|
||||
className="rounded-xl border border-gray-200 bg-white p-4"
|
||||
>
|
||||
<p className="text-xs font-semibold text-brand-400 font-mono mb-3">
|
||||
{new Date(day).toLocaleDateString('es-ES', {
|
||||
@@ -400,10 +400,10 @@ export default function CalendarClient({
|
||||
|
||||
{selectedPost && (
|
||||
<div className="fixed inset-0 z-50 bg-black/75 backdrop-blur-sm flex items-center justify-center p-4">
|
||||
<div className="bg-[#0D121F] border border-gray-800 rounded-2xl w-full max-w-2xl max-h-[90vh] overflow-hidden shadow-2xl flex flex-col">
|
||||
<div className="p-5 border-b border-gray-800 flex items-center justify-between bg-[#111827]">
|
||||
<div className="bg-white border border-gray-200 rounded-2xl w-full max-w-2xl max-h-[90vh] overflow-hidden shadow-2xl flex flex-col">
|
||||
<div className="p-5 border-b border-gray-200 flex items-center justify-between bg-white">
|
||||
<div>
|
||||
<h3 className="text-base font-bold text-white">{selectedPost.title}</h3>
|
||||
<h3 className="text-base font-bold text-gray-900">{selectedPost.title}</h3>
|
||||
<p className="text-xs text-gray-400 font-mono mt-0.5">
|
||||
{selectedPost.platform} · {selectedPost.date} · {selectedPost.time}h
|
||||
</p>
|
||||
@@ -411,13 +411,13 @@ export default function CalendarClient({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelectedPost(null)}
|
||||
className="text-gray-400 hover:text-white p-1 rounded-lg hover:bg-gray-800"
|
||||
className="text-gray-400 hover:text-gray-900 p-1 rounded-lg hover:bg-gray-50"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="p-6 overflow-y-auto space-y-4 text-sm text-gray-200">
|
||||
<div className="p-6 overflow-y-auto space-y-4 text-sm text-gray-800">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<DualBadge dual={dualMap[selectedPost.id]} />
|
||||
<span className="text-[10px] text-gray-500">
|
||||
@@ -437,8 +437,8 @@ export default function CalendarClient({
|
||||
</Block>
|
||||
|
||||
{canCollaborate && (
|
||||
<div className="rounded-xl border border-gray-800 bg-black/20 p-4 space-y-3">
|
||||
<div className="flex items-center gap-2 text-xs font-semibold text-white">
|
||||
<div className="rounded-xl border border-gray-200 bg-gray-50 p-4 space-y-3">
|
||||
<div className="flex items-center gap-2 text-xs font-semibold text-gray-900">
|
||||
<MessageSquare className="w-3.5 h-3.5 text-sky-400" />
|
||||
Comentarios
|
||||
</div>
|
||||
@@ -449,7 +449,7 @@ export default function CalendarClient({
|
||||
{comments.map((c) => (
|
||||
<li
|
||||
key={c.id}
|
||||
className="text-xs border border-gray-800 rounded-lg px-2.5 py-2"
|
||||
className="text-xs border border-gray-200 rounded-lg px-2.5 py-2"
|
||||
>
|
||||
<div className="flex justify-between gap-2 text-[10px] text-gray-500 mb-1">
|
||||
<span>
|
||||
@@ -465,7 +465,7 @@ export default function CalendarClient({
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-gray-200 whitespace-pre-wrap">{c.body}</p>
|
||||
<p className="text-gray-800 whitespace-pre-wrap">{c.body}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -474,7 +474,7 @@ export default function CalendarClient({
|
||||
value={commentText}
|
||||
onChange={(e) => setCommentText(e.target.value)}
|
||||
placeholder="Escribe un comentario…"
|
||||
className="flex-1 rounded-lg bg-gray-900 border border-gray-700 px-3 py-2 text-xs text-white placeholder:text-gray-600 focus:outline-none focus:border-brand-500/50"
|
||||
className="flex-1 rounded-lg bg-gray-900 border border-gray-200 px-3 py-2 text-xs text-gray-900 placeholder:text-gray-600 focus:outline-none focus:border-brand-500/50"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -492,11 +492,11 @@ export default function CalendarClient({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="p-4 border-t border-gray-800 bg-[#111827] flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="p-4 border-t border-gray-200 bg-white flex flex-wrap items-center justify-between gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyFullCopy(selectedPost)}
|
||||
className="px-3 py-2 rounded-xl bg-gray-800 hover:bg-gray-700 text-gray-200 text-xs font-semibold inline-flex items-center gap-1.5"
|
||||
className="px-3 py-2 rounded-xl bg-gray-100 hover:bg-gray-700 text-gray-800 text-xs font-semibold inline-flex items-center gap-1.5"
|
||||
>
|
||||
{copied ? <Check className="w-3.5 h-3.5 text-emerald-300" /> : <Copy className="w-3.5 h-3.5" />}
|
||||
Copiar copy
|
||||
@@ -508,7 +508,7 @@ export default function CalendarClient({
|
||||
onClick={() => approve(myApproved ? 'revoke' : 'approve')}
|
||||
className={`px-4 py-2 rounded-xl text-xs font-semibold inline-flex items-center gap-1.5 ${
|
||||
myApproved
|
||||
? 'bg-gray-800 text-gray-300 border border-gray-700'
|
||||
? 'bg-gray-100 text-gray-600 border border-gray-200'
|
||||
: 'bg-emerald-500/20 text-emerald-300 border border-emerald-500/40'
|
||||
}`}
|
||||
>
|
||||
@@ -526,9 +526,9 @@ export default function CalendarClient({
|
||||
|
||||
function EmptyState() {
|
||||
return (
|
||||
<div className="col-span-full bg-[#111827] border border-gray-800 rounded-xl p-12 text-center text-gray-400">
|
||||
<div className="col-span-full bg-white border border-gray-200 rounded-xl p-12 text-center text-gray-400">
|
||||
<CalendarDays className="w-10 h-10 text-gray-600 mx-auto mb-3" />
|
||||
<p className="text-base font-semibold text-white">Sin piezas con este filtro.</p>
|
||||
<p className="text-base font-semibold text-gray-900">Sin piezas con este filtro.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -548,7 +548,7 @@ function Block({
|
||||
{label}
|
||||
</label>
|
||||
<div
|
||||
className={`p-3.5 rounded-xl bg-gray-900 border border-gray-800 whitespace-pre-wrap ${className}`}
|
||||
className={`p-3.5 rounded-xl bg-gray-900 border border-gray-200 whitespace-pre-wrap ${className}`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
@@ -569,7 +569,7 @@ function PostCard({
|
||||
}) {
|
||||
const meta = platformMeta(post.platform);
|
||||
return (
|
||||
<div className="bg-[#0D121F] border border-gray-800 hover:border-gray-700 rounded-xl p-4 flex flex-col justify-between">
|
||||
<div className="bg-white border border-gray-200 hover:border-gray-200 rounded-xl p-4 flex flex-col justify-between">
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-2 gap-2">
|
||||
<span
|
||||
@@ -586,10 +586,10 @@ function PostCard({
|
||||
<p className="text-[11px] text-brand-400 font-mono mb-1">
|
||||
{post.time ? `${post.time}h` : '—'} · {post.format}
|
||||
</p>
|
||||
<h4 className="font-bold text-white text-sm mb-1.5 line-clamp-2">{post.title}</h4>
|
||||
<h4 className="font-bold text-gray-900 text-sm mb-1.5 line-clamp-2">{post.title}</h4>
|
||||
<p className="text-xs text-gray-400 line-clamp-2 italic">«{post.hook}»</p>
|
||||
</div>
|
||||
<div className="pt-3 mt-3 border-t border-gray-800/80 flex items-center justify-between">
|
||||
<div className="pt-3 mt-3 border-t border-gray-200 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpen}
|
||||
@@ -600,7 +600,7 @@ function PostCard({
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCopy}
|
||||
className="p-1.5 rounded-md hover:bg-gray-800 text-gray-400"
|
||||
className="p-1.5 rounded-md hover:bg-gray-50 text-gray-400"
|
||||
title="Copiar"
|
||||
>
|
||||
<Copy className="w-3.5 h-3.5" />
|
||||
|
||||
@@ -45,7 +45,7 @@ export default async function CalendarioPage({
|
||||
|
||||
if (ctx.portfolioWide) {
|
||||
return (
|
||||
<p className="text-sm text-gray-500 border border-gray-800 rounded-xl p-6 bg-[#111827]">
|
||||
<p className="text-sm text-gray-500 border border-gray-200 rounded-xl p-6 bg-white">
|
||||
Selecciona un cliente en Contexto para ver su hub RRSS (privado).
|
||||
</p>
|
||||
);
|
||||
@@ -107,7 +107,7 @@ export default async function CalendarioPage({
|
||||
<p className="text-[11px] font-bold tracking-[0.16em] uppercase text-sky-400 mb-2">
|
||||
RRSS · privado
|
||||
</p>
|
||||
<h2 className="text-3xl font-extrabold text-white tracking-tight">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900 tracking-tight">
|
||||
{ctx.label}
|
||||
</h2>
|
||||
<p className="text-sm text-gray-400 mt-2 max-w-xl">
|
||||
@@ -118,13 +118,13 @@ export default async function CalendarioPage({
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Link
|
||||
href="/dashboard/calendario?view=archive"
|
||||
className="inline-flex items-center justify-center min-h-[52px] px-6 rounded-xl bg-[#16204A] text-white text-sm font-bold hover:bg-[#1a2a63]"
|
||||
className="inline-flex items-center justify-center min-h-[52px] px-6 rounded-xl bg-[#16204A] text-gray-900 text-sm font-bold hover:bg-[#1a2a63]"
|
||||
>
|
||||
<Instagram className="w-4 h-4 mr-2" /> IG / FB
|
||||
</Link>
|
||||
<Link
|
||||
href="/dashboard/calendario?view=month&month=2026-10&tab=linkedin"
|
||||
className="inline-flex items-center justify-center min-h-[52px] px-6 rounded-xl bg-[#2071CF] text-white text-sm font-bold hover:bg-[#1a5fb8]"
|
||||
className="inline-flex items-center justify-center min-h-[52px] px-6 rounded-xl bg-[#2071CF] text-gray-900 text-sm font-bold hover:bg-[#1a5fb8]"
|
||||
>
|
||||
<Linkedin className="w-4 h-4 mr-2" /> LinkedIn
|
||||
</Link>
|
||||
|
||||
@@ -52,12 +52,12 @@ function ProgressBar({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between text-sm">
|
||||
<span className="text-gray-300 font-medium">{label}</span>
|
||||
<span className="text-white font-semibold tabular-nums">
|
||||
<span className="text-gray-600 font-medium">{label}</span>
|
||||
<span className="text-gray-900 font-semibold tabular-nums">
|
||||
{p}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-2 bg-gray-800 rounded-full overflow-hidden">
|
||||
<div className="h-2 bg-gray-100 rounded-full overflow-hidden">
|
||||
<div className={`h-full ${bar}`} style={{ width: `${p}%` }} />
|
||||
</div>
|
||||
<p className="text-xs text-gray-500 tabular-nums">
|
||||
@@ -195,7 +195,7 @@ export default async function EstrategiaPage() {
|
||||
) : (
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
{/* Presupuesto */}
|
||||
<section className="bg-[#111827] border border-gray-800 rounded-xl p-6 space-y-5">
|
||||
<section className="bg-white border border-gray-200 rounded-xl p-6 space-y-5">
|
||||
<div className="flex items-center gap-2 text-amber-300">
|
||||
<Wallet className="w-4 h-4" />
|
||||
<h3 className="text-sm font-bold uppercase tracking-wider">
|
||||
@@ -214,22 +214,22 @@ export default async function EstrategiaPage() {
|
||||
tone="amber"
|
||||
/>
|
||||
) : (
|
||||
<div className="rounded-lg border border-dashed border-gray-700 px-3 py-4 text-xs text-gray-500">
|
||||
<div className="rounded-lg border border-dashed border-gray-200 px-3 py-4 text-xs text-gray-500">
|
||||
Sin <code className="text-gray-400">spend_target</code> para este
|
||||
mes en <code className="text-gray-400">targets</code>. Gasto
|
||||
actual: {spendActual.toLocaleString('es-ES')} €.
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-2 gap-3 pt-1">
|
||||
<div className="rounded-lg bg-black/25 border border-gray-800 px-3 py-2">
|
||||
<div className="rounded-lg bg-gray-50 border border-gray-200 px-3 py-2">
|
||||
<p className="text-[10px] uppercase text-gray-500">Ppto</p>
|
||||
<p className="text-lg font-bold text-white tabular-nums">
|
||||
<p className="text-lg font-bold text-gray-900 tabular-nums">
|
||||
{spendTarget.toLocaleString('es-ES')} €
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-lg bg-black/25 border border-gray-800 px-3 py-2">
|
||||
<div className="rounded-lg bg-gray-50 border border-gray-200 px-3 py-2">
|
||||
<p className="text-[10px] uppercase text-gray-500">Gastado</p>
|
||||
<p className="text-lg font-bold text-white tabular-nums">
|
||||
<p className="text-lg font-bold text-gray-900 tabular-nums">
|
||||
{spendActual.toLocaleString('es-ES')} €
|
||||
</p>
|
||||
</div>
|
||||
@@ -237,7 +237,7 @@ export default async function EstrategiaPage() {
|
||||
</section>
|
||||
|
||||
{/* Consecución */}
|
||||
<section className="bg-[#111827] border border-gray-800 rounded-xl p-6 space-y-5">
|
||||
<section className="bg-white border border-gray-200 rounded-xl p-6 space-y-5">
|
||||
<div className="flex items-center gap-2 text-emerald-300">
|
||||
<Trophy className="w-4 h-4" />
|
||||
<h3 className="text-sm font-bold uppercase tracking-wider">
|
||||
|
||||
@@ -82,11 +82,11 @@ export default async function CanalDashPage({
|
||||
<div>
|
||||
<Link
|
||||
href="/dashboard/kpis"
|
||||
className="inline-flex items-center gap-1.5 text-xs text-gray-400 hover:text-white mb-3"
|
||||
className="inline-flex items-center gap-1.5 text-xs text-gray-400 hover:text-gray-900 mb-3"
|
||||
>
|
||||
<ArrowLeft className="w-3.5 h-3.5" /> Volver a métricas
|
||||
</Link>
|
||||
<h2 className="text-2xl font-bold text-white capitalize">
|
||||
<h2 className="text-2xl font-bold text-gray-900 capitalize">
|
||||
Canal · {channel}
|
||||
</h2>
|
||||
<p className="text-sm text-gray-400 mt-1">
|
||||
@@ -103,18 +103,18 @@ export default async function CanalDashPage({
|
||||
].map((s) => (
|
||||
<div
|
||||
key={s.label}
|
||||
className="rounded-xl border border-gray-800 bg-[#111827] px-4 py-3"
|
||||
className="rounded-xl border border-gray-200 bg-white px-4 py-3"
|
||||
>
|
||||
<p className="text-[10px] uppercase tracking-wider text-gray-500">
|
||||
{s.label}
|
||||
</p>
|
||||
<p className="text-xl font-bold text-white mt-1">{s.value}</p>
|
||||
<p className="text-xl font-bold text-gray-900 mt-1">{s.value}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="rounded-xl border border-gray-800 bg-[#111827] p-5">
|
||||
<h3 className="text-sm font-semibold text-white mb-3">
|
||||
<div className="rounded-xl border border-gray-200 bg-white p-5">
|
||||
<h3 className="text-sm font-semibold text-gray-900 mb-3">
|
||||
Semanas ({points.length})
|
||||
</h3>
|
||||
{points.length === 0 ? (
|
||||
@@ -124,10 +124,10 @@ export default async function CanalDashPage({
|
||||
{points.map((p) => (
|
||||
<li
|
||||
key={p.week}
|
||||
className="flex flex-wrap items-center justify-between gap-2 text-xs border border-gray-800 rounded-lg px-3 py-2"
|
||||
className="flex flex-wrap items-center justify-between gap-2 text-xs border border-gray-200 rounded-lg px-3 py-2"
|
||||
>
|
||||
<span className="font-mono text-brand-400">{p.week}</span>
|
||||
<span className="text-gray-300">
|
||||
<span className="text-gray-600">
|
||||
{formatEur(p.spend)} · {formatNum(p.leads)} leads · CPL{' '}
|
||||
{p.cpl ? `${formatNum(p.cpl)} €` : '—'}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user