teste
parent
3390923c66
commit
15355007de
|
|
@ -0,0 +1,106 @@
|
|||
// app/dashboard.tsx
|
||||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity, StyleSheet, ScrollView, SafeAreaView } from 'react-native';
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<SafeAreaView style={styles.safe}>
|
||||
<ScrollView style={styles.container} contentContainerStyle={{ padding: 20 }}>
|
||||
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>Bem-vindo, João!</Text>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.icon}>🔔</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Sumários */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>Sumários Recentes</Text>
|
||||
<View style={styles.card}>
|
||||
<Text>Sumário 1 - 10/12/2025</Text>
|
||||
<Text>Sumário 2 - 09/12/2025</Text>
|
||||
<TouchableOpacity style={styles.button}>
|
||||
<Text style={styles.buttonText}>Criar Sumário</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Presença */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>Presença</Text>
|
||||
<TouchableOpacity style={styles.button}>
|
||||
<Text style={styles.buttonText}>📌 Marcar presença</Text>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.lastText}>Última presença: 10/12/2025</Text>
|
||||
</View>
|
||||
|
||||
{/* Calendário */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>Calendário</Text>
|
||||
<View style={styles.card}>
|
||||
<Text>[Calendário]</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Justificar faltas */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>Justificar Faltas</Text>
|
||||
<TouchableOpacity style={styles.button}>
|
||||
<Text style={styles.buttonText}>Justificar falta</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Chat */}
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.sectionTitle}>Chat com o professor</Text>
|
||||
<TouchableOpacity style={styles.button}>
|
||||
<Text style={styles.buttonText}>💬 Abrir chat</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
safe: {
|
||||
flex: 1,
|
||||
backgroundColor: '#f8f9fa',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
paddingHorizontal: 5,
|
||||
},
|
||||
title: { fontSize: 24, fontWeight: '700' },
|
||||
icon: { fontSize: 24 },
|
||||
section: { marginBottom: 20 },
|
||||
sectionTitle: { fontSize: 18, fontWeight: '600', marginBottom: 8 },
|
||||
card: {
|
||||
backgroundColor: '#fff',
|
||||
padding: 16,
|
||||
borderRadius: 12,
|
||||
shadowColor: '#000',
|
||||
shadowOpacity: 0.1,
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowRadius: 4,
|
||||
elevation: 3,
|
||||
},
|
||||
button: {
|
||||
marginTop: 10,
|
||||
backgroundColor: '#0984e3',
|
||||
paddingVertical: 12,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
buttonText: { color: '#fff', fontWeight: '700' },
|
||||
lastText: { marginTop: 8 },
|
||||
});
|
||||
146
app/index.tsx
146
app/index.tsx
|
|
@ -1,6 +1,4 @@
|
|||
// app/index.tsx - SUA TELA DE LOGIN
|
||||
// Adicione esta linha com os outros imports:
|
||||
import { Link } from 'expo-router';
|
||||
// app/index.tsx - TELA DE LOGIN
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
|
|
@ -11,37 +9,42 @@ import {
|
|||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
Alert,
|
||||
Image,
|
||||
ActivityIndicator
|
||||
} from 'react-native';
|
||||
import { useRouter, Link } from 'expo-router';
|
||||
|
||||
export default function LoginScreen() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const router = useRouter(); // Inicializa o router
|
||||
|
||||
const handleLogin = () => {
|
||||
if (!email || !password) {
|
||||
Alert.alert('Atenção', 'Por favor, preencha todos os campos');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!email.includes('@')) {
|
||||
Alert.alert('Email inválido', 'Por favor, insira um email válido');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setLoading(true);
|
||||
|
||||
// SIMULAÇÃO DE LOGIN (depois troca por API real)
|
||||
|
||||
// SIMULAÇÃO DE LOGIN
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
Alert.alert(
|
||||
'Login realizado!',
|
||||
`Bem-vindo(a), ${email.split('@')[0]}!`,
|
||||
[{ text: 'OK', onPress: () => console.log('Login OK') }]
|
||||
);
|
||||
// Aqui você navegaria para o app principal: router.replace('/(tabs)');
|
||||
|
||||
// Primeiro navega para a dashboard
|
||||
router.replace('/dashboard'); // ⬅️ Certifica-te que o ficheiro é app/dashboard.tsx
|
||||
|
||||
// Depois mostra alert de boas-vindas (opcional)
|
||||
setTimeout(() => {
|
||||
Alert.alert('Login realizado!', `Bem-vindo(a), ${email.split('@')[0]}!`);
|
||||
}, 300); // delay pequeno para garantir que a navegação ocorreu
|
||||
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
|
|
@ -106,9 +109,9 @@ export default function LoginScreen() {
|
|||
<View style={styles.footer}>
|
||||
<Text style={styles.footerText}>Não tem uma conta?</Text>
|
||||
<Link href="/register" asChild>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.registerText}> Crie uma conta agora</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.registerText}> Crie uma conta agora</Text>
|
||||
</TouchableOpacity>
|
||||
</Link>
|
||||
</View>
|
||||
|
||||
|
|
@ -119,97 +122,20 @@ export default function LoginScreen() {
|
|||
|
||||
// ESTILOS
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#f8f9fa',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
header: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 48,
|
||||
},
|
||||
title: {
|
||||
fontSize: 32,
|
||||
fontWeight: '800',
|
||||
color: '#2d3436',
|
||||
marginBottom: 8,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 16,
|
||||
color: '#636e72',
|
||||
textAlign: 'center',
|
||||
},
|
||||
form: {
|
||||
backgroundColor: '#fff',
|
||||
borderRadius: 20,
|
||||
padding: 24,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.1,
|
||||
shadowRadius: 12,
|
||||
elevation: 5,
|
||||
},
|
||||
label: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#2d3436',
|
||||
marginBottom: 8,
|
||||
marginLeft: 4,
|
||||
},
|
||||
input: {
|
||||
backgroundColor: '#f8f9fa',
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
fontSize: 16,
|
||||
marginBottom: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: '#dfe6e9',
|
||||
color: '#2d3436',
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#0984e3',
|
||||
borderRadius: 12,
|
||||
paddingVertical: 16,
|
||||
alignItems: 'center',
|
||||
marginTop: 8,
|
||||
marginBottom: 24,
|
||||
},
|
||||
buttonDisabled: {
|
||||
backgroundColor: '#74b9ff',
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
},
|
||||
forgotLink: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
forgotText: {
|
||||
color: '#0984e3',
|
||||
fontSize: 15,
|
||||
fontWeight: '500',
|
||||
},
|
||||
footer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
marginTop: 40,
|
||||
paddingTop: 24,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#dfe6e9',
|
||||
},
|
||||
footerText: {
|
||||
color: '#636e72',
|
||||
fontSize: 15,
|
||||
},
|
||||
registerText: {
|
||||
color: '#0984e3',
|
||||
fontSize: 15,
|
||||
fontWeight: '700',
|
||||
},
|
||||
container: { flex: 1, backgroundColor: '#f8f9fa' },
|
||||
content: { flex: 1, justifyContent: 'center', paddingHorizontal: 24 },
|
||||
header: { alignItems: 'center', marginBottom: 48 },
|
||||
title: { fontSize: 32, fontWeight: '800', color: '#2d3436', marginBottom: 8 },
|
||||
subtitle: { fontSize: 16, color: '#636e72', textAlign: 'center' },
|
||||
form: { backgroundColor: '#fff', borderRadius: 20, padding: 24, shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.1, shadowRadius: 12, elevation: 5 },
|
||||
label: { fontSize: 14, fontWeight: '600', color: '#2d3436', marginBottom: 8, marginLeft: 4 },
|
||||
input: { backgroundColor: '#f8f9fa', borderRadius: 12, paddingHorizontal: 16, paddingVertical: 14, fontSize: 16, marginBottom: 20, borderWidth: 1, borderColor: '#dfe6e9', color: '#2d3436' },
|
||||
button: { backgroundColor: '#0984e3', borderRadius: 12, paddingVertical: 16, alignItems: 'center', marginTop: 8, marginBottom: 24 },
|
||||
buttonDisabled: { backgroundColor: '#74b9ff' },
|
||||
buttonText: { color: '#fff', fontSize: 16, fontWeight: '700' },
|
||||
forgotLink: { alignItems: 'center' },
|
||||
forgotText: { color: '#0984e3', fontSize: 15, fontWeight: '500' },
|
||||
footer: { flexDirection: 'row', justifyContent: 'center', marginTop: 40, paddingTop: 24, borderTopWidth: 1, borderTopColor: '#dfe6e9' },
|
||||
footerText: { color: '#636e72', fontSize: 15 },
|
||||
registerText: { color: '#0984e3', fontSize: 15, fontWeight: '700' },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default function RegisterScreen() {
|
|||
|
||||
const handleRegister = () => {
|
||||
if (!form.nome.trim()) {
|
||||
Alert.alert('Erro', 'Por favor, insira seu nome');
|
||||
Alert.alert('Erro', 'Por favor, insira o seu nome');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ export default function RegisterScreen() {
|
|||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
{/* BOTÃO VOLTAR NO TOPO (AGORA SEM BUG DO NOTCH) */}
|
||||
{/* BOTÃO VOLTAR ATRÁS */}
|
||||
<Link href="/" asChild>
|
||||
<TouchableOpacity style={styles.backHeaderButton} disabled={loading}>
|
||||
<Text style={styles.backHeaderText}>←</Text>
|
||||
|
|
@ -102,12 +102,12 @@ export default function RegisterScreen() {
|
|||
|
||||
{/* FORMULÁRIO */}
|
||||
<View style={styles.formCard}>
|
||||
{/* NOME */}
|
||||
{/* NOME COMPLETO */}
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>Nome Completo</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Digite seu nome completo"
|
||||
placeholder="Insira o seu nome completo..."
|
||||
value={form.nome}
|
||||
onChangeText={(text) => handleChange('nome', text)}
|
||||
editable={!loading}
|
||||
|
|
@ -119,7 +119,7 @@ export default function RegisterScreen() {
|
|||
<Text style={styles.label}>Email</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="exemplo@email.com"
|
||||
placeholder="Insira o seu email..."
|
||||
value={form.email}
|
||||
onChangeText={(text) => handleChange('email', text)}
|
||||
keyboardType="email-address"
|
||||
|
|
@ -128,12 +128,12 @@ export default function RegisterScreen() {
|
|||
/>
|
||||
</View>
|
||||
|
||||
{/* TELEFONE */}
|
||||
{/* Nº TELEMÓVEL */}
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>Telefone</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="912 345 678"
|
||||
placeholder="Insira o seu nº telemóvel..."
|
||||
value={form.telefone}
|
||||
onChangeText={(text) => handleChange('telefone', text)}
|
||||
keyboardType="phone-pad"
|
||||
|
|
@ -141,12 +141,12 @@ export default function RegisterScreen() {
|
|||
/>
|
||||
</View>
|
||||
|
||||
{/* SENHA */}
|
||||
{/* PALAVRA-PASSE */}
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>Senha</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Mínimo 6 caracteres"
|
||||
placeholder="Mínimo de 6 caracteres"
|
||||
value={form.password}
|
||||
onChangeText={(text) => handleChange('password', text)}
|
||||
secureTextEntry
|
||||
|
|
@ -154,12 +154,12 @@ export default function RegisterScreen() {
|
|||
/>
|
||||
</View>
|
||||
|
||||
{/* CONFIRMAR SENHA */}
|
||||
{/* CONFIRMAR PALAVRA-PASSE */}
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>Confirmar Senha</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Digite novamente a senha"
|
||||
placeholder="Insira novamente a sua palavra-passe"
|
||||
value={form.confirmarPassword}
|
||||
onChangeText={(text) => handleChange('confirmarPassword', text)}
|
||||
secureTextEntry
|
||||
|
|
@ -167,7 +167,7 @@ export default function RegisterScreen() {
|
|||
/>
|
||||
</View>
|
||||
|
||||
{/* BOTÃO REGISTRAR */}
|
||||
{/* BOTÃO CRIAR CONTA */}
|
||||
<TouchableOpacity
|
||||
style={[styles.registerButton, loading && styles.buttonDisabled]}
|
||||
onPress={handleRegister}
|
||||
|
|
@ -205,7 +205,7 @@ const styles = StyleSheet.create({
|
|||
scrollContainer: {
|
||||
flexGrow: 1,
|
||||
padding: 20,
|
||||
paddingTop: 20, // SafeArea já resolve o notch
|
||||
paddingTop: 20,
|
||||
},
|
||||
backHeaderButton: {
|
||||
position: 'absolute',
|
||||
|
|
|
|||
Loading…
Reference in New Issue