/** * Revisión del outbox: operaciones en conflicto o con error. Permite reintentar * (volver a encolar) o descartar. Los conflictos muestran el valor del servidor. */ import { useFocusEffect } from '@react-navigation/native'; import React, { useCallback, useState } from 'react'; import { ScrollView, StyleSheet, Text, View } from 'react-native'; import { discardOp, getProblemOps, ProblemOp, retryOp } from '../db/outbox'; import { Badge, Card, COLORS, EmptyState, PrimaryButton } from '../ui/components'; export function OutboxScreen() { const [ops, setOps] = useState([]); const load = useCallback(() => { void getProblemOps().then(setOps); }, []); useFocusEffect(load); const onRetry = useCallback( async (uuid: string) => { await retryOp(uuid); load(); }, [load], ); const onDiscard = useCallback( async (uuid: string) => { await discardOp(uuid); load(); }, [load], ); return ( {ops.length === 0 && } {ops.map((o) => ( {o.entity}.{o.op} {o.error ? {o.error} : null} {o.server_payload ? ( Servidor: {o.server_payload} ) : null} Local: {o.data} void onRetry(o.uuid)} /> void onDiscard(o.uuid)} /> ))} ); } const styles = StyleSheet.create({ body: { padding: 16, gap: 12 }, card: { gap: 8 }, headerRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }, entity: { fontSize: 15, fontWeight: '700' }, error: { color: COLORS.danger, fontSize: 13 }, mono: { fontSize: 12, color: COLORS.muted, fontFamily: 'monospace' }, actions: { flexDirection: 'row', gap: 8, marginTop: 4 }, });