chore: add new features

This commit is contained in:
2026-03-05 19:09:16 +01:00
parent 532584edb2
commit 5ca480ea0b
23 changed files with 695 additions and 284 deletions
@@ -6,6 +6,7 @@ import {
FlatList,
RefreshControl,
ScrollView,
TouchableOpacity,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { spacing, fontSize, borderRadius } from "../../theme";
@@ -14,6 +15,9 @@ import { getAllCommands } from "../../api/api_admin";
import {
getCommandItems,
deleteCommand,
confirmReceptionCabine,
getCabineLivreursList,
assignDeliveryPersonByCabine,
} from "../../api/api_cabine";
import type { CommandResponse } from "../../api/types";
import StatusBadge from "../../components/StatusBadge";
@@ -61,6 +65,11 @@ export default function OrdersScreen() {
commandInfo: null,
clientInfo: null,
});
const [assignModal, setAssignModal] = useState<{
visible: boolean;
commandId: number | null;
}>({ visible: false, commandId: null });
const [livreurs, setLivreurs] = useState<{ id: number; username: string }[]>([]);
const loadData = useCallback(async () => {
try {
@@ -81,6 +90,13 @@ export default function OrdersScreen() {
loadData();
}, [loadData]);
useEffect(() => {
const interval = setInterval(() => {
loadData();
}, 30000);
return () => clearInterval(interval);
}, [loadData]);
const onRefresh = async () => {
setRefreshing(true);
await loadData();
@@ -103,6 +119,22 @@ export default function OrdersScreen() {
};
const handleConfirmReception = (commandId: number) => {
showConfirm(
"Confirmer la réception",
`Confirmer la réception de la commande #${commandId} au nom du client ?`,
async () => {
try {
await confirmReceptionCabine(commandId);
await loadData();
} catch (e: any) {
showError("Erreur", e.message);
}
},
"Confirmer",
);
};
const handleDelete = (commandId: number) => {
showConfirm(
"Supprimer",
@@ -128,6 +160,27 @@ export default function OrdersScreen() {
clientInfo: null,
});
const openAssignModal = async (commandId: number) => {
try {
const list = await getCabineLivreursList();
setLivreurs(list);
setAssignModal({ visible: true, commandId });
} catch {
showError("Erreur", "Impossible de charger les livreurs");
}
};
const handleAssign = async (livreurUsername: string) => {
if (!assignModal.commandId) return;
try {
await assignDeliveryPersonByCabine(assignModal.commandId, livreurUsername);
setAssignModal({ visible: false, commandId: null });
await loadData();
} catch (e: any) {
showError("Erreur", e.message);
}
};
const styles = useMemo(
() =>
StyleSheet.create({
@@ -271,6 +324,16 @@ export default function OrdersScreen() {
fontSize: fontSize.xs,
fontWeight: "600",
},
livreurItem: {
flexDirection: "row",
alignItems: "center",
padding: spacing.m,
backgroundColor: colors.bgCard,
borderRadius: borderRadius.sm,
marginBottom: spacing.s,
gap: spacing.m,
},
livreurName: { color: colors.textWhite, fontSize: fontSize.md },
}),
[colors],
);
@@ -293,6 +356,20 @@ export default function OrdersScreen() {
size="sm"
variant="primary"
/>
<Button
title="Assigner"
onPress={() => openAssignModal(item.id)}
size="sm"
variant="secondary"
/>
{item.status === "livre" && (
<Button
title="Confirmer réception"
onPress={() => handleConfirmReception(item.id)}
size="sm"
variant="success"
/>
)}
<Button
title="Supprimer"
onPress={() => handleDelete(item.id)}
@@ -461,6 +538,33 @@ export default function OrdersScreen() {
</ScrollView>
</Modal>
<Modal
visible={assignModal.visible}
onClose={() =>
setAssignModal({ visible: false, commandId: null })
}
title={`Assigner commande #${assignModal.commandId}`}
icon="bicycle-outline"
>
{livreurs.map((l) => (
<TouchableOpacity
key={l.username}
style={styles.livreurItem}
onPress={() => handleAssign(l.username)}
>
<Ionicons
name="person-outline"
size={20}
color={colors.accent}
/>
<Text style={styles.livreurName}>{l.username}</Text>
</TouchableOpacity>
))}
{livreurs.length === 0 && (
<Text style={styles.empty}>Aucun livreur disponible</Text>
)}
</Modal>
<AlertModal
visible={alert.visible}
type={alert.type}