From e9e72677a4d0615a55a4efd3970b634e992a194f Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Fri, 20 Dec 2024 10:49:03 -0300 Subject: [PATCH] =?UTF-8?q?style:=20padroniza=20layout=20das=20p=C3=A1gina?= =?UTF-8?q?s=20de=20Classes=20e=20Professores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- src/components/dashboard/StatsCard.tsx | 24 ++++ src/pages/dashboard/DashboardHome.tsx | 51 ++++---- src/pages/dashboard/classes/ClassesPage.tsx | 80 ++++++------ src/pages/dashboard/teachers/TeachersPage.tsx | 120 ++++-------------- 4 files changed, 111 insertions(+), 164 deletions(-) create mode 100644 src/components/dashboard/StatsCard.tsx diff --git a/src/components/dashboard/StatsCard.tsx b/src/components/dashboard/StatsCard.tsx new file mode 100644 index 0000000..46d960b --- /dev/null +++ b/src/components/dashboard/StatsCard.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { LucideIcon } from 'lucide-react'; + +interface StatsCardProps { + icon: LucideIcon; + title: string; + value: number; + iconBgColor: string; + iconColor: string; +} + +export function StatsCard({ icon: Icon, title, value, iconBgColor, iconColor }: StatsCardProps) { + return ( +
+
+ +
+
+

{title}

+

{value}

+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/dashboard/DashboardHome.tsx b/src/pages/dashboard/DashboardHome.tsx index 19f031c..52c74f1 100644 --- a/src/pages/dashboard/DashboardHome.tsx +++ b/src/pages/dashboard/DashboardHome.tsx @@ -1,6 +1,7 @@ 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; @@ -90,35 +91,27 @@ export function DashboardHome() {

Dashboard

-
-
- -
-
-

Total de Turmas

-

{stats.totalClasses}

-
-
- -
-
- -
-
-

Total de Professores

-

{stats.totalTeachers}

-
-
- -
-
- -
-
-

Total de Alunos

-

{stats.totalStudents}

-
-
+ + +
diff --git a/src/pages/dashboard/classes/ClassesPage.tsx b/src/pages/dashboard/classes/ClassesPage.tsx index 9d6e127..f5a32b1 100644 --- a/src/pages/dashboard/classes/ClassesPage.tsx +++ b/src/pages/dashboard/classes/ClassesPage.tsx @@ -10,6 +10,7 @@ export function ClassesPage() { const [classes, setClasses] = React.useState([]); const [searchTerm, setSearchTerm] = React.useState(''); const [loading, setLoading] = React.useState(true); + const [error, setError] = React.useState(null); React.useEffect(() => { const fetchClasses = async () => { @@ -30,6 +31,7 @@ export function ClassesPage() { setClasses(data || []); } catch (err) { console.error('Erro ao buscar turmas:', err); + setError('Erro ao buscar turmas'); } finally { setLoading(false); } @@ -44,66 +46,70 @@ export function ClassesPage() { ); return ( -
-
-

Turmas

+
+
+

Turmas

-
-
- - setSearchTerm(e.target.value)} - className="w-full pl-12 pr-4 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:ring-purple-500 focus:border-purple-500" - /> + {error && ( +
+ {error} +
+ )} + +
+
+
+ + setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-purple-500 focus:border-purple-500" + /> +
{loading ? ( -
-
-
+
Carregando...
) : filteredClasses.length === 0 ? ( -
+
{searchTerm ? 'Nenhuma turma encontrada' : 'Nenhuma turma cadastrada'}
) : ( -
+
{filteredClasses.map((classItem) => (
navigate(`/dashboard/turmas/${classItem.id}`)} > -
-
- -
+

{classItem.name}

-

+

+ {classItem.grade} • {(classItem as any).students?.count || 0} alunos -

+
+
+
+ + Ativo + +
-
- -
- - Ativo - -
))} diff --git a/src/pages/dashboard/teachers/TeachersPage.tsx b/src/pages/dashboard/teachers/TeachersPage.tsx index 66bb819..75777fa 100644 --- a/src/pages/dashboard/teachers/TeachersPage.tsx +++ b/src/pages/dashboard/teachers/TeachersPage.tsx @@ -1,107 +1,42 @@ import React from 'react'; -import { Plus, Search, MoreVertical, Mail } from 'lucide-react'; +import { Plus, Search, MoreVertical, GraduationCap, Mail } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; -import { useDatabase } from '../../../hooks/useDatabase'; import { supabase } from '../../../lib/supabase'; - -interface Teacher { - id: string; - name: string; - email: string; - subject?: string; - class_count: number; - status: 'active' | 'pending' | 'inactive'; -} +import type { Teacher } from '../../../types/database'; export function TeachersPage() { const navigate = useNavigate(); - const { loading, error } = useDatabase(); const [teachers, setTeachers] = React.useState([]); const [searchTerm, setSearchTerm] = React.useState(''); + const [loading, setLoading] = React.useState(true); + const [error, setError] = React.useState(null); React.useEffect(() => { const fetchTeachers = async () => { try { - const { data: authData } = await supabase.auth.getSession(); - if (!authData.session?.user) return; + const { data: { session } } = await supabase.auth.getSession(); + if (!session?.user?.id) return; - const { data: schoolData, error: schoolError } = await supabase - .from('schools') - .select('id') - .eq('id', authData.session.user.id) - .single(); - - if (schoolError) throw schoolError; - - const { data: teachersData, error: teachersError } = await supabase + const { data, error } = await supabase .from('teachers') - .select(` - id, - name, - email, - subject, - status - `) - .eq('school_id', schoolData.id); + .select('*') + .eq('school_id', session.user.id); - if (teachersError) throw teachersError; - - // Buscar contagem de turmas para cada professor - const teachersWithCounts = await Promise.all( - teachersData.map(async (teacher) => { - const { data: countData } = await supabase - .rpc('get_teacher_class_count', { teacher_id: teacher.id }); - - return { - ...teacher, - class_count: countData || 0 - }; - }) - ); - - setTeachers(teachersWithCounts); + if (error) throw error; + setTeachers(data || []); } catch (err) { console.error('Erro ao buscar professores:', err); + setError('Erro ao buscar professores'); + } finally { + setLoading(false); } }; fetchTeachers(); }, []); - const handleInviteTeacher = () => { - navigate('/dashboard/professores/convidar'); - }; - - const handleTeacherClick = (teacherId: string) => { - navigate(`/dashboard/professores/${teacherId}`); - }; - - const getStatusColor = (status: Teacher['status']) => { - switch (status) { - case 'active': - return 'bg-green-100 text-green-800'; - case 'pending': - return 'bg-yellow-100 text-yellow-800'; - case 'inactive': - return 'bg-gray-100 text-gray-800'; - } - }; - - const getStatusText = (status: Teacher['status']) => { - switch (status) { - case 'active': - return 'Ativo'; - case 'pending': - return 'Pendente'; - case 'inactive': - return 'Inativo'; - } - }; - - const filteredTeachers = teachers.filter(t => - t.name.toLowerCase().includes(searchTerm.toLowerCase()) || - t.email.toLowerCase().includes(searchTerm.toLowerCase()) || - (t.subject && t.subject.toLowerCase().includes(searchTerm.toLowerCase())) + const filteredTeachers = teachers.filter(teacher => + teacher.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( @@ -109,7 +44,7 @@ export function TeachersPage() {

Professores

- {teacher.subject && ( -

- {teacher.subject} -

- )}
))}