feat: conectar Tablero CDC a Supabase empresarial

This commit is contained in:
2026-06-01 09:27:26 -04:00
parent a88f106eec
commit c546f59009
8 changed files with 69 additions and 69 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
VITE_SUPABASE_URL="https://ecngyelpabyqbdxhftdy.supabase.co"
VITE_SUPABASE_URL="https://dbit.digitalcompass.agency"
VITE_SUPABASE_ANON_KEY="TU_ANON_PUBLIC_KEY"
VITE_WEBHOOK_URL=""
VITE_WEBHOOK_URL="https://agenteit.digitalcompass.agency/webhook/tablero-cdc-sync-proyecto"
+11 -11
View File
@@ -24,7 +24,7 @@ Esta versión incluye:
- Paginación local en las vistas de Todos, Activos y Cerrados con 12 proyectos por página.
- Persistencia de proyectos en Supabase.
- Sincronización multiusuario con Supabase Realtime.
- Desplegables dinámicos desde Supabase `app_lists`, con fallback local mientras se termina la sincronización del Sheet.
- Desplegables dinámicos desde Supabase `tablero_cdc_app_lists`, con fallback local mientras se termina la sincronización del Sheet.
---
@@ -50,7 +50,7 @@ Esta versión incluye:
Las siguientes funcionalidades se implementarán en próximas fases:
1. Sincronización automática de la hoja `listas` del Google Sheet original hacia Supabase `app_lists`.
1. Sincronización automática de la hoja `listas` del Google Sheet original hacia Supabase `tablero_cdc_app_lists`.
2. Escritura automática de datos en el Sheet original mediante n8n u otra integración definida.
3. Agregar una nueva columna final para enlace de brief en el Sheet original.
4. Reglas de seguridad definitivas con Supabase RLS.
@@ -173,22 +173,22 @@ Desarrollo y soporte técnico: **Isaac Aracena**.
Esta versión ya no depende de `localStorage` para los proyectos. El tablero lee y guarda la información en Supabase usando las tablas:
- `projects`
- `project_links`
- `profiles`
- `app_lists`
- `tablero_cdc_projects`
- `tablero_cdc_project_links`
- `tablero_cdc_profiles`
- `tablero_cdc_app_lists`
Notas importantes:
- Los proyectos abiertos se guardan en base de datos con `status = 'Activo'`, pero en la interfaz se muestran como proyectos sin estatus para mantener el comportamiento visual original.
- Los usuarios normales no ven ni actualizan el monto interno desde la app.
- Solo Gerardo Marrero puede modificar estatus, monto interno y eliminar proyectos desde la interfaz.
- Los links de propuestas y artes finales se guardan en `project_links`.
- Los desplegables se leen desde `app_lists`. Si una categoría todavía no existe en Supabase, la app usa una lista local de respaldo para no bloquear el formulario.
- Los links de propuestas y artes finales se guardan en `tablero_cdc_project_links`.
- Los desplegables se leen desde `tablero_cdc_app_lists`. Si una categoría todavía no existe en Supabase, la app usa una lista local de respaldo para no bloquear el formulario.
## Supabase Realtime
Para que la sincronización multiusuario funcione, habilita Realtime para las tablas `projects`, `project_links` y `app_lists` ejecutando en Supabase SQL Editor el archivo:
Para que la sincronización multiusuario funcione, habilita Realtime para las tablas `tablero_cdc_projects`, `tablero_cdc_project_links` y `tablero_cdc_app_lists` ejecutando en Supabase SQL Editor el archivo:
```text
supabase_realtime_projects.sql
@@ -199,7 +199,7 @@ Luego abre la app en dos pestañas o dos navegadores: al crear, editar o elimina
## Desplegables dinámicos
La app intenta cargar estos desplegables desde `public.app_lists`:
La app intenta cargar estos desplegables desde `public.tablero_cdc_app_lists`:
- `client` / `cliente` / `clientes`
- `brand` / `marca` / `marcas`
@@ -207,4 +207,4 @@ La app intenta cargar estos desplegables desde `public.app_lists`:
- `status` / `estatus`
- `country_manager` / `cm` / `bu_cm` para mapear BU → Country Manager
Si una categoría aún no existe en Supabase, se usa el respaldo local del frontend. Más adelante n8n sincronizará la hoja `listas` del Sheet original hacia `app_lists`.
Si una categoría aún no existe en Supabase, se usa el respaldo local del frontend. Más adelante n8n sincronizará la hoja `listas` del Sheet original hacia `tablero_cdc_app_lists`.
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
<meta name="description" content="Herramienta interna del Departamento de Diseño Creativo." />
<meta name="author" content="CDC" />
<link rel="icon" type="image/svg+xml" href="/tablero-cdc/favicon.svg" />
<script type="module" crossorigin src="/tablero-cdc/assets/index-BYKs5Exj.js"></script>
<script type="module" crossorigin src="/tablero-cdc/assets/index-BEinrcZb.js"></script>
<link rel="stylesheet" crossorigin href="/tablero-cdc/assets/index-DjXLQf1G.css">
</head>
<body>
+1 -1
View File
@@ -108,7 +108,7 @@ export function ProjectDialog({ open, onOpenChange, project }: Props) {
return match?.[1] ?? "";
};
// BU → Country Manager automático desde Supabase app_lists, con fallback local.
// BU → Country Manager automático desde Supabase tablero_cdc_app_lists, con fallback local.
const onBU = (bu: string) => {
const cleanBu = canonicalOptionLabel(bu);
setForm((f) => ({ ...f, bu: cleanBu, cm: getCountryManager(cleanBu) }));
+3 -3
View File
@@ -137,7 +137,7 @@ export async function loadAppLists() {
try {
const { data, error } = await supabase
.from("app_lists")
.from("tablero_cdc_app_lists")
.select("category, value, label, sort_order, is_active")
.eq("is_active", true)
.order("category", { ascending: true })
@@ -180,12 +180,12 @@ function startAppListsRealtime() {
appListsRealtimeChannel = supabase
.channel("tablero-cdc-app-lists")
.on("postgres_changes", { event: "*", schema: "public", table: "app_lists" }, () =>
.on("postgres_changes", { event: "*", schema: "public", table: "tablero_cdc_app_lists" }, () =>
scheduleRealtimeRefresh(),
)
.subscribe((status) => {
if (status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
console.warn("Supabase Realtime no pudo suscribirse a app_lists:", status);
console.warn("Supabase Realtime no pudo suscribirse a tablero_cdc_app_lists:", status);
}
});
}
+8 -8
View File
@@ -294,12 +294,12 @@ function startProjectsRealtime() {
.channel("tablero-cdc-projects")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "projects" },
{ event: "*", schema: "public", table: "tablero_cdc_projects" },
() => scheduleRealtimeRefresh(),
)
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "project_links" },
{ event: "*", schema: "public", table: "tablero_cdc_project_links" },
() => scheduleRealtimeRefresh(),
)
.subscribe((status) => {
@@ -323,7 +323,7 @@ function stopProjectsRealtime() {
async function replaceProjectLinks(projectId: string, project: Pick<Project, "propuestaLinks" | "afLinks">) {
const { error: deleteError } = await supabase
.from("project_links")
.from("tablero_cdc_project_links")
.delete()
.eq("project_id", projectId);
@@ -333,7 +333,7 @@ async function replaceProjectLinks(projectId: string, project: Pick<Project, "pr
if (linkRows.length === 0) return;
const { error: insertError } = await supabase.from("project_links").insert(linkRows);
const { error: insertError } = await supabase.from("tablero_cdc_project_links").insert(linkRows);
if (insertError) throw insertError;
}
@@ -359,7 +359,7 @@ async function loadProjects() {
brief_link,
created_at,
extra_data,
project_links (
project_links:tablero_cdc_project_links (
id,
link_type,
url,
@@ -368,7 +368,7 @@ async function loadProjects() {
`;
const { data, error } = await supabase
.from("projects")
.from("tablero_cdc_projects")
.select(selectColumns)
.order("created_at", { ascending: false });
@@ -399,7 +399,7 @@ async function addProject(project: Project) {
};
const { data, error } = await supabase
.from("projects")
.from("tablero_cdc_projects")
.insert(insertPayload)
.select("id")
.single();
@@ -447,7 +447,7 @@ async function updateProject(id: string, patch: Partial<Project>) {
updated_by: userId,
};
const { error } = await supabase.from("projects").update(updatePayload).eq("id", id);
const { error } = await supabase.from("tablero_cdc_projects").update(updatePayload).eq("id", id);
if (error) {
setError(error.message);
+6 -6
View File
@@ -11,9 +11,9 @@ begin
from pg_publication_tables
where pubname = 'supabase_realtime'
and schemaname = 'public'
and tablename = 'projects'
and tablename = 'tablero_cdc_projects'
) then
alter publication supabase_realtime add table public.projects;
alter publication supabase_realtime add table public.tablero_cdc_projects;
end if;
if not exists (
@@ -21,9 +21,9 @@ begin
from pg_publication_tables
where pubname = 'supabase_realtime'
and schemaname = 'public'
and tablename = 'project_links'
and tablename = 'tablero_cdc_project_links'
) then
alter publication supabase_realtime add table public.project_links;
alter publication supabase_realtime add table public.tablero_cdc_project_links;
end if;
if not exists (
@@ -31,8 +31,8 @@ begin
from pg_publication_tables
where pubname = 'supabase_realtime'
and schemaname = 'public'
and tablename = 'app_lists'
and tablename = 'tablero_cdc_app_lists'
) then
alter publication supabase_realtime add table public.app_lists;
alter publication supabase_realtime add table public.tablero_cdc_app_lists;
end if;
end $$;