story-generator/src/pages/dashboard/DashboardHome.tsx
Lucas Santana 021ef87203 style: padroniza layout das páginas de Classes e Professores
- Alinha o visual das páginas com o padrão do StudentsPage
- Ajusta espaçamentos, cores e tipografia
- Melhora a consistência dos componentes de lista
- Adiciona tratamento de erros uniforme
- Padroniza os estados de loading e empty
2024-12-20 10:49:03 -03:00

172 lines
5.4 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { Users, GraduationCap, BookOpen } from 'lucide-react';
import { supabase } from '../../lib/supabase';
import { StatsCard } from '../../components/dashboard/StatsCard';
interface DashboardStats {
totalClasses: number;
totalTeachers: number;
totalStudents: number;
recentClasses: any[];
recentStories: any[];
}
export function DashboardHome() {
const [stats, setStats] = useState<DashboardStats>({
totalClasses: 0,
totalTeachers: 0,
totalStudents: 0,
recentClasses: [],
recentStories: []
});
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchDashboardStats = async () => {
try {
const { data: { session } } = await supabase.auth.getSession();
if (!session?.user?.id) return;
const schoolId = session.user.id;
// Buscar total de turmas
const { count: classesCount } = await supabase
.from('classes')
.select('*', { count: 'exact', head: true })
.eq('school_id', schoolId);
// Buscar total de professores
const { count: teachersCount } = await supabase
.from('teacher_classes')
.select('teacher_id', { count: 'exact', head: true })
.eq('school_id', schoolId);
// Buscar total de alunos
const { count: studentsCount } = await supabase
.from('students')
.select('*', { count: 'exact', head: true })
.eq('school_id', schoolId);
// Buscar turmas recentes
const { data: recentClasses } = await supabase
.from('classes')
.select(`
*,
students:students(count)
`)
.eq('school_id', schoolId)
.order('created_at', { ascending: false })
.limit(5);
// Buscar histórias recentes
const { data: recentStories } = await supabase
.from('stories')
.select(`
*,
students:students(name)
`)
.eq('school_id', schoolId)
.order('created_at', { ascending: false })
.limit(5);
setStats({
totalClasses: classesCount || 0,
totalTeachers: teachersCount || 0,
totalStudents: studentsCount || 0,
recentClasses: recentClasses || [],
recentStories: recentStories || []
});
} catch (error) {
console.error('Erro ao buscar estatísticas:', error);
} finally {
setLoading(false);
}
};
fetchDashboardStats();
}, []);
return (
<div className="p-6">
<h1 className="text-2xl font-bold mb-8">Dashboard</h1>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3 mb-8">
<StatsCard
icon={Users}
title="Total de Turmas"
value={stats.totalClasses}
iconBgColor="bg-purple-100"
iconColor="text-purple-600"
/>
<StatsCard
icon={GraduationCap}
title="Total de Professores"
value={stats.totalTeachers}
iconBgColor="bg-blue-100"
iconColor="text-blue-600"
/>
<StatsCard
icon={BookOpen}
title="Total de Alunos"
value={stats.totalStudents}
iconBgColor="bg-green-100"
iconColor="text-green-600"
/>
</div>
<div className="grid gap-6 md:grid-cols-2">
<div className="bg-white rounded-2xl p-6">
<h2 className="text-xl font-semibold mb-4">Últimas Turmas</h2>
{loading ? (
<div className="animate-pulse space-y-4">
{[...Array(3)].map((_, i) => (
<div key={i} className="h-12 bg-gray-100 rounded-lg" />
))}
</div>
) : stats.recentClasses.length === 0 ? (
<p className="text-gray-500 text-center py-4">Nenhuma turma cadastrada</p>
) : (
<div className="space-y-4">
{stats.recentClasses.map((classItem) => (
<div key={classItem.id} className="flex justify-between items-center">
<div>
<h3 className="font-medium">{classItem.name}</h3>
<p className="text-sm text-gray-500">
{classItem.grade} {classItem.students.count} alunos
</p>
</div>
</div>
))}
</div>
)}
</div>
<div className="bg-white rounded-2xl p-6">
<h2 className="text-xl font-semibold mb-4">Histórias Recentes</h2>
{loading ? (
<div className="animate-pulse space-y-4">
{[...Array(3)].map((_, i) => (
<div key={i} className="h-12 bg-gray-100 rounded-lg" />
))}
</div>
) : stats.recentStories.length === 0 ? (
<p className="text-gray-500 text-center py-4">Nenhuma história registrada</p>
) : (
<div className="space-y-4">
{stats.recentStories.map((story) => (
<div key={story.id} className="flex justify-between items-center">
<div>
<h3 className="font-medium">{story.title}</h3>
<p className="text-sm text-gray-500">
por {story.students.name}
</p>
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
);
}