This commit is contained in:
@@ -8,6 +8,7 @@ import type {
|
|||||||
DeliveryPerson,
|
DeliveryPerson,
|
||||||
DeliveryPersonsStats,
|
DeliveryPersonsStats,
|
||||||
Alert,
|
Alert,
|
||||||
|
MonthlyStats,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const V2 = `${API_BASE_URL}/api/v2`;
|
const V2 = `${API_BASE_URL}/api/v2`;
|
||||||
@@ -126,7 +127,13 @@ export interface DailyDetail {
|
|||||||
categories: DailyCategoryDetail[];
|
categories: DailyCategoryDetail[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StatSection = "commandes" | "revenus" | "produits" | "heures" | "jours" | "doses";
|
export type StatSection =
|
||||||
|
| "commandes"
|
||||||
|
| "revenus"
|
||||||
|
| "produits"
|
||||||
|
| "heures"
|
||||||
|
| "jours"
|
||||||
|
| "doses";
|
||||||
|
|
||||||
export interface AdminStats {
|
export interface AdminStats {
|
||||||
summary: StatsSummary;
|
summary: StatsSummary;
|
||||||
@@ -150,8 +157,12 @@ export const getAdminStats = async (): Promise<AdminStats> => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const resetAdminStats = async (section: StatSection): Promise<{ success: boolean; reset_at: string }> => {
|
export const resetAdminStats = async (
|
||||||
const { data } = await apiClient.post(`${V2}/admin/protected/stats/reset/${section}`);
|
section: StatSection,
|
||||||
|
): Promise<{ success: boolean; reset_at: string }> => {
|
||||||
|
const { data } = await apiClient.post(
|
||||||
|
`${V2}/admin/protected/stats/reset/${section}`,
|
||||||
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -273,9 +284,17 @@ export const validateCommand = async (commandId: number) => {
|
|||||||
`${V2}/admin/protected/orders/${commandId}/force-validate`,
|
`${V2}/admin/protected/orders/${commandId}/force-validate`,
|
||||||
{ command_id: commandId },
|
{ command_id: commandId },
|
||||||
);
|
);
|
||||||
const validated = (data.validated ?? []) as { command_id: number; points_awarded: number }[];
|
const validated = (data.validated ?? []) as {
|
||||||
const points = validated.find((v) => v.command_id === commandId)?.points_awarded ?? 0;
|
command_id: number;
|
||||||
return { success: true, points_awarded: points, validated_count: data.validated_count ?? 0 };
|
points_awarded: number;
|
||||||
|
}[];
|
||||||
|
const points =
|
||||||
|
validated.find((v) => v.command_id === commandId)?.points_awarded ?? 0;
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
points_awarded: points,
|
||||||
|
validated_count: data.validated_count ?? 0,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const proposeAddressChangeAdmin = async (
|
export const proposeAddressChangeAdmin = async (
|
||||||
@@ -300,7 +319,6 @@ export const notifyClientToDescend = async (commandId: number) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
export const getAvailableDeliveryPersons = async () => {
|
export const getAvailableDeliveryPersons = async () => {
|
||||||
@@ -335,8 +353,17 @@ export const getDeliveryPersonDetails = async (username: string) => {
|
|||||||
return data.deliveryman || data;
|
return data.deliveryman || data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLivreurRatings = async (username: string): Promise<{
|
export const getLivreurRatings = async (
|
||||||
ratings: { id: number; order_id: number; client_username: string; rating: number; comment: string; created_at: string }[];
|
username: string,
|
||||||
|
): Promise<{
|
||||||
|
ratings: {
|
||||||
|
id: number;
|
||||||
|
order_id: number;
|
||||||
|
client_username: string;
|
||||||
|
rating: number;
|
||||||
|
comment: string;
|
||||||
|
created_at: string;
|
||||||
|
}[];
|
||||||
average: number;
|
average: number;
|
||||||
count: number;
|
count: number;
|
||||||
}> => {
|
}> => {
|
||||||
@@ -963,7 +990,9 @@ export const reorderCategoriesAdmin = async (
|
|||||||
ids: number[],
|
ids: number[],
|
||||||
): Promise<{ success: boolean; error?: string }> => {
|
): Promise<{ success: boolean; error?: string }> => {
|
||||||
try {
|
try {
|
||||||
await apiClient.put(`${V2}/admin/protected/categories/reorder`, { ids });
|
await apiClient.put(`${V2}/admin/protected/categories/reorder`, {
|
||||||
|
ids,
|
||||||
|
});
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
@@ -1223,3 +1252,15 @@ export const updateSettings = async (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getAdminStatsByMonth = async (
|
||||||
|
month?: string,
|
||||||
|
): Promise<MonthlyStats> => {
|
||||||
|
const { data } = await apiClient.get(
|
||||||
|
`${V2}/admin/protected/stats/monthly`,
|
||||||
|
{
|
||||||
|
params: month ? { month } : undefined,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
+142
-114
@@ -1,166 +1,194 @@
|
|||||||
// Shared types for admin panel
|
// Shared types for admin panel
|
||||||
|
|
||||||
export interface AdminUser {
|
export interface AdminUser {
|
||||||
id: number;
|
id: number;
|
||||||
username: string;
|
username: string;
|
||||||
role: string;
|
role: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthResponse {
|
export interface AuthResponse {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
message?: string;
|
message?: string;
|
||||||
access_token?: string;
|
access_token?: string;
|
||||||
token_type?: string;
|
token_type?: string;
|
||||||
expires_in?: number;
|
expires_in?: number;
|
||||||
user?: AdminUser;
|
user?: AdminUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientResponse {
|
export interface ClientResponse {
|
||||||
id: number;
|
id: number;
|
||||||
username: string;
|
username: string;
|
||||||
nom: string;
|
nom: string;
|
||||||
prenom: string;
|
prenom: string;
|
||||||
telephone: string;
|
telephone: string;
|
||||||
adresse?: string;
|
adresse?: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
created_at?: string;
|
created_at?: string;
|
||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
command: number;
|
command: number;
|
||||||
points_extra: Record<string, number>;
|
points_extra: Record<string, number>;
|
||||||
amende: number;
|
amende: number;
|
||||||
cancellations_count: number;
|
cancellations_count: number;
|
||||||
last_penalty_reason?: string;
|
last_penalty_reason?: string;
|
||||||
referral_balance?: number;
|
referral_balance?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommandResponse {
|
export interface CommandResponse {
|
||||||
id: number;
|
id: number;
|
||||||
client_order_number?: number;
|
client_order_number?: number;
|
||||||
username: string;
|
username: string;
|
||||||
status: string;
|
status: string;
|
||||||
adresse: string;
|
adresse: string;
|
||||||
total_prix: number;
|
total_prix: number;
|
||||||
livreur_assign?: string | null;
|
livreur_assign?: string | null;
|
||||||
proposed_address?: string | null;
|
proposed_address?: string | null;
|
||||||
address_proposal_status?: string;
|
address_proposal_status?: string;
|
||||||
referral_used?: number;
|
referral_used?: number;
|
||||||
cancel_reason?: string;
|
cancel_reason?: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderItem {
|
export interface OrderItem {
|
||||||
id: number;
|
id: number;
|
||||||
command_id: number;
|
command_id: number;
|
||||||
product_id: number;
|
product_id: number;
|
||||||
product_name: string;
|
product_name: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
price: number;
|
price: number;
|
||||||
status: string;
|
status: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Alert {
|
export interface Alert {
|
||||||
id: number;
|
id: number;
|
||||||
username: string;
|
username: string;
|
||||||
status: string;
|
status: string;
|
||||||
message: string;
|
message: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryPerson {
|
export interface DeliveryPerson {
|
||||||
id: number;
|
id: number;
|
||||||
username: string;
|
username: string;
|
||||||
status: 'available' | 'busy' | 'offline';
|
status: "available" | "busy" | "offline";
|
||||||
location: {
|
location: {
|
||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
last_update: string;
|
last_update: string;
|
||||||
is_recent: boolean;
|
is_recent: boolean;
|
||||||
};
|
};
|
||||||
stats: {
|
stats: {
|
||||||
total_deliveries: number;
|
total_deliveries: number;
|
||||||
completed_today: number;
|
completed_today: number;
|
||||||
queue_size: number;
|
queue_size: number;
|
||||||
current_command: number | null;
|
current_command: number | null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryPersonsStats {
|
export interface DeliveryPersonsStats {
|
||||||
total: number;
|
total: number;
|
||||||
available: number;
|
available: number;
|
||||||
busy: number;
|
busy: number;
|
||||||
offline: number;
|
offline: number;
|
||||||
active_deliveries: number;
|
active_deliveries: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Product {
|
export interface Product {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
category: string;
|
category: string;
|
||||||
stock: number;
|
stock: number;
|
||||||
unit: string;
|
unit: string;
|
||||||
prices?: Array<{ id?: number; quantity: number; price: number; active_price?: boolean }>;
|
prices?: Array<{
|
||||||
media?: Array<{ url: string; type: string; id?: number; created_at?: string }>;
|
id?: number;
|
||||||
coming_soon?: boolean;
|
quantity: number;
|
||||||
created_at?: string;
|
price: number;
|
||||||
updated_at?: string;
|
active_price?: boolean;
|
||||||
|
}>;
|
||||||
|
media?: Array<{
|
||||||
|
url: string;
|
||||||
|
type: string;
|
||||||
|
id?: number;
|
||||||
|
created_at?: string;
|
||||||
|
}>;
|
||||||
|
coming_soon?: boolean;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryStatus {
|
export interface DeliveryStatus {
|
||||||
status: 'available' | 'busy' | 'offline';
|
status: "available" | "busy" | "offline";
|
||||||
current_command?: number;
|
current_command?: number;
|
||||||
last_update?: number;
|
last_update?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueueInfo {
|
export interface QueueInfo {
|
||||||
queue_size: number;
|
queue_size: number;
|
||||||
commands: any[];
|
commands: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryItemProduct {
|
export interface DeliveryItemProduct {
|
||||||
produit: string;
|
produit: string;
|
||||||
quantite: number;
|
quantite: number;
|
||||||
prix: number;
|
prix: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryItem {
|
export interface DeliveryItem {
|
||||||
id: number;
|
id: number;
|
||||||
status: string;
|
status: string;
|
||||||
adresse: string;
|
adresse: string;
|
||||||
total_prix: number;
|
total_prix: number;
|
||||||
referral_used?: number;
|
referral_used?: number;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
eta?: string;
|
eta?: string;
|
||||||
items?: DeliveryItemProduct[];
|
items?: DeliveryItemProduct[];
|
||||||
items_count?: number;
|
items_count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientInfo {
|
export interface ClientInfo {
|
||||||
username: string;
|
username: string;
|
||||||
nom?: string;
|
nom?: string;
|
||||||
prenom?: string;
|
prenom?: string;
|
||||||
telephone?: string;
|
telephone?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeliveryDetails {
|
export interface DeliveryDetails {
|
||||||
delivery: DeliveryItem;
|
delivery: DeliveryItem;
|
||||||
client_info: ClientInfo;
|
client_info: ClientInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PenaltyInfo {
|
export interface PenaltyInfo {
|
||||||
client_username: string;
|
client_username: string;
|
||||||
current_amende: number;
|
current_amende: number;
|
||||||
cancellations_count: number;
|
cancellations_count: number;
|
||||||
next_penalty: number;
|
next_penalty: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MapLinks {
|
export interface MapLinks {
|
||||||
google_maps: string;
|
google_maps: string;
|
||||||
waze: string;
|
waze: string;
|
||||||
apple_maps: string;
|
apple_maps: string;
|
||||||
openstreetmap: string;
|
openstreetmap: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MonthlyDayStat {
|
||||||
|
day: string; // "2026-06-05"
|
||||||
|
label: string; // "05/06"
|
||||||
|
count: number;
|
||||||
|
revenue: number;
|
||||||
|
quantity: number;
|
||||||
|
}
|
||||||
|
export interface MonthlyStatsSummary {
|
||||||
|
total_orders: number;
|
||||||
|
total_revenue: number;
|
||||||
|
total_quantity: number;
|
||||||
|
}
|
||||||
|
export interface MonthlyStats {
|
||||||
|
month: string; // "2026-06"
|
||||||
|
summary: MonthlyStatsSummary;
|
||||||
|
by_day: MonthlyDayStat[];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user