diff --git a/src/components/header/Header.tsx b/src/components/header/Header.tsx new file mode 100644 index 0000000..d743452 --- /dev/null +++ b/src/components/header/Header.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { useAuth } from '../../hooks/useAuth'; +import { ProfileMenu } from './ProfileMenu'; + +export function Header() { + const { user } = useAuth(); + + return ( + + + + + + Histórias Mágicas + + + + {user ? ( + + ) : ( + <> + + Entrar + + + Cadastrar Escola + + > + )} + + + + + ); +} \ No newline at end of file diff --git a/src/components/header/ProfileMenu.tsx b/src/components/header/ProfileMenu.tsx new file mode 100644 index 0000000..f607717 --- /dev/null +++ b/src/components/header/ProfileMenu.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { LogOut, Settings, LayoutDashboard } from 'lucide-react'; +import { useAuth } from '../../hooks/useAuth'; + +export function ProfileMenu() { + const { user, userRole, signOut } = useAuth(); + const navigate = useNavigate(); + const [isOpen, setIsOpen] = React.useState(false); + const menuRef = React.useRef(null); + + // Fecha o menu quando clicar fora dele + React.useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (menuRef.current && !menuRef.current.contains(event.target as Node)) { + setIsOpen(false); + } + } + + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, []); + + const getDashboardPath = () => { + switch (userRole) { + case 'school': + return '/dashboard'; + case 'teacher': + return '/professor'; + case 'student': + return '/aluno'; + default: + return '/'; + } + }; + + const getProfilePath = () => { + switch (userRole) { + case 'school': + return '/dashboard/configuracoes'; + case 'teacher': + return '/professor/perfil'; + case 'student': + return '/aluno/perfil'; + default: + return '/'; + } + }; + + return ( + + setIsOpen(!isOpen)} + className="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center hover:bg-purple-200 transition" + > + + {user?.user_metadata?.name?.[0]?.toUpperCase() || user?.email?.[0]?.toUpperCase()} + + + + {isOpen && ( + + { + navigate(getDashboardPath()); + setIsOpen(false); + }} + className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2" + > + + Acessar Dashboard + + + { + navigate(getProfilePath()); + setIsOpen(false); + }} + className="w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 flex items-center gap-2" + > + + Meu Perfil + + + + + + + Sair + + + )} + + ); +} \ No newline at end of file diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index 0ea4382..958f066 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -5,6 +5,9 @@ import { supabase } from '../lib/supabase'; interface AuthContextType { user: any; loading: boolean; + error: string | null; + signIn: (email: string, password: string) => Promise; + signUp: (email: string, password: string) => Promise; signOut: () => Promise; userRole: string | null; } diff --git a/src/pages/admin/UserManagementPage.tsx b/src/pages/admin/UserManagementPage.tsx index 1ffeb63..a0f70fd 100644 --- a/src/pages/admin/UserManagementPage.tsx +++ b/src/pages/admin/UserManagementPage.tsx @@ -23,7 +23,7 @@ export function UserManagementPage() { try { const { data: { users }, error } = await supabase.auth.admin.listUsers(); if (error) throw error; - setUsers(users || []); + setUsers(users?.filter(user => user.email) || []); } catch (err) { console.error('Erro ao buscar usuários:', err); setError('Não foi possível carregar os usuários'); diff --git a/src/pages/student-dashboard/StoryPage.tsx b/src/pages/student-dashboard/StoryPage.tsx index 2962cfc..0cb165a 100644 --- a/src/pages/student-dashboard/StoryPage.tsx +++ b/src/pages/student-dashboard/StoryPage.tsx @@ -129,6 +129,8 @@ export function StoryPage() { { console.log('Áudio gravado:', audioUrl); }} diff --git a/src/pages/student-dashboard/StudentDashboardPage.tsx b/src/pages/student-dashboard/StudentDashboardPage.tsx index be89c8a..0e5b604 100644 --- a/src/pages/student-dashboard/StudentDashboardPage.tsx +++ b/src/pages/student-dashboard/StudentDashboardPage.tsx @@ -117,8 +117,8 @@ export function StudentDashboardPage() { {student?.avatar_url ? ( ) : ( @@ -128,8 +128,8 @@ export function StudentDashboardPage() { {student?.name} - - {(student?.class as any)?.grade} • {(student?.class as any)?.name} • {(student?.school as any)?.name} + + {student?.class?.name} - {student?.class?.grade} • {student?.school?.name} diff --git a/src/types/database.ts b/src/types/database.ts index e304dc0..070c42e 100644 --- a/src/types/database.ts +++ b/src/types/database.ts @@ -33,6 +33,7 @@ export interface Class { export interface Student { id: string; class_id: string; + school_id: string; name: string; email: string; birth_date?: string; @@ -41,6 +42,18 @@ export interface Student { guardian_email?: string; created_at: string; updated_at: string; + status?: string; + avatar_url?: string; + // Relacionamentos + class?: { + id: string; + name: string; + grade: string; + }; + school?: { + id: string; + name: string; + }; } export interface TeacherClass {
- {(student?.class as any)?.grade} • {(student?.class as any)?.name} • {(student?.school as any)?.name} +
+ {student?.class?.name} - {student?.class?.grade} • {student?.school?.name}