diff --git a/src/main.tsx b/src/main.tsx
index b17f59a..5c26aa6 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,6 +1,6 @@
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
-import { RouterProvider, createRouter } from '@tanstack/react-router'
+import { RouterProvider, createRouteMask, createRouter } from '@tanstack/react-router'
// Import the generated route tree
import { routeTree } from './routeTree.gen'
@@ -15,7 +15,7 @@ const router = createRouter({
scrollRestoration: true,
defaultStructuralSharing: true,
defaultPreloadStaleTime: 0,
- context:{
+ context: {
auth: undefined!,
},
})
diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts
index f7a84b6..afa473e 100644
--- a/src/routeTree.gen.ts
+++ b/src/routeTree.gen.ts
@@ -16,10 +16,9 @@ import { Route as AuthenticatedUsuariosRouteImport } from './routes/_authenticat
import { Route as AuthenticatedPlanesRouteImport } from './routes/_authenticated/planes'
import { Route as AuthenticatedFacultadesRouteImport } from './routes/_authenticated/facultades'
import { Route as AuthenticatedDashboardRouteImport } from './routes/_authenticated/dashboard'
-import { Route as AuthenticatedAsignaturasRouteImport } from './routes/_authenticated/asignaturas'
import { Route as AuthenticatedPlanPlanIdRouteImport } from './routes/_authenticated/plan/$planId'
import { Route as AuthenticatedFacultadFacultadIdRouteImport } from './routes/_authenticated/facultad/$facultadId'
-import { Route as AuthenticatedPlanPlanIdModalRouteImport } from './routes/_authenticated/plan/$planId/modal'
+import { Route as AuthenticatedAsignaturasPlanIdRouteImport } from './routes/_authenticated/asignaturas/$planId'
const LoginRoute = LoginRouteImport.update({
id: '/login',
@@ -55,12 +54,6 @@ const AuthenticatedDashboardRoute = AuthenticatedDashboardRouteImport.update({
path: '/dashboard',
getParentRoute: () => AuthenticatedRoute,
} as any)
-const AuthenticatedAsignaturasRoute =
- AuthenticatedAsignaturasRouteImport.update({
- id: '/asignaturas',
- path: '/asignaturas',
- getParentRoute: () => AuthenticatedRoute,
- } as any)
const AuthenticatedPlanPlanIdRoute = AuthenticatedPlanPlanIdRouteImport.update({
id: '/plan/$planId',
path: '/plan/$planId',
@@ -72,89 +65,83 @@ const AuthenticatedFacultadFacultadIdRoute =
path: '/facultad/$facultadId',
getParentRoute: () => AuthenticatedRoute,
} as any)
-const AuthenticatedPlanPlanIdModalRoute =
- AuthenticatedPlanPlanIdModalRouteImport.update({
- id: '/modal',
- path: '/modal',
- getParentRoute: () => AuthenticatedPlanPlanIdRoute,
+const AuthenticatedAsignaturasPlanIdRoute =
+ AuthenticatedAsignaturasPlanIdRouteImport.update({
+ id: '/asignaturas/$planId',
+ path: '/asignaturas/$planId',
+ getParentRoute: () => AuthenticatedRoute,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/login': typeof LoginRoute
- '/asignaturas': typeof AuthenticatedAsignaturasRoute
'/dashboard': typeof AuthenticatedDashboardRoute
'/facultades': typeof AuthenticatedFacultadesRoute
'/planes': typeof AuthenticatedPlanesRoute
'/usuarios': typeof AuthenticatedUsuariosRoute
+ '/asignaturas/$planId': typeof AuthenticatedAsignaturasPlanIdRoute
'/facultad/$facultadId': typeof AuthenticatedFacultadFacultadIdRoute
- '/plan/$planId': typeof AuthenticatedPlanPlanIdRouteWithChildren
- '/plan/$planId/modal': typeof AuthenticatedPlanPlanIdModalRoute
+ '/plan/$planId': typeof AuthenticatedPlanPlanIdRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/login': typeof LoginRoute
- '/asignaturas': typeof AuthenticatedAsignaturasRoute
'/dashboard': typeof AuthenticatedDashboardRoute
'/facultades': typeof AuthenticatedFacultadesRoute
'/planes': typeof AuthenticatedPlanesRoute
'/usuarios': typeof AuthenticatedUsuariosRoute
+ '/asignaturas/$planId': typeof AuthenticatedAsignaturasPlanIdRoute
'/facultad/$facultadId': typeof AuthenticatedFacultadFacultadIdRoute
- '/plan/$planId': typeof AuthenticatedPlanPlanIdRouteWithChildren
- '/plan/$planId/modal': typeof AuthenticatedPlanPlanIdModalRoute
+ '/plan/$planId': typeof AuthenticatedPlanPlanIdRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/_authenticated': typeof AuthenticatedRouteWithChildren
'/login': typeof LoginRoute
- '/_authenticated/asignaturas': typeof AuthenticatedAsignaturasRoute
'/_authenticated/dashboard': typeof AuthenticatedDashboardRoute
'/_authenticated/facultades': typeof AuthenticatedFacultadesRoute
'/_authenticated/planes': typeof AuthenticatedPlanesRoute
'/_authenticated/usuarios': typeof AuthenticatedUsuariosRoute
+ '/_authenticated/asignaturas/$planId': typeof AuthenticatedAsignaturasPlanIdRoute
'/_authenticated/facultad/$facultadId': typeof AuthenticatedFacultadFacultadIdRoute
- '/_authenticated/plan/$planId': typeof AuthenticatedPlanPlanIdRouteWithChildren
- '/_authenticated/plan/$planId/modal': typeof AuthenticatedPlanPlanIdModalRoute
+ '/_authenticated/plan/$planId': typeof AuthenticatedPlanPlanIdRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/'
| '/login'
- | '/asignaturas'
| '/dashboard'
| '/facultades'
| '/planes'
| '/usuarios'
+ | '/asignaturas/$planId'
| '/facultad/$facultadId'
| '/plan/$planId'
- | '/plan/$planId/modal'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
| '/login'
- | '/asignaturas'
| '/dashboard'
| '/facultades'
| '/planes'
| '/usuarios'
+ | '/asignaturas/$planId'
| '/facultad/$facultadId'
| '/plan/$planId'
- | '/plan/$planId/modal'
id:
| '__root__'
| '/'
| '/_authenticated'
| '/login'
- | '/_authenticated/asignaturas'
| '/_authenticated/dashboard'
| '/_authenticated/facultades'
| '/_authenticated/planes'
| '/_authenticated/usuarios'
+ | '/_authenticated/asignaturas/$planId'
| '/_authenticated/facultad/$facultadId'
| '/_authenticated/plan/$planId'
- | '/_authenticated/plan/$planId/modal'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
@@ -214,13 +201,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedDashboardRouteImport
parentRoute: typeof AuthenticatedRoute
}
- '/_authenticated/asignaturas': {
- id: '/_authenticated/asignaturas'
- path: '/asignaturas'
- fullPath: '/asignaturas'
- preLoaderRoute: typeof AuthenticatedAsignaturasRouteImport
- parentRoute: typeof AuthenticatedRoute
- }
'/_authenticated/plan/$planId': {
id: '/_authenticated/plan/$planId'
path: '/plan/$planId'
@@ -235,48 +215,34 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedFacultadFacultadIdRouteImport
parentRoute: typeof AuthenticatedRoute
}
- '/_authenticated/plan/$planId/modal': {
- id: '/_authenticated/plan/$planId/modal'
- path: '/modal'
- fullPath: '/plan/$planId/modal'
- preLoaderRoute: typeof AuthenticatedPlanPlanIdModalRouteImport
- parentRoute: typeof AuthenticatedPlanPlanIdRoute
+ '/_authenticated/asignaturas/$planId': {
+ id: '/_authenticated/asignaturas/$planId'
+ path: '/asignaturas/$planId'
+ fullPath: '/asignaturas/$planId'
+ preLoaderRoute: typeof AuthenticatedAsignaturasPlanIdRouteImport
+ parentRoute: typeof AuthenticatedRoute
}
}
}
-interface AuthenticatedPlanPlanIdRouteChildren {
- AuthenticatedPlanPlanIdModalRoute: typeof AuthenticatedPlanPlanIdModalRoute
-}
-
-const AuthenticatedPlanPlanIdRouteChildren: AuthenticatedPlanPlanIdRouteChildren =
- {
- AuthenticatedPlanPlanIdModalRoute: AuthenticatedPlanPlanIdModalRoute,
- }
-
-const AuthenticatedPlanPlanIdRouteWithChildren =
- AuthenticatedPlanPlanIdRoute._addFileChildren(
- AuthenticatedPlanPlanIdRouteChildren,
- )
-
interface AuthenticatedRouteChildren {
- AuthenticatedAsignaturasRoute: typeof AuthenticatedAsignaturasRoute
AuthenticatedDashboardRoute: typeof AuthenticatedDashboardRoute
AuthenticatedFacultadesRoute: typeof AuthenticatedFacultadesRoute
AuthenticatedPlanesRoute: typeof AuthenticatedPlanesRoute
AuthenticatedUsuariosRoute: typeof AuthenticatedUsuariosRoute
+ AuthenticatedAsignaturasPlanIdRoute: typeof AuthenticatedAsignaturasPlanIdRoute
AuthenticatedFacultadFacultadIdRoute: typeof AuthenticatedFacultadFacultadIdRoute
- AuthenticatedPlanPlanIdRoute: typeof AuthenticatedPlanPlanIdRouteWithChildren
+ AuthenticatedPlanPlanIdRoute: typeof AuthenticatedPlanPlanIdRoute
}
const AuthenticatedRouteChildren: AuthenticatedRouteChildren = {
- AuthenticatedAsignaturasRoute: AuthenticatedAsignaturasRoute,
AuthenticatedDashboardRoute: AuthenticatedDashboardRoute,
AuthenticatedFacultadesRoute: AuthenticatedFacultadesRoute,
AuthenticatedPlanesRoute: AuthenticatedPlanesRoute,
AuthenticatedUsuariosRoute: AuthenticatedUsuariosRoute,
+ AuthenticatedAsignaturasPlanIdRoute: AuthenticatedAsignaturasPlanIdRoute,
AuthenticatedFacultadFacultadIdRoute: AuthenticatedFacultadFacultadIdRoute,
- AuthenticatedPlanPlanIdRoute: AuthenticatedPlanPlanIdRouteWithChildren,
+ AuthenticatedPlanPlanIdRoute: AuthenticatedPlanPlanIdRoute,
}
const AuthenticatedRouteWithChildren = AuthenticatedRoute._addFileChildren(
diff --git a/src/routes/_authenticated/asignaturas.tsx b/src/routes/_authenticated/asignaturas.tsx
deleted file mode 100644
index d0d0c93..0000000
--- a/src/routes/_authenticated/asignaturas.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { createFileRoute } from '@tanstack/react-router'
-
-export const Route = createFileRoute('/_authenticated/asignaturas')({
- component: RouteComponent,
-})
-
-function RouteComponent() {
- return
Hello "/_authenticated/asignaturas"!
-}
diff --git a/src/routes/_authenticated/asignaturas/$planId.tsx b/src/routes/_authenticated/asignaturas/$planId.tsx
new file mode 100644
index 0000000..861389f
--- /dev/null
+++ b/src/routes/_authenticated/asignaturas/$planId.tsx
@@ -0,0 +1,142 @@
+import { createFileRoute, useRouter } from "@tanstack/react-router"
+import { supabase } from "@/auth/supabase"
+import * as Icons from "lucide-react"
+import { useMemo, useState } from "react"
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"
+import { Input } from "@/components/ui/input"
+import { Badge } from "@/components/ui/badge"
+
+type Asignatura = {
+ id: string
+ nombre: string
+ semestre: number | null
+ creditos: number | null
+ horas_teoricas: number | null
+ horas_practicas: number | null
+}
+
+type ModalData = {
+ planId: string
+ planNombre: string
+ asignaturas: Asignatura[]
+}
+
+export const Route = createFileRoute("/_authenticated/asignaturas/$planId")({
+ component: ModalComponent,
+ loader: async ({ params }): Promise => {
+ const planId = params.planId
+
+ const { data: plan, error: planErr } = await supabase
+ .from("plan_estudios")
+ .select("id, nombre")
+ .eq("id", planId)
+ .single()
+ if (planErr || !plan) throw planErr ?? new Error("Plan no encontrado")
+
+ const { data: asignaturas, error: aErr } = await supabase
+ .from("asignaturas")
+ .select("id, nombre, semestre, creditos, horas_teoricas, horas_practicas")
+ .eq("plan_id", planId)
+ .order("semestre", { ascending: true })
+ .order("nombre", { ascending: true })
+
+ if (aErr) throw aErr
+
+ return {
+ planId,
+ planNombre: plan.nombre,
+ asignaturas: (asignaturas ?? []) as Asignatura[],
+ }
+ },
+})
+
+function ModalComponent() {
+ const { planId, planNombre, asignaturas } = Route.useLoaderData() as ModalData
+ const router = useRouter()
+ const [q, setQ] = useState("")
+
+ const filtered = useMemo(() => {
+ const t = q.trim().toLowerCase()
+ if (!t) return asignaturas
+ return asignaturas.filter(a =>
+ [a.nombre, a.semestre, a.creditos]
+ .filter(Boolean)
+ .some(v => String(v).toLowerCase().includes(t))
+ )
+ }, [q, asignaturas])
+
+ // Agrupar por semestre
+ const groups = useMemo(() => {
+ const m = new Map()
+ for (const a of filtered) {
+ const k = a.semestre ?? "—"
+ if (!m.has(k)) m.set(k, [])
+ m.get(k)!.push(a)
+ }
+ return Array.from(m.entries()).sort(([a], [b]) => {
+ if (a === "—") return 1
+ if (b === "—") return -1
+ return Number(a) - Number(b)
+ })
+ }, [filtered])
+
+ return (
+
+ )
+}
diff --git a/src/routes/_authenticated/facultad/$facultadId.tsx b/src/routes/_authenticated/facultad/$facultadId.tsx
index b79dcd7..bebd4a0 100644
--- a/src/routes/_authenticated/facultad/$facultadId.tsx
+++ b/src/routes/_authenticated/facultad/$facultadId.tsx
@@ -5,6 +5,7 @@ import { createFileRoute, Link } from '@tanstack/react-router'
import * as Icons from 'lucide-react'
import { supabase } from '@/auth/supabase'
import { useMemo } from 'react'
+import { useTheme } from '@/components/theme-provider'
type Facultad = { id: string; nombre: string; icon: string; color?: string | null }
type Plan = {
@@ -121,13 +122,14 @@ function gradientFrom(color?: string | null) {
}
// ====== UI helpers ======
-function ProgressRing({ pct }: { pct: number }) {
+function ProgressRing({ pct, color }: { pct: number, color: string }) {
const r = 42, c = 2 * Math.PI * r
const offset = c * (1 - Math.min(Math.max(pct, 0), 100) / 100)
+ // Puedes ajustar el color del stroke según el tema
return (