From 543bf48115ef15e0fcfe7db5ad8ddeb0f35e172e Mon Sep 17 00:00:00 2001 From: Ricardo Gomes <230413@epvc.pt> Date: Tue, 9 Jun 2026 17:16:57 +0100 Subject: [PATCH] atualizacoes --- app/Empresas/fichaAvaliacao.tsx | 910 +++++++++++++------------------- 1 file changed, 373 insertions(+), 537 deletions(-) diff --git a/app/Empresas/fichaAvaliacao.tsx b/app/Empresas/fichaAvaliacao.tsx index debec27..54e612f 100644 --- a/app/Empresas/fichaAvaliacao.tsx +++ b/app/Empresas/fichaAvaliacao.tsx @@ -1,585 +1,421 @@ -// app/Professor/Alunos/relatorios.tsx +// app/Empresa/FichaAvaliacao.tsx +// Navegar para esta página passando: { estagio_id, aluno_nome, aluno_turma, n_escola } + import { Ionicons } from '@expo/vector-icons'; -import { useFocusEffect } from '@react-navigation/native'; -import { Asset } from 'expo-asset'; -import * as FileSystem from 'expo-file-system/legacy'; -import * as Print from 'expo-print'; -import { useRouter } from 'expo-router'; -import * as Sharing from 'expo-sharing'; -import * as WebBrowser from 'expo-web-browser'; -import { useCallback, useMemo, useState } from 'react'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { useMemo, useState } from 'react'; import { ActivityIndicator, Alert, - RefreshControl, + KeyboardAvoidingView, + Platform, SafeAreaView, ScrollView, StatusBar, StyleSheet, Text, + TextInput, TouchableOpacity, - View + View, } from 'react-native'; import { supabase } from '../../lib/supabase'; import { useTheme } from '../../themecontext'; -export default function GestaoRelatorios() { +// ─── Perguntas de Avaliação ──────────────────────────────────────────────────── +const PERGUNTAS = [ + { id: 'p1', categoria: 'Competências Técnicas', texto: 'Domínio das tarefas e conhecimentos técnicos exigidos.' }, + { id: 'p2', categoria: 'Competências Técnicas', texto: 'Capacidade de aprendizagem e adaptação a novas situações.' }, + { id: 'p3', categoria: 'Competências Técnicas', texto: 'Qualidade e rigor do trabalho realizado.' }, + { id: 'p4', categoria: 'Atitude Profissional', texto: 'Pontualidade, assiduidade e cumprimento de horários.' }, + { id: 'p5', categoria: 'Atitude Profissional', texto: 'Iniciativa, proatividade e autonomia nas tarefas.' }, + { id: 'p6', categoria: 'Atitude Profissional', texto: 'Responsabilidade e cumprimento das normas da empresa.' }, + { id: 'p7', categoria: 'Relacionamento', texto: 'Relacionamento com colegas e integração na equipa.' }, + { id: 'p8', categoria: 'Relacionamento', texto: 'Comunicação e postura com clientes e superiores.' }, + { id: 'p9', categoria: 'Desenvolvimento Pessoal', texto: 'Capacidade de gerir dificuldades e resolver problemas.' }, + { id: 'p10', categoria: 'Desenvolvimento Pessoal', texto: 'Evolução e progresso ao longo do período de estágio.' }, +]; + +const ESCALA = [ + { valor: 1, label: 'Insatisfatório' }, + { valor: 2, label: 'A Melhorar' }, + { valor: 3, label: 'Satisfatório' }, + { valor: 4, label: 'Bom' }, + { valor: 5, label: 'Excelente' }, +]; + +// ─── Componente ─────────────────────────────────────────────────────────────── +export default function FichaAvaliacao() { const { isDarkMode } = useTheme(); const router = useRouter(); + const params = useLocalSearchParams<{ + estagio_id: string; + aluno_nome: string; + aluno_turma: string; + n_escola: string; + }>(); - const [relatorios, setRelatorios] = useState([]); - const [loading, setLoading] = useState(true); - const [refreshing, setRefreshing] = useState(false); - const [gerandoPDF, setGerandoPDF] = useState(null); + const [respostas, setRespostas] = useState>({}); + const [notaFinal, setNotaFinal] = useState(''); + const [observacoes, setObservacoes] = useState(''); + const [submitting, setSubmitting] = useState(false); const cores = useMemo(() => ({ - fundo: isDarkMode ? '#0A0A0A' : '#F4F7FA', - card: isDarkMode ? '#161618' : '#FFFFFF', - texto: isDarkMode ? '#F8FAFC' : '#0D2235', - textoSecundario: isDarkMode ? '#94A3B8' : '#64748B', - borda: isDarkMode ? '#2D2D2D' : '#E2E8F0', - azulMarinho: '#003049', - verdeAgua: '#71BEB3', - laranja: '#F18721', + fundo: isDarkMode ? '#0A0A0A' : '#F4F7FA', + card: isDarkMode ? '#161618' : '#FFFFFF', + texto: isDarkMode ? '#F8FAFC' : '#0D2235', + textoSecundario: isDarkMode ? '#94A3B8' : '#64748B', + borda: isDarkMode ? '#2D2D2D' : '#E2E8F0', + azulMarinho: '#003049', + verdeAgua: '#71BEB3', + laranja: '#F18721', + vermelho: '#EF4444', + verde: '#22C55E', + inputFundo: isDarkMode ? '#1E1E20' : '#F8FAFC', }), [isDarkMode]); - // Função para carregar as imagens locais para Base64 - const getBase64Image = async (imageModule: any) => { - try { - const asset = Asset.fromModule(imageModule); - await asset.downloadAsync(); - const fileUri = asset.localUri || asset.uri; - if (!fileUri) return ""; - const base64 = await FileSystem.readAsStringAsync(fileUri, { encoding: 'base64' }); - return `data:image/png;base64,${base64}`; - } catch (e) { - console.error("Erro no Base64:", e); - return ""; - } + // Cor do botão de escala consoante o valor selecionado + const corEscala = (valor: number, selecionado: boolean) => { + if (!selecionado) return { bg: cores.inputFundo, borda: cores.borda, texto: cores.textoSecundario }; + const mapa: Record = { + 1: { bg: '#FEE2E2', borda: '#EF4444', texto: '#B91C1C' }, + 2: { bg: '#FEF3C7', borda: '#F59E0B', texto: '#B45309' }, + 3: { bg: '#FEF9C3', borda: '#EAB308', texto: '#854D0E' }, + 4: { bg: '#DCFCE7', borda: '#22C55E', texto: '#15803D' }, + 5: { bg: '#D1FAE5', borda: '#10B981', texto: '#065F46' }, + }; + return mapa[valor]; }; - const fetchRelatorios = async (isManualRefresh = false) => { - if (!isManualRefresh) setLoading(true); - try { - const { data, error } = await supabase - .from('estagios') - .select(` - id, horas_totais, horas_concluidas, nota_final, avaliacao_url, data_inicio, data_fim, - alunos (id, nome, turma_curso, n_escola), - empresas (nome, tutor_nome) - `) - .order('data_inicio', { ascending: false }); + // Validação da nota final + const notaValida = useMemo(() => { + const n = parseFloat(notaFinal.replace(',', '.')); + return !isNaN(n) && n >= 0 && n <= 20; + }, [notaFinal]); - if (error) throw error; + const todasRespondidas = PERGUNTAS.every(p => respostas[p.id] !== undefined); + const podeSometer = todasRespondidas && notaValida; - const formatados = data?.map((estagio: any) => { - const aluno = Array.isArray(estagio.alunos) ? estagio.alunos[0] : estagio.alunos; - const empresa = Array.isArray(estagio.empresas) ? estagio.empresas[0] : estagio.empresas; - - return { - id_estagio: estagio.id, - aluno_id: aluno?.id, - aluno_nome: aluno?.nome || 'Desconhecido', - turma: aluno?.turma_curso || 'N/A', - n_escola: aluno?.n_escola || '--', - empresa_nome: empresa?.nome || 'N/A', - tutor_nome: empresa?.tutor_nome || 'N/A', - data_inicio: estagio.data_inicio, - data_fim: estagio.data_fim, - horas_totais: estagio.horas_totais || 0, - horas_concluidas: estagio.horas_concluidas || 0, - nota_empresa: estagio.nota_final, - pdf_empresa: estagio.avaliacao_url - }; - }) || []; + // Agrupa perguntas por categoria + const categorias = useMemo(() => { + const mapa: Record = {}; + PERGUNTAS.forEach(p => { + if (!mapa[p.categoria]) mapa[p.categoria] = []; + mapa[p.categoria].push(p); + }); + return mapa; + }, []); - setRelatorios(formatados); - } catch (error) { - console.error(error); - Alert.alert('Erro', 'Não foi possível carregar os dados dos estágios.'); - } finally { - if (!isManualRefresh) setLoading(false); - setRefreshing(false); + const handleSubmit = async () => { + if (!podeSometer) { + Alert.alert('Atenção', 'Preenche todas as questões e insere uma nota final válida (0–20).'); + return; } - }; - useFocusEffect(useCallback(() => { fetchRelatorios(); }, [])); + Alert.alert( + 'Submeter Avaliação', + `Confirmas a avaliação de ${params.aluno_nome} com nota final ${notaFinal} valores?`, + [ + { text: 'Cancelar', style: 'cancel' }, + { + text: 'Confirmar', + onPress: async () => { + setSubmitting(true); + try { + const notaNum = parseFloat(notaFinal.replace(',', '.')); - // 1. GERAR EXCEL (CSV) PERFEITO - const gerarExcelGeral = async () => { - try { - let csvContent = "\uFEFFNumero;Aluno;Turma;Empresa;Horas Feitas;Horas Totais;Nota Empresa;Autoavaliacao\n"; - - relatorios.forEach(r => { - const nota = r.nota_empresa ? r.nota_empresa : 'Pendente'; - const autoav = 'Pendente'; - csvContent += `${r.n_escola};${r.aluno_nome};${r.turma};${r.empresa_nome};${r.horas_concluidas};${r.horas_totais};${nota};${autoav}\n`; - }); + // Guarda as respostas individuais + nota + observações + const { error } = await supabase + .from('estagios') + .update({ + nota_final: notaNum, + avaliacao_observacoes: observacoes.trim() || null, + avaliacao_respostas: respostas, // jsonb no Supabase + avaliacao_data: new Date().toISOString(), + }) + .eq('id', params.estagio_id); - const fileName = `Pauta_Estagios_${new Date().toISOString().split('T')[0]}.csv`; - const fileUri = FileSystem.documentDirectory + fileName; - - await FileSystem.writeAsStringAsync(fileUri, csvContent, { encoding: FileSystem.EncodingType.UTF8 }); - - if (await Sharing.isAvailableAsync()) { - await Sharing.shareAsync(fileUri, { mimeType: 'text/csv', dialogTitle: 'Exportar Pauta Excel' }); - } - } catch (e) { - Alert.alert('Erro', 'Falha ao gerar o Excel.'); - } - }; + if (error) throw error; - // 2. GERAR PAUTA GLOBAL EM PDF COM DESIGN OFICIAL - const gerarPautaPDF = async () => { - try { - const logoEPVC_b64 = await getBase64Image(require('../../../assets/images/logoepvc2.png')); - const logoEstagios_b64 = await getBase64Image(require('../../../assets/images/logo.png')); - const bannerEU_b64 = await getBase64Image(require('../../../assets/images/logoepvc.png')); - - let linhasTabela = ''; - relatorios.forEach(r => { - const nota = r.nota_empresa ? `${r.nota_empresa}` : 'Pendente'; - linhasTabela += ` - - ${r.n_escola} - ${r.aluno_nome} - ${r.turma} - ${r.empresa_nome} - ${r.horas_concluidas}/${r.horas_totais}h - ${nota} - - `; - }); - - const htmlContent = ` - - - - - - - - - - - - - - -
-

Pauta Geral de Estágios

-

Formação em Contexto de Trabalho

-
- -
Resumo de Processos Individuais
- - - - - - - - - - ${linhasTabela} -
Nome do AlunoTurma/CursoEmpresaHorasNota Final
- - - - - - `; - - const { uri } = await Print.printToFileAsync({ html: htmlContent }); - const newFileUri = `${FileSystem.documentDirectory}Pauta_Geral_Estagios.pdf`; - - await FileSystem.moveAsync({ from: uri, to: newFileUri }); - - if (await Sharing.isAvailableAsync()) { - await Sharing.shareAsync(newFileUri, { mimeType: 'application/pdf', UTI: 'com.adobe.pdf' }); - } - } catch (e) { - console.error(e); - Alert.alert('Erro', 'Falha ao gerar a Pauta em PDF.'); - } - }; - - // 3. GERAR PDF DOS SUMÁRIOS DIÁRIOS COM DESIGN OFICIAL - const gerarSumariosPDF = async (r: any) => { - setGerandoPDF(r.id_estagio); - try { - let { data: sumarios, error } = await supabase - .from('registos_diarios') - .select('data, tipo, sumario') - .eq('estagio_id', r.id_estagio) - .order('data', { ascending: true }); - - if (error) throw error; - - if (!sumarios || sumarios.length === 0) { - if (!r.aluno_id) throw new Error("ID do aluno não encontrado."); - - const { data: presencas, error: presencasErr } = await supabase - .from('presencas') - .select('data, estado, sumario') - .eq('aluno_id', r.aluno_id) - .order('data', { ascending: true }); - - if (presencasErr) throw presencasErr; - - if (presencas && presencas.length > 0) { - sumarios = presencas.map(p => ({ - data: p.data, - tipo: p.estado || 'Presença', - sumario: p.sumario - })); - } - } - - if (!sumarios || sumarios.length === 0) { - Alert.alert('Aviso', 'Não foram encontrados registos diários nem presenças para este aluno.'); - setGerandoPDF(null); - return; - } - - let linhasTabela = ''; - sumarios.forEach((s: any) => { - const dataFormatada = new Date(s.data).toLocaleDateString('pt-PT'); - linhasTabela += ` - - ${dataFormatada} - ${s.tipo} - ${s.sumario || 'Sem descrição submetida.'} - - `; - }); - - const logoEPVC_b64 = await getBase64Image(require('../../../assets/images/logoepvc2.png')); - const logoEstagios_b64 = await getBase64Image(require('../../../assets/images/logo.png')); - const bannerEU_b64 = await getBase64Image(require('../../../assets/images/logoepvc.png')); - - const dataInicioFormatada = r.data_inicio ? new Date(r.data_inicio).toLocaleDateString('pt-PT') : 'N/A'; - const dataFimFormatada = r.data_fim ? new Date(r.data_fim).toLocaleDateString('pt-PT') : 'N/A'; - - const htmlContent = ` - - - - - - - - - - - - - - -
-

Diário de Bordo

-

Formação em Contexto de Trabalho

-
- - - - - - - - - - - - - - - - - - - - -
Estagiário:${r.aluno_nome} (Nº ${r.n_escola})Turma/Curso:${r.turma}
Entidade:${r.empresa_nome}Tutor(a):${r.tutor_nome}
Carga Horária:${r.horas_totais} HorasPeríodo:${dataInicioFormatada} a ${dataFimFormatada}
- -
Registo de Atividades Diárias
- - - - - - - ${linhasTabela} -
DataNatureza/EstadoSumário / Atividades Desenvolvidas
- - - - - - `; - - const { uri } = await Print.printToFileAsync({ html: htmlContent }); - const safeName = r.aluno_nome.replace(/[^a-zA-Z0-9]/g, '_'); - const newFileUri = `${FileSystem.documentDirectory}Diario_Bordo_${safeName}.pdf`; - - await FileSystem.moveAsync({ from: uri, to: newFileUri }); - - if (await Sharing.isAvailableAsync()) { - await Sharing.shareAsync(newFileUri, { - mimeType: 'application/pdf', - dialogTitle: `Partilhar Diário de Bordo de ${r.aluno_nome}`, - UTI: 'com.adobe.pdf' - }); - } - - } catch (e) { - console.error("Erro a gerar Sumários PDF:", e); - Alert.alert('Erro', 'Não foi possível ler os registos.'); - } finally { - setGerandoPDF(null); - } + }, + }, + ] + ); }; + // ─── Render ──────────────────────────────────────────────────────────────── return ( - + - - - router.back()}> + + {/* Header */} + + router.back()} style={s.btnBack}> - Gestão de Avaliações - + + Ficha de Avaliação + Formação em Contexto de Trabalho + - { setRefreshing(true); fetchRelatorios(true); }} tintColor={cores.azulMarinho} />} - > - - {/* BOTÕES DE EXPORTAÇÃO GLOBAL */} - - - - Excel (CSV) - - - - - Pauta em PDF - - - - Processos Individuais - - {loading && !refreshing ? ( - - ) : relatorios.length === 0 ? ( - Nenhum estágio encontrado. - ) : ( - relatorios.map((r, index) => ( - - - - - {r.aluno_nome.charAt(0)} - - - {r.aluno_nome} - {r.empresa_nome} • {r.turma} - - - - - - {/* 1. AVALIAÇÃO DA EMPRESA */} - - - 1. Avaliação da Empresa - {r.nota_empresa ? ( - {r.nota_empresa} Val. - ) : ( - Pendente - )} - - {r.pdf_empresa && ( - WebBrowser.openBrowserAsync(r.pdf_empresa)}> - - Ver Ficha de Avaliação - - )} - - - {/* 2. AUTOAVALIAÇÃO DO ALUNO */} - - - 2. Autoavaliação do Aluno - Em Breve - - - - {/* 3. DIÁRIO DE BORDO (PDF) */} - - - 3. Diário de Bordo - {r.horas_concluidas}h Registadas - - gerarSumariosPDF(r)} /* PASSEI A VARIÁVEL COMPLETA AQUI! */ - disabled={gerandoPDF === r.id_estagio} - > - {gerandoPDF === r.id_estagio ? ( - - ) : ( - <> - - Exportar Histórico (PDF) - - )} - - + + + {/* Cartão do Aluno */} + + + {params.aluno_nome?.charAt(0) ?? '?'} - )) - )} + + {params.aluno_nome} + Nº {params.n_escola} · {params.aluno_turma} + + + FCT + + - + {/* Instruções */} + + + + Avalia cada item de 1 (Insatisfatório) a 5 (Excelente). No final, atribui uma nota de 0 a 20. + + + + {/* Perguntas agrupadas por categoria */} + {Object.entries(categorias).map(([categoria, perguntas], catIdx) => ( + + {/* Cabeçalho de categoria */} + + {categoria} + + + {perguntas.map((pergunta, idx) => { + const selecionado = respostas[pergunta.id]; + const globalIdx = PERGUNTAS.findIndex(p => p.id === pergunta.id) + 1; + + return ( + + {/* Número + Texto */} + + + {globalIdx} + + {pergunta.texto} + + + {/* Escala */} + + {ESCALA.map(e => { + const esteSelecionado = selecionado === e.valor; + const cor = corEscala(e.valor, esteSelecionado); + return ( + setRespostas(prev => ({ ...prev, [pergunta.id]: e.valor }))} + activeOpacity={0.75} + > + {e.valor} + + ); + })} + + + {/* Label do selecionado */} + {selecionado && ( + + {ESCALA.find(e => e.valor === selecionado)?.label} + + )} + + ); + })} + + ))} + + {/* Nota Final */} + + Nota Final + + Atribui uma nota de 0 a 20 valores. Abaixo de 9,5 é negativa. + + + + + / 20 valores + + {notaFinal !== '' && ( + = 9.5 ? '#DCFCE7' : '#FEE2E2') : '#F3F4F6' } + ]}> + = 9.5 ? '#15803D' : '#B91C1C') : cores.textoSecundario } + ]}> + {notaValida + ? parseFloat(notaFinal.replace(',', '.')) >= 9.5 ? '✓ Positiva' : '✗ Negativa' + : 'Inválido'} + + + )} + + + + {/* Observações */} + + Observações + Opcional — comentários adicionais sobre o desempenho. + + + + {/* Progresso */} + + + + {Object.keys(respostas).length} de {PERGUNTAS.length} questões respondidas + + + {todasRespondidas ? '✓ Completo' : 'Incompleto'} + + + + + + + + {/* Botão Submeter */} + + {submitting ? ( + + ) : ( + <> + + + Submeter Avaliação + + + )} + + + + + ); } -const styles = StyleSheet.create({ - safeArea: { flex: 1 }, - header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingTop: 15, paddingBottom: 10 }, - btnVoltar: { padding: 5, marginLeft: -5 }, - headerTitle: { fontSize: 18, fontWeight: '900' }, - scrollContent: { padding: 20, paddingBottom: 40 }, - - botoesGlobaisContainer: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 25, gap: 15 }, - btnGlobal: { flex: 1, flexDirection: 'column', alignItems: 'center', paddingVertical: 18, borderRadius: 20, borderWidth: 1.5, elevation: 1 }, - btnGlobalText: { fontSize: 14, fontWeight: '900', marginTop: 8 }, - - sectionTitle: { fontSize: 14, fontWeight: '900', textTransform: 'uppercase', color: '#64748B', marginBottom: 15, marginLeft: 5, letterSpacing: 1 }, - - card: { padding: 20, borderRadius: 20, borderWidth: 1, marginBottom: 20 }, - cardHeader: { flexDirection: 'row', alignItems: 'center' }, - avatar: { width: 44, height: 44, borderRadius: 22, justifyContent: 'center', alignItems: 'center' }, - alunoName: { fontSize: 16, fontWeight: '900' }, - alunoSub: { fontSize: 12, fontWeight: '600', marginTop: 2 }, - divider: { height: 1, marginVertical: 15 }, - - moduloBox: { borderBottomWidth: 1, borderBottomColor: '#E2E8F0', paddingBottom: 15, marginBottom: 15 }, - moduloHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }, - moduloTitle: { fontSize: 13, fontWeight: '800' }, - notaTag: { fontSize: 11, fontWeight: '900', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 6 }, - - btnAcaoLigeiro: { flexDirection: 'row', alignItems: 'center', alignSelf: 'flex-start', paddingVertical: 6, paddingHorizontal: 12, borderRadius: 8, borderWidth: 1, marginTop: 10, gap: 6 }, - textoAcao: { fontSize: 12, fontWeight: '800' } +// ─── Estilos ────────────────────────────────────────────────────────────────── +const s = StyleSheet.create({ + safe: { flex: 1 }, + header: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 20, paddingTop: 15, paddingBottom: 12, gap: 14 }, + btnBack: { padding: 4 }, + headerTitle: { fontSize: 18, fontWeight: '900' }, + headerSub: { fontSize: 12, fontWeight: '500', marginTop: 1 }, + scroll: { paddingHorizontal: 16, paddingBottom: 20 }, + + // Aluno card + alunoCard: { flexDirection: 'row', alignItems: 'center', borderRadius: 18, padding: 18, marginBottom: 16 }, + alunoAvatar: { width: 46, height: 46, borderRadius: 23, backgroundColor: 'rgba(255,255,255,0.2)', justifyContent: 'center', alignItems: 'center' }, + alunoAvatarLetra: { color: '#fff', fontSize: 20, fontWeight: '900' }, + alunoNome: { color: '#fff', fontSize: 16, fontWeight: '900' }, + alunoMeta: { color: 'rgba(255,255,255,0.7)', fontSize: 12, fontWeight: '600', marginTop: 3 }, + badgeFCT: { paddingHorizontal: 10, paddingVertical: 5, borderRadius: 8 }, + badgeFCTText: { color: '#fff', fontSize: 11, fontWeight: '900', letterSpacing: 1 }, + + // Instruções + instrucoes: { flexDirection: 'row', alignItems: 'flex-start', borderRadius: 12, borderWidth: 1, padding: 12, marginBottom: 20 }, + instrucoesTxt: { flex: 1, fontSize: 13, lineHeight: 19 }, + + // Categoria + catHeader: { borderRadius: 8, paddingVertical: 7, paddingHorizontal: 14, marginBottom: 10, marginTop: 6 }, + catHeaderTxt: { color: '#fff', fontSize: 11, fontWeight: '800', letterSpacing: 1, textTransform: 'uppercase' }, + + // Pergunta + perguntaCard: { borderRadius: 16, borderWidth: 1, padding: 16, marginBottom: 10 }, + perguntaTop: { flexDirection: 'row', alignItems: 'flex-start', marginBottom: 14, gap: 12 }, + numCircle: { width: 28, height: 28, borderRadius: 14, justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: 1 }, + numTxt: { fontSize: 13, fontWeight: '900' }, + perguntaTxt: { flex: 1, fontSize: 14, fontWeight: '600', lineHeight: 20 }, + + // Escala + escalaRow: { flexDirection: 'row', gap: 8, justifyContent: 'space-between' }, + escalaBotao: { flex: 1, aspectRatio: 1, borderRadius: 12, borderWidth: 1.5, justifyContent: 'center', alignItems: 'center', maxWidth: 54 }, + escalaNum: { fontSize: 17, fontWeight: '900' }, + escalaLabel: { fontSize: 11, fontWeight: '600', marginTop: 8, textAlign: 'center' }, + + // Nota final + secaoFinal: { borderRadius: 18, borderWidth: 1, padding: 18, marginBottom: 14 }, + secaoTitulo: { fontSize: 16, fontWeight: '900', marginBottom: 4 }, + secaoDesc: { fontSize: 13, marginBottom: 14, lineHeight: 18 }, + notaRow: { flexDirection: 'row', alignItems: 'center', gap: 12 }, + notaInput: { borderWidth: 2, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 12, fontSize: 22, fontWeight: '900', width: 90, textAlign: 'center' }, + notaSufixo: { fontSize: 15, fontWeight: '700' }, + notaBadge: { paddingHorizontal: 10, paddingVertical: 6, borderRadius: 8 }, + notaBadgeTxt: { fontSize: 13, fontWeight: '800' }, + + // Observações + obsInput: { borderWidth: 1.5, borderRadius: 12, padding: 14, fontSize: 14, minHeight: 100, lineHeight: 21 }, + + // Progresso + progressoBox: { borderRadius: 14, borderWidth: 1, padding: 14, marginBottom: 16 }, + progressoRow: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 8 }, + progressoLabel: { fontSize: 12, fontWeight: '600' }, + progressoBar: { height: 6, borderRadius: 3, overflow: 'hidden' }, + progressoFill: { height: '100%', borderRadius: 3 }, + + // Botão submeter + btnSubmeter: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 10, paddingVertical: 17, borderRadius: 18, marginTop: 4 }, + btnSubmeterTxt: { fontSize: 16, fontWeight: '900' }, }); \ No newline at end of file