add: new button in admin & cabine
This commit is contained in:
@@ -130,6 +130,13 @@ export const getCommandItems = async (commandId: number) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteCommand = async (commandId: number) => {
|
||||
const { data } = await apiClient.delete(
|
||||
`${V2}/admin/protected/orders/${commandId}`,
|
||||
);
|
||||
return { success: true, message: data.message };
|
||||
};
|
||||
|
||||
export const deleteCommandItem = async (commandId: number, itemId: number) => {
|
||||
const { data } = await apiClient.delete(
|
||||
`${V2}/admin/protected/orders/${commandId}/items/${itemId}`,
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
StatusBar,
|
||||
Alert,
|
||||
} from "react-native";
|
||||
import { useRoute, type RouteProp } from "@react-navigation/native";
|
||||
import { useRoute, useNavigation, type RouteProp } from "@react-navigation/native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import MapView, { Marker, Polyline, PROVIDER_DEFAULT } from "react-native-maps";
|
||||
import { spacing, fontSize, borderRadius } from "../../theme";
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
notifyClientToDescend,
|
||||
getDeliveryPersonDetails,
|
||||
deleteCommandItem,
|
||||
deleteCommand,
|
||||
} from "../../api/api_admin";
|
||||
import { geocodeAddress, calculateRoute } from "../../api/tomtom";
|
||||
import type { RouteInfo, LatLng } from "../../api/tomtom";
|
||||
@@ -41,10 +42,12 @@ const MAP_HEIGHT = 240;
|
||||
export default function OrderDetailScreen() {
|
||||
const { colors } = useTheme();
|
||||
const route = useRoute<Route>();
|
||||
const navigation = useNavigation();
|
||||
const { orderId } = route.params;
|
||||
const [command, setCommand] = useState<any>(null);
|
||||
const [items, setItems] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [showItemsModal, setShowItemsModal] = useState(false);
|
||||
|
||||
// Map / tracking
|
||||
const mapRef = useRef<MapView | null>(null);
|
||||
@@ -218,6 +221,28 @@ export default function OrderDetailScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteCommand = () => {
|
||||
Alert.alert(
|
||||
"Supprimer la commande",
|
||||
`Supprimer définitivement la commande #${orderId} ?`,
|
||||
[
|
||||
{ text: "Annuler", style: "cancel" },
|
||||
{
|
||||
text: "Supprimer",
|
||||
style: "destructive",
|
||||
onPress: async () => {
|
||||
try {
|
||||
await deleteCommand(orderId);
|
||||
navigation.goBack();
|
||||
} catch (e: any) {
|
||||
showError("Erreur", e.message);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
const styles = useMemo(
|
||||
() =>
|
||||
StyleSheet.create({
|
||||
@@ -374,6 +399,37 @@ export default function OrderDetailScreen() {
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
|
||||
// Items modal
|
||||
itemsModalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: "rgba(0,0,0,0.6)",
|
||||
justifyContent: "flex-end",
|
||||
},
|
||||
itemsModalContainer: {
|
||||
backgroundColor: colors.bgPrimary,
|
||||
borderTopLeftRadius: borderRadius.lg,
|
||||
borderTopRightRadius: borderRadius.lg,
|
||||
maxHeight: "75%",
|
||||
padding: spacing.l,
|
||||
},
|
||||
itemsModalHeader: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: spacing.m,
|
||||
},
|
||||
itemsModalTitle: {
|
||||
fontSize: fontSize.lg,
|
||||
fontWeight: "700",
|
||||
color: colors.textWhite,
|
||||
},
|
||||
itemsModalCard: {
|
||||
backgroundColor: colors.bgCard,
|
||||
borderRadius: borderRadius.sm,
|
||||
padding: spacing.m,
|
||||
marginBottom: spacing.s,
|
||||
},
|
||||
|
||||
// Fullscreen
|
||||
fullscreenContainer: {
|
||||
flex: 1,
|
||||
@@ -681,6 +737,12 @@ export default function OrderDetailScreen() {
|
||||
{/* Actions */}
|
||||
<Text style={styles.sectionTitle}>Actions</Text>
|
||||
<View style={styles.actions}>
|
||||
<Button
|
||||
title="Voir les items"
|
||||
onPress={() => setShowItemsModal(true)}
|
||||
variant="secondary"
|
||||
fullWidth
|
||||
/>
|
||||
{command.status !== "approved" &&
|
||||
command.status !== "cancelled" && (
|
||||
<Button
|
||||
@@ -688,6 +750,7 @@ export default function OrderDetailScreen() {
|
||||
onPress={handleValidate}
|
||||
variant="success"
|
||||
fullWidth
|
||||
style={{ marginTop: spacing.s }}
|
||||
/>
|
||||
)}
|
||||
{command.status === "pending" && (
|
||||
@@ -717,16 +780,89 @@ export default function OrderDetailScreen() {
|
||||
style={{ marginTop: spacing.s }}
|
||||
/>
|
||||
)}
|
||||
{command.status === "livre" && (
|
||||
{!["approved", "cancelled"].includes(command.status) && (
|
||||
<Button
|
||||
title="Confirmer la réception"
|
||||
title="Confirmer la commande"
|
||||
onPress={handleConfirmReception}
|
||||
variant="primary"
|
||||
fullWidth
|
||||
style={{ marginTop: spacing.s }}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
title="Supprimer la commande"
|
||||
onPress={handleDeleteCommand}
|
||||
variant="danger"
|
||||
fullWidth
|
||||
style={{ marginTop: spacing.s }}
|
||||
/>
|
||||
</View>
|
||||
{/* Items modal */}
|
||||
<Modal
|
||||
visible={showItemsModal}
|
||||
animationType="slide"
|
||||
onRequestClose={() => setShowItemsModal(false)}
|
||||
transparent
|
||||
>
|
||||
<View style={styles.itemsModalOverlay}>
|
||||
<View style={styles.itemsModalContainer}>
|
||||
<View style={styles.itemsModalHeader}>
|
||||
<Text style={styles.itemsModalTitle}>
|
||||
Articles ({items.length})
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.closeBtn}
|
||||
onPress={() => setShowItemsModal(false)}
|
||||
>
|
||||
<Ionicons
|
||||
name="close"
|
||||
size={22}
|
||||
color={colors.textWhite}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{items.map((item: any) => (
|
||||
<View key={item.id} style={styles.itemsModalCard}>
|
||||
<View style={styles.row}>
|
||||
<Text style={[styles.itemName, { flex: 1 }]}>
|
||||
{item.produit ?? item.product_name}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.itemDeleteBtn}
|
||||
onPress={() => {
|
||||
setShowItemsModal(false);
|
||||
handleDeleteItem(
|
||||
item.id,
|
||||
item.produit ?? item.product_name,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Ionicons
|
||||
name="trash-outline"
|
||||
size={18}
|
||||
color={colors.danger}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.itemDetails}>
|
||||
<Text style={styles.info}>
|
||||
Quantité: {item.quantite}
|
||||
</Text>
|
||||
<Text style={styles.info}>
|
||||
Prix: {item.prix?.toFixed(2)} €
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
))}
|
||||
{items.length === 0 && (
|
||||
<Text style={styles.empty}>Aucun article</Text>
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
|
||||
<AlertModal
|
||||
visible={alert.visible}
|
||||
type={alert.type}
|
||||
|
||||
@@ -213,6 +213,7 @@ export default function OrdersScreen() {
|
||||
},
|
||||
actions: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: spacing.s,
|
||||
marginTop: spacing.m,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user