157 lines
3.8 KiB
TypeScript
157 lines
3.8 KiB
TypeScript
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.
|