|
|
@@ -1,14 +1,54 @@
|
|
|
+'use client'
|
|
|
+
|
|
|
import { MainLayout } from '@/components/layout/main-layout'
|
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
|
-import { Users, BookOpen, GraduationCap, User, TrendingUp, Calendar, UserCheck, Clock } from 'lucide-react'
|
|
|
+import { Button } from '@/components/ui/button'
|
|
|
+import { Users, BookOpen, GraduationCap, User, TrendingUp, Calendar, UserCheck, Clock, ChevronDown, ChevronUp } from 'lucide-react'
|
|
|
import { getDashboardStats, getRecentActivities, getCurrentPeriod } from './actions'
|
|
|
+import { useState, useEffect } from 'react'
|
|
|
+
|
|
|
+export default function AdminDashboard() {
|
|
|
+ const [stats, setStats] = useState<any>(null)
|
|
|
+ const [recentActivities, setRecentActivities] = useState<any[]>([])
|
|
|
+ const [currentPeriod, setCurrentPeriod] = useState<any>(null)
|
|
|
+ const [showAllActivities, setShowAllActivities] = useState(false)
|
|
|
+ const [loading, setLoading] = useState(true)
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ const loadData = async () => {
|
|
|
+ try {
|
|
|
+ const [statsData, activitiesData, periodData] = await Promise.all([
|
|
|
+ getDashboardStats(),
|
|
|
+ getRecentActivities(),
|
|
|
+ getCurrentPeriod()
|
|
|
+ ])
|
|
|
+ setStats(statsData)
|
|
|
+ setRecentActivities(activitiesData)
|
|
|
+ setCurrentPeriod(periodData)
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error loading dashboard data:', error)
|
|
|
+ } finally {
|
|
|
+ setLoading(false)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ loadData()
|
|
|
+ }, [])
|
|
|
|
|
|
-export default async function AdminDashboard() {
|
|
|
- const [stats, recentActivities, currentPeriod] = await Promise.all([
|
|
|
- getDashboardStats(),
|
|
|
- getRecentActivities(),
|
|
|
- getCurrentPeriod()
|
|
|
- ])
|
|
|
+ if (loading || !stats) {
|
|
|
+ return (
|
|
|
+ <MainLayout
|
|
|
+ title="Dashboard Administrativo"
|
|
|
+ subtitle="Resumen general del sistema"
|
|
|
+ requiredRole="ADMIN"
|
|
|
+ >
|
|
|
+ <div className="flex items-center justify-center h-64">
|
|
|
+ <div className="text-lg">Cargando dashboard...</div>
|
|
|
+ </div>
|
|
|
+ </MainLayout>
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ const displayedActivities = showAllActivities ? recentActivities : recentActivities.slice(0, 5)
|
|
|
|
|
|
const statsCards = [
|
|
|
{
|
|
|
@@ -91,30 +131,54 @@ export default async function AdminDashboard() {
|
|
|
<CardContent>
|
|
|
<div className="space-y-4">
|
|
|
{recentActivities.length > 0 ? (
|
|
|
- recentActivities.map((activity) => {
|
|
|
- const getActivityColor = (type: string) => {
|
|
|
- switch (type) {
|
|
|
- case 'user': return 'bg-blue-600'
|
|
|
- case 'enrollment': return 'bg-green-600'
|
|
|
- case 'assignment': return 'bg-purple-600'
|
|
|
- default: return 'bg-gray-600'
|
|
|
+ <>
|
|
|
+ {displayedActivities.map((activity) => {
|
|
|
+ const getActivityColor = (type: string) => {
|
|
|
+ switch (type) {
|
|
|
+ case 'user': return 'bg-blue-600'
|
|
|
+ case 'enrollment': return 'bg-green-600'
|
|
|
+ case 'assignment': return 'bg-purple-600'
|
|
|
+ default: return 'bg-gray-600'
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- return (
|
|
|
- <div key={activity.id} className="flex items-center space-x-4">
|
|
|
- <div className={`w-2 h-2 rounded-full ${getActivityColor(activity.type)}`}></div>
|
|
|
- <div className="flex-1 space-y-1">
|
|
|
- <p className="text-sm font-medium leading-none">
|
|
|
- {activity.action}
|
|
|
- </p>
|
|
|
- <p className="text-sm text-muted-foreground">
|
|
|
- {activity.user} • {activity.time}
|
|
|
- </p>
|
|
|
+ return (
|
|
|
+ <div key={activity.id} className="flex items-center space-x-4">
|
|
|
+ <div className={`w-2 h-2 rounded-full ${getActivityColor(activity.type)}`}></div>
|
|
|
+ <div className="flex-1 space-y-1">
|
|
|
+ <p className="text-sm font-medium leading-none">
|
|
|
+ {activity.action}
|
|
|
+ </p>
|
|
|
+ <p className="text-sm text-muted-foreground">
|
|
|
+ {activity.user} • {activity.time}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ {recentActivities.length > 5 && (
|
|
|
+ <div className="pt-2 border-t">
|
|
|
+ <Button
|
|
|
+ variant="ghost"
|
|
|
+ size="sm"
|
|
|
+ onClick={() => setShowAllActivities(!showAllActivities)}
|
|
|
+ className="w-full flex items-center gap-2"
|
|
|
+ >
|
|
|
+ {showAllActivities ? (
|
|
|
+ <>
|
|
|
+ <ChevronUp className="h-4 w-4" />
|
|
|
+ Ver menos
|
|
|
+ </>
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <ChevronDown className="h-4 w-4" />
|
|
|
+ Ver más ({recentActivities.length - 5} actividades más)
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </Button>
|
|
|
</div>
|
|
|
- )
|
|
|
- })
|
|
|
+ )}
|
|
|
+ </>
|
|
|
) : (
|
|
|
<div className="text-center py-4">
|
|
|
<Clock className="h-8 w-8 mx-auto text-muted-foreground mb-2" />
|
|
|
@@ -128,7 +192,7 @@ export default async function AdminDashboard() {
|
|
|
</Card>
|
|
|
|
|
|
{/* Resumen del Periodo */}
|
|
|
- <Card>
|
|
|
+ {/* <Card>
|
|
|
<CardHeader>
|
|
|
<CardTitle className="flex items-center gap-2">
|
|
|
<Calendar className="h-5 w-5" />
|
|
|
@@ -177,7 +241,7 @@ export default async function AdminDashboard() {
|
|
|
</div>
|
|
|
)}
|
|
|
</CardContent>
|
|
|
- </Card>
|
|
|
+ </Card> */}
|
|
|
</div>
|
|
|
|
|
|
{/* Estadísticas adicionales */}
|