import React, { useState, useEffect, useCallback, useMemo } from "react"; import { View, Text, StyleSheet, FlatList, TouchableOpacity, RefreshControl, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, fontSize } from "../../theme"; import { useTheme } from "../../context/ThemeContext"; import { addAddress, deleteAddress, getAllAddresses } from "../../api/api_admin"; import { useAlert } from "../../hooks/useAlert"; import Card from "../../components/ui/Card"; import Modal from "../../components/ui/Modal"; import TextInput from "../../components/ui/TextInput"; import Button from "../../components/ui/Button"; import AlertModal from "../../components/ui/AlertModal"; type AddressEntry = { invalid_address: string; correct_address: string; }; export default function AddressScreen() { const { colors } = useTheme(); const { alert, showError, showSuccess, showConfirm, hideAlert } = useAlert(); const [addresses, setAddresses] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [addModal, setAddModal] = useState(false); const [invalidInput, setInvalidInput] = useState(""); const [correctInput, setCorrectInput] = useState(""); const [saving, setSaving] = useState(false); const loadAddresses = useCallback(async () => { try { const result = await getAllAddresses(); setAddresses(result); } catch (e: any) { showError("Erreur", e.response?.data?.error ?? e.message); } finally { setLoading(false); } }, [showError]); useEffect(() => { loadAddresses(); }, [loadAddresses]); const onRefresh = async () => { setRefreshing(true); await loadAddresses(); setRefreshing(false); }; const openAddModal = () => { setInvalidInput(""); setCorrectInput(""); setAddModal(true); }; const handleAdd = useCallback(async () => { const inv = invalidInput.trim(); const cor = correctInput.trim(); if (!inv || !cor) { showError("Erreur", "Les deux champs sont obligatoires."); return; } setSaving(true); try { await addAddress(inv, cor); setAddresses((prev) => [ ...prev, { invalid_address: inv, correct_address: cor }, ]); setAddModal(false); showSuccess("Succès", "Adresse ajoutée avec succès."); } catch (e: any) { showError("Erreur", e.response?.data?.error ?? e.message); } finally { setSaving(false); } }, [invalidInput, correctInput, showError, showSuccess]); const handleDelete = useCallback( (item: AddressEntry) => { showConfirm( "Supprimer", `Supprimer la correction :\n"${item.invalid_address}" → "${item.correct_address}" ?`, async () => { try { await deleteAddress(item.invalid_address, item.correct_address); setAddresses((prev) => prev.filter( (a) => a.invalid_address !== item.invalid_address || a.correct_address !== item.correct_address, ), ); showSuccess("Supprimé", "Adresse supprimée."); } catch (e: any) { showError("Erreur", e.response?.data?.error ?? e.message); } }, "Supprimer", ); }, [showConfirm, showError, showSuccess], ); const styles = useMemo( () => StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bgPrimary }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", padding: spacing.l, paddingBottom: spacing.s, }, title: { color: colors.textWhite, fontSize: fontSize.lg, fontWeight: "700", }, addBtn: { backgroundColor: colors.accent, borderRadius: 20, padding: spacing.s, }, invalid: { color: colors.danger, fontSize: fontSize.md, fontWeight: "600", }, correct: { color: colors.success, fontSize: fontSize.md, fontWeight: "600", marginTop: 6, }, label: { fontSize: fontSize.xs, fontWeight: "700", letterSpacing: 0.5, marginBottom: 2, }, labelInvalid: { color: colors.danger, }, labelCorrect: { color: colors.success, }, arrow: { color: colors.textMuted, fontSize: fontSize.lg, marginVertical: 4, }, row: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", }, empty: { color: colors.textMuted, textAlign: "center", marginTop: spacing.xxl, fontSize: fontSize.md, }, }), [colors], ); const renderItem = ({ item }: { item: AddressEntry }) => ( {item.invalid_address} {item.correct_address} handleDelete(item)}> ); return ( Corrections d'adresses `${item.invalid_address}-${i}`} renderItem={renderItem} contentContainerStyle={{ padding: spacing.l, paddingTop: spacing.s }} refreshControl={ } ListEmptyComponent={ {loading ? "Chargement..." : "Aucune correction.\nAppuyez sur + pour en ajouter une."} } /> setAddModal(false)} title="Ajouter une correction" icon="map-outline" >