import { createFileRoute, useNavigate } from '@tanstack/react-router' import { Plus, Copy, Search, Filter, ChevronRight, BookOpen, Loader2, } from 'lucide-react' import { useState, useMemo } from 'react' import type { Materia } from '@/types/plan' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { usePlanAsignaturas, usePlanLineas } from '@/data' // --- Configuración de Estilos --- const statusConfig: Record = { borrador: { label: 'Borrador', className: 'bg-slate-100 text-slate-600' }, revisada: { label: 'Revisada', className: 'bg-amber-100 text-amber-700' }, aprobada: { label: 'Aprobada', className: 'bg-emerald-100 text-emerald-700' }, } const tipoConfig: Record = { obligatoria: { label: 'Obligatoria', className: 'bg-blue-100 text-blue-700' }, optativa: { label: 'Optativa', className: 'bg-purple-100 text-purple-700' }, troncal: { label: 'Troncal', className: 'bg-slate-100 text-slate-700' }, } // --- Mapeadores de API --- const mapAsignaturas = (asigApi: Array = []): Array => { return asigApi.map((asig) => ({ id: asig.id, clave: asig.codigo, nombre: asig.nombre, creditos: asig.creditos ?? 0, ciclo: asig.numero_ciclo ?? null, lineaCurricularId: asig.linea_plan_id ?? null, tipo: asig.tipo?.toLowerCase() === 'obligatoria' ? 'obligatoria' : 'optativa', estado: 'borrador', // O el campo que venga de tu API hd: Math.floor((asig.horas_semana ?? 0) / 2), hi: Math.ceil((asig.horas_semana ?? 0) / 2), })) } export const Route = createFileRoute('/planes/$planId/_detalle/asignaturas')({ component: MateriasPage, }) function MateriasPage() { const { planId } = Route.useParams() const navigate = useNavigate() // 1. Fetch de datos reales const { data: asignaturasApi, isLoading: loadingAsig } = usePlanAsignaturas(planId) const { data: lineasApi, isLoading: loadingLineas } = usePlanLineas(planId) // 2. Estados de filtrado const [searchTerm, setSearchTerm] = useState('') const [filterTipo, setFilterTipo] = useState('all') const [filterEstado, setFilterEstado] = useState('all') const [filterLinea, setFilterLinea] = useState('all') // 3. Procesamiento de datos const materias = useMemo( () => mapAsignaturas(asignaturasApi), [asignaturasApi], ) const lineas = useMemo(() => lineasApi || [], [lineasApi]) const filteredMaterias = materias.filter((m) => { const matchesSearch = m.nombre.toLowerCase().includes(searchTerm.toLowerCase()) || m.clave.toLowerCase().includes(searchTerm.toLowerCase()) const matchesTipo = filterTipo === 'all' || m.tipo === filterTipo const matchesEstado = filterEstado === 'all' || m.estado === filterEstado const matchesLinea = filterLinea === 'all' || m.lineaCurricularId === filterLinea return matchesSearch && matchesTipo && matchesEstado && matchesLinea }) const getLineaNombre = (lineaId: string | null) => { if (!lineaId) return 'Sin asignar' return lineas.find((l: any) => l.id === lineaId)?.nombre || 'Desconocida' } if (loadingAsig || loadingLineas) { return (
) } return (
{/* Header */}

Materias del Plan

{materias.length} materias en total • {filteredMaterias.length}{' '} filtradas

{/* Barra de Filtros Avanzada */}
setSearchTerm(e.target.value)} className="bg-white pl-9" />
{/* Tabla Pro */}
Clave Nombre Créditos Ciclo Línea Curricular Tipo Estado {filteredMaterias.length === 0 ? (

No se encontraron materias

Intenta cambiar los filtros de búsqueda

) : ( filteredMaterias.map((materia) => ( navigate({ to: '/planes/$planId/asignaturas/$asignaturaId', params: { planId, asignaturaId: materia.id, // 👈 puede ser índice, consecutivo o slug }, state: { realId: materia.id, // 👈 ID largo oculto asignaturaId: materia.id, } as any, }) } > {materia.clave} {materia.nombre} {materia.creditos} {materia.ciclo ? ( Ciclo {materia.ciclo} ) : ( )} {getLineaNombre(materia.lineaCurricularId)} {tipoConfig[materia.tipo]?.label} {statusConfig[materia.estado]?.label}
)) )}
) }