chore: subir version inicial del Tablero CDC

This commit is contained in:
2026-05-23 11:58:41 -04:00
commit 36fdf98419
77 changed files with 15092 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
import { useEffect, useState } from "react";
import type { ColorId, Status } from "@/data/lists";
export interface Project {
id: string;
nombre: string;
color: ColorId;
cliente: string;
bu: string;
cm: string; // autocompletado desde BU
marca: string;
solicitante: string;
comentarios: string;
briefLink: string;
propuestaLinks: string[];
afLinks: string[];
status: Status | "";
monto: number | null; // solo Marrero
mes: string;
anio: number;
createdAt: number;
}
const STORAGE_KEY = "cdc-board-v1";
function load(): Project[] {
if (typeof window === "undefined") return [];
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return seed();
return JSON.parse(raw);
} catch {
return seed();
}
}
function seed(): Project[] {
const now = Date.now();
const mesIdx = new Date().getMonth();
const mes = [
"Enero",
"Febrero",
"Marzo",
"Abril",
"Mayo",
"Junio",
"Julio",
"Agosto",
"Septiembre",
"Octubre",
"Noviembre",
"Diciembre",
][mesIdx];
const anio = new Date().getFullYear();
return [
{
id: crypto.randomUUID(),
nombre: "Promoción Día de las Madres",
color: "pink",
cliente: "Nestlé",
bu: "Republica Dominicana",
cm: "Liz",
marca: "Carnation",
solicitante: "Luiscar",
comentarios: "Solicitado por Luiscar",
briefLink: "https://drive.google.com/drive/folders/ejemplo-brief",
propuestaLinks: ["https://docs.google.com/presentation/d/ejemplo-1"],
afLinks: [],
status: "",
monto: null,
mes,
anio,
createdAt: now,
},
{
id: crypto.randomUUID(),
nombre: "KV Coffee Mate y Nescafé",
color: "blue",
cliente: "Nestlé",
bu: "Republica Dominicana",
cm: "Liz",
marca: "Coffee Mate",
solicitante: "Luiscar",
comentarios: "Dupla que eleva el momento",
briefLink: "",
propuestaLinks: [
"https://docs.google.com/presentation/d/ejemplo-kv-1",
"https://docs.google.com/presentation/d/ejemplo-kv-2",
],
afLinks: ["https://drive.google.com/drive/af-coffee"],
status: "Pre aprobado",
monto: 1250,
mes,
anio,
createdAt: now - 1000,
},
{
id: crypto.randomUUID(),
nombre: "Stand KitchenAid",
color: "green",
cliente: "KitchenAid",
bu: "Republica Dominicana",
cm: "Liz",
marca: "Whirlpool",
solicitante: "Luiscar",
comentarios: "",
briefLink: "https://drive.google.com/drive/brief-kitchen",
propuestaLinks: ["https://drive.google.com/file/stand-kitchen"],
afLinks: ["https://drive.google.com/af-stand"],
status: "Aprobado",
monto: 850,
mes,
anio,
createdAt: now - 2000,
},
];
}
function save(p: Project[]) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(p));
}
let listeners: Array<() => void> = [];
let cache: Project[] | null = null;
function getAll(): Project[] {
if (cache === null) cache = load();
return cache;
}
function setAll(next: Project[]) {
cache = next;
save(next);
listeners.forEach((l) => l());
}
export function useProjects() {
const [, force] = useState(0);
useEffect(() => {
const l = () => force((n) => n + 1);
listeners.push(l);
return () => {
listeners = listeners.filter((x) => x !== l);
};
}, []);
return {
projects: getAll(),
add: (p: Project) => setAll([p, ...getAll()]),
update: (id: string, patch: Partial<Project>) =>
setAll(getAll().map((x) => (x.id === id ? { ...x, ...patch } : x))),
remove: (id: string) => setAll(getAll().filter((x) => x.id !== id)),
};
}
// NOTE: useRole() was removed in favour of useAuth() from AuthContext.
// Role logic (isGerardo) is now derived from the real Firebase authenticated user.