diff --git a/app/Aluno/AlunoHome.tsx b/app/Aluno/AlunoHome.tsx index 296fbd3..eaac02b 100644 --- a/app/Aluno/AlunoHome.tsx +++ b/app/Aluno/AlunoHome.tsx @@ -174,11 +174,11 @@ const AlunoHome = memo(() => { - router.push('/perfil')}> + router.push('/Aluno/perfil')}> Estágios+ - router.push('/definicoes')}> + router.push('/Aluno/definicoes')}> diff --git a/app/Professor/Alunos/Faltas.tsx b/app/Professor/Alunos/Faltas.tsx index 1d964ad..8553f45 100644 --- a/app/Professor/Alunos/Faltas.tsx +++ b/app/Professor/Alunos/Faltas.tsx @@ -2,22 +2,21 @@ import { Ionicons } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; import { useState } from 'react'; import { - Modal, - Platform, - SafeAreaView, - ScrollView, - StatusBar, - StyleSheet, - Text, - TouchableOpacity, - View, + Modal, + Platform, + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + TouchableOpacity, + View, } from 'react-native'; import { WebView } from 'react-native-webview'; -import { useTheme } from '../../../themecontext'; // <- seu contexto de tema +import { useTheme } from '../../../themecontext'; interface Falta { dia: string; - motivo?: string; pdfUrl?: string; } @@ -33,16 +32,22 @@ const alunosData: Aluno[] = [ id: 1, nome: 'João Silva', faltas: [ - { dia: '2026-01-20', motivo: 'Doença', pdfUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf' }, - { dia: '2026-01-22', motivo: 'Atraso' }, + { + dia: '2026-01-20', + pdfUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + }, + { dia: '2026-01-22' }, ], }, { id: 2, nome: 'Maria Fernandes', faltas: [ - { dia: '2026-01-21', motivo: 'Consulta médica' }, - { dia: '2026-01-23', motivo: 'Doença', pdfUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf' }, + { dia: '2026-01-21' }, + { + dia: '2026-01-23', + pdfUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + }, ], }, ]; @@ -82,18 +87,22 @@ export default function FaltasAlunos() { {/* Top Bar */} - { - if (alunoSelecionado) { - setAlunoSelecionado(null); // voltar para lista de alunos - } else { - router.back(); // voltar para menu - } - }}> + { + if (alunoSelecionado) { + setAlunoSelecionado(null); + } else { + router.back(); + } + }} + > + {!alunoSelecionado ? 'Faltas dos Alunos' : alunoSelecionado.nome} + @@ -107,8 +116,14 @@ export default function FaltasAlunos() { onPress={() => setAlunoSelecionado(aluno)} > - {aluno.nome} - + + {aluno.nome} + + ))} @@ -118,17 +133,38 @@ export default function FaltasAlunos() { {alunoSelecionado && ( {alunoSelecionado.faltas.map((falta, idx) => ( - + - {falta.dia} - {falta.motivo || 'Sem motivo'} - - {falta.pdfUrl ? 'Justificada com PDF' : 'Não justificada'} + + {falta.dia} + + + + {falta.pdfUrl + ? 'Falta justificada' + : 'Falta não justificada'} + {falta.pdfUrl && ( verPdf(falta)}> - + )} @@ -140,13 +176,21 @@ export default function FaltasAlunos() { {/* Modal PDF */} - + setPdfModalVisible(false)}> - Visualizador de PDF + + Visualizador de PDF + + {pdfUrl && } @@ -155,10 +199,23 @@ export default function FaltasAlunos() { } const styles = StyleSheet.create({ - safe: { flex: 1, paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }, + safe: { + flex: 1, + paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0, + }, container: { padding: 20, paddingBottom: 40 }, - topBar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }, - topTitle: { fontSize: 20, fontWeight: '700', textAlign: 'center', flex: 1 }, + topBar: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: 16, + }, + topTitle: { + fontSize: 20, + fontWeight: '700', + textAlign: 'center', + flex: 1, + }, alunoCard: { flexDirection: 'row', alignItems: 'center', @@ -171,7 +228,12 @@ const styles = StyleSheet.create({ shadowRadius: 4, elevation: 2, }, - alunoName: { fontSize: 16, fontWeight: '600', marginLeft: 12, flex: 1 }, + alunoName: { + fontSize: 16, + fontWeight: '600', + marginLeft: 12, + flex: 1, + }, faltaCard: { flexDirection: 'row', alignItems: 'center', @@ -185,9 +247,15 @@ const styles = StyleSheet.create({ shadowRadius: 4, elevation: 2, }, - dia: { fontSize: 14, fontWeight: '700', marginBottom: 4 }, - motivo: { fontSize: 14, marginBottom: 4 }, - status: { fontSize: 13, fontWeight: '600' }, + dia: { + fontSize: 14, + fontWeight: '700', + marginBottom: 6, + }, + status: { + fontSize: 13, + fontWeight: '600', + }, pdfHeader: { flexDirection: 'row', alignItems: 'center', @@ -195,5 +263,8 @@ const styles = StyleSheet.create({ padding: 16, borderBottomWidth: 1, }, - pdfTitle: { fontSize: 18, fontWeight: '700' }, + pdfTitle: { + fontSize: 18, + fontWeight: '700', + }, }); diff --git a/app/Professor/Empresas/DetalhesEmpresa.tsx b/app/Professor/Empresas/DetalhesEmpresa.tsx index 1a129bb..e2ffd1f 100644 --- a/app/Professor/Empresas/DetalhesEmpresa.tsx +++ b/app/Professor/Empresas/DetalhesEmpresa.tsx @@ -2,6 +2,7 @@ import { Ionicons } from '@expo/vector-icons'; import { useLocalSearchParams, useRouter } from 'expo-router'; import { memo, useMemo, useState } from 'react'; import { + ActivityIndicator, Alert, Platform, SafeAreaView, @@ -14,22 +15,38 @@ import { View } from 'react-native'; import { useTheme } from '../../../themecontext'; -import type { Empresa } from './ListaEmpresas'; +import { supabase } from '../../lib/supabase'; + +// Interface atualizada para incluir a lista de alunos +export interface Empresa { + id: number; + nome: string; + morada: string; + tutor_nome: string; + tutor_telefone: string; + curso: string; + alunos?: string[]; // Array com nomes dos alunos +} const DetalhesEmpresa = memo(() => { const { isDarkMode } = useTheme(); const router = useRouter(); const params = useLocalSearchParams(); - // Parse da empresa recebida + // Parse seguro dos dados vindos da navegação const empresaOriginal: Empresa = useMemo(() => { - if (!params.empresa) return null as any; + if (!params.empresa) return {} as Empresa; const str = Array.isArray(params.empresa) ? params.empresa[0] : params.empresa; - return JSON.parse(str); + try { + return JSON.parse(str); + } catch { + return {} as Empresa; + } }, [params.empresa]); const [empresaLocal, setEmpresaLocal] = useState({ ...empresaOriginal }); const [editando, setEditando] = useState(false); + const [loading, setLoading] = useState(false); const cores = { fundo: isDarkMode ? '#121212' : '#f1f3f5', @@ -41,115 +58,150 @@ const DetalhesEmpresa = memo(() => { vermelho: '#dc3545', }; - const handleSave = () => { - setEditando(false); - Alert.alert('Sucesso', 'Empresa atualizada!'); - // Aqui depois substituis por update no Supabase + const handleSave = async () => { + try { + setLoading(true); + const { error } = await supabase + .from('empresas') + .update({ + nome: empresaLocal.nome, + morada: empresaLocal.morada, + tutor_nome: empresaLocal.tutor_nome, + tutor_telefone: empresaLocal.tutor_telefone, + curso: empresaLocal.curso, + }) + .eq('id', empresaLocal.id); + + if (error) throw error; + setEditando(false); + Alert.alert('Sucesso', 'Dados atualizados!'); + } catch (error: any) { + Alert.alert('Erro', error.message); + } finally { + setLoading(false); + } }; const handleDelete = () => { - Alert.alert( - 'Apagar Empresa', - 'Tem a certeza que deseja apagar esta empresa?', - [ - { text: 'Cancelar', style: 'cancel' }, - { text: 'Apagar', style: 'destructive', onPress: () => router.back() } - ] - ); + Alert.alert('Apagar', `Apagar ${empresaLocal.nome}?`, [ + { text: 'Cancelar', style: 'cancel' }, + { + text: 'Apagar', + style: 'destructive', + onPress: async () => { + await supabase.from('empresas').delete().eq('id', empresaLocal.id); + router.back(); + } + } + ]); }; return ( - - + + - - router.back()}> - - - - {empresaLocal.nome} - - - setEditando(!editando)}> - + + + router.back()}> + - - - - - - - {/* Dados da Empresa */} - - Dados da Empresa - - {['nome', 'curso', 'morada', 'tutor', 'telefone'].map((campo) => ( - - - {campo.charAt(0).toUpperCase() + campo.slice(1)} - - {editando ? ( - setEmpresaLocal({ ...empresaLocal, [campo]: v })} - /> - ) : ( - - {(empresaLocal as any)[campo]} - - )} - - ))} - - - {/* Botão Guardar alterações */} - {editando && ( - - Guardar alterações - - )} - - {/* Estatísticas */} - - Estatísticas - Total de Alunos - - {empresaLocal.alunos?.length || 0} + + {empresaLocal.nome || 'Detalhes'} + + + setEditando(!editando)} + > + + + + + + - {/* Lista de Alunos */} - {empresaLocal.alunos && empresaLocal.alunos.length > 0 && ( + + {/* CARD DE DADOS */} - Alunos na Empresa - {empresaLocal.alunos.map((aluno, index) => ( - - {aluno} - + Informações da Empresa + {[ + { label: 'Nome', key: 'nome' }, + { label: 'Curso', key: 'curso' }, + { label: 'Morada', key: 'morada' }, + { label: 'Tutor', key: 'tutor_nome' }, + { label: 'Telefone', key: 'tutor_telefone' }, + ].map((item) => ( + + {item.label} + {editando ? ( + setEmpresaLocal(prev => ({ ...prev, [item.key]: v }))} + /> + ) : ( + {(empresaLocal as any)[item.key] || '---'} + )} + ))} - )} - - + {editando && ( + + {loading ? : Confirmar Alterações} + + )} + + {/* ESTATÍSTICAS COM LISTA DE ALUNOS */} + + Alunos em Estágio + + {empresaLocal.alunos && empresaLocal.alunos.length > 0 ? ( + empresaLocal.alunos.map((aluno, index) => ( + + + {aluno} + + )) + ) : ( + + Nenhum aluno associado. + + )} + + + Total de Alunos + + {empresaLocal.alunos?.length || 0} + + + + + + ); }); export default DetalhesEmpresa; const styles = StyleSheet.create({ - safe: { flex: 1, paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }, - header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 20, paddingVertical: 10 }, + safe: { flex: 1, paddingTop: Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 0 }, + header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 15, paddingVertical: 10 }, + headerAcoes: { flexDirection: 'row', gap: 8 }, btnVoltar: { width: 40, height: 40, borderRadius: 20, justifyContent: 'center', alignItems: 'center', elevation: 2 }, - btnAcao: { width: 40, height: 40, borderRadius: 10, justifyContent: 'center', alignItems: 'center' }, - tituloGeral: { fontSize: 22, fontWeight: 'bold' }, - container: { padding: 20, gap: 20, paddingBottom: 40 }, - card: { padding: 20, borderRadius: 16, elevation: 2, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4 }, - tituloCard: { fontSize: 18, fontWeight: 'bold', textAlign: 'center', marginBottom: 10, borderBottomWidth: 1, paddingBottom: 8 }, - label: { marginTop: 12, fontSize: 13 }, - valor: { fontSize: 16, fontWeight: '600' }, - input: { borderWidth: 1, borderRadius: 10, padding: 10, marginTop: 2 }, - saveButton: { padding: 16, borderRadius: 10, marginTop: 16 }, -}); + btnAcao: { width: 38, height: 38, borderRadius: 10, justifyContent: 'center', alignItems: 'center', elevation: 2 }, + tituloGeral: { fontSize: 18, fontWeight: 'bold', flex: 1, textAlign: 'center', marginHorizontal: 10 }, + container: { padding: 20, gap: 15 }, + card: { padding: 20, borderRadius: 16, elevation: 3, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4 }, + tituloCard: { fontSize: 16, fontWeight: 'bold', marginBottom: 15, textAlign: 'center', borderBottomWidth: 1, borderBottomColor: '#f0f0f0', paddingBottom: 8 }, + campoWrapper: { marginBottom: 15 }, + label: { fontSize: 11, fontWeight: '700', textTransform: 'uppercase', marginBottom: 4 }, + valor: { fontSize: 16, fontWeight: '500' }, + alunoRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 8, paddingLeft: 5 }, + input: { borderWidth: 1, borderRadius: 8, padding: 10, fontSize: 16, marginTop: 2 }, + saveButton: { padding: 16, borderRadius: 12, alignItems: 'center', justifyContent: 'center', marginBottom: 10 }, + txtBtn: { color: '#fff', fontWeight: 'bold', fontSize: 16 } +}); \ No newline at end of file diff --git a/app/Professor/Empresas/ListaEmpresas.tsx b/app/Professor/Empresas/ListaEmpresas.tsx index e2af789..1856cdb 100644 --- a/app/Professor/Empresas/ListaEmpresas.tsx +++ b/app/Professor/Empresas/ListaEmpresas.tsx @@ -1,136 +1,321 @@ import { Ionicons } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; -import { memo, useMemo, useState } from 'react'; +import { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { + ActivityIndicator, Alert, - FlatList, Platform, SafeAreaView, StatusBar, - StyleSheet, Text, TextInput, TouchableOpacity, View + FlatList, + Modal, + Platform, + RefreshControl, + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + TextInput, + TouchableOpacity, + View } from 'react-native'; import { useTheme } from '../../../themecontext'; +import { supabase } from '../../lib/supabase'; export interface Empresa { id: number; nome: string; morada: string; - tutor: string; - telefone: string; + tutor_nome: string; + tutor_telefone: string; curso: string; - alunos?: string[]; } -const initialEmpresasData: Empresa[] = [ - { id: 1, nome: 'Empresa X', morada: 'Rua das Flores, 12', tutor: 'João Santos', telefone: '912345678', curso: 'Técnico de Informática', alunos: ['João Silva'] }, - { id: 2, nome: 'Empresa W', morada: 'Av. Central, 45', tutor: 'Ana Costa', telefone: '912345679', curso: 'Técnico de Design', alunos: ['Maria Fernandes'] }, -]; - const ListaEmpresasProfessor = memo(() => { const { isDarkMode } = useTheme(); const router = useRouter(); - const [search, setSearch] = useState(''); - const [empresas, setEmpresas] = useState(initialEmpresasData); - const cores = { + const [search, setSearch] = useState(''); + const [empresas, setEmpresas] = useState([]); + const [loading, setLoading] = useState(true); + const [refreshing, setRefreshing] = useState(false); + + // MODAL + FORM + const [modalVisible, setModalVisible] = useState(false); + const [nome, setNome] = useState(''); + const [morada, setMorada] = useState(''); + const [tutorNome, setTutorNome] = useState(''); + const [tutorTelefone, setTutorTelefone] = useState(''); + const [curso, setCurso] = useState(''); + + const cores = useMemo(() => ({ fundo: isDarkMode ? '#121212' : '#f1f3f5', card: isDarkMode ? '#1e1e1e' : '#fff', texto: isDarkMode ? '#fff' : '#000', textoSecundario: isDarkMode ? '#adb5bd' : '#6c757d', azul: '#0d6efd', + }), [isDarkMode]); + + const fetchEmpresas = async () => { + try { + setLoading(true); + const { data, error } = await supabase + .from('empresas') + .select('*') + .order('nome', { ascending: true }); + + if (error) throw error; + setEmpresas(data || []); + } catch (error: any) { + Alert.alert('Erro ao carregar', error.message); + } finally { + setLoading(false); + setRefreshing(false); + } }; - // Filtrar empresas + useEffect(() => { + fetchEmpresas(); + }, []); + + const onRefresh = useCallback(() => { + setRefreshing(true); + fetchEmpresas(); + }, []); + const filteredEmpresas = useMemo( - () => empresas.filter(e => e.nome.toLowerCase().includes(search.toLowerCase())), + () => empresas.filter(e => + e.nome?.toLowerCase().includes(search.toLowerCase()) + ), [search, empresas] ); - // Criar nova empresa - const criarEmpresa = () => { - Alert.prompt( - 'Nova Empresa', - 'Insira o nome da empresa', - (nome) => { - if (!nome) return; - const nova: Empresa = { - id: Date.now(), - nome, - morada: 'Não definida', - tutor: 'Não definido', - telefone: '000000000', - curso: 'Não definido', - alunos: [] - }; - setEmpresas(prev => [nova, ...prev]); - router.push({ - pathname: '/Professor/Empresas/DetalhesEmpresa', - params: { empresa: JSON.stringify(nova) } - }); - } - ); + // 👉 CRIAR EMPRESA (AGORA COM TODOS OS CAMPOS) + const criarEmpresa = async () => { + if (!nome || !morada || !tutorNome || !tutorTelefone || !curso) { + Alert.alert('Erro', 'Preenche todos os campos.'); + return; + } + + try { + setLoading(true); + + const { data, error } = await supabase + .from('empresas') + .insert([{ + nome: nome.trim(), + morada: morada.trim(), + tutor_nome: tutorNome.trim(), + tutor_telefone: tutorTelefone.trim(), + curso: curso.trim(), + }]) + .select(); + + if (error) throw error; + + setEmpresas(prev => [data![0], ...prev]); + + // limpar form + setNome(''); + setMorada(''); + setTutorNome(''); + setTutorTelefone(''); + setCurso(''); + + setModalVisible(false); + Alert.alert('Sucesso', 'Empresa criada com sucesso!'); + } catch (error: any) { + Alert.alert('Erro ao criar', error.message); + } finally { + setLoading(false); + } }; return ( - - - - {/* Header com botão voltar */} - - router.back()}> - - - Empresas - - - - {/* Input de pesquisa */} - + - {/* Botão criar empresa */} - - + Criar Empresa - - - {/* Lista de empresas */} - item.id.toString()} - renderItem={({ item }) => ( + + {/* HEADER */} + - router.push({ - pathname: '/Professor/Empresas/DetalhesEmpresa', - params: { empresa: JSON.stringify(item) } - }) - } + style={[styles.btnVoltar, { backgroundColor: cores.card }]} + onPress={() => router.back()} > - {item.nome} - {item.curso} - {item.tutor} + + + Empresas + + + + + {/* SEARCH */} + + + + + + {/* BOTÃO NOVA EMPRESA */} + setModalVisible(true)} + > + + Nova Empresa + + + {/* LISTA */} + {loading && !refreshing ? ( + + ) : ( + item.id.toString()} + refreshControl={ + + } + renderItem={({ item }) => ( + + router.push({ + pathname: '/Professor/Empresas/DetalhesEmpresa', + params: { empresa: JSON.stringify(item) } + }) + } + > + + {item.nome} + + {item.curso} + + + {item.tutor_nome} + + + + + )} + contentContainerStyle={styles.listContent} + /> )} - /> - + + + {/* MODAL */} + + + + + Nova Empresa + + + + + + + + + + + + setModalVisible(false)}> + + Cancelar + + + + + + Criar + + + + + + + ); }); export default ListaEmpresasProfessor; +/* INPUT */ +const Input = ({ label, cores, ...props }: any) => ( + + + {label} + + + +); + const styles = StyleSheet.create({ - safe: { flex: 1, paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }, - header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 20, paddingVertical: 10 }, - btnVoltar: { width: 40, height: 40, borderRadius: 20, justifyContent: 'center', alignItems: 'center', elevation: 2 }, + safe: { flex: 1, paddingTop: Platform.OS === 'android' ? 10 : 0 }, + header: { flexDirection: 'row', justifyContent: 'space-between', padding: 20 }, + btnVoltar: { width: 40, height: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center' }, tituloGeral: { fontSize: 22, fontWeight: 'bold' }, - spacer: { width: 40 }, - search: { borderRadius: 10, padding: 10, margin: 10 }, - btnCriar: { marginHorizontal: 10, padding: 12, borderRadius: 10, alignItems: 'center', marginBottom: 10 }, - card: { borderRadius: 10, padding: 15, marginBottom: 10, elevation: 2 }, + searchContainer: { marginHorizontal: 15, marginBottom: 10 }, + searchIcon: { position: 'absolute', left: 15, top: 14 }, + search: { borderRadius: 12, padding: 12, paddingLeft: 45 }, + btnCriar: { flexDirection: 'row', margin: 15, padding: 15, borderRadius: 12, justifyContent: 'center', gap: 8 }, + txtBtnCriar: { color: '#fff', fontWeight: 'bold' }, + listContent: { padding: 15 }, + card: { flexDirection: 'row', justifyContent: 'space-between', padding: 18, borderRadius: 15, marginBottom: 12 }, nomeEmpresa: { fontSize: 18, fontWeight: 'bold' }, - curso: { fontSize: 14, marginTop: 2 }, - tutor: { fontSize: 14, marginTop: 2 }, + info: { fontSize: 14, marginTop: 3 }, + + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.5)', + justifyContent: 'center', + padding: 20, + }, + modalContent: { + borderRadius: 16, + padding: 20, + maxHeight: '90%', + }, + modalTitle: { + fontSize: 20, + fontWeight: 'bold', + marginBottom: 15, + textAlign: 'center', + }, + modalButtons: { + flexDirection: 'row', + justifyContent: 'space-between', + marginTop: 15, + }, + btnConfirmar: { + padding: 14, + borderRadius: 10, + minWidth: 100, + alignItems: 'center', + }, }); diff --git a/app/index.tsx b/app/index.tsx index 50e2589..9f3d161 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,25 +1,79 @@ // app/index.tsx import { useRouter } from 'expo-router'; -import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, Text, View } from 'react-native'; +import { + Alert, + KeyboardAvoidingView, + Platform, + ScrollView, + StyleSheet, + Text, + View, +} from 'react-native'; import Auth from '../components/Auth'; +import { supabase } from './lib/supabase'; export default function LoginScreen() { const router = useRouter(); - const handleLoginSuccess = () => { - router.replace('/Professor/ProfessorHome'); + const handleLoginSuccess = async () => { + try { + // 1️⃣ buscar utilizador autenticado + const { + data: { user }, + error: userError, + } = await supabase.auth.getUser(); + + if (userError || !user) { + Alert.alert('Erro', 'Utilizador não autenticado'); + return; + } + + // 2️⃣ buscar tipo (professor / aluno) + const { data, error } = await supabase + .from('profiles') + .select('tipo') + .eq('id', user.id) + .single(); + + if (error || !data) { + Alert.alert( + 'Erro', + 'Não foi possível obter o tipo de utilizador' + ); + return; + } + + // 3️⃣ redirecionar conforme o tipo + if (data.tipo === 'professor') { + router.replace('/Professor/ProfessorHome'); + } else if (data.tipo === 'aluno') { + router.replace('/Aluno/AlunoHome'); + } else { + Alert.alert('Erro', 'Tipo de utilizador inválido'); + } + } catch (err) { + Alert.alert('Erro', 'Erro inesperado no login'); + } }; return ( - - + + 📱 Estágios+ - Escola Profissional de Vila do Conde + + Escola Profissional de Vila do Conde + - {/* Componente Auth */} + {/* COMPONENTE DE LOGIN */} @@ -28,9 +82,29 @@ export default function LoginScreen() { } const styles = StyleSheet.create({ - scrollContainer: { flexGrow: 1, justifyContent: 'center', paddingHorizontal: 24, paddingVertical: 40 }, - content: { flex: 1, justifyContent: 'center' }, - header: { alignItems: 'center', marginBottom: 48 }, - title: { fontSize: 32, fontWeight: '800', color: '#2d3436', marginBottom: 8 }, - subtitle: { fontSize: 16, color: '#636e72', textAlign: 'center' }, + scrollContainer: { + flexGrow: 1, + justifyContent: 'center', + paddingHorizontal: 24, + paddingVertical: 40, + }, + content: { + flex: 1, + justifyContent: 'center', + }, + header: { + alignItems: 'center', + marginBottom: 48, + }, + title: { + fontSize: 32, + fontWeight: '800', + color: '#2d3436', + marginBottom: 8, + }, + subtitle: { + fontSize: 16, + color: '#636e72', + textAlign: 'center', + }, });