diff --git a/frontend-admin/src/api/api_admin.ts b/frontend-admin/src/api/api_admin.ts
index 4dfa5f6d..baff19fc 100644
--- a/frontend-admin/src/api/api_admin.ts
+++ b/frontend-admin/src/api/api_admin.ts
@@ -119,7 +119,7 @@ export const getCommandByID = async (commandId: number) => {
export const getCommandItems = async (commandId: number) => {
const { data } = await apiClient.get(
- `${CABINE_URL}/commands/${commandId}/items`,
+ `${V2}/admin/protected/orders/${commandId}/items`,
);
return {
success: true,
@@ -130,6 +130,13 @@ export const getCommandItems = async (commandId: number) => {
};
};
+export const deleteCommandItem = async (commandId: number, itemId: number) => {
+ const { data } = await apiClient.delete(
+ `${V2}/admin/protected/orders/${commandId}/items/${itemId}`,
+ );
+ return { success: true, message: data.message };
+};
+
export const updateCommandStatus = async (
commandId: number,
newStatus: string,
@@ -159,6 +166,13 @@ export const validateCommand = async (commandId: number) => {
return { success: true, message: data.message };
};
+export const notifyClientToDescend = async (commandId: number) => {
+ const { data } = await apiClient.post(
+ `${V2}/admin/protected/orders/${commandId}/notify-client`,
+ );
+ return { success: true, message: data.message, client_username: data.client_username };
+};
+
export const confirmReceptionAdmin = async (commandId: number) => {
const { data } = await apiClient.post(
`${V2}/admin/protected/orders/${commandId}/confirm-reception`,
diff --git a/frontend-admin/src/api/api_cabine.ts b/frontend-admin/src/api/api_cabine.ts
index f89185e7..78f64f0a 100644
--- a/frontend-admin/src/api/api_cabine.ts
+++ b/frontend-admin/src/api/api_cabine.ts
@@ -117,6 +117,13 @@ export const deleteCommand = async (commandId: number) => {
return { success: true, message: data.message };
};
+export const notifyClientToDescendCabine = async (commandId: number) => {
+ const { data } = await apiClient.post(
+ `${API}/commands/${commandId}/notify-client`,
+ );
+ return { success: true, message: data.message, client_username: data.client_username };
+};
+
export const getCabineLivreursList = async (): Promise<
{ id: number; username: string }[]
> => {
diff --git a/frontend-admin/src/components/ui/Button.tsx b/frontend-admin/src/components/ui/Button.tsx
index e0f8fc9c..070ddc0d 100644
--- a/frontend-admin/src/components/ui/Button.tsx
+++ b/frontend-admin/src/components/ui/Button.tsx
@@ -18,6 +18,7 @@ interface ButtonProps {
| "secondary"
| "danger"
| "success"
+ | "warning"
| "outline"
| "ghost";
size?: "sm" | "md" | "lg";
@@ -46,6 +47,7 @@ export default function Button({
secondary: colors.bgCard,
danger: colors.danger,
success: colors.success,
+ warning: colors.warning,
outline: "transparent",
ghost: "transparent",
}[variant];
diff --git a/frontend-admin/src/screens/admin/OrderDetailScreen.tsx b/frontend-admin/src/screens/admin/OrderDetailScreen.tsx
index 6650e0f6..603a090d 100644
--- a/frontend-admin/src/screens/admin/OrderDetailScreen.tsx
+++ b/frontend-admin/src/screens/admin/OrderDetailScreen.tsx
@@ -7,6 +7,7 @@ import {
TouchableOpacity,
Modal,
StatusBar,
+ Alert,
} from "react-native";
import { useRoute, type RouteProp } from "@react-navigation/native";
import { Ionicons } from "@expo/vector-icons";
@@ -19,7 +20,9 @@ import {
updateCommandStatus,
validateCommand,
confirmReceptionAdmin,
+ notifyClientToDescend,
getDeliveryPersonDetails,
+ deleteCommandItem,
} from "../../api/api_admin";
import { geocodeAddress, calculateRoute } from "../../api/tomtom";
import type { RouteInfo, LatLng } from "../../api/tomtom";
@@ -167,6 +170,40 @@ export default function OrderDetailScreen() {
}
};
+ const handleNotifyClient = async () => {
+ try {
+ await notifyClientToDescend(orderId);
+ showSuccess("Notification envoyée", "Le client a été prévenu de descendre");
+ } catch (e: any) {
+ showError("Erreur", e.message);
+ }
+ };
+
+ const handleDeleteItem = (itemId: number, itemName: string) => {
+ Alert.alert(
+ "Supprimer l'article",
+ `Supprimer "${itemName}" de la commande ?`,
+ [
+ { text: "Annuler", style: "cancel" },
+ {
+ text: "Supprimer",
+ style: "destructive",
+ onPress: async () => {
+ try {
+ await deleteCommandItem(orderId, itemId);
+ const itemsRes = await getCommandItems(orderId);
+ setItems(itemsRes.items);
+ const cmdRes = await getCommandByID(orderId);
+ setCommand(cmdRes.command);
+ } catch (e: any) {
+ showError("Erreur", e.message);
+ }
+ },
+ },
+ ],
+ );
+ };
+
const handleConfirmReception = async () => {
try {
const res = await confirmReceptionAdmin(orderId);
@@ -222,6 +259,11 @@ export default function OrderDetailScreen() {
itemDetails: {
flexDirection: "row",
justifyContent: "space-between",
+ alignItems: "center",
+ },
+ itemDeleteBtn: {
+ padding: spacing.xs,
+ marginLeft: spacing.s,
},
actions: { marginTop: spacing.m, marginBottom: spacing.xxl },
empty: {
@@ -605,7 +647,26 @@ export default function OrderDetailScreen() {
Articles ({items.length})
{items.map((item: any) => (
- {item.product_name}
+
+
+ {item.produit ?? item.product_name}
+
+
+ handleDeleteItem(
+ item.id,
+ item.produit ?? item.product_name,
+ )
+ }
+ >
+
+
+
Quantité: {item.quantite}
@@ -647,6 +708,15 @@ export default function OrderDetailScreen() {
style={{ marginTop: spacing.s }}
/>
)}
+ {!["approved", "cancelled"].includes(command.status) && (
+
+ )}
{command.status === "livre" && (