feat: add WordPress, PrestaShop and Shopify connection slots
Per-client CMS/ecommerce channels in the agency hub with URL/API placeholders; live sync can come later. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
31
sql/cms_integrations.sql
Normal file
31
sql/cms_integrations.sql
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
-- CMS / ecommerce connection slots per tenant
|
||||||
|
-- Idempotent.
|
||||||
|
|
||||||
|
alter table public.integrations drop constraint if exists integrations_provider_check;
|
||||||
|
alter table public.integrations
|
||||||
|
add constraint integrations_provider_check
|
||||||
|
check (provider in (
|
||||||
|
'meta_ads',
|
||||||
|
'google_ads',
|
||||||
|
'ga4',
|
||||||
|
'search_console',
|
||||||
|
'tag_manager',
|
||||||
|
'clientify',
|
||||||
|
'klaviyo',
|
||||||
|
'mailchimp',
|
||||||
|
'google_drive',
|
||||||
|
'wordpress',
|
||||||
|
'prestashop',
|
||||||
|
'shopify'
|
||||||
|
));
|
||||||
|
|
||||||
|
insert into public.integrations (tenant_id, provider, status, label)
|
||||||
|
select t.id, p.provider, 'disconnected', p.label
|
||||||
|
from public.tenants t
|
||||||
|
cross join (
|
||||||
|
values
|
||||||
|
('wordpress', 'WordPress'),
|
||||||
|
('prestashop', 'PrestaShop'),
|
||||||
|
('shopify', 'Shopify')
|
||||||
|
) as p(provider, label)
|
||||||
|
on conflict (tenant_id, provider) do nothing;
|
||||||
@@ -55,6 +55,9 @@ export async function POST(req: NextRequest) {
|
|||||||
['klaviyo', 'Klaviyo'],
|
['klaviyo', 'Klaviyo'],
|
||||||
['mailchimp', 'Mailchimp'],
|
['mailchimp', 'Mailchimp'],
|
||||||
['google_drive', 'Google Drive'],
|
['google_drive', 'Google Drive'],
|
||||||
|
['wordpress', 'WordPress'],
|
||||||
|
['prestashop', 'PrestaShop'],
|
||||||
|
['shopify', 'Shopify'],
|
||||||
];
|
];
|
||||||
await fetch(`${url}/rest/v1/integrations`, {
|
await fetch(`${url}/rest/v1/integrations`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -55,17 +55,17 @@ type AlertRow = {
|
|||||||
const MATRIX_PROVIDERS = [
|
const MATRIX_PROVIDERS = [
|
||||||
'meta_ads',
|
'meta_ads',
|
||||||
'google_ads',
|
'google_ads',
|
||||||
'ga4',
|
|
||||||
'clientify',
|
'clientify',
|
||||||
'google_drive',
|
'google_drive',
|
||||||
|
'wordpress',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const SHORT: Record<string, string> = {
|
const SHORT: Record<string, string> = {
|
||||||
meta_ads: 'Meta',
|
meta_ads: 'Meta',
|
||||||
google_ads: 'GAds',
|
google_ads: 'GAds',
|
||||||
ga4: 'GA4',
|
|
||||||
clientify: 'CRM',
|
clientify: 'CRM',
|
||||||
google_drive: 'Drive',
|
google_drive: 'Drive',
|
||||||
|
wordpress: 'WP',
|
||||||
};
|
};
|
||||||
|
|
||||||
function healthBadge(h: string) {
|
function healthBadge(h: string) {
|
||||||
@@ -241,8 +241,8 @@ export default function AgencyPortfolioBoard() {
|
|||||||
Panel de control · clientes y conexiones
|
Panel de control · clientes y conexiones
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-[11px] text-gray-500 mt-0.5">
|
<p className="text-[11px] text-gray-500 mt-0.5">
|
||||||
Cada cliente con su Meta, Google Ads, GA4, Clientify y Drive.
|
Cada cliente con su Meta, Google Ads, Clientify, Drive y web
|
||||||
Activa/apaga canales en Integraciones.
|
(WordPress…). Activa/apaga canales en Conexiones.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ const PLACEHOLDERS: Record<string, string> = {
|
|||||||
klaviyo: 'Account / list ID',
|
klaviyo: 'Account / list ID',
|
||||||
mailchimp: 'Audience ID',
|
mailchimp: 'Audience ID',
|
||||||
google_drive: 'Folder ID (auto-match o pegar)',
|
google_drive: 'Folder ID (auto-match o pegar)',
|
||||||
|
wordpress: 'https://sitio.com + Application Password',
|
||||||
|
prestashop: 'https://tienda.com + API key',
|
||||||
|
shopify: 'mitienda.myshopify.com + Admin API token',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ClientIntegrationsPanel({
|
export default function ClientIntegrationsPanel({
|
||||||
@@ -106,6 +109,7 @@ export default function ClientIntegrationsPanel({
|
|||||||
{ id: 'analytics', title: 'Analítica y medición' },
|
{ id: 'analytics', title: 'Analítica y medición' },
|
||||||
{ id: 'crm', title: 'CRM' },
|
{ id: 'crm', title: 'CRM' },
|
||||||
{ id: 'email', title: 'Email / lifecycle' },
|
{ id: 'email', title: 'Email / lifecycle' },
|
||||||
|
{ id: 'cms', title: 'Web / e‑commerce' },
|
||||||
{ id: 'files', title: 'Archivos' },
|
{ id: 'files', title: 'Archivos' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -278,6 +282,15 @@ export default function ClientIntegrationsPanel({
|
|||||||
ID manual.
|
ID manual.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
{(p.id === 'wordpress' ||
|
||||||
|
p.id === 'prestashop' ||
|
||||||
|
p.id === 'shopify') && (
|
||||||
|
<p className="text-[10px] text-gray-500">
|
||||||
|
Guarda la URL del site (y key/token si aplica) en el
|
||||||
|
campo. Sync automático de pedidos/contenidos: siguiente
|
||||||
|
fase.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ export const INTEGRATION_PROVIDERS = [
|
|||||||
{ id: 'klaviyo', label: 'Klaviyo', group: 'email' },
|
{ id: 'klaviyo', label: 'Klaviyo', group: 'email' },
|
||||||
{ id: 'mailchimp', label: 'Mailchimp', group: 'email' },
|
{ id: 'mailchimp', label: 'Mailchimp', group: 'email' },
|
||||||
{ id: 'google_drive', label: 'Google Drive', group: 'files' },
|
{ id: 'google_drive', label: 'Google Drive', group: 'files' },
|
||||||
|
{ id: 'wordpress', label: 'WordPress', group: 'cms' },
|
||||||
|
{ id: 'prestashop', label: 'PrestaShop', group: 'cms' },
|
||||||
|
{ id: 'shopify', label: 'Shopify', group: 'cms' },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type IntegrationProviderId =
|
export type IntegrationProviderId =
|
||||||
|
|||||||
Reference in New Issue
Block a user