chore: add modal detail
This commit is contained in:
@@ -48,6 +48,7 @@ import TomTomMap, {
|
|||||||
TomTomMapRef,
|
TomTomMapRef,
|
||||||
TomTomMarker,
|
TomTomMarker,
|
||||||
} from "../../components/TomTomMap";
|
} from "../../components/TomTomMap";
|
||||||
|
import DetailsModal from "../../components/ui/Modal";
|
||||||
import {
|
import {
|
||||||
setupDeliveryNotificationChannel,
|
setupDeliveryNotificationChannel,
|
||||||
registerForPushNotificationsAsync,
|
registerForPushNotificationsAsync,
|
||||||
@@ -72,6 +73,9 @@ const STATUS_LABELS: Record<string, string> = {
|
|||||||
interface EnrichedDelivery extends DeliveryItem {
|
interface EnrichedDelivery extends DeliveryItem {
|
||||||
clientName?: string;
|
clientName?: string;
|
||||||
clientPhone?: string;
|
clientPhone?: string;
|
||||||
|
clientUsername?: string;
|
||||||
|
clientNom?: string;
|
||||||
|
clientPrenom?: string;
|
||||||
items?: Array<{ produit: string; quantite: number; prix: number }>;
|
items?: Array<{ produit: string; quantite: number; prix: number }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +112,7 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
const [unreadNotifCount, setUnreadNotifCount] = useState(0);
|
const [unreadNotifCount, setUnreadNotifCount] = useState(0);
|
||||||
|
const [detailsDelivery, setDetailsDelivery] = useState<EnrichedDelivery | null>(null);
|
||||||
const pushTokenRef = useRef<string | null>(null);
|
const pushTokenRef = useRef<string | null>(null);
|
||||||
|
|
||||||
const STATUS_COLORS: Record<string, string> = useMemo(
|
const STATUS_COLORS: Record<string, string> = useMemo(
|
||||||
@@ -240,6 +245,9 @@ export default function DashboardScreen() {
|
|||||||
? `${client.prenom || ""} ${client.nom}`.trim()
|
? `${client.prenom || ""} ${client.nom}`.trim()
|
||||||
: client?.username || undefined,
|
: client?.username || undefined,
|
||||||
clientPhone: client?.telephone || undefined,
|
clientPhone: client?.telephone || undefined,
|
||||||
|
clientUsername: client?.username || undefined,
|
||||||
|
clientNom: client?.nom || undefined,
|
||||||
|
clientPrenom: client?.prenom || undefined,
|
||||||
items:
|
items:
|
||||||
detail.delivery?.items ||
|
detail.delivery?.items ||
|
||||||
(d as any).items ||
|
(d as any).items ||
|
||||||
@@ -641,12 +649,21 @@ export default function DashboardScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.detailsBtn}
|
||||||
|
onPress={() => setDetailsDelivery(item)}
|
||||||
|
activeOpacity={0.7}
|
||||||
|
>
|
||||||
|
<Ionicons name="list-outline" size={16} color={colors.accent} />
|
||||||
|
<Text style={styles.detailsBtnText}>Détails</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
{(item.status === "pending" || item.status === "assigned") && (
|
{(item.status === "pending" || item.status === "assigned") && (
|
||||||
<Button
|
<Button
|
||||||
title="Démarrer la livraison"
|
title="Démarrer la livraison"
|
||||||
onPress={() => handleStartDelivery(item.id)}
|
onPress={() => handleStartDelivery(item.id)}
|
||||||
style={{
|
style={{
|
||||||
marginTop: spacing.m,
|
marginTop: spacing.s,
|
||||||
backgroundColor: colors.success,
|
backgroundColor: colors.success,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -657,7 +674,7 @@ export default function DashboardScreen() {
|
|||||||
title="Terminer la livraison"
|
title="Terminer la livraison"
|
||||||
onPress={() => handleCompleteDelivery(item.id)}
|
onPress={() => handleCompleteDelivery(item.id)}
|
||||||
style={{
|
style={{
|
||||||
marginTop: spacing.m,
|
marginTop: spacing.s,
|
||||||
backgroundColor: colors.accent,
|
backgroundColor: colors.accent,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -1288,6 +1305,102 @@ export default function DashboardScreen() {
|
|||||||
fontSize: fontSize.sm,
|
fontSize: fontSize.sm,
|
||||||
fontFamily: "monospace",
|
fontFamily: "monospace",
|
||||||
},
|
},
|
||||||
|
// Bouton détails
|
||||||
|
detailsBtn: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
gap: spacing.xs,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: colors.accent,
|
||||||
|
paddingVertical: spacing.s,
|
||||||
|
borderRadius: borderRadius.sm,
|
||||||
|
marginTop: spacing.m,
|
||||||
|
},
|
||||||
|
detailsBtnText: {
|
||||||
|
color: colors.accent,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Modal détails
|
||||||
|
detailSection: { marginBottom: spacing.m },
|
||||||
|
detailSectionTitle: {
|
||||||
|
color: colors.textWhite,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
fontWeight: "700",
|
||||||
|
marginBottom: spacing.s,
|
||||||
|
},
|
||||||
|
detailRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingVertical: spacing.xs,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: colors.borderSubtle,
|
||||||
|
},
|
||||||
|
detailLabel: {
|
||||||
|
color: colors.textMuted,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
},
|
||||||
|
detailValue: {
|
||||||
|
color: colors.textWhite,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
detailDivider: {
|
||||||
|
height: 1,
|
||||||
|
backgroundColor: colors.border,
|
||||||
|
marginBottom: spacing.m,
|
||||||
|
},
|
||||||
|
detailProductRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingVertical: spacing.s,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: colors.borderSubtle,
|
||||||
|
},
|
||||||
|
detailProductName: {
|
||||||
|
color: colors.textWhite,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
detailProductQty: {
|
||||||
|
color: colors.textMuted,
|
||||||
|
fontSize: fontSize.xs,
|
||||||
|
marginTop: 2,
|
||||||
|
},
|
||||||
|
detailProductPrice: {
|
||||||
|
color: colors.success,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
detailEmpty: {
|
||||||
|
color: colors.textMuted,
|
||||||
|
fontSize: fontSize.sm,
|
||||||
|
textAlign: "center",
|
||||||
|
paddingVertical: spacing.m,
|
||||||
|
},
|
||||||
|
detailTotalRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: spacing.m,
|
||||||
|
paddingTop: spacing.m,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: colors.border,
|
||||||
|
},
|
||||||
|
detailTotalLabel: {
|
||||||
|
color: colors.textSecondary,
|
||||||
|
fontSize: fontSize.md,
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
detailTotalValue: {
|
||||||
|
color: colors.textWhite,
|
||||||
|
fontSize: fontSize.lg,
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
|
||||||
notifBadgeBar: {
|
notifBadgeBar: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -1480,6 +1593,79 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
{/* ── Modal détails commande ── */}
|
||||||
|
<DetailsModal
|
||||||
|
visible={detailsDelivery !== null}
|
||||||
|
onClose={() => setDetailsDelivery(null)}
|
||||||
|
title={`Commande #${detailsDelivery?.id}`}
|
||||||
|
icon="receipt-outline"
|
||||||
|
iconColor={colors.accent}
|
||||||
|
>
|
||||||
|
<ScrollView showsVerticalScrollIndicator={false}>
|
||||||
|
{/* Infos client */}
|
||||||
|
<View style={styles.detailSection}>
|
||||||
|
<Text style={styles.detailSectionTitle}>
|
||||||
|
<Ionicons name="person-outline" size={14} color={colors.accent} />
|
||||||
|
{" "}Client
|
||||||
|
</Text>
|
||||||
|
<View style={styles.detailRow}>
|
||||||
|
<Text style={styles.detailLabel}>Pseudo</Text>
|
||||||
|
<Text style={styles.detailValue}>
|
||||||
|
{detailsDelivery?.clientUsername || "—"}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.detailRow}>
|
||||||
|
<Text style={styles.detailLabel}>Prénom</Text>
|
||||||
|
<Text style={styles.detailValue}>
|
||||||
|
{detailsDelivery?.clientPrenom || "—"}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.detailRow}>
|
||||||
|
<Text style={styles.detailLabel}>Nom</Text>
|
||||||
|
<Text style={styles.detailValue}>
|
||||||
|
{detailsDelivery?.clientNom || "—"}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Séparateur */}
|
||||||
|
<View style={styles.detailDivider} />
|
||||||
|
|
||||||
|
{/* Produits */}
|
||||||
|
<Text style={styles.detailSectionTitle}>
|
||||||
|
<Ionicons name="bag-outline" size={14} color={colors.success} />
|
||||||
|
{" "}Produits
|
||||||
|
</Text>
|
||||||
|
{detailsDelivery?.items && detailsDelivery.items.length > 0 ? (
|
||||||
|
detailsDelivery.items.map((prod, idx) => (
|
||||||
|
<View key={idx} style={styles.detailProductRow}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<Text style={styles.detailProductName}>
|
||||||
|
{prod.produit}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.detailProductQty}>
|
||||||
|
Quantité : {prod.quantite}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.detailProductPrice}>
|
||||||
|
{(prod.prix ?? 0).toFixed(2)}€
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Text style={styles.detailEmpty}>Aucun produit</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Total */}
|
||||||
|
<View style={styles.detailTotalRow}>
|
||||||
|
<Text style={styles.detailTotalLabel}>Total</Text>
|
||||||
|
<Text style={styles.detailTotalValue}>
|
||||||
|
{detailsDelivery?.total_prix ?? 0}€
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</DetailsModal>
|
||||||
|
|
||||||
{/* ── Badge notifications ── */}
|
{/* ── Badge notifications ── */}
|
||||||
{unreadNotifCount > 0 && (
|
{unreadNotifCount > 0 && (
|
||||||
<View style={styles.notifBadgeBar}>
|
<View style={styles.notifBadgeBar}>
|
||||||
|
|||||||
Reference in New Issue
Block a user