feat: agency portfolio with per-client integrations hub

Admin home lists tenants, alerts, and connection health; header
selector enables superadmin context; Meta/GA4/GSC/GTM/CRM/email
slots live per tenant (manual status until OAuth).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-22 01:31:47 +02:00
parent 9d1609c88b
commit 791976a3d8
19 changed files with 1503 additions and 20 deletions

View File

@@ -38,6 +38,45 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ error: error.message || 'Error al provisionar cliente en base de datos.' }, { status: 500 });
}
// Seed integration slots (best-effort; ignore if table missing)
try {
const tenantId =
data?.tenant_id || data?.id || data?.client?.tenant_id || null;
const serviceKey = process.env.SUPABASE_SERVICE_ROLE_KEY?.trim();
const url = process.env.NEXT_PUBLIC_SUPABASE_URL || 'https://supabase.4ventures.es';
if (tenantId && serviceKey) {
const providers = [
['meta_ads', 'Meta Ads'],
['google_ads', 'Google Ads (MCC)'],
['ga4', 'Google Analytics 4'],
['search_console', 'Search Console'],
['tag_manager', 'Tag Manager'],
['clientify', 'Clientify'],
['klaviyo', 'Klaviyo'],
['mailchimp', 'Mailchimp'],
];
await fetch(`${url}/rest/v1/integrations`, {
method: 'POST',
headers: {
apikey: serviceKey,
Authorization: `Bearer ${serviceKey}`,
'Content-Type': 'application/json',
Prefer: 'resolution=ignore-duplicates',
},
body: JSON.stringify(
providers.map(([provider, label]) => ({
tenant_id: tenantId,
provider,
status: 'disconnected',
label,
}))
),
});
}
} catch (e) {
console.warn('seed integrations skipped', e);
}
return NextResponse.json({ success: true, client: data });
} catch (err: any) {
console.error('Server error creating client:', err);