diff --git a/src/components/layout/AppLayout.tsx b/src/components/layout/AppLayout.tsx
new file mode 100644
index 0000000..341e987
--- /dev/null
+++ b/src/components/layout/AppLayout.tsx
@@ -0,0 +1,27 @@
+import type { ReactNode } from 'react'
+import { Sidebar } from './Sidebar'
+import { Header } from './Header'
+import { StatsGrid } from '../plans/StatsGrid'
+
+export function AppLayout({ children }: { children: ReactNode }) {
+ return (
+
+ {/*
*/}
+
+
+
+
+ {/* Separación Header → Stats */}
+
+
+
+ {children}
+
+
+
+ )
+}
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
new file mode 100644
index 0000000..f9335af
--- /dev/null
+++ b/src/components/layout/Header.tsx
@@ -0,0 +1,18 @@
+export function Header() {
+ return (
+
+
+ 🎓
+
+
+
+
+ Gestión Curricular
+
+
+ Sistema de Planes de Estudio
+
+
+
+ )
+}
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
new file mode 100644
index 0000000..d37ebff
--- /dev/null
+++ b/src/components/layout/Sidebar.tsx
@@ -0,0 +1,32 @@
+import { LayoutGrid, BookOpen } from 'lucide-react'
+
+export function Sidebar() {
+ return (
+
+ )
+}
+
+function NavItem({ icon: Icon, label, active }: any) {
+ return (
+
+
+ {label}
+
+ )
+}
diff --git a/src/components/plans/PlanCard.tsx b/src/components/plans/PlanCard.tsx
new file mode 100644
index 0000000..d233a80
--- /dev/null
+++ b/src/components/plans/PlanCard.tsx
@@ -0,0 +1,26 @@
+import { StatusBadge } from "./StatusBadge";
+
+export function PlanCard({ plan }: any) {
+ return (
+
+
+ ⚙ Ingeniería
+
+
+
+
+ {plan.title}
+
+
+
+ {plan.subtitle}
+
+
+
+ {plan.cycles} ciclos
+ {plan.credits} créditos
+ ➜
+
+
+ )
+}
diff --git a/src/components/plans/PlanGrid.tsx b/src/components/plans/PlanGrid.tsx
new file mode 100644
index 0000000..c6bcd65
--- /dev/null
+++ b/src/components/plans/PlanGrid.tsx
@@ -0,0 +1,38 @@
+import { PlanCard } from './PlanCard'
+
+const mockPlans = [
+ {
+ id: 1,
+ name: 'Ingeniería en Sistemas',
+ level: 'Licenciatura',
+ status: 'Activo',
+ },
+ {
+ id: 2,
+ name: 'Arquitectura',
+ level: 'Licenciatura',
+ status: 'Activo',
+ },
+ {
+ id: 3,
+ name: 'Maestría en Educación',
+ level: 'Maestría',
+ status: 'Inactivo',
+ },
+]
+
+export function PlanGrid() {
+ return (
+
+
+ Planes disponibles
+
+
+
+ {mockPlans.map(plan => (
+
+ ))}
+
+
+ )
+}
diff --git a/src/components/plans/StatCard.tsx b/src/components/plans/StatCard.tsx
new file mode 100644
index 0000000..d108612
--- /dev/null
+++ b/src/components/plans/StatCard.tsx
@@ -0,0 +1,11 @@
+export function StatCard({ icon, value, label }: any) {
+ return (
+
+
+ {icon}
+ {value}
+
+
{label}
+
+ )
+}
diff --git a/src/components/plans/StatsGrid.tsx b/src/components/plans/StatsGrid.tsx
new file mode 100644
index 0000000..ca1bf96
--- /dev/null
+++ b/src/components/plans/StatsGrid.tsx
@@ -0,0 +1,12 @@
+import { StatCard } from "./StatCard";
+
+export function StatsGrid() {
+ return (
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/plans/StatusBadge.tsx b/src/components/plans/StatusBadge.tsx
new file mode 100644
index 0000000..9de2053
--- /dev/null
+++ b/src/components/plans/StatusBadge.tsx
@@ -0,0 +1,19 @@
+export function StatusBadge({ status }: { status: string }) {
+ const styles: any = {
+ revision: 'bg-blue-100 text-blue-700',
+ aprobado: 'bg-green-100 text-green-700',
+ borrador: 'bg-gray-200 text-gray-600',
+ }
+
+ return (
+
+ {status === 'revision'
+ ? 'En Revisión'
+ : status === 'aprobado'
+ ? 'Aprobado'
+ : 'Borrador'}
+
+ )
+}
diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts
index 9858c80..60c0fe7 100644
--- a/src/routeTree.gen.ts
+++ b/src/routeTree.gen.ts
@@ -13,6 +13,7 @@ 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 DemoTanstackQueryRouteImport } from './routes/demo/tanstack-query'
const PlanesRoute = PlanesRouteImport.update({
@@ -35,6 +36,11 @@ const IndexRoute = IndexRouteImport.update({
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
+const PlanesIndexRoute = PlanesIndexRouteImport.update({
+ id: '/planes/',
+ path: '/planes/',
+ getParentRoute: () => rootRouteImport,
+} as any)
const DemoTanstackQueryRoute = DemoTanstackQueryRouteImport.update({
id: '/demo/tanstack-query',
path: '/demo/tanstack-query',
@@ -47,6 +53,7 @@ export interface FileRoutesByFullPath {
'/login': typeof LoginRoute
'/planes': typeof PlanesRoute
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
+ '/planes': typeof PlanesIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
@@ -54,6 +61,7 @@ export interface FileRoutesByTo {
'/login': typeof LoginRoute
'/planes': typeof PlanesRoute
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
+ '/planes': typeof PlanesIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
@@ -62,19 +70,31 @@ export interface FileRoutesById {
'/login': typeof LoginRoute
'/planes': typeof PlanesRoute
'/demo/tanstack-query': typeof DemoTanstackQueryRoute
+ '/planes/': typeof PlanesIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
+<<<<<<< HEAD
fullPaths: '/' | '/dashboard' | '/login' | '/planes' | '/demo/tanstack-query'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/dashboard' | '/login' | '/planes' | '/demo/tanstack-query'
+=======
+ fullPaths: '/' | '/dashboard' | '/login' | '/demo/tanstack-query' | '/planes'
+ fileRoutesByTo: FileRoutesByTo
+ to: '/' | '/dashboard' | '/login' | '/demo/tanstack-query' | '/planes'
+>>>>>>> origin/main
id:
| '__root__'
| '/'
| '/dashboard'
| '/login'
+<<<<<<< HEAD
| '/planes'
| '/demo/tanstack-query'
+=======
+ | '/demo/tanstack-query'
+ | '/planes/'
+>>>>>>> origin/main
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
@@ -83,6 +103,7 @@ export interface RootRouteChildren {
LoginRoute: typeof LoginRoute
PlanesRoute: typeof PlanesRoute
DemoTanstackQueryRoute: typeof DemoTanstackQueryRoute
+ PlanesIndexRoute: typeof PlanesIndexRoute
}
declare module '@tanstack/react-router' {
@@ -115,6 +136,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
+ '/planes/': {
+ id: '/planes/'
+ path: '/planes'
+ fullPath: '/planes'
+ preLoaderRoute: typeof PlanesIndexRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/demo/tanstack-query': {
id: '/demo/tanstack-query'
path: '/demo/tanstack-query'
@@ -131,6 +159,7 @@ const rootRouteChildren: RootRouteChildren = {
LoginRoute: LoginRoute,
PlanesRoute: PlanesRoute,
DemoTanstackQueryRoute: DemoTanstackQueryRoute,
+ PlanesIndexRoute: PlanesIndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
diff --git a/src/routes/planes/index.tsx b/src/routes/planes/index.tsx
new file mode 100644
index 0000000..096e925
--- /dev/null
+++ b/src/routes/planes/index.tsx
@@ -0,0 +1,15 @@
+import { createFileRoute } from '@tanstack/react-router'
+import { AppLayout } from '@/components/layout/AppLayout'
+import { PlanGrid } from '@/components/plans/PlanGrid'
+
+export const Route = createFileRoute('/planes/')({
+ component: PlanesPage,
+})
+
+function PlanesPage() {
+ return (
+
+
+
+ )
+}