import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Separator } from "@/components/ui/separator"; import { AlertCircle, Loader2, Lock, DollarSign, Calendar, Trash2 } from "lucide-react"; import { ColorPicker } from "./ColorPicker"; import { LinkList } from "./LinkList"; import { MESES, type Status } from "@/data/lists"; import { useAppLists } from "@/lib/appLists"; import { useProjects, type Project } from "@/lib/store"; import { useAuth } from "@/context/AuthContext"; import { colorHex } from "@/lib/colors"; import { cn } from "@/lib/utils"; import { canonicalOptionLabel, dedupeOptions, ensureOption, normalizeOptionKey, } from "@/lib/optionUtils"; import { toast } from "sonner"; interface Props { open: boolean; onOpenChange: (v: boolean) => void; project?: Project | null; // editar; vacío = crear onDelete?: (project: Project) => void; deleting?: boolean; } const WALMART_CONNECT_CLIENT = "Walmart Connect WMC"; function isWalmartConnectClient(client: string | null | undefined) { return normalizeOptionKey(client) === normalizeOptionKey(WALMART_CONNECT_CLIENT); } const empty = (): Omit => { const now = new Date(); return { nombre: "", color: "blue", cliente: "", bu: "", cm: "", marca: "", solicitante: "", comentarios: "", briefLink: "", propuestaLinks: [], afLinks: [], status: "", monto: null, mes: MESES[now.getMonth()], anio: now.getFullYear(), }; }; export function ProjectDialog({ open, onOpenChange, project, onDelete, deleting = false }: Props) { const { add, update } = useProjects(); const { lists, loading: listsLoading, error: listsError, refresh: refreshLists } = useAppLists(); const { isGerardo, canDeleteProjects } = useAuth(); const isEdit = !!project; const [form, setForm] = useState>(empty()); const [selectedWmcCountries, setSelectedWmcCountries] = useState([]); const [saving, setSaving] = useState(false); const [savingStep, setSavingStep] = useState(null); const [formError, setFormError] = useState(null); const clienteOptions = dedupeOptions(ensureOption(lists.clientes, form.cliente)); const marcaOptions = dedupeOptions(ensureOption(lists.marcas, form.marca)); const buOptions = dedupeOptions(ensureOption(lists.bus, form.bu)); const statusOptions = dedupeOptions(ensureOption(lists.status, form.status)) as Status[]; useEffect(() => { setFormError(null); setSavingStep(null); if (project) { const { id: _i, createdAt: _c, ...rest } = project; const cleanBu = canonicalOptionLabel(rest.bu); setForm({ ...rest, bu: cleanBu, }); setSelectedWmcCountries(cleanBu ? [cleanBu] : []); } else if (open) { setForm(empty()); setSelectedWmcCountries([]); } }, [project, open]); const set = (k: K, v: (typeof form)[K]) => setForm((f) => ({ ...f, [k]: v })); const getCountryManager = (bu: string) => { const direct = lists.buCm[bu]; if (direct) return direct; const buKey = normalizeOptionKey(bu); const match = Object.entries(lists.buCm).find(([key]) => normalizeOptionKey(key) === buKey); return match?.[1] ?? ""; }; // 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) })); }; const onCliente = (cliente: string) => { const cleanCliente = canonicalOptionLabel(cliente); setForm((f) => ({ ...f, cliente: cleanCliente, ...(isWalmartConnectClient(cleanCliente) && !isEdit ? { bu: "", cm: "" } : f.cliente && isWalmartConnectClient(f.cliente) ? { bu: "", cm: "" } : {}), })); if (!isWalmartConnectClient(cleanCliente)) { setSelectedWmcCountries([]); } }; const isWalmartConnectCreate = !isEdit && isWalmartConnectClient(form.cliente); const toggleWmcCountry = (country: string, checked: boolean) => { const cleanCountry = canonicalOptionLabel(country); setSelectedWmcCountries((current) => { if (checked) { return dedupeOptions([...current, cleanCountry]); } return current.filter( (item) => normalizeOptionKey(item) !== normalizeOptionKey(cleanCountry), ); }); }; const selectedWmcCountryManagers = selectedWmcCountries.map((country) => ({ country, manager: getCountryManager(country), })); const requiredOk = form.nombre.trim() && form.cliente && form.marca && form.solicitante.trim() && (isWalmartConnectCreate ? selectedWmcCountries.length > 0 : form.bu); const showSaveToast = (result: Awaited>) => { if (result.sheetSyncStatus === "synced") { toast.success(isEdit ? "Proyecto actualizado" : "Proyecto creado", { description: "Se guardó y se sincronizó con el Google Sheet.", }); return; } if (result.sheetSyncStatus === "skipped") { toast.success(isEdit ? "Proyecto actualizado" : "Proyecto creado", { description: "Se guardó. La sincronización con Google Sheet no está configurada.", }); return; } toast.warning("Proyecto guardado con aviso", { description: result.sheetSyncMessage, }); }; const submit = async () => { if (!requiredOk || saving) return; const safeForm = isGerardo ? form : { ...form, status: project?.status ?? "", monto: project?.monto ?? null, }; try { setSaving(true); setFormError(null); setSavingStep("Guardando y sincronizando con Google Sheet…"); if (isWalmartConnectCreate) { const countries = selectedWmcCountries; const results = []; for (const [index, country] of countries.entries()) { setSavingStep( `Guardando Walmart Connect WMC ${index + 1} de ${countries.length}: ${country}…`, ); const countryProject = { ...safeForm, bu: country, cm: getCountryManager(country), id: crypto.randomUUID(), createdAt: Date.now() + index, }; results.push(await add(countryProject)); } const failedSyncs = results.filter((result) => result.sheetSyncStatus !== "synced"); if (failedSyncs.length === 0) { toast.success("Proyectos Walmart Connect creados", { description: `Se crearon ${countries.length} proyectos y ${countries.length} filas en Google Sheet.`, }); } else { toast.warning("Proyectos Walmart Connect creados con aviso", { description: `${failedSyncs.length} de ${countries.length} sincronizaciones con Google Sheet requieren revisión.`, }); } } else { const result = isEdit && project ? await update(project.id, safeForm) : await add({ ...safeForm, id: crypto.randomUUID(), createdAt: Date.now() }); showSaveToast(result); } onOpenChange(false); } catch (error) { console.error("Error guardando proyecto:", error); const message = error instanceof Error ? error.message : "No se pudo guardar el proyecto. Revisa los permisos o intenta de nuevo."; setFormError(message); toast.error("No se pudo guardar el proyecto", { description: message, }); } finally { setSaving(false); setSavingStep(null); } }; const closed = !!form.status; return ( {/* Pestaña de color superior */}
{isEdit ? form.nombre || "Sin título" : "Nuevo proyecto"} {form.mes} · {form.anio} {closed && ( Cerrado )}
{/* Nombre */}
set("nombre", e.target.value)} placeholder="Ej: Promoción Día de las Madres" className="h-10" />
{/* Color */}
set("color", c)} />
{(listsLoading || listsError) && (
{listsLoading ? ( <> Cargando listas… ) : ( <> No se pudieron cargar las listas. Se usaron opciones locales. )} {listsError && ( )}
)} {/* Cliente */}
{/* Marca */}
{/* BU */} {isWalmartConnectCreate ? (
{selectedWmcCountries.length} seleccionado(s)

Para Walmart Connect WMC puedes seleccionar varios países. La app creará un proyecto y una fila del Sheet por cada país.

{buOptions.map((b) => { const checked = selectedWmcCountries.some( (country) => normalizeOptionKey(country) === normalizeOptionKey(b), ); const manager = getCountryManager(b); return ( ); })}
) : (
)} {/* CM autocompletado */}
{isWalmartConnectCreate ? (
{selectedWmcCountryManagers.length === 0 ? ( Selecciona uno o más países. ) : (
{selectedWmcCountryManagers.map(({ country, manager }) => ( {country}: {manager || "—"} ))}
)}
) : ( )}
{/* Solicitante */}
set("solicitante", e.target.value)} placeholder="Nombre de quien solicita" className="h-10" />
{/* Comentarios */}