From f025edc15db7a5d48c36ef687ab92fa027f5d8f1 Mon Sep 17 00:00:00 2001 From: Ricardo Gomes <230413@epvc.pt> Date: Thu, 8 Jan 2026 10:43:55 +0000 Subject: [PATCH] atalizacoes --- app/AlunoHome.tsx | 290 +++++++++++++++++++++++++++++++++------------- package-lock.json | 10 ++ package.json | 1 + 3 files changed, 221 insertions(+), 80 deletions(-) diff --git a/app/AlunoHome.tsx b/app/AlunoHome.tsx index a03dc68..9a45eae 100644 --- a/app/AlunoHome.tsx +++ b/app/AlunoHome.tsx @@ -1,122 +1,252 @@ import React, { useState } from 'react'; -import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView } from 'react-native'; +import { + View, + Text, + TouchableOpacity, + StyleSheet, + SafeAreaView, + TextInput, + ScrollView, + Alert, +} from 'react-native'; import { Calendar, LocaleConfig } from 'react-native-calendars'; +import { Ionicons } from '@expo/vector-icons'; +import * as DocumentPicker from 'expo-document-picker'; -// Configurações de idioma do calendário (opcional) +// Calendário PT LocaleConfig.locales['pt'] = { monthNames: [ 'Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro' ], - monthNamesShort: [ - 'Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez' - ], - dayNames: [ - 'Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado' - ], + monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], + dayNames: ['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado'], dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], }; LocaleConfig.defaultLocale = 'pt'; export default function AlunoHome() { - const [presencaMarcada, setPresencaMarcada] = useState(true); + const hoje = new Date().toISOString().split('T')[0]; + + const [selectedDate, setSelectedDate] = useState(hoje); + const [presencas, setPresencas] = useState({}); + const [sumarios, setSumarios] = useState({}); + const [faltas, setFaltas] = useState({}); + const [faltasJustificadas, setFaltasJustificadas] = useState({}); + const [textoSumario, setTextoSumario] = useState(''); + const [pdf, setPdf] = useState(null); function marcarPresenca() { - setPresencaMarcada(true); + setPresencas({ ...presencas, [selectedDate]: true }); } - // Exemplo de datas marcadas no calendário - const diasMarcados = { - '2026-01-07': { marked: true, dotColor: 'green' }, // hoje presente marcada - '2026-01-06': { marked: true, dotColor: 'blue' }, // sumário enviado + function marcarFalta() { + setFaltas({ ...faltas, [selectedDate]: true }); + } + + async function escolherPDF() { + const result = await DocumentPicker.getDocumentAsync({ + type: 'application/pdf', + }); + + if (!result.canceled) { + setPdf(result.assets[0]); + } + } + + function enviarJustificacao() { + if (!pdf) { + Alert.alert('PDF em falta', 'Anexe o documento de justificação.'); + return; + } + + setFaltasJustificadas({ + ...faltasJustificadas, + [selectedDate]: true, + }); + + Alert.alert('Justificação enviada', 'Falta justificada com sucesso.'); + } + + function guardarSumario() { + if (!presencas[selectedDate]) { + Alert.alert('Erro', 'Não marcou presença neste dia.'); + return; + } + if (!textoSumario.trim()) { + Alert.alert('Erro', 'Sumário vazio.'); + return; + } + setSumarios({ ...sumarios, [selectedDate]: textoSumario }); + } + + // Marcação do calendário + const diasMarcados: any = {}; + + Object.keys(presencas).forEach((d) => { + diasMarcados[d] = { + marked: true, + dotColor: sumarios[d] ? 'green' : 'orange', + }; + }); + + Object.keys(faltas).forEach((d) => { + diasMarcados[d] = { marked: true, dotColor: 'red' }; + }); + + Object.keys(faltasJustificadas).forEach((d) => { + diasMarcados[d] = { marked: true, dotColor: 'gray' }; + }); + + diasMarcados[selectedDate] = { + ...(diasMarcados[selectedDate] || {}), + selected: true, + selectedColor: '#0d6efd', }; return ( - + - {/* Header */} - - Estágio - Controlo diário do aluno + {/* TOPO */} + + + + Estágios+ + Organização do Estágio Escolar + + - {/* Botão Presença */} - - - {presencaMarcada ? 'Presença Marcada ✅' : 'Marcar Presença'} - - + {/* BOTÕES */} + + + Marcar Presença + - {/* Calendário abaixo do botão */} - - + + Faltei + - + { + setSelectedDate(day.dateString); + setTextoSumario(sumarios[day.dateString] || ''); + setPdf(null); + }} + /> + + {/* SUMÁRIO */} + {presencas[selectedDate] && ( + + Sumário + + + Guardar Sumário + + + )} + + {/* JUSTIFICAR FALTA */} + {faltas[selectedDate] && !faltasJustificadas[selectedDate] && ( + + Justificar Falta + + + {pdf ? pdf.name : 'Anexar PDF'} + + + + Enviar Justificação + + + )} + + ); } const styles = StyleSheet.create({ - safeArea: { - flex: 1, - backgroundColor: '#f1f3f5', - }, - container: { - flex: 1, - paddingHorizontal: 20, - }, - header: { - marginTop: 20, - marginBottom: 25, - }, - headerTitulo: { - fontSize: 30, - fontWeight: 'bold', - color: '#111', - }, - headerSubtitulo: { - fontSize: 16, - color: '#6c757d', - marginTop: 4, - }, - botaoPresenca: { - backgroundColor: '#0d6efd', - paddingVertical: 16, - borderRadius: 12, + safeArea: { flex: 1, backgroundColor: '#f1f3f5' }, + container: { padding: 20, paddingBottom: 40 }, + + topBar: { + flexDirection: 'row', + justifyContent: 'space-between', alignItems: 'center', marginBottom: 20, }, - botaoDesativado: { - backgroundColor: '#b6d4fe', + title: { fontSize: 22, fontWeight: 'bold' }, + subtitle: { fontSize: 13, color: '#6c757d' }, + + botoesLinha: { + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 15, }, - textoBotao: { - color: '#ffffff', - fontSize: 17, - fontWeight: '600', + + botaoPresenca: { + backgroundColor: '#0d6efd', + padding: 14, + borderRadius: 12, + width: '48%', + alignItems: 'center', }, - calendarioContainer: { - marginBottom: 20, + botaoFalta: { + backgroundColor: '#dc3545', + padding: 14, + borderRadius: 12, + width: '48%', + alignItems: 'center', }, - calendario: { - borderRadius: 16, + textoBotao: { color: '#fff', fontWeight: '600' }, + + card: { backgroundColor: '#fff', + padding: 16, + borderRadius: 16, + marginTop: 20, + }, + cardTitulo: { fontSize: 18, fontWeight: '600', marginBottom: 10 }, + + textArea: { + borderWidth: 1, + borderColor: '#ddd', + borderRadius: 10, padding: 10, + height: 100, + marginBottom: 10, + }, + + botaoGuardar: { + backgroundColor: '#198754', + padding: 14, + borderRadius: 10, + alignItems: 'center', + }, + botaoPDF: { + borderWidth: 1, + borderColor: '#adb5bd', + padding: 12, + borderRadius: 10, + marginBottom: 10, }, }); diff --git a/package-lock.json b/package-lock.json index 8e90ea4..c472266 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@react-navigation/native": "^7.1.8", "expo": "~54.0.27", "expo-constants": "~18.0.11", + "expo-document-picker": "~14.0.8", "expo-font": "~14.0.10", "expo-haptics": "~15.0.8", "expo-image": "~3.0.11", @@ -6088,6 +6089,15 @@ "react-native": "*" } }, + "node_modules/expo-document-picker": { + "version": "14.0.8", + "resolved": "https://registry.npmjs.org/expo-document-picker/-/expo-document-picker-14.0.8.tgz", + "integrity": "sha512-3tyQKpPqWWFlI8p9RiMX1+T1Zge5mEKeBuXWp1h8PEItFMUDSiOJbQ112sfdC6Hxt8wSxreV9bCRl/NgBdt+fA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-file-system": { "version": "19.0.20", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.20.tgz", diff --git a/package.json b/package.json index 14c9869..450d304 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@react-navigation/native": "^7.1.8", "expo": "~54.0.27", "expo-constants": "~18.0.11", + "expo-document-picker": "~14.0.8", "expo-font": "~14.0.10", "expo-haptics": "~15.0.8", "expo-image": "~3.0.11",