chore: fix comming soon

This commit is contained in:
2026-03-07 18:42:18 +01:00
parent ab7d8929a8
commit 91ad46c0f8
4 changed files with 315 additions and 131 deletions
@@ -54,7 +54,8 @@ export default function OrdersScreen() {
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [openMenuId, setOpenMenuId] = useState<number | null>(null);
const { alert, showError, showSuccess, showConfirm, hideAlert } = useAlert();
const { alert, showError, showSuccess, showConfirm, hideAlert } =
useAlert();
const [itemsModal, setItemsModal] = useState<{
visible: boolean;
commandId: number | null;
@@ -77,7 +78,9 @@ export default function OrdersScreen() {
commandId: number | null;
input: string;
}>({ visible: false, commandId: null, input: "" });
const [livreurs, setLivreurs] = useState<{ id: number; username: string }[]>([]);
const [livreurs, setLivreurs] = useState<
{ id: number; username: string }[]
>([]);
const loadData = useCallback(async () => {
try {
@@ -148,7 +151,10 @@ export default function OrdersScreen() {
setOpenMenuId(null);
try {
await notifyClientToDescendCabine(commandId);
showSuccess("Notification envoyée", "Le client a été prévenu de descendre");
showSuccess(
"Notification envoyée",
"Le client a été prévenu de descendre",
);
} catch (e: any) {
showError("Erreur", e.message);
}
@@ -157,9 +163,15 @@ export default function OrdersScreen() {
const handleProposeAddress = async () => {
if (!addressModal.commandId || !addressModal.input.trim()) return;
try {
await proposeAddressChangeCabine(addressModal.commandId, addressModal.input.trim());
await proposeAddressChangeCabine(
addressModal.commandId,
addressModal.input.trim(),
);
setAddressModal({ visible: false, commandId: null, input: "" });
showSuccess("Proposition envoyée", "Le client a été notifié de la nouvelle adresse proposée");
showSuccess(
"Proposition envoyée",
"Le client a été notifié de la nouvelle adresse proposée",
);
} catch (e: any) {
showError("Erreur", e.message);
}
@@ -205,7 +217,10 @@ export default function OrdersScreen() {
const handleAssign = async (livreurUsername: string) => {
if (!assignModal.commandId) return;
try {
await assignDeliveryPersonByCabine(assignModal.commandId, livreurUsername);
await assignDeliveryPersonByCabine(
assignModal.commandId,
livreurUsername,
);
setAssignModal({ visible: false, commandId: null });
await loadData();
} catch (e: any) {
@@ -412,40 +427,49 @@ export default function OrdersScreen() {
condition?: boolean;
};
const actions: Action[] = ([
{
label: "Voir items",
icon: "receipt-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => openItems(item.id),
},
{
label: "Proposer adresse",
icon: "location-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => { setOpenMenuId(null); setAddressModal({ visible: true, commandId: item.id, input: "" }); },
},
{
label: "Le client est là",
icon: "notifications-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleNotifyClient(item.id),
},
{
label: "Assigner livreur",
icon: "bicycle-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => openAssignModal(item.id),
},
{
label: "Confirmer réception",
icon: "checkmark-circle-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleConfirmReception(item.id),
condition: item.status === "livre",
},
{
label: "Supprimer",
icon: "trash-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleDelete(item.id),
danger: true,
},
] as Action[]).filter((a) => a.condition !== false);
const actions: Action[] = (
[
{
label: "Voir items",
icon: "receipt-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => openItems(item.id),
},
{
label: "Proposer adresse",
icon: "location-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => {
setOpenMenuId(null);
setAddressModal({
visible: true,
commandId: item.id,
input: "",
});
},
},
{
label: "Le livreur est là",
icon: "notifications-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleNotifyClient(item.id),
},
{
label: "Assigner livreur",
icon: "bicycle-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => openAssignModal(item.id),
},
{
label: "Confirmer réception",
icon: "checkmark-circle-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleConfirmReception(item.id),
condition: item.status === "livre",
},
{
label: "Supprimer",
icon: "trash-outline" as keyof typeof Ionicons.glyphMap,
onPress: () => handleDelete(item.id),
danger: true,
},
] as Action[]
).filter((a) => a.condition !== false);
return (
<Card style={{ marginBottom: spacing.m }}>
@@ -478,14 +502,19 @@ export default function OrdersScreen() {
key={action.label}
style={[
styles.dropdownItem,
index === actions.length - 1 && styles.dropdownItemLast,
index === actions.length - 1 &&
styles.dropdownItemLast,
]}
onPress={action.onPress}
>
<Ionicons
name={action.icon}
size={16}
color={action.danger ? colors.danger : colors.accent}
color={
action.danger
? colors.danger
: colors.accent
}
/>
<Text
style={
@@ -504,7 +533,9 @@ export default function OrdersScreen() {
);
};
const readyCount = itemsModal.items.filter((i) => i.status === "ready").length;
const readyCount = itemsModal.items.filter(
(i) => i.status === "ready",
).length;
const totalCount = itemsModal.items.length;
const progress = totalCount > 0 ? readyCount / totalCount : 0;
@@ -535,12 +566,19 @@ export default function OrdersScreen() {
title={`Commande #${itemsModal.commandId}`}
icon="receipt-outline"
>
<ScrollView showsVerticalScrollIndicator={false} bounces={false}>
<ScrollView
showsVerticalScrollIndicator={false}
bounces={false}
>
{(itemsModal.commandInfo || itemsModal.clientInfo) && (
<View style={styles.modalSummary}>
{itemsModal.clientInfo?.username && (
<View style={styles.modalSummaryRow}>
<Ionicons name="person-outline" size={14} color={colors.textMuted} />
<Ionicons
name="person-outline"
size={14}
color={colors.textMuted}
/>
<Text style={styles.modalSummaryText}>
{itemsModal.clientInfo.prenom}{" "}
{itemsModal.clientInfo.nom} ·{" "}
@@ -548,17 +586,26 @@ export default function OrdersScreen() {
</Text>
</View>
)}
{(itemsModal.commandInfo?.address || itemsModal.commandInfo?.adresse) && (
{(itemsModal.commandInfo?.address ||
itemsModal.commandInfo?.adresse) && (
<View style={styles.modalSummaryRow}>
<Ionicons name="location-outline" size={14} color={colors.textMuted} />
<Ionicons
name="location-outline"
size={14}
color={colors.textMuted}
/>
<Text style={styles.modalSummaryText}>
{itemsModal.commandInfo.address || itemsModal.commandInfo.adresse}
{itemsModal.commandInfo.address ||
itemsModal.commandInfo.adresse}
</Text>
</View>
)}
{itemsModal.commandInfo?.total_prix != null && (
<Text style={styles.modalTotal}>
{Number(itemsModal.commandInfo.total_prix).toFixed(2)}
{Number(
itemsModal.commandInfo.total_prix,
).toFixed(2)}{" "}
</Text>
)}
</View>
@@ -576,7 +623,9 @@ export default function OrdersScreen() {
{
width: `${progress * 100}%`,
backgroundColor:
progress === 1 ? STATUS_COLORS.ready : colors.info,
progress === 1
? STATUS_COLORS.ready
: colors.info,
},
]}
/>
@@ -585,30 +634,51 @@ export default function OrdersScreen() {
)}
{itemsModal.items.map((item: any, index: number) => {
const statusColor = STATUS_COLORS[item.status] || colors.textMuted;
const statusColor =
STATUS_COLORS[item.status] || colors.textMuted;
return (
<View key={item.id} style={styles.itemCard}>
<View style={[styles.itemCardAccent, { backgroundColor: statusColor }]} />
<View
style={[
styles.itemCardAccent,
{ backgroundColor: statusColor },
]}
/>
<View style={styles.itemCardBody}>
<View style={styles.itemIndex}>
<Text style={styles.itemIndexText}>{index + 1}</Text>
<Text style={styles.itemIndexText}>
{index + 1}
</Text>
</View>
<View style={styles.itemInfo}>
<Text style={styles.itemName}>
{item.produit ?? item.product_name}
</Text>
<Text style={styles.itemMeta}>
Qté: {item.quantite ?? item.quantity} ·{" "}
{(item.prix ?? item.price)?.toFixed(2)}
Qté:{" "}
{item.quantite ?? item.quantity} ·{" "}
{(item.prix ?? item.price)?.toFixed(
2,
)}{" "}
</Text>
<View style={styles.itemStatusRow}>
<Ionicons
name={STATUS_ICONS[item.status] || "ellipse-outline"}
name={
STATUS_ICONS[item.status] ||
"ellipse-outline"
}
size={13}
color={statusColor}
/>
<Text style={[styles.itemStatusText, { color: statusColor }]}>
{STATUS_LABELS[item.status] || item.status}
<Text
style={[
styles.itemStatusText,
{ color: statusColor },
]}
>
{STATUS_LABELS[item.status] ||
item.status}
</Text>
</View>
</View>
@@ -625,7 +695,9 @@ export default function OrdersScreen() {
<Modal
visible={assignModal.visible}
onClose={() => setAssignModal({ visible: false, commandId: null })}
onClose={() =>
setAssignModal({ visible: false, commandId: null })
}
title={`Assigner commande #${assignModal.commandId}`}
icon="bicycle-outline"
>
@@ -635,7 +707,11 @@ export default function OrdersScreen() {
style={styles.livreurItem}
onPress={() => handleAssign(l.username)}
>
<Ionicons name="person-outline" size={20} color={colors.accent} />
<Ionicons
name="person-outline"
size={20}
color={colors.accent}
/>
<Text style={styles.livreurName}>{l.username}</Text>
</TouchableOpacity>
))}
@@ -647,7 +723,13 @@ export default function OrdersScreen() {
{/* Modal proposition adresse */}
<Modal
visible={addressModal.visible}
onClose={() => setAddressModal({ visible: false, commandId: null, input: "" })}
onClose={() =>
setAddressModal({
visible: false,
commandId: null,
input: "",
})
}
title={`Proposer adresse — commande #${addressModal.commandId}`}
icon="location-outline"
>
@@ -656,14 +738,18 @@ export default function OrdersScreen() {
placeholder="Nouvelle adresse..."
placeholderTextColor={colors.textMuted}
value={addressModal.input}
onChangeText={(t) => setAddressModal((prev) => ({ ...prev, input: t }))}
onChangeText={(t) =>
setAddressModal((prev) => ({ ...prev, input: t }))
}
multiline
/>
<TouchableOpacity
style={styles.addressConfirmBtn}
onPress={handleProposeAddress}
>
<Text style={styles.addressConfirmText}>Envoyer la proposition</Text>
<Text style={styles.addressConfirmText}>
Envoyer la proposition
</Text>
</TouchableOpacity>
</Modal>