1 Commits

Author SHA1 Message Date
Robert
449a83d43d Se agrega avance sobre detalle de plan de estudios 2025-12-26 18:22:11 -06:00
5 changed files with 276 additions and 28 deletions

View File

@@ -13,8 +13,11 @@ import { Route as PlanesRouteImport } from './routes/planes'
import { Route as LoginRouteImport } from './routes/login'
import { Route as DashboardRouteImport } from './routes/dashboard'
import { Route as IndexRouteImport } from './routes/index'
import { Route as PlanesIndexRouteImport } from './routes/planes/index'
import { Route as Planes2IndexRouteImport } from './routes/planes2/index'
import { Route as DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
import { Route as Planes2PlanIdRouteRouteImport } from './routes/planes2/$planId/route'
import { Route as Planes2PlanIdIndexRouteImport } from './routes/planes2/$planId/index'
import { Route as Planes2PlanIdMapaRouteImport } from './routes/planes2/$planId/mapa'
const PlanesRoute = PlanesRouteImport.update({
id: '/planes',
@@ -36,40 +39,64 @@ const IndexRoute = IndexRouteImport.update({
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const PlanesIndexRoute = PlanesIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => PlanesRoute,
const Planes2IndexRoute = Planes2IndexRouteImport.update({
id: '/planes2/',
path: '/planes2/',
getParentRoute: () => rootRouteImport,
} as any)
const DemoTanstackQueryRoute = DemoTanstackQueryRouteImport.update({
id: '/demo/tanstack-query',
path: '/demo/tanstack-query',
getParentRoute: () => rootRouteImport,
} as any)
const Planes2PlanIdRouteRoute = Planes2PlanIdRouteRouteImport.update({
id: '/planes2/$planId',
path: '/planes2/$planId',
getParentRoute: () => rootRouteImport,
} as any)
const Planes2PlanIdIndexRoute = Planes2PlanIdIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => Planes2PlanIdRouteRoute,
} as any)
const Planes2PlanIdMapaRoute = Planes2PlanIdMapaRouteImport.update({
id: '/mapa',
path: '/mapa',
getParentRoute: () => Planes2PlanIdRouteRoute,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/dashboard': typeof DashboardRoute
'/login': typeof LoginRoute
'/planes': typeof PlanesRouteWithChildren
'/planes': typeof PlanesRoute
'/planes2/$planId': typeof Planes2PlanIdRouteRouteWithChildren
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
'/planes/': typeof PlanesIndexRoute
'/planes2': typeof Planes2IndexRoute
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
'/planes2/$planId/': typeof Planes2PlanIdIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/dashboard': typeof DashboardRoute
'/login': typeof LoginRoute
'/planes': typeof PlanesRoute
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
'/planes': typeof PlanesIndexRoute
'/planes2': typeof Planes2IndexRoute
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
'/planes2/$planId': typeof Planes2PlanIdIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/dashboard': typeof DashboardRoute
'/login': typeof LoginRoute
'/planes': typeof PlanesRouteWithChildren
'/planes': typeof PlanesRoute
'/planes2/$planId': typeof Planes2PlanIdRouteRouteWithChildren
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
'/planes/': typeof PlanesIndexRoute
'/planes2/': typeof Planes2IndexRoute
'/planes2/$planId/mapa': typeof Planes2PlanIdMapaRoute
'/planes2/$planId/': typeof Planes2PlanIdIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
@@ -78,26 +105,42 @@ export interface FileRouteTypes {
| '/dashboard'
| '/login'
| '/planes'
| '/planes2/$planId'
| '/demo/tanstack-query'
| '/planes/'
| '/planes2'
| '/planes2/$planId/mapa'
| '/planes2/$planId/'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/dashboard' | '/login' | '/demo/tanstack-query' | '/planes'
to:
| '/'
| '/dashboard'
| '/login'
| '/planes'
| '/demo/tanstack-query'
| '/planes2'
| '/planes2/$planId/mapa'
| '/planes2/$planId'
id:
| '__root__'
| '/'
| '/dashboard'
| '/login'
| '/planes'
| '/planes2/$planId'
| '/demo/tanstack-query'
| '/planes/'
| '/planes2/'
| '/planes2/$planId/mapa'
| '/planes2/$planId/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
DashboardRoute: typeof DashboardRoute
LoginRoute: typeof LoginRoute
PlanesRoute: typeof PlanesRouteWithChildren
PlanesRoute: typeof PlanesRoute
Planes2PlanIdRouteRoute: typeof Planes2PlanIdRouteRouteWithChildren
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
Planes2IndexRoute: typeof Planes2IndexRoute
}
declare module '@tanstack/react-router' {
@@ -130,12 +173,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/planes/': {
id: '/planes/'
path: '/'
fullPath: '/planes/'
preLoaderRoute: typeof PlanesIndexRouteImport
parentRoute: typeof PlanesRoute
'/planes2/': {
id: '/planes2/'
path: '/planes2'
fullPath: '/planes2'
preLoaderRoute: typeof Planes2IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/demo/tanstack-query': {
id: '/demo/tanstack-query'
@@ -144,26 +187,51 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DemoTanstackQueryRouteImport
parentRoute: typeof rootRouteImport
}
'/planes2/$planId': {
id: '/planes2/$planId'
path: '/planes2/$planId'
fullPath: '/planes2/$planId'
preLoaderRoute: typeof Planes2PlanIdRouteRouteImport
parentRoute: typeof rootRouteImport
}
'/planes2/$planId/': {
id: '/planes2/$planId/'
path: '/'
fullPath: '/planes2/$planId/'
preLoaderRoute: typeof Planes2PlanIdIndexRouteImport
parentRoute: typeof Planes2PlanIdRouteRoute
}
'/planes2/$planId/mapa': {
id: '/planes2/$planId/mapa'
path: '/mapa'
fullPath: '/planes2/$planId/mapa'
preLoaderRoute: typeof Planes2PlanIdMapaRouteImport
parentRoute: typeof Planes2PlanIdRouteRoute
}
}
}
interface PlanesRouteChildren {
PlanesIndexRoute: typeof PlanesIndexRoute
interface Planes2PlanIdRouteRouteChildren {
Planes2PlanIdMapaRoute: typeof Planes2PlanIdMapaRoute
Planes2PlanIdIndexRoute: typeof Planes2PlanIdIndexRoute
}
const PlanesRouteChildren: PlanesRouteChildren = {
PlanesIndexRoute: PlanesIndexRoute,
const Planes2PlanIdRouteRouteChildren: Planes2PlanIdRouteRouteChildren = {
Planes2PlanIdMapaRoute: Planes2PlanIdMapaRoute,
Planes2PlanIdIndexRoute: Planes2PlanIdIndexRoute,
}
const PlanesRouteWithChildren =
PlanesRoute._addFileChildren(PlanesRouteChildren)
const Planes2PlanIdRouteRouteWithChildren =
Planes2PlanIdRouteRoute._addFileChildren(Planes2PlanIdRouteRouteChildren)
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
DashboardRoute: DashboardRoute,
LoginRoute: LoginRoute,
PlanesRoute: PlanesRouteWithChildren,
PlanesRoute: PlanesRoute,
Planes2PlanIdRouteRoute: Planes2PlanIdRouteRouteWithChildren,
DemoTanstackQueryRoute: DemoTanstackQueryRoute,
Planes2IndexRoute: Planes2IndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)

View File

@@ -0,0 +1,36 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/planes2/$planId/')({
component: DatosGenerales,
})
function DatosGenerales() {
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card title="Objetivo General">
Formar profesionales altamente capacitados...
</Card>
<Card title="Perfil de Ingreso">
Egresados de educación media superior...
</Card>
<Card title="Perfil de Egreso">
Profesional capaz de diseñar...
</Card>
<Card title="Competencias Genéricas">
Pensamiento crítico, comunicación efectiva...
</Card>
</div>
)
}
function Card({ title, children }) {
return (
<div className="rounded-lg border bg-white p-4">
<h3 className="font-semibold mb-2">{title}</h3>
<p className="text-sm text-gray-600">{children}</p>
</div>
)
}

View File

@@ -0,0 +1,86 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/planes2/$planId/mapa')({
component: MapaCurricular,
})
const CICLOS = ["Ciclo 1", "Ciclo 2", "Ciclo 3", "Ciclo 4", "Ciclo 5", "Ciclo 6", "Ciclo 7", "Ciclo 8", "Ciclo 9"];
const LINEAS = ["Formación Básica", "Ciencias de la Computación", "Desarrollo de Software", "Redes y Seguridad", "Gestión y Profesionalización"];
// Ejemplo de materia
const MATERIAS = [
{ nombre: "Cálculo Diferencial", linea: "Formación Básica", ciclo: 1, creditos: 8 },
{ nombre: "Fundamentos de Programación", linea: "Ciencias de la Computación", ciclo: 1, creditos: 8 },
{ nombre: "Fundamentos de Programación 2", linea: "Ciencias de la Computación", ciclo: 1, creditos: 8 },
// ... más materias
];
function MapaCurricular() {
return (
<div className="p-4 overflow-x-auto">
<h2 className="text-xl font-semibold mb-6">Mapa Curricular</h2>
{/* Contenedor de la Grid */}
<div
className="grid min-w-[1200px] border-l border-t border-slate-200"
style={{
// 1 columna para nombres de líneas + 9 ciclos
gridTemplateColumns: '200px repeat(9, 1fr)',
}}
>
{/* Header: Espacio vacío + Ciclos */}
<div className="bg-slate-50 p-2 border-r border-b border-slate-200 font-medium text-sm text-slate-500">
Línea Curricular
</div>
{CICLOS.map((ciclo) => (
<div key={ciclo} className="bg-slate-50 p-2 border-r border-b border-slate-200 text-center font-medium text-sm text-slate-500">
{ciclo}
</div>
))}
{/* Filas por cada Línea Curricular */}
{LINEAS.map((linea) => (
<>
{/* Nombre de la línea (Primera columna) */}
<div className="bg-slate-50 p-3 border-r border-b border-slate-200 flex items-center text-xs font-bold uppercase text-slate-600">
{linea}
</div>
{/* Celdas para cada ciclo en esta línea */}
{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((numCiclo) => (
<div
key={`${linea}-${numCiclo}`}
className="p-2 border-r border-b border-slate-100 min-h-[120px] bg-white/50"
>
{/* Filtrar materias que pertenecen a esta posición */}
{MATERIAS.filter(m => m.linea === linea && m.ciclo === numCiclo).map((materia, i) => (
<div
key={i}
className="p-2 mb-2 rounded border border-blue-200 bg-blue-50 text-[10px] shadow-sm hover:shadow-md transition-shadow cursor-pointer"
>
<div className="font-bold text-blue-900 leading-tight mb-1">{materia.nombre}</div>
<div className="flex justify-between text-blue-700 opacity-80">
<span>{materia.creditos} CR</span>
<span>ID: {i + 100}</span>
</div>
</div>
))}
</div>
))}
</>
))}
</div>
{/* Sección de materias sin asignar (como en tu imagen) */}
<div className="mt-8">
<h3 className="text-sm font-bold text-slate-500 mb-3 uppercase tracking-wider">Materias sin asignar</h3>
<div className="flex gap-4">
<div className="p-3 border rounded-lg bg-slate-50 border-dashed border-slate-300 w-48 text-[10px]">
<div className="font-bold">Inglés Técnico</div>
<div className="text-slate-500">4 cr HD: 2 HI: 2</div>
</div>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,58 @@
import { createFileRoute, Outlet, Link } from '@tanstack/react-router'
export const Route = createFileRoute('/planes2/$planId')({
component: PlanLayout,
})
function PlanLayout() {
const { planId } = Route.useParams()
return (
<div className="space-y-6">
{/* Header del plan */}
<div>
<Link to="/planes2" className="text-sm text-gray-500">
Volver a planes
</Link>
<h1 className="text-2xl font-bold mt-2">Plan de Estudios 2024</h1>
<p className="text-gray-600">
Ingeniería en Sistemas Computacionales
</p>
</div>
{/* Tabs */}
<nav className="flex gap-6 border-b">
<Tab to="/planes2/$planId" params={{ planId }}>
Datos Generales
</Tab>
<Tab to="/planes2/$planId/mapa" params={{ planId }}>
Mapa Curricular
</Tab>
<Tab to="/planes2/$planId/materias" params={{ planId }}>
Materias
</Tab>
</nav>
{/* Aquí se renderiza cada tab */}
<Outlet />
</div>
)
}
function Tab({ to, params, children }) {
return (
<Link
to={to}
params={params}
className="pb-2 border-b-2 border-transparent hover:border-teal-600"
activeProps={{
className: 'border-teal-600 text-teal-700 font-medium',
}}
>
{children}
</Link>
)
}

View File

@@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router'
import { AppLayout } from '@/components/layout/AppLayout'
import { PlanGrid } from '@/components/plans/PlanGrid'
export const Route = createFileRoute('/planes/')({
export const Route = createFileRoute('/planes2/')({
component: PlanesPage,
})