Se agrega vista principaldel detalle del plan

This commit is contained in:
Robert
2025-12-24 15:12:27 -06:00
parent b303398cd4
commit c9ab32598a
10 changed files with 225 additions and 3 deletions

View File

@@ -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 (
<div className="min-h-screen flex bg-gray-100">
{/* <Sidebar /> */}
<div className="flex-1 flex flex-col">
<Header />
{/* Separación Header → Stats */}
<section className="mt-4 bg-white border-b">
<div className="px-6 py-6">
<StatsGrid />
</div>
</section>
<main className="flex-1 p-6">
{children}
</main>
</div>
</div>
)
}

View File

@@ -0,0 +1,18 @@
export function Header() {
return (
<div className="flex items-center gap-4 bg-white border-b shadow-[0_1px_2px_rgba(0,0,0,0.05)] z-10 relative">
<div className="h-12 w-12 rounded-full bg-emerald-600 flex items-center justify-center text-white">
🎓
</div>
<div>
<h1 className="text-xl font-semibold text-gray-900">
Gestión Curricular
</h1>
<p className="text-sm text-gray-500">
Sistema de Planes de Estudio
</p>
</div>
</div>
)
}

View File

@@ -0,0 +1,32 @@
import { LayoutGrid, BookOpen } from 'lucide-react'
export function Sidebar() {
return (
<aside className="w-64 bg-white border-r px-4 py-6">
<h2 className="text-lg font-semibold mb-6">
Planes de Estudio
</h2>
<nav className="space-y-2">
<NavItem icon={LayoutGrid} label="Dashboard" active />
<NavItem icon={BookOpen} label="Planes" />
</nav>
</aside>
)
}
function NavItem({ icon: Icon, label, active }: any) {
return (
<div
className={`flex items-center gap-3 px-3 py-2 rounded-lg cursor-pointer
${
active
? 'bg-gray-100 text-gray-900'
: 'text-gray-500 hover:bg-gray-50'
}`}
>
<Icon size={18} />
<span className="text-sm font-medium">{label}</span>
</div>
)
}

View File

@@ -0,0 +1,26 @@
import { StatusBadge } from "./StatusBadge";
export function PlanCard({ plan }: any) {
return (
<div className="bg-[#eaf6fa] rounded-2xl p-6 border hover:shadow-md transition">
<div className="flex justify-between items-start mb-4">
<span className="text-sm text-gray-500"> Ingeniería</span>
<StatusBadge status={plan.status} />
</div>
<h3 className="text-lg font-semibold text-gray-900">
{plan.title}
</h3>
<p className="text-sm text-gray-600 mb-6">
{plan.subtitle}
</p>
<div className="flex justify-between text-sm text-gray-500">
<span>{plan.cycles} ciclos</span>
<span>{plan.credits} créditos</span>
<span></span>
</div>
</div>
)
}

View File

@@ -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 (
<div>
<h2 className="text-lg font-semibold mb-4">
Planes disponibles
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{mockPlans.map(plan => (
<PlanCard key={plan.id} plan={plan} />
))}
</div>
</div>
)
}

View File

@@ -0,0 +1,11 @@
export function StatCard({ icon, value, label }: any) {
return (
<div className="bg-white rounded-xl border p-6">
<div className="flex items-center gap-3 mb-2">
<span className="text-xl">{icon}</span>
<span className="text-2xl font-semibold">{value}</span>
</div>
<p className="text-sm text-gray-500">{label}</p>
</div>
)
}

View File

@@ -0,0 +1,12 @@
import { StatCard } from "./StatCard";
export function StatsGrid() {
return (
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<StatCard icon="📘" value="12" label="Planes Activos" />
<StatCard icon="🕒" value="4" label="En Revisión" />
<StatCard icon="✅" value="8" label="Aprobados" />
<StatCard icon="👥" value="6" label="Carreras" />
</div>
)
}

View File

@@ -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 (
<span
className={`text-xs px-3 py-1 rounded-full font-medium ${styles[status]}`}
>
{status === 'revision'
? 'En Revisión'
: status === 'aprobado'
? 'Aprobado'
: 'Borrador'}
</span>
)
}