feat: add CSV export for approved orders && add non-delivery reason modal for livreurs
This commit is contained in:
@@ -39,7 +39,10 @@ import {
|
||||
generateLivreurLinkToken,
|
||||
unlinkLivreurTelegram,
|
||||
getDeliveryNavLink,
|
||||
reportDeliveryIssue,
|
||||
ISSUE_LABELS,
|
||||
} from "../../api/api_delivery";
|
||||
import type { IssueType } from "../../api/api_delivery";
|
||||
import { geocodeAddress, calculateRoute } from "../../api/tomtom";
|
||||
import type { RouteInfo } from "../../api/tomtom";
|
||||
import type { DeliveryStatus, DeliveryItem, QueueInfo } from "../../api/types";
|
||||
@@ -118,8 +121,9 @@ export default function DashboardScreen() {
|
||||
const [cancelModal, setCancelModal] = useState<{
|
||||
visible: boolean;
|
||||
deliveryId: number | null;
|
||||
reason: string;
|
||||
}>({ visible: false, deliveryId: null, reason: "" });
|
||||
issueType: IssueType | null;
|
||||
description: string;
|
||||
}>({ visible: false, deliveryId: null, issueType: null, description: "" });
|
||||
|
||||
const STATUS_COLORS: Record<string, string> = useMemo(
|
||||
() => ({
|
||||
@@ -502,17 +506,25 @@ export default function DashboardScreen() {
|
||||
};
|
||||
|
||||
const handleCancelDelivery = async () => {
|
||||
if (!cancelModal.deliveryId) return;
|
||||
if (!cancelModal.deliveryId || !cancelModal.issueType) return;
|
||||
const lat = lastCoords?.lat || 0;
|
||||
const lng = lastCoords?.lng || 0;
|
||||
const issueLabel = ISSUE_LABELS[cancelModal.issueType];
|
||||
const res = await updateDeliveryStatus(
|
||||
cancelModal.deliveryId,
|
||||
"cancelled",
|
||||
lat,
|
||||
lng,
|
||||
cancelModal.reason || "Client absent",
|
||||
cancelModal.description || issueLabel,
|
||||
);
|
||||
setCancelModal({ visible: false, deliveryId: null, reason: "" });
|
||||
if (res.success) {
|
||||
await reportDeliveryIssue(
|
||||
cancelModal.deliveryId,
|
||||
cancelModal.issueType,
|
||||
cancelModal.description,
|
||||
);
|
||||
}
|
||||
setCancelModal({ visible: false, deliveryId: null, issueType: null, description: "" });
|
||||
if (res.success) {
|
||||
showSuccess("Succès", "Livraison annulée");
|
||||
loadData();
|
||||
@@ -736,7 +748,8 @@ export default function DashboardScreen() {
|
||||
setCancelModal({
|
||||
visible: true,
|
||||
deliveryId: item.id,
|
||||
reason: "",
|
||||
issueType: null,
|
||||
description: "",
|
||||
})
|
||||
}
|
||||
style={{ flex: 1, backgroundColor: colors.danger }}
|
||||
@@ -1860,24 +1873,51 @@ export default function DashboardScreen() {
|
||||
<DetailsModal
|
||||
visible={cancelModal.visible}
|
||||
onClose={() =>
|
||||
setCancelModal({ visible: false, deliveryId: null, reason: "" })
|
||||
setCancelModal({ visible: false, deliveryId: null, issueType: null, description: "" })
|
||||
}
|
||||
title="Annuler la livraison"
|
||||
title="Motif de non-livraison"
|
||||
icon="close-circle-outline"
|
||||
>
|
||||
<Text style={[styles.cancelInput, { color: colors.textSecondary, fontSize: 13, marginBottom: spacing.s, backgroundColor: "transparent", borderWidth: 0, padding: 0 }]}>
|
||||
Sélectionnez un motif
|
||||
</Text>
|
||||
<View style={{ flexDirection: "row", flexWrap: "wrap", gap: spacing.s, marginBottom: spacing.m }}>
|
||||
{(Object.keys(ISSUE_LABELS) as IssueType[]).map((type) => {
|
||||
const selected = cancelModal.issueType === type;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={type}
|
||||
onPress={() => setCancelModal((prev) => ({ ...prev, issueType: type }))}
|
||||
style={{
|
||||
paddingHorizontal: spacing.m,
|
||||
paddingVertical: spacing.s,
|
||||
borderRadius: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: selected ? colors.danger : colors.border,
|
||||
backgroundColor: selected ? colors.danger + "22" : colors.bgCard,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: selected ? colors.danger : colors.textSecondary, fontSize: 13 }}>
|
||||
{ISSUE_LABELS[type]}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
<TextInput
|
||||
style={styles.cancelInput}
|
||||
placeholder="Motif (ex: client absent)..."
|
||||
placeholder="Précisions (facultatif)..."
|
||||
placeholderTextColor={colors.textMuted}
|
||||
value={cancelModal.reason}
|
||||
value={cancelModal.description}
|
||||
onChangeText={(t) =>
|
||||
setCancelModal((prev) => ({ ...prev, reason: t }))
|
||||
setCancelModal((prev) => ({ ...prev, description: t }))
|
||||
}
|
||||
multiline
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.cancelConfirmBtn}
|
||||
style={[styles.cancelConfirmBtn, !cancelModal.issueType && { opacity: 0.4 }]}
|
||||
onPress={handleCancelDelivery}
|
||||
disabled={!cancelModal.issueType}
|
||||
>
|
||||
<Text style={styles.cancelConfirmText}>Confirmer l'annulation</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
Reference in New Issue
Block a user