diff --git a/src/routes/planes/$planId/_detalle/mapa.tsx b/src/routes/planes/$planId/_detalle/mapa.tsx index 9709f9d..8c8f3ab 100644 --- a/src/routes/planes/$planId/_detalle/mapa.tsx +++ b/src/routes/planes/$planId/_detalle/mapa.tsx @@ -5,7 +5,6 @@ import { Plus, ChevronDown, AlertTriangle, - GripVertical, Trash2, Pencil, } from 'lucide-react' @@ -46,16 +45,33 @@ import { useUpdateAsignatura, useUpdateLinea, } from '@/data' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip' // --- Mapeadores (Fuera del componente para mayor limpieza) --- +const palette = [ + '#4F46E5', // índigo + '#7C3AED', // violeta + '#EA580C', // naranja + '#059669', // esmeralda + '#DC2626', // rojo + '#0891B2', // cyan + '#CA8A04', // ámbar + '#C026D3', // fucsia +] + const mapLineasToLineaCurricular = ( lineasApi: Array = [], ): Array => { - return lineasApi.map((linea) => ({ + return lineasApi.map((linea, index) => ({ id: linea.id, nombre: linea.nombre, orden: linea.orden ?? 0, - color: '#1976d2', + color: palette[index % palette.length], })) } @@ -121,52 +137,216 @@ function StatItem({ ) } +import * as Icons from 'lucide-react' + +const estadoConfig: Record< + Asignatura['estado'], + { + label: string + dot: string + soft: string + icon: React.ComponentType<{ className?: string }> + } +> = { + borrador: { + label: 'Borrador', + dot: 'bg-slate-500', + soft: 'bg-slate-100 text-slate-700', + icon: Icons.FileText, + }, + revisada: { + label: 'Revisada', + dot: 'bg-amber-500', + soft: 'bg-amber-100 text-amber-700', + icon: Icons.ScanSearch, + }, + aprobada: { + label: 'Aprobada', + dot: 'bg-emerald-500', + soft: 'bg-emerald-100 text-emerald-700', + icon: Icons.BadgeCheck, + }, + generando: { + label: 'Generando', + dot: 'bg-sky-500', + soft: 'bg-sky-100 text-sky-700', + icon: Icons.LoaderCircle, + }, +} + +function hexToRgba(hex: string, alpha: number) { + const clean = hex.replace('#', '') + const bigint = parseInt(clean, 16) + const r = (bigint >> 16) & 255 + const g = (bigint >> 8) & 255 + const b = bigint & 255 + return `rgba(${r}, ${g}, ${b}, ${alpha})` +} + function AsignaturaCardItem({ asignatura, + lineaColor, + lineaNombre, onDragStart, isDragging, onClick, }: { asignatura: Asignatura + lineaColor: string + lineaNombre?: string onDragStart: (e: React.DragEvent, id: string) => void isDragging: boolean onClick: () => void }) { + const estado = estadoConfig[asignatura.estado] ?? estadoConfig.borrador + const EstadoIcon = estado.icon + return ( - + + + + + + + +
+ {lineaNombre ? `${lineaNombre} · ` : ''} + {asignatura.nombre} +
+
+
+
) } @@ -524,15 +704,15 @@ function MapaCurricularPage() { {asignaturas.filter((m) => !m.ciclo || !m.lineaCurricularId).length > 0 && ( - - {' '} - { - asignaturas.filter((m) => !m.ciclo || !m.lineaCurricularId) - .length - }{' '} - sin asignar - - )} + + {' '} + { + asignaturas.filter((m) => !m.ciclo || !m.lineaCurricularId) + .length + }{' '} + sin asignar + + )}