chore: build
This commit is contained in:
@@ -299,6 +299,21 @@ export const getDeliveryPersonDetails = async (username: string) => {
|
||||
return data.deliveryman || data;
|
||||
};
|
||||
|
||||
export const getLivreurRatings = async (username: string): Promise<{
|
||||
ratings: { id: number; order_id: number; client_username: string; rating: number; comment: string; created_at: string }[];
|
||||
average: number;
|
||||
count: number;
|
||||
}> => {
|
||||
try {
|
||||
const { data } = await apiClient.get(
|
||||
`${V2}/admin/protected/delivery-persons/${username}/ratings`,
|
||||
);
|
||||
return data;
|
||||
} catch {
|
||||
return { ratings: [], average: 0, count: 0 };
|
||||
}
|
||||
};
|
||||
|
||||
const parseStatus = (status: any): "available" | "busy" | "offline" => {
|
||||
if (!status) return "offline";
|
||||
if (status === "available" || status === "busy" || status === "offline")
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
Modal,
|
||||
StatusBar,
|
||||
useWindowDimensions,
|
||||
ScrollView,
|
||||
Pressable,
|
||||
} from "react-native";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { spacing, fontSize, borderRadius } from "../../theme";
|
||||
@@ -22,6 +24,7 @@ import { useTheme } from "../../context/ThemeContext";
|
||||
import {
|
||||
getAllDeliveryPersonsWithDetails,
|
||||
getCommandByID,
|
||||
getLivreurRatings,
|
||||
} from "../../api/api_admin";
|
||||
import { geocodeAddress, calculateRoute } from "../../api/tomtom";
|
||||
import type { RouteInfo } from "../../api/tomtom";
|
||||
@@ -61,6 +64,22 @@ export default function DeliveryScreen() {
|
||||
const [routeInfo, setRouteInfo] = useState<RouteInfo | null>(null);
|
||||
const [routeLoading, setRouteLoading] = useState(false);
|
||||
|
||||
// Avis livreur
|
||||
const [ratingsModal, setRatingsModal] = useState<{
|
||||
username: string;
|
||||
ratings: { id: number; order_id: number; client_username: string; rating: number; comment: string; created_at: string }[];
|
||||
average: number;
|
||||
count: number;
|
||||
} | null>(null);
|
||||
const [ratingsLoading, setRatingsLoading] = useState(false);
|
||||
|
||||
const openRatings = async (username: string) => {
|
||||
setRatingsLoading(true);
|
||||
const data = await getLivreurRatings(username);
|
||||
setRatingsModal({ username, ...data });
|
||||
setRatingsLoading(false);
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
try {
|
||||
const result = await getAllDeliveryPersonsWithDetails();
|
||||
@@ -338,6 +357,24 @@ export default function DeliveryScreen() {
|
||||
fontWeight: "500",
|
||||
},
|
||||
|
||||
ratingsBtn: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: spacing.s,
|
||||
marginTop: spacing.m,
|
||||
paddingVertical: spacing.s,
|
||||
paddingHorizontal: spacing.m,
|
||||
borderRadius: borderRadius.sm,
|
||||
borderWidth: 1,
|
||||
borderColor: "#f59e0b",
|
||||
},
|
||||
ratingsBtnText: {
|
||||
color: "#f59e0b",
|
||||
fontSize: fontSize.sm,
|
||||
fontWeight: "600",
|
||||
},
|
||||
|
||||
trackBtn: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
@@ -356,6 +393,80 @@ export default function DeliveryScreen() {
|
||||
fontWeight: "600",
|
||||
},
|
||||
|
||||
ratingsOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: "rgba(0,0,0,0.7)",
|
||||
justifyContent: "flex-end",
|
||||
},
|
||||
ratingsSheet: {
|
||||
backgroundColor: colors.bgCard,
|
||||
borderTopLeftRadius: borderRadius.xl,
|
||||
borderTopRightRadius: borderRadius.xl,
|
||||
padding: spacing.l,
|
||||
maxHeight: "80%",
|
||||
},
|
||||
ratingsHeader: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: spacing.s,
|
||||
},
|
||||
ratingsTitle: {
|
||||
color: colors.textWhite,
|
||||
fontSize: fontSize.lg,
|
||||
fontWeight: "700",
|
||||
},
|
||||
ratingsAvg: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: spacing.xs,
|
||||
marginBottom: spacing.l,
|
||||
},
|
||||
ratingsAvgText: {
|
||||
color: "#f59e0b",
|
||||
fontSize: fontSize.md,
|
||||
fontWeight: "700",
|
||||
},
|
||||
ratingsCount: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.sm,
|
||||
},
|
||||
ratingItem: {
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: colors.borderLight,
|
||||
paddingVertical: spacing.m,
|
||||
},
|
||||
ratingItemHeader: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: spacing.xs,
|
||||
},
|
||||
ratingItemClient: {
|
||||
color: colors.textPrimary,
|
||||
fontSize: fontSize.sm,
|
||||
fontWeight: "600",
|
||||
},
|
||||
ratingItemDate: {
|
||||
color: colors.textMuted,
|
||||
fontSize: fontSize.xs,
|
||||
},
|
||||
ratingStarsRow: {
|
||||
flexDirection: "row",
|
||||
gap: 2,
|
||||
marginBottom: spacing.xs,
|
||||
},
|
||||
ratingItemComment: {
|
||||
color: colors.textSecondary,
|
||||
fontSize: fontSize.sm,
|
||||
fontStyle: "italic",
|
||||
},
|
||||
ratingsEmpty: {
|
||||
color: colors.textMuted,
|
||||
textAlign: "center",
|
||||
paddingVertical: spacing.xl,
|
||||
},
|
||||
|
||||
empty: {
|
||||
color: colors.textMuted,
|
||||
textAlign: "center",
|
||||
@@ -523,6 +634,15 @@ export default function DeliveryScreen() {
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.ratingsBtn}
|
||||
onPress={() => openRatings(item.username)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Ionicons name="star-outline" size={14} color="#f59e0b" />
|
||||
<Text style={styles.ratingsBtnText}>Voir les avis</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{hasGPS && (
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
@@ -835,6 +955,78 @@ export default function DeliveryScreen() {
|
||||
<Text style={styles.empty}>Aucun livreur</Text>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* ── Modal avis livreur ── */}
|
||||
<Modal
|
||||
visible={ratingsModal !== null}
|
||||
transparent
|
||||
animationType="slide"
|
||||
onRequestClose={() => setRatingsModal(null)}
|
||||
>
|
||||
<Pressable style={styles.ratingsOverlay} onPress={() => setRatingsModal(null)}>
|
||||
<Pressable onPress={() => {}}>
|
||||
<View style={styles.ratingsSheet}>
|
||||
<View style={styles.ratingsHeader}>
|
||||
<Text style={styles.ratingsTitle}>
|
||||
Avis — {ratingsModal?.username}
|
||||
</Text>
|
||||
<TouchableOpacity onPress={() => setRatingsModal(null)}>
|
||||
<Ionicons name="close" size={22} color={colors.textMuted} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{ratingsLoading ? (
|
||||
<Text style={styles.ratingsEmpty}>Chargement...</Text>
|
||||
) : ratingsModal && ratingsModal.count > 0 ? (
|
||||
<>
|
||||
<View style={styles.ratingsAvg}>
|
||||
{[1,2,3,4,5].map((s) => (
|
||||
<Ionicons
|
||||
key={s}
|
||||
name={s <= Math.round(ratingsModal.average) ? "star" : "star-outline"}
|
||||
size={20}
|
||||
color="#f59e0b"
|
||||
/>
|
||||
))}
|
||||
<Text style={styles.ratingsAvgText}>
|
||||
{ratingsModal.average.toFixed(1)}
|
||||
</Text>
|
||||
<Text style={styles.ratingsCount}>
|
||||
({ratingsModal.count} avis)
|
||||
</Text>
|
||||
</View>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{ratingsModal.ratings.map((r) => (
|
||||
<View key={r.id} style={styles.ratingItem}>
|
||||
<View style={styles.ratingItemHeader}>
|
||||
<Text style={styles.ratingItemClient}>{r.client_username}</Text>
|
||||
<Text style={styles.ratingItemDate}>
|
||||
{new Date(r.created_at).toLocaleDateString("fr-FR")}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.ratingStarsRow}>
|
||||
{[1,2,3,4,5].map((s) => (
|
||||
<Ionicons
|
||||
key={s}
|
||||
name={s <= r.rating ? "star" : "star-outline"}
|
||||
size={14}
|
||||
color="#f59e0b"
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
{r.comment !== "" && (
|
||||
<Text style={styles.ratingItemComment}>"{r.comment}"</Text>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</>
|
||||
) : (
|
||||
<Text style={styles.ratingsEmpty}>Aucun avis pour ce livreur</Text>
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
</Pressable>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user