chore: fix
This commit is contained in:
@@ -531,6 +531,22 @@ export const getClientReferralAdmin = async (
|
||||
}
|
||||
};
|
||||
|
||||
export const resetClientReferral = async (
|
||||
username: string,
|
||||
): Promise<{ success: boolean; message?: string }> => {
|
||||
try {
|
||||
const { data } = await apiClient.delete(
|
||||
`${V2}/admin/protected/client/${username}/referral/reset`,
|
||||
);
|
||||
return { success: true, message: data.message };
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
message: error.response?.data?.error || "Erreur reset parrainage",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export interface CancelledOrder {
|
||||
id: number;
|
||||
username: string;
|
||||
|
||||
@@ -35,11 +35,16 @@ export interface ClientResponse {
|
||||
|
||||
export interface CommandResponse {
|
||||
id: number;
|
||||
client_order_number?: number;
|
||||
username: string;
|
||||
status: string;
|
||||
adresse: string;
|
||||
total_prix: number;
|
||||
livreur_assign?: string | null;
|
||||
proposed_address?: string | null;
|
||||
address_proposal_status?: string;
|
||||
referral_used?: number;
|
||||
cancel_reason?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ScrollView,
|
||||
TextInput,
|
||||
Share,
|
||||
ActivityIndicator,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
@@ -38,6 +39,7 @@ import AlertModal from "../../components/ui/AlertModal";
|
||||
import { useAlert } from "../../hooks/useAlert";
|
||||
|
||||
type Nav = NativeStackNavigationProp<AdminStackParamList>;
|
||||
type ArchiveTab = "approved" | "cancelled";
|
||||
|
||||
export default function OrdersScreen() {
|
||||
const { colors } = useTheme();
|
||||
@@ -77,6 +79,48 @@ export default function OrdersScreen() {
|
||||
|
||||
const [exporting, setExporting] = useState(false);
|
||||
|
||||
// --- Archive (approved / cancelled) ---
|
||||
const [archiveTab, setArchiveTab] = useState<ArchiveTab | null>(null);
|
||||
const [archiveSearch, setArchiveSearch] = useState("");
|
||||
const [archiveCommands, setArchiveCommands] = useState<CommandResponse[]>([]);
|
||||
const [archiveLoading, setArchiveLoading] = useState(false);
|
||||
const archiveDebounce = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
const loadArchive = useCallback(
|
||||
async (tab: ArchiveTab, search: string) => {
|
||||
setArchiveLoading(true);
|
||||
try {
|
||||
const result = await getAllCommands(tab, search.trim() || undefined);
|
||||
setArchiveCommands(result.commands);
|
||||
} catch {
|
||||
setArchiveCommands([]);
|
||||
}
|
||||
setArchiveLoading(false);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleArchiveTab = (tab: ArchiveTab) => {
|
||||
if (archiveTab === tab) {
|
||||
setArchiveTab(null);
|
||||
setArchiveCommands([]);
|
||||
setArchiveSearch("");
|
||||
return;
|
||||
}
|
||||
setArchiveTab(tab);
|
||||
setArchiveSearch("");
|
||||
loadArchive(tab, "");
|
||||
};
|
||||
|
||||
const handleArchiveSearch = (text: string) => {
|
||||
setArchiveSearch(text);
|
||||
if (archiveDebounce.current) clearTimeout(archiveDebounce.current);
|
||||
archiveDebounce.current = setTimeout(() => {
|
||||
if (archiveTab) loadArchive(archiveTab, text);
|
||||
}, 400);
|
||||
};
|
||||
|
||||
// --- Active orders ---
|
||||
const loadData = useCallback(async () => {
|
||||
try {
|
||||
const result = await getAllCommands(undefined);
|
||||
@@ -106,6 +150,7 @@ export default function OrdersScreen() {
|
||||
const onRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
await loadData();
|
||||
if (archiveTab) loadArchive(archiveTab, archiveSearch);
|
||||
setRefreshing(false);
|
||||
};
|
||||
|
||||
@@ -258,6 +303,7 @@ export default function OrdersScreen() {
|
||||
gap: spacing.s,
|
||||
paddingBottom: spacing.m,
|
||||
alignItems: "center",
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
refreshBtn: {
|
||||
flexDirection: "row",
|
||||
@@ -274,11 +320,79 @@ export default function OrdersScreen() {
|
||||
color: colors.textSecondary,
|
||||
fontSize: fontSize.sm,
|
||||
},
|
||||
archiveRow: {
|
||||
flexDirection: "row",
|
||||
gap: spacing.s,
|
||||
marginBottom: spacing.m,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
archiveTabBtn: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: spacing.xs,
|
||||
paddingHorizontal: spacing.m,
|
||||
paddingVertical: spacing.s,
|
||||
borderRadius: borderRadius.sm,
|
||||
borderWidth: 1,
|
||||
},
|
||||
archiveTabBtnText: {
|
||||
fontSize: fontSize.sm,
|
||||
fontWeight: "600",
|
||||
},
|
||||
searchBar: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: spacing.s,
|
||||
backgroundColor: colors.bgCard,
|
||||
borderRadius: borderRadius.sm,
|
||||
borderWidth: 1,
|
||||
borderColor: colors.border,
|
||||
paddingHorizontal: spacing.m,
|
||||
paddingVertical: spacing.s,
|
||||
marginBottom: spacing.m,
|
||||
},
|
||||
searchInput: {
|
||||
flex: 1,
|
||||
color: colors.textWhite,
|
||||
fontSize: fontSize.sm,
|
||||
padding: 0,
|
||||
},
|
||||
archiveHeader: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
marginBottom: spacing.s,
|
||||
},
|
||||
archiveHeaderText: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.xs,
|
||||
fontWeight: "600",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 0.8,
|
||||
},
|
||||
divider: {
|
||||
height: 1,
|
||||
backgroundColor: colors.border,
|
||||
marginVertical: spacing.m,
|
||||
},
|
||||
activeSectionTitle: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.xs,
|
||||
fontWeight: "600",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 0.8,
|
||||
marginBottom: spacing.m,
|
||||
},
|
||||
cardText: {
|
||||
color: colors.textSecondary,
|
||||
fontSize: fontSize.sm,
|
||||
marginTop: 2,
|
||||
},
|
||||
cardTextMuted: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.xs,
|
||||
marginTop: 2,
|
||||
},
|
||||
cardDate: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.xs,
|
||||
@@ -289,12 +403,54 @@ export default function OrdersScreen() {
|
||||
fontWeight: "bold",
|
||||
color: colors.textWhite,
|
||||
},
|
||||
orderIdSub: {
|
||||
fontSize: fontSize.xs,
|
||||
color: colors.textMuted,
|
||||
marginLeft: spacing.xs,
|
||||
},
|
||||
row: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: spacing.s,
|
||||
},
|
||||
idRow: {
|
||||
flexDirection: "row",
|
||||
alignItems: "baseline",
|
||||
gap: spacing.xs,
|
||||
marginBottom: spacing.s,
|
||||
},
|
||||
chip: {
|
||||
paddingHorizontal: spacing.s,
|
||||
paddingVertical: 2,
|
||||
borderRadius: borderRadius.full ?? 99,
|
||||
alignSelf: "flex-start",
|
||||
marginTop: spacing.xs,
|
||||
},
|
||||
chipText: {
|
||||
fontSize: fontSize.xs,
|
||||
fontWeight: "600",
|
||||
},
|
||||
cancelReasonBox: {
|
||||
backgroundColor: colors.bgPrimary,
|
||||
borderRadius: borderRadius.sm,
|
||||
padding: spacing.s,
|
||||
marginTop: spacing.s,
|
||||
borderLeftWidth: 3,
|
||||
borderLeftColor: colors.danger,
|
||||
},
|
||||
cancelReasonText: {
|
||||
color: colors.textSecondary,
|
||||
fontSize: fontSize.xs,
|
||||
},
|
||||
proposedAddressBox: {
|
||||
backgroundColor: colors.bgPrimary,
|
||||
borderRadius: borderRadius.sm,
|
||||
padding: spacing.s,
|
||||
marginTop: spacing.s,
|
||||
borderLeftWidth: 3,
|
||||
borderLeftColor: colors.warning,
|
||||
},
|
||||
selectBtn: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
@@ -343,6 +499,12 @@ export default function OrdersScreen() {
|
||||
marginTop: spacing.xxl,
|
||||
fontSize: fontSize.md,
|
||||
},
|
||||
archiveEmpty: {
|
||||
color: colors.textMuted,
|
||||
textAlign: "center",
|
||||
marginVertical: spacing.l,
|
||||
fontSize: fontSize.sm,
|
||||
},
|
||||
livreurItem: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
@@ -353,8 +515,6 @@ export default function OrdersScreen() {
|
||||
gap: spacing.m,
|
||||
},
|
||||
livreurName: { color: colors.textWhite, fontSize: fontSize.md },
|
||||
|
||||
// Modal items
|
||||
modalSummary: {
|
||||
backgroundColor: colors.bgCard,
|
||||
borderRadius: borderRadius.sm,
|
||||
@@ -432,6 +592,103 @@ export default function OrdersScreen() {
|
||||
[colors],
|
||||
);
|
||||
|
||||
const renderArchiveCard = (item: CommandResponse) => {
|
||||
const isCancelled = item.status === "cancelled";
|
||||
const accentColor = isCancelled ? colors.danger : colors.success;
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={item.id}
|
||||
style={{ marginBottom: spacing.s, borderLeftWidth: 3, borderLeftColor: accentColor }}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate("OrderDetail", { orderId: item.id })}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
{/* ID row */}
|
||||
<View style={styles.idRow}>
|
||||
<Text style={styles.orderId}>#{item.id}</Text>
|
||||
{item.client_order_number != null && item.client_order_number > 0 && (
|
||||
<Text style={styles.orderIdSub}>
|
||||
(commande #{item.client_order_number} du client)
|
||||
</Text>
|
||||
)}
|
||||
<StatusBadge status={item.status} />
|
||||
</View>
|
||||
|
||||
{/* Client */}
|
||||
<Text style={styles.cardText}>
|
||||
<Text style={{ color: colors.textMuted }}>Client : </Text>
|
||||
{item.username}
|
||||
</Text>
|
||||
|
||||
{/* Adresse */}
|
||||
{!!item.adresse && (
|
||||
<Text style={styles.cardText}>
|
||||
<Text style={{ color: colors.textMuted }}>Adresse : </Text>
|
||||
{item.adresse}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Adresse proposée */}
|
||||
{!!item.proposed_address && (
|
||||
<View style={styles.proposedAddressBox}>
|
||||
<Text style={[styles.cancelReasonText, { color: colors.warning }]}>
|
||||
Adresse proposée ({item.address_proposal_status ?? "—"}) :{" "}
|
||||
{item.proposed_address}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Total + parrainage */}
|
||||
<Text style={styles.cardText}>
|
||||
<Text style={{ color: colors.textMuted }}>Total : </Text>
|
||||
{item.total_prix.toFixed(2)} €
|
||||
{(item.referral_used ?? 0) > 0 && (
|
||||
<Text style={{ color: colors.accent }}>
|
||||
{" "}(parrainage -{item.referral_used!.toFixed(2)} €)
|
||||
</Text>
|
||||
)}
|
||||
</Text>
|
||||
|
||||
{/* Livreur */}
|
||||
{!!item.livreur_assign && (
|
||||
<Text style={styles.cardText}>
|
||||
<Text style={{ color: colors.textMuted }}>Livreur : </Text>
|
||||
{item.livreur_assign}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Raison annulation */}
|
||||
{isCancelled && !!item.cancel_reason && (
|
||||
<View style={styles.cancelReasonBox}>
|
||||
<Text style={styles.cancelReasonText}>
|
||||
Raison : {item.cancel_reason}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Dates */}
|
||||
<Text style={styles.cardDate}>
|
||||
Créée : {new Date(item.created_at).toLocaleString("fr-FR")}
|
||||
</Text>
|
||||
<Text style={styles.cardDate}>
|
||||
Modifiée : {new Date(item.updated_at).toLocaleString("fr-FR")}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Action rapide items */}
|
||||
<TouchableOpacity
|
||||
style={[styles.selectBtn, { marginTop: spacing.s }]}
|
||||
onPress={() => openItems(item.id)}
|
||||
>
|
||||
<Text style={styles.selectBtnText}>Voir les articles</Text>
|
||||
<Ionicons name="receipt-outline" size={14} color={colors.accent} />
|
||||
</TouchableOpacity>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
const renderOrder = ({ item }: { item: CommandResponse }) => {
|
||||
const isOpen = openMenuId === item.id;
|
||||
const isDone = ["approved", "cancelled"].includes(item.status);
|
||||
@@ -592,6 +849,189 @@ export default function OrdersScreen() {
|
||||
);
|
||||
};
|
||||
|
||||
const ListHeader = (
|
||||
<View>
|
||||
{/* Boutons actions */}
|
||||
<View style={styles.refreshRow}>
|
||||
<TouchableOpacity
|
||||
style={styles.refreshBtn}
|
||||
onPress={onRefresh}
|
||||
disabled={refreshing}
|
||||
>
|
||||
<Ionicons
|
||||
name="refresh-outline"
|
||||
size={16}
|
||||
color={refreshing ? colors.textMuted : colors.accent}
|
||||
/>
|
||||
<Text style={styles.refreshBtnText}>Actualiser</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.refreshBtn}
|
||||
onPress={handleExportCSV}
|
||||
disabled={exporting}
|
||||
>
|
||||
<Ionicons
|
||||
name="download-outline"
|
||||
size={16}
|
||||
color={exporting ? colors.textMuted : colors.accent}
|
||||
/>
|
||||
<Text style={styles.refreshBtnText}>
|
||||
{exporting ? "Export..." : "Export CSV"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Boutons archives */}
|
||||
<View style={styles.archiveRow}>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.archiveTabBtn,
|
||||
{
|
||||
backgroundColor:
|
||||
archiveTab === "approved"
|
||||
? colors.success + "22"
|
||||
: colors.bgCard,
|
||||
borderColor:
|
||||
archiveTab === "approved"
|
||||
? colors.success
|
||||
: colors.border,
|
||||
},
|
||||
]}
|
||||
onPress={() => handleArchiveTab("approved")}
|
||||
>
|
||||
<Ionicons
|
||||
name="checkmark-circle-outline"
|
||||
size={16}
|
||||
color={
|
||||
archiveTab === "approved"
|
||||
? colors.success
|
||||
: colors.textMuted
|
||||
}
|
||||
/>
|
||||
<Text
|
||||
style={[
|
||||
styles.archiveTabBtnText,
|
||||
{
|
||||
color:
|
||||
archiveTab === "approved"
|
||||
? colors.success
|
||||
: colors.textMuted,
|
||||
},
|
||||
]}
|
||||
>
|
||||
Approuvées
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.archiveTabBtn,
|
||||
{
|
||||
backgroundColor:
|
||||
archiveTab === "cancelled"
|
||||
? colors.danger + "22"
|
||||
: colors.bgCard,
|
||||
borderColor:
|
||||
archiveTab === "cancelled"
|
||||
? colors.danger
|
||||
: colors.border,
|
||||
},
|
||||
]}
|
||||
onPress={() => handleArchiveTab("cancelled")}
|
||||
>
|
||||
<Ionicons
|
||||
name="close-circle-outline"
|
||||
size={16}
|
||||
color={
|
||||
archiveTab === "cancelled"
|
||||
? colors.danger
|
||||
: colors.textMuted
|
||||
}
|
||||
/>
|
||||
<Text
|
||||
style={[
|
||||
styles.archiveTabBtnText,
|
||||
{
|
||||
color:
|
||||
archiveTab === "cancelled"
|
||||
? colors.danger
|
||||
: colors.textMuted,
|
||||
},
|
||||
]}
|
||||
>
|
||||
Annulées
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Section archive */}
|
||||
{archiveTab !== null && (
|
||||
<View>
|
||||
{/* Barre de recherche */}
|
||||
<View style={styles.searchBar}>
|
||||
<Ionicons
|
||||
name="search-outline"
|
||||
size={16}
|
||||
color={colors.textMuted}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.searchInput}
|
||||
placeholder="Rechercher par username..."
|
||||
placeholderTextColor={colors.textMuted}
|
||||
value={archiveSearch}
|
||||
onChangeText={handleArchiveSearch}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
/>
|
||||
{archiveSearch.length > 0 && (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setArchiveSearch("");
|
||||
if (archiveTab) loadArchive(archiveTab, "");
|
||||
}}
|
||||
>
|
||||
<Ionicons
|
||||
name="close-outline"
|
||||
size={18}
|
||||
color={colors.textMuted}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Header résultats */}
|
||||
<View style={styles.archiveHeader}>
|
||||
<Text style={styles.archiveHeaderText}>
|
||||
{archiveTab === "approved" ? "Commandes approuvées" : "Commandes annulées"}
|
||||
</Text>
|
||||
{!archiveLoading && (
|
||||
<Text style={styles.archiveHeaderText}>
|
||||
{archiveCommands.length} résultat{archiveCommands.length !== 1 ? "s" : ""}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{archiveLoading ? (
|
||||
<View style={{ paddingVertical: spacing.l, alignItems: "center" }}>
|
||||
<ActivityIndicator size="small" color={colors.accent} />
|
||||
</View>
|
||||
) : archiveCommands.length === 0 ? (
|
||||
<Text style={styles.archiveEmpty}>Aucune commande trouvée</Text>
|
||||
) : (
|
||||
archiveCommands.map((item) => renderArchiveCard(item))
|
||||
)}
|
||||
|
||||
<View style={styles.divider} />
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Titre section commandes actives */}
|
||||
<Text style={styles.activeSectionTitle}>
|
||||
Commandes actives ({commands.length})
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
if (loading) return <LoadingSpinner message="Chargement commandes..." />;
|
||||
|
||||
return (
|
||||
@@ -608,42 +1048,12 @@ export default function OrdersScreen() {
|
||||
/>
|
||||
}
|
||||
contentContainerStyle={{ padding: spacing.l }}
|
||||
ListHeaderComponent={
|
||||
<View style={styles.refreshRow}>
|
||||
<TouchableOpacity
|
||||
style={styles.refreshBtn}
|
||||
onPress={onRefresh}
|
||||
disabled={refreshing}
|
||||
>
|
||||
<Ionicons
|
||||
name="refresh-outline"
|
||||
size={16}
|
||||
color={refreshing ? colors.textMuted : colors.accent}
|
||||
/>
|
||||
<Text style={styles.refreshBtnText}>Actualiser</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.refreshBtn}
|
||||
onPress={handleExportCSV}
|
||||
disabled={exporting}
|
||||
>
|
||||
<Ionicons
|
||||
name="download-outline"
|
||||
size={16}
|
||||
color={exporting ? colors.textMuted : colors.accent}
|
||||
/>
|
||||
<Text style={styles.refreshBtnText}>
|
||||
{exporting ? "Export..." : "Export CSV"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
}
|
||||
ListHeaderComponent={ListHeader}
|
||||
ListEmptyComponent={
|
||||
<Text style={styles.empty}>Aucune commande</Text>
|
||||
<Text style={styles.empty}>Aucune commande active</Text>
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
{/* Modal items */}
|
||||
<Modal
|
||||
visible={itemsModal.visible}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
createUserByAdmin,
|
||||
setClientParrain,
|
||||
creditClientReferral,
|
||||
resetClientReferral,
|
||||
getClientCancelledOrders,
|
||||
getSettings,
|
||||
applyClientPenalty,
|
||||
@@ -452,6 +453,20 @@ export default function UsersScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetReferral = async (username: string) => {
|
||||
try {
|
||||
const res = await resetClientReferral(username);
|
||||
if (res.success) {
|
||||
showSuccess("Parrainage", "Solde remis à zéro");
|
||||
await loadData();
|
||||
} else {
|
||||
showError("Erreur", res.message || "Echec du reset");
|
||||
}
|
||||
} catch (e: any) {
|
||||
showError("Erreur", e.message);
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------
|
||||
// Points & amende
|
||||
// --------------------------------------------------
|
||||
@@ -934,6 +949,18 @@ export default function UsersScreen() {
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{referralEnabled && (item.clientData!.referral_balance ?? 0) > 0 && (
|
||||
<TouchableOpacity
|
||||
style={styles.editIconBtn}
|
||||
onPress={() => handleResetReferral(item.clientData!.username)}
|
||||
>
|
||||
<Ionicons
|
||||
name="refresh-outline"
|
||||
size={20}
|
||||
color={colors.danger}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
<TouchableOpacity
|
||||
style={styles.editIconBtn}
|
||||
onPress={() => openCancelledOrders(item.clientData!)}
|
||||
|
||||
@@ -58,7 +58,7 @@ import TomTomMap, {
|
||||
} from "../../components/TomTomMap";
|
||||
import DetailsModal from "../../components/ui/Modal";
|
||||
|
||||
const LOCATION_INTERVAL_MS = 15000;
|
||||
const LOCATION_INTERVAL_MS = 5000;
|
||||
|
||||
const STATUS_LABELS: Record<string, string> = {
|
||||
available: "Disponible",
|
||||
|
||||
Reference in New Issue
Block a user