feat: RRSS hub estilo Miia + Ad Tracker por cliente

Replica agua-miia/rrss (hub, archivo, octubre 2026 con 27 piezas) y añade Ad Tracker por tenant al estilo Brava (periodos, Meta+Google, CPL/clics, campañas).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-23 02:55:14 +02:00
parent a1a3c26c30
commit b4ee23874e
10 changed files with 2455 additions and 38 deletions

View File

@@ -0,0 +1,66 @@
import React from 'react';
import { createClient } from '@/lib/supabase/server';
import { redirect } from 'next/navigation';
import { resolveActiveTenant, restGet } from '@/lib/tenant-context';
import { isAgencyRole, userRole } from '@/lib/agency';
import { AdDailyRow } from '@/lib/metrics';
import AdTrackerClient from '@/components/AdTrackerClient';
export const dynamic = 'force-dynamic';
const TAGLINES: Record<string, string> = {
'agua miia': 'Agua limpia, en casa, sin complicaciones',
'brava': 'Realza tu belleza natural',
};
function taglineFor(label: string): string | undefined {
const low = label.toLowerCase();
for (const [k, v] of Object.entries(TAGLINES)) {
if (low.includes(k)) return v;
}
return undefined;
}
export default async function AdTrackerPage() {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) redirect('/login');
const ctx = await resolveActiveTenant(user);
const agency = isAgencyRole(userRole(user));
if (ctx.portfolioWide) {
return (
<p className="text-sm text-gray-500 border border-gray-800 rounded-xl p-6 bg-[#111827]">
Selecciona un cliente en Contexto para abrir su Ad Tracker (privado por
tenant).
</p>
);
}
let daily: AdDailyRow[] = [];
if (agency && ctx.viaView && ctx.tenantId) {
const tid = encodeURIComponent(ctx.tenantId);
const d = await restGet<AdDailyRow[]>(
`/rest/v1/ad_daily?tenant_id=eq.${tid}&select=*&order=date.desc&limit=2000`
);
daily = d.data || [];
} else {
const { data } = await supabase
.from('ad_daily')
.select('*')
.order('date', { ascending: false })
.limit(2000);
daily = (data as AdDailyRow[]) || [];
}
return (
<AdTrackerClient
label={ctx.label}
tagline={taglineFor(ctx.label)}
rows={daily}
/>
);
}