From 3390923c66ae3e9732d20e16b295bb5309a1991b Mon Sep 17 00:00:00 2001 From: Ricardo Gomes <230413@epvc.pt> Date: Fri, 12 Dec 2025 09:29:15 +0000 Subject: [PATCH] first commit --- app/(tabs)/_layout.tsx | 35 ----- app/(tabs)/explore.tsx | 112 --------------- app/(tabs)/index.tsx | 98 ------------- app/_layout.tsx | 22 +-- app/index.tsx | 215 ++++++++++++++++++++++++++++ app/modal.tsx | 29 ---- app/register.tsx | 309 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 530 insertions(+), 290 deletions(-) delete mode 100644 app/(tabs)/_layout.tsx delete mode 100644 app/(tabs)/explore.tsx delete mode 100644 app/(tabs)/index.tsx create mode 100644 app/index.tsx delete mode 100644 app/modal.tsx create mode 100644 app/register.tsx diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx deleted file mode 100644 index 54e11d0..0000000 --- a/app/(tabs)/_layout.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Tabs } from 'expo-router'; -import React from 'react'; - -import { HapticTab } from '@/components/haptic-tab'; -import { IconSymbol } from '@/components/ui/icon-symbol'; -import { Colors } from '@/constants/theme'; -import { useColorScheme } from '@/hooks/use-color-scheme'; - -export default function TabLayout() { - const colorScheme = useColorScheme(); - - return ( - - , - }} - /> - , - }} - /> - - ); -} diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx deleted file mode 100644 index 71518f9..0000000 --- a/app/(tabs)/explore.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } from 'react-native'; - -import { Collapsible } from '@/components/ui/collapsible'; -import { ExternalLink } from '@/components/external-link'; -import ParallaxScrollView from '@/components/parallax-scroll-view'; -import { ThemedText } from '@/components/themed-text'; -import { ThemedView } from '@/components/themed-view'; -import { IconSymbol } from '@/components/ui/icon-symbol'; -import { Fonts } from '@/constants/theme'; - -export default function TabTwoScreen() { - return ( - - }> - - - Explore - - - This app includes example code to help you get started. - - - This app has two screens:{' '} - app/(tabs)/index.tsx and{' '} - app/(tabs)/explore.tsx - - - The layout file in app/(tabs)/_layout.tsx{' '} - sets up the tab navigator. - - - Learn more - - - - - You can open this project on Android, iOS, and the web. To open the web version, press{' '} - w in the terminal running this project. - - - - - For static images, you can use the @2x and{' '} - @3x suffixes to provide files for - different screen densities - - - - Learn more - - - - - This template has light and dark mode support. The{' '} - useColorScheme() hook lets you inspect - what the user's current color scheme is, and so you can adjust UI colors accordingly. - - - Learn more - - - - - This template includes an example of an animated component. The{' '} - components/HelloWave.tsx component uses - the powerful{' '} - - react-native-reanimated - {' '} - library to create a waving hand animation. - - {Platform.select({ - ios: ( - - The components/ParallaxScrollView.tsx{' '} - component provides a parallax effect for the header image. - - ), - })} - - - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: '#808080', - bottom: -90, - left: -35, - position: 'absolute', - }, - titleContainer: { - flexDirection: 'row', - gap: 8, - }, -}); diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx deleted file mode 100644 index 786b736..0000000 --- a/app/(tabs)/index.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } from 'react-native'; - -import { HelloWave } from '@/components/hello-wave'; -import ParallaxScrollView from '@/components/parallax-scroll-view'; -import { ThemedText } from '@/components/themed-text'; -import { ThemedView } from '@/components/themed-view'; -import { Link } from 'expo-router'; - -export default function HomeScreen() { - return ( - - }> - - Welcome! - - - - Step 1: Try it - - Edit app/(tabs)/index.tsx to see changes. - Press{' '} - - {Platform.select({ - ios: 'cmd + d', - android: 'cmd + m', - web: 'F12', - })} - {' '} - to open developer tools. - - - - - - Step 2: Explore - - - - alert('Action pressed')} /> - alert('Share pressed')} - /> - - alert('Delete pressed')} - /> - - - - - - {`Tap the Explore tab to learn more about what's included in this starter app.`} - - - - Step 3: Get a fresh start - - {`When you're ready, run `} - npm run reset-project to get a fresh{' '} - app directory. This will move the current{' '} - app to{' '} - app-example. - - - - ); -} - -const styles = StyleSheet.create({ - titleContainer: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - }, - stepContainer: { - gap: 8, - marginBottom: 8, - }, - reactLogo: { - height: 178, - width: 290, - bottom: 0, - left: 0, - position: 'absolute', - }, -}); diff --git a/app/_layout.tsx b/app/_layout.tsx index f518c9b..51abe36 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,24 +1,14 @@ -import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; +// app/_layout.tsx import { Stack } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; -import 'react-native-reanimated'; - -import { useColorScheme } from '@/hooks/use-color-scheme'; - -export const unstable_settings = { - anchor: '(tabs)', -}; export default function RootLayout() { - const colorScheme = useColorScheme(); - return ( - - - - + <> + + + - - + ); } diff --git a/app/index.tsx b/app/index.tsx new file mode 100644 index 0000000..46572bf --- /dev/null +++ b/app/index.tsx @@ -0,0 +1,215 @@ +// app/index.tsx - SUA TELA DE LOGIN +// Adicione esta linha com os outros imports: +import { Link } from 'expo-router'; +import React, { useState } from 'react'; +import { + View, + TextInput, + TouchableOpacity, + Text, + StyleSheet, + KeyboardAvoidingView, + Platform, + Alert, + Image, + ActivityIndicator +} from 'react-native'; + +export default function LoginScreen() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [loading, setLoading] = useState(false); + + 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) + 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)'); + }, 1500); + }; + + return ( + + + + {/* LOGO/TÍTULO */} + + 📱 Estágios+ + Escola Profissional de Vila do Conde + + + {/* FORMULÁRIO */} + + Email + + + Palavra-passe + + + {/* BOTÃO ENTRAR */} + + {loading ? ( + + ) : ( + ENTRAR + )} + + + {/* LINK ESQUECI SENHA */} + + Esqueceu-se da palavra-passe? + + + + {/* CADASTRO */} + + Não tem uma conta? + + + Crie uma conta agora + + + + + + + ); +} + +// 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', + }, +}); diff --git a/app/modal.tsx b/app/modal.tsx deleted file mode 100644 index 6dfbc1a..0000000 --- a/app/modal.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Link } from 'expo-router'; -import { StyleSheet } from 'react-native'; - -import { ThemedText } from '@/components/themed-text'; -import { ThemedView } from '@/components/themed-view'; - -export default function ModalScreen() { - return ( - - This is a modal - - Go to home screen - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - padding: 20, - }, - link: { - marginTop: 15, - paddingVertical: 15, - }, -}); diff --git a/app/register.tsx b/app/register.tsx new file mode 100644 index 0000000..a4f41f5 --- /dev/null +++ b/app/register.tsx @@ -0,0 +1,309 @@ +// app/register.tsx - TELA DE CRIAR CONTA (CORRIGIDA) + +import React, { useState } from 'react'; +import { + View, + TextInput, + TouchableOpacity, + Text, + StyleSheet, + ScrollView, + Alert, + ActivityIndicator, + KeyboardAvoidingView, + Platform +} from 'react-native'; +import { Link } from 'expo-router'; +import { StatusBar } from 'expo-status-bar'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +export default function RegisterScreen() { + const [form, setForm] = useState({ + nome: '', + email: '', + telefone: '', + password: '', + confirmarPassword: '' + }); + const [loading, setLoading] = useState(false); + + const handleChange = (field: string, value: string) => { + setForm(prev => ({ ...prev, [field]: value })); + }; + + const handleRegister = () => { + if (!form.nome.trim()) { + Alert.alert('Erro', 'Por favor, insira seu nome'); + return; + } + + if (!form.email.includes('@')) { + Alert.alert('Erro', 'Por favor, insira um email válido'); + return; + } + + if (form.password.length < 6) { + Alert.alert('Erro', 'A senha deve ter pelo menos 6 caracteres'); + return; + } + + if (form.password !== form.confirmarPassword) { + Alert.alert('Erro', 'As senhas não coincidem'); + return; + } + + setLoading(true); + + setTimeout(() => { + setLoading(false); + Alert.alert( + 'Sucesso!', + `Conta criada para ${form.nome}`, + [{ text: 'OK' }] + ); + + setForm({ + nome: '', + email: '', + telefone: '', + password: '', + confirmarPassword: '' + }); + }, 1500); + }; + + return ( + + + + + + {/* BOTÃO VOLTAR NO TOPO (AGORA SEM BUG DO NOTCH) */} + + + + + + + {/* CABEÇALHO */} + + Criar Nova Conta + + Preencha os dados abaixo para se registar + + + + {/* FORMULÁRIO */} + + {/* NOME */} + + Nome Completo + handleChange('nome', text)} + editable={!loading} + /> + + + {/* EMAIL */} + + Email + handleChange('email', text)} + keyboardType="email-address" + autoCapitalize="none" + editable={!loading} + /> + + + {/* TELEFONE */} + + Telefone + handleChange('telefone', text)} + keyboardType="phone-pad" + editable={!loading} + /> + + + {/* SENHA */} + + Senha + handleChange('password', text)} + secureTextEntry + editable={!loading} + /> + + + {/* CONFIRMAR SENHA */} + + Confirmar Senha + handleChange('confirmarPassword', text)} + secureTextEntry + editable={!loading} + /> + + + {/* BOTÃO REGISTRAR */} + + {loading ? ( + + ) : ( + CRIAR CONTA + )} + + + {/* AVISO */} + + + Ao criar uma conta, concorda com os nossos Termos de Serviço e Política de Privacidade. + + + + + + + ); +} + +// ESTILOS +const styles = StyleSheet.create({ + safeArea: { + flex: 1, + backgroundColor: '#FFFFFF', + }, + container: { + flex: 1, + }, + scrollContainer: { + flexGrow: 1, + padding: 20, + paddingTop: 20, // SafeArea já resolve o notch + }, + backHeaderButton: { + position: 'absolute', + top: 0, + left: 10, + zIndex: 50, + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: '#f0f0f0', + justifyContent: 'center', + alignItems: 'center', + }, + backHeaderText: { + fontSize: 24, + color: '#007AFF', + fontWeight: 'bold', + }, + header: { + alignItems: 'center', + marginTop: 50, + marginBottom: 40, + }, + title: { + fontSize: 28, + fontWeight: 'bold', + color: '#1a1a1a', + marginBottom: 8, + }, + subtitle: { + fontSize: 16, + color: '#666', + textAlign: 'center', + }, + formCard: { + backgroundColor: '#f8f9fa', + borderRadius: 16, + padding: 24, + marginBottom: 24, + borderWidth: 1, + borderColor: '#e9ecef', + }, + inputGroup: { + marginBottom: 20, + }, + label: { + fontSize: 14, + fontWeight: '600', + color: '#333', + marginBottom: 6, + marginLeft: 4, + }, + input: { + backgroundColor: '#FFFFFF', + borderRadius: 12, + paddingHorizontal: 16, + paddingVertical: 14, + fontSize: 16, + borderWidth: 1, + borderColor: '#ddd', + color: '#333', + }, + registerButton: { + backgroundColor: '#007AFF', + borderRadius: 12, + paddingVertical: 16, + alignItems: 'center', + marginTop: 10, + marginBottom: 20, + }, + buttonDisabled: { + backgroundColor: '#7bb8ff', + }, + registerButtonText: { + color: '#FFFFFF', + fontSize: 16, + fontWeight: 'bold', + }, + termsContainer: { + backgroundColor: '#e8f4ff', + borderRadius: 8, + padding: 12, + borderWidth: 1, + borderColor: '#cce5ff', + }, + termsText: { + fontSize: 13, + color: '#0066cc', + textAlign: 'center', + lineHeight: 18, + }, + backButton: { + paddingVertical: 14, + alignItems: 'center', + }, + backButtonText: { + color: '#007AFF', + fontSize: 16, + fontWeight: '500', + }, +});