import { useCallback, useEffect, useState } from "react"; import { View, Text, Pressable, FlatList, StyleSheet, Alert } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useAuth } from "@/auth"; import { api, ApiError, type Asset } from "@/api"; import { C } from "@/theme"; export default function Review() { const { token, logout } = useAuth(); const [assets, setAssets] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const onErr = useCallback( (err: unknown): void => { if (err instanceof ApiError && err.status === 401) void logout(); else setError(err instanceof Error ? err.message : "Erreur"); }, [logout], ); const refresh = useCallback(async (): Promise => { if (!token) return; setLoading(true); try { const { assets } = await api.review(token); setAssets(assets); setError(null); } catch (err) { onErr(err); } finally { setLoading(false); } }, [token, onErr]); useEffect(() => { void refresh(); }, [refresh]); const decide = async (id: string, action: "approve" | "refuse"): Promise => { if (!token) return; try { if (action === "approve") await api.approve(token, id); else await api.refuse(token, id); await refresh(); } catch (err) { onErr(err); } }; const confirmRefuse = (id: string): void => { Alert.alert("Refuser", `Refuser définitivement ${id} ?`, [ { text: "Annuler", style: "cancel" }, { text: "Refuser", style: "destructive", onPress: () => void decide(id, "refuse") }, ]); }; return ( a.id} contentContainerStyle={{ padding: 12, gap: 8 }} onRefresh={() => void refresh()} refreshing={loading} ListEmptyComponent={!loading ? Aucun asset en attente. : null} ListHeaderComponent={error ? {error} : null} renderItem={({ item: a }) => ( {a.id} {a.riskTier} · {a.status} · v{a.version} void decide(a.id, "approve")}> Approuver confirmRefuse(a.id)}> Refuser )} /> void logout()}> Déconnexion ); } const s = StyleSheet.create({ wrap: { flex: 1, backgroundColor: C.bg }, muted: { color: C.muted, fontSize: 13 }, error: { color: C.danger, fontSize: 13, marginBottom: 8 }, card: { backgroundColor: C.surface, borderColor: C.border, borderWidth: 1, borderRadius: 10, padding: 12, gap: 6 }, id: { color: C.fg, fontFamily: "monospace", fontSize: 13 }, tier: { fontSize: 12 }, actions: { flexDirection: "row", gap: 8, marginTop: 4 }, act: { flexDirection: "row", alignItems: "center", gap: 4, borderWidth: 1, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 6 }, approve: { borderColor: C.success }, refuse: { borderColor: C.danger }, actText: { fontSize: 13 }, logout: { flexDirection: "row", alignItems: "center", justifyContent: "center", padding: 12, borderTopWidth: 1, borderTopColor: C.border }, });