feat(android): app de campo móvil+tablet (UI, mapa, fotos, auto-sync, reconciliación)

Fase 0: config Android (package, permisos, orientación), eas.json (APK), deps
  nativas (react-native-maps, image-picker, location), app.config.js para la key
  de Google Maps por secreto EAS.
Fase 1: capa responsive (useLayout) + componente MasterDetail (dos paneles en
  tablet, navegación en móvil).
Fase 2: pantallas funcionales — detalle de proyecto con secciones Fases/Features/
  Incidencias, edición de progreso/estado, formulario de inspección dinámico
  desde plantilla, incidencias maestro-detalle (checklist + comentarios), alta de
  incidencia; gating por permisos Spatie.
Fase 3: fotos (cámara/galería) → cola de media, con miniaturas pendientes/sync.
Fase 4: mapa de features (Google Maps) con geometría GeoJSON y selección.
Fase 5: auto-sync (foreground/reconexión/intervalo, con candado) + reconciliación
  de creaciones offline (id temporal negativo → server_id, remapeo de FKs hijas).
Fase 6: revisión de conflictos/errores del outbox, indicadores y APK preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
javier
2026-06-18 18:30:44 +02:00
co-authored by Claude Opus 4.8
parent 4e9c7d059f
commit 9bcc51e3b2
36 changed files with 2532 additions and 131 deletions
+2 -1
View File
@@ -12,7 +12,7 @@ import {
import * as api from '../api/endpoints';
import { Project } from '../api/types';
import { useSession } from '../auth/session';
import { getCursor, getProjects, saveProjectList } from '../db/repositories';
import { getCursor, getProjects, saveProjectList, setActiveProjectId } from '../db/repositories';
import { isOnline } from '../net/connectivity';
import { initialPull, runSync } from '../sync/engine';
import { RootStackParamList } from '../navigation/types';
@@ -52,6 +52,7 @@ export function ProjectsScreen({ navigation }: Props) {
async (p: Project) => {
setOpening(p.id);
try {
await setActiveProjectId(p.id);
const online = await isOnline();
if (online) {
const cursor = await getCursor(p.id);