Aplicativo multiplataforma (Android, iOS e Web) construído em React Native com Expo SDK 58 e Expo Router, conectado em tempo real à API REST em Node.js e Express hospedada em produção (https://krono.engine.lat/api).
- Nome da aplicação: Krono (
com.sagihtt.krono) - Problema que busca resolver: Equipes presenciais, híbridas ou em campo frequentemente enfrentam atrasos no fechamento de folha quando o controle de ponto depende de anotações manuais, planilhas soltas ou sistemas que travam sem sinal de celular. Isso gera divergências sobre o horário e o local da batida, perda de atestados médicos e lentidão na hora de registrar entradas e intervalos. O Krono resolve esse fluxo reunindo confirmação biométrica, localização convertida em endereço legível e fotografia de comprovação em uma única tela rápida. Os registros vão direto para o servidor em nuvem (
https://krono.engine.lat/api) com histórico isolado por aparelho, mantendo o armazenamento local como contingência automática quando o dispositivo fica sem internet.
- Marcação de Ponto Instantânea com Pré-seleção Inteligente (
app/(tabs)/index.tsxeutils/jornada.ts): Exibe data, turno ativo e relógio digital contínuo, sugere automaticamente a próxima batida do dia na ordem natural da jornada (Entrada Regular,Intervalo,Retorno,Saída RegulareHora Extra) e atualiza a tela na hora do toque enquanto sincroniza foto e dados em segundo plano. - Histórico Sincronizado e Modo Compacto (
app/(tabs)/index.tsxecomponents/RegistroCard.tsx): Lista cronológica das marcações com selos que indicam se o registro já está salvo na nuvem (Sincronizado) ou aguardando conexão (Salvo no aparelho), indicadores de foto ou PDF anexado e chave para alternar a densidade visual dos cartões. - Comprovante Individual com Edição, Exclusão e Mapa (
app/detalhes/[id].tsx): Tela dedicada para cada registro que mostra todos os metadados da batida, abre a posição no Google Maps, compartilha o recibo formatado, edita informações (PUT /pontos/:id) e remove marcações com confirmação direta (DELETE /pontos/:id). - Central de Documentos, Atestados e Espelho de Ponto (
app/(tabs)/explore.tsx): Permite anexar justificativas em PDF ao registro mais recente, enviar fotos da galeria ao servidor viamultipart/form-data(POST /upload), gerar o relatóriovistoria-ponto.txtno armazenamento interno do celular e salvar cópias de comprovantes fotográficos no álbum do aparelho. - Perfil do Colaborador e Escala de Trabalho (
app/(tabs)/cadastro.tsx): Cadastro com máscaras automáticas para CPF, telefone e data de nascimento, grade 2x2 para escolha do turno de trabalho (Diurno,Flexível,Escala 12x36eRemoto / Híbrido) e configuração do endereço da API.
| Categoria | Recursos Utilizados | Aplicação no Projeto |
|---|---|---|
| React Hooks | useState, useEffect, useCallback, useRef, useFocusEffect |
Controle dos campos, listas, permissões e estados de carregamento (useState); ciclo do relógio isolado em components/RelogioDigital.tsx e aquecimento de GPS (useEffect); referência da câmera e cache temporal (useRef); atualização ao alternar abas (useFocusEffect). |
| Componentes Nativos e Listas | FlatList, ScrollView, Switch, TextInput, Pressable, TouchableOpacity, Alert, Image, ActivityIndicator, KeyboardAvoidingView, Modal |
Listagem virtualizada do histórico com FlatList (keyExtractor, renderItem e ListHeaderComponent); alternância do modo compacto (Switch); formulários controlados com máscaras em utils/masks.ts; gaveta lateral em Modal. |
| Desempenho e Layout | React.memo, Animated, useWindowDimensions, AbortController |
Cartões memorizados em components/RegistroCard.tsx; animações de mola nos botões (components/BotaoPress.tsx) e no menu deslizante (components/AppShell.tsx); layout adaptativo entre celular (< 960px) e Web (>= 960px); timeout controlado nas chamadas de rede. |
| Navegação | React Navigation (@react-navigation/native, bottom-tabs) e Expo Router (Stack, Tabs, Link, useRouter, useLocalSearchParams, usePathname) |
Abas inferiores (Jornada, Documentos e Perfil em app/(tabs)/_layout.tsx), pilha principal (app/_layout.tsx), rota dinâmica de comprovantes (app/detalhes/[id].tsx), links declarativos (<Link>) e navegação imperativa (router.push, router.replace). |
| Persistência Local | AsyncStorage (@react-native-async-storage/async-storage) |
Camada services/storageService.ts com setItem, getItem, removeItem e serialização JSON.stringify / JSON.parse para guardar perfil, preferências, identificador do aparelho (X-Krono-Client-Id) e fila offline de registros. |
| APIs e Servidor | fetch(), FormData, Node.js + Express (api/server.js), Docker, Nginx e OpenStreetMap Nominatim |
Cliente HTTP (services/apiService.ts) integrado às rotas GET /health, GET /clima, GET /pontos, GET /pontos/:id, POST /pontos, PUT /pontos/:id, DELETE /pontos/:id e POST /upload, com persistência em disco no servidor krono.engine.lat e geocodificação reversa de endereços. |
O aplicativo utiliza seis integrações nativas do sistema operacional móvel, destacando-se na operação diária:
- Câmera Integrada (
expo-cameraemapp/(tabs)/index.tsx): Solicita permissão pelo hookuseCameraPermissions(), renderiza o visor ao vivo com<CameraView />, alterna entre lente frontal e traseira e dispara a captura rápida (takePictureAsync({ quality: 0.45, skipProcessing: true })) no ato da batida, exibindo a miniatura anexada e enviando o arquivo ao servidor. - Geolocalização GPS e Geocodificação Reversa (
expo-locationemapp/(tabs)/index.tsxeapp/detalhes/[id].tsx): Requisita acesso em primeiro plano (requestForegroundPermissionsAsync), lê coordenadas físicas com reaproveitamento de leitura recente (getLastKnownPositionAsyncegetCurrentPositionAsync) e converte latitude e longitude em rua, bairro e cidade (reverseGeocodeAsync), oferecendo atalho direto para abrir o ponto no mapa. - Biometria do Dispositivo (
expo-local-authenticationemapp/(tabs)/index.tsx): Consulta a presença de leitor biométrico cadastrado (hasHardwareAsynceisEnrolledAsync) e exige confirmação por impressão digital ou reconhecimento facial (authenticateAsync) antes de efetivar a marcação no celular. - Sistema de Arquivos Interno (
expo-file-systememapp/(tabs)/explore.tsx): Grava e lê o arquivo físicovistoria-ponto.txtdentro do diretório privado do aplicativo (Paths.documente classeFile) para emissão offline do espelho de jornada. - Seletor de Documentos PDF e Galeria (
expo-document-pickereexpo-image-pickeremapp/(tabs)/explore.tsx): Abre o seletor nativo filtrando arquivosapplication/pdf(getDocumentAsync) para vincular atestados médicos ao ponto e acessa a galeria com corte4:3(launchImageLibraryAsync). - Compartilhamento Nativo, Galeria Pública e Resposta Tátil (
expo-sharing,Share,expo-media-libraryeexpo-haptics): Compartilha arquivos físicos (Sharing.shareAsync) e recibos em texto (Share.share), salva fotos no álbum do aparelho com permissão exclusiva de escrita (MediaLibrary.saveToLibraryAsync) e aciona vibração tátil na troca de abas (components/haptic-tab.tsx).
As telas abaixo retratam o aplicativo conectado ao servidor https://krono.engine.lat/api:
- Aplicação Web em Produção: https://krono.engine.lat
- API REST Online (Healthcheck): https://krono.engine.lat/api/health
- Download Direto do APK Android (
v2.3.0no GitHub): krono-v2.3.0.apk - Download Direto do APK Android (
v2.3.0no Expo EAS): luksox1m1-J3wl4eQmMySwmBQC-InKL-_W0PiU-z2lQ.apk - Compilação EAS Build (
v2.3.0): Build6cffc7e2-3b00-4f90-975a-3e06e4676630 - Release Oficial no GitHub: https://github.com/sagihtt/Krono/releases/tag/v2.3.0
- Painel de Compilações no Expo (EAS): https://expo.dev/accounts/sagihtt/projects/registrodeponto/builds
Qualquer pessoa que instalar o APK no Android já sai conectada por padrão ao endereço
https://krono.engine.lat/api, sem precisar configurar IP local nem depender apenas do armazenamento interno.
registroDePonto/
├── __tests__/
│ └── krono.test.mjs # Testes unitários de máscaras, jornada e auditoria de UI
├── api/ # Backend Node.js + Express (v2.3.0)
│ ├── __tests__/server.test.js # Testes de integração REST, isolamento e upload binário
│ ├── nginx/ # Configuração de proxy reverso para krono.engine.lat
│ ├── Dockerfile # Imagem de produção Node 20 Alpine
│ ├── docker-compose.yml # Orquestração com volume persistente em disco
│ └── server.js # Servidor Express com persistência atômica por cliente
├── app/ # Rotas do Expo Router
│ ├── (tabs)/
│ │ ├── _layout.tsx # Abas inferiores (Jornada, Documentos e Perfil)
│ │ ├── index.tsx # Registro otimista, biometria, GPS, câmera e FlatList
│ │ ├── explore.tsx # Anexos PDF, upload multipart, espelho TXT e galeria
│ │ └── cadastro.tsx # Perfil cadastral, máscaras e seletor de turnos 2x2
│ ├── detalhes/[id].tsx # Comprovante individual com edição, exclusão e compartilhamento
│ └── _layout.tsx # Pilha raiz de navegação
├── assets/images/ # Logotipo vetorial SVG e ícones adaptativos com fundo escuro
├── components/ # Componentes reutilizáveis (AppShell, KronoLogo, RelogioDigital, etc.)
├── constants/ # Paleta de cores, raios e registros demonstrativos
├── models/ # Tipagens TypeScript (PontoRegistro, PerfilColaborador, etc.)
├── services/ # Cliente HTTP com timeout (apiService) e cache local (storageService)
├── utils/ # Regras de progressão de jornada e máscaras de formulário
├── CHANGELOG.md # Histórico de versões (v1.0.0 a v2.3.0)
└── README.md
npm install
npx expo startnpm run test:all
./node_modules/.bin/tsc --noEmit
npm run lintcd api
npm install
npm startCaso queira apontar o aplicativo para http://localhost:3000 durante testes locais, basta alterar o campo de servidor na aba Perfil.







