app-sidebar.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. "use client"
  2. import * as React from "react"
  3. import { useSession } from "next-auth/react"
  4. import {
  5. BookOpen,
  6. Calendar,
  7. GraduationCap,
  8. Home,
  9. Settings,
  10. Users,
  11. BarChart3,
  12. ClipboardList,
  13. UserCheck,
  14. UserPlus,
  15. School,
  16. Download,
  17. } from "lucide-react"
  18. import {
  19. Sidebar,
  20. SidebarContent,
  21. SidebarFooter,
  22. SidebarGroup,
  23. SidebarGroupContent,
  24. SidebarGroupLabel,
  25. SidebarHeader,
  26. SidebarMenu,
  27. SidebarMenuButton,
  28. SidebarMenuItem,
  29. SidebarRail,
  30. } from "@/components/ui/sidebar"
  31. import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
  32. import { Button } from "@/components/ui/button"
  33. import { signOut } from "next-auth/react"
  34. import Link from "next/link"
  35. import { ModeToggle } from "@/components/mode-toggle"
  36. // Menú para Administrador - Agrupado por secciones
  37. const adminMenuSections = [
  38. {
  39. label: "Principal",
  40. items: [
  41. {
  42. title: "Dashboard",
  43. url: "/admin/dashboard",
  44. icon: Home,
  45. },
  46. ],
  47. },
  48. {
  49. label: "Gestión de Usuarios",
  50. items: [
  51. {
  52. title: "Profesores",
  53. url: "/admin/teachers",
  54. icon: Users,
  55. },
  56. {
  57. title: "Estudiantes",
  58. url: "/admin/students",
  59. icon: GraduationCap,
  60. },
  61. ],
  62. },
  63. {
  64. label: "Gestión Académica",
  65. items: [
  66. {
  67. title: "Períodos Académicos",
  68. url: "/admin/periods",
  69. icon: Calendar,
  70. },
  71. {
  72. title: "Clases",
  73. url: "/admin/classes",
  74. icon: BookOpen,
  75. },
  76. {
  77. title: "Secciones",
  78. url: "/admin/sections",
  79. icon: School,
  80. },
  81. ],
  82. },
  83. {
  84. label: "Asignaciones e Inscripciones",
  85. items: [
  86. {
  87. title: "Asignaciones de Profesores",
  88. url: "/admin/teacher-assignments",
  89. icon: UserCheck,
  90. },
  91. {
  92. title: "Inscripciones de Estudiantes",
  93. url: "/admin/student-enrollments",
  94. icon: UserPlus,
  95. },
  96. {
  97. title: "Historial de Inscripciones",
  98. url: "/admin/enrollment-history",
  99. icon: BarChart3,
  100. },
  101. ],
  102. },
  103. {
  104. label: "Configuración",
  105. items: [
  106. {
  107. title: "Parciales",
  108. url: "/admin/partials",
  109. icon: Settings,
  110. },
  111. ],
  112. },
  113. ]
  114. // Menú para Profesor - Agrupado por secciones
  115. const teacherMenuSections = [
  116. {
  117. label: "Principal",
  118. items: [
  119. {
  120. title: "Dashboard",
  121. url: "/teacher",
  122. icon: Home,
  123. },
  124. {
  125. title: "Estudiantes",
  126. url: "/teacher/students",
  127. icon: GraduationCap,
  128. },
  129. ],
  130. },
  131. {
  132. label: "Gestión de Asistencia",
  133. items: [
  134. {
  135. title: "Tomar Asistencia",
  136. url: "/teacher/attendance",
  137. icon: UserCheck,
  138. },
  139. {
  140. title: "Historial de Asistencia",
  141. url: "/teacher/attendance-history",
  142. icon: ClipboardList,
  143. },
  144. // {
  145. // title: "Asistencia por Estudiante",
  146. // url: "/teacher/student-attendance",
  147. // icon: Users,
  148. // },
  149. ],
  150. },
  151. {
  152. label: "Reportes",
  153. items: [
  154. {
  155. title: "Exportar Reportes",
  156. url: "/teacher/export-reports",
  157. icon: Download,
  158. },
  159. ],
  160. },
  161. ]
  162. // Menú para Estudiante - Agrupado por secciones
  163. const studentMenuSections = [
  164. {
  165. label: "Principal",
  166. items: [
  167. {
  168. title: "Dashboard",
  169. url: "/student/dashboard",
  170. icon: Home,
  171. },
  172. ],
  173. },
  174. {
  175. label: "Académico",
  176. items: [
  177. {
  178. title: "Mis Clases",
  179. url: "/student/classes",
  180. icon: BookOpen,
  181. },
  182. {
  183. title: "Horarios",
  184. url: "/student/schedule",
  185. icon: Calendar,
  186. },
  187. ],
  188. },
  189. {
  190. label: "Asistencia",
  191. items: [
  192. {
  193. title: "Mi Asistencia",
  194. url: "/student/attendance",
  195. icon: ClipboardList,
  196. },
  197. ],
  198. },
  199. ]
  200. export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
  201. const { data: session, status } = useSession()
  202. if (status === "loading") {
  203. return null
  204. }
  205. if (!session?.user) {
  206. return null
  207. }
  208. const isAdmin = session.user.role === "admin"
  209. const isTeacher = session.user.role === "teacher"
  210. const isStudent = session.user.role === "student"
  211. const menuSections = isAdmin ? adminMenuSections : isTeacher ? teacherMenuSections : studentMenuSections
  212. const userInitials = session.user.firstName?.[0] + (session.user.lastName?.[0] || "")
  213. return (
  214. <Sidebar collapsible="icon" {...props}>
  215. <SidebarHeader>
  216. <SidebarMenu>
  217. <SidebarMenuItem>
  218. <SidebarMenuButton size="lg" asChild>
  219. <Link href={isAdmin ? "/admin/dashboard" : isTeacher ? "/teacher/dashboard" : "/student/dashboard"}>
  220. <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
  221. <School className="size-4" />
  222. </div>
  223. <div className="grid flex-1 text-left text-sm leading-tight">
  224. <span className="truncate font-semibold">Sistema de Asistencia</span>
  225. <span className="truncate text-xs">
  226. {isAdmin ? "Administrador" : isTeacher ? "Profesor" : "Estudiante"}
  227. </span>
  228. </div>
  229. </Link>
  230. </SidebarMenuButton>
  231. </SidebarMenuItem>
  232. </SidebarMenu>
  233. </SidebarHeader>
  234. <SidebarContent>
  235. {menuSections.map((section) => (
  236. <SidebarGroup key={section.label}>
  237. <SidebarGroupLabel>{section.label}</SidebarGroupLabel>
  238. <SidebarGroupContent>
  239. <SidebarMenu>
  240. {section.items.map((item) => (
  241. <SidebarMenuItem key={item.title}>
  242. <SidebarMenuButton asChild>
  243. <Link href={item.url}>
  244. <item.icon />
  245. <span>{item.title}</span>
  246. </Link>
  247. </SidebarMenuButton>
  248. </SidebarMenuItem>
  249. ))}
  250. </SidebarMenu>
  251. </SidebarGroupContent>
  252. </SidebarGroup>
  253. ))}
  254. </SidebarContent>
  255. <SidebarFooter>
  256. <SidebarMenuItem>
  257. <div className="flex items-center gap-2 px-2 py-1.5">
  258. <ModeToggle />
  259. </div>
  260. </SidebarMenuItem>
  261. <SidebarMenu>
  262. <SidebarMenuItem>
  263. <div className="flex items-center gap-2 px-2 py-1.5">
  264. <div className="grid flex-1 text-left text-sm leading-tight">
  265. <span className="truncate font-semibold">
  266. {session.user.firstName} {session.user.lastName}
  267. </span>
  268. <span className="truncate text-xs text-muted-foreground">
  269. {session.user.email}
  270. </span>
  271. </div>
  272. </div>
  273. </SidebarMenuItem>
  274. <SidebarMenuItem>
  275. <Button
  276. variant="ghost"
  277. size="sm"
  278. className="w-full justify-start"
  279. onClick={() => signOut({ callbackUrl: "/" })}
  280. >
  281. Cerrar Sesión
  282. </Button>
  283. </SidebarMenuItem>
  284. </SidebarMenu>
  285. </SidebarFooter>
  286. <SidebarRail />
  287. </Sidebar>
  288. )
  289. }