chore: build

This commit is contained in:
2026-06-14 18:09:44 +02:00
parent 3a0f725159
commit 6d4e0862ff
45 changed files with 3745 additions and 873 deletions
+123 -31
View File
@@ -1,4 +1,5 @@
import apiClient, { API_BASE_URL } from "./client";
import apiClient from "./client";
import { API_BASE_URL } from "./client";
import type {
AuthResponse,
ClientResponse,
@@ -52,6 +53,72 @@ export const logoutAdmin = async (): Promise<void> => {
}
};
export interface StatsSummary {
total_orders: number;
total_revenue: number;
peak_weekday: string;
top_product: string;
avg_per_day: number;
}
export interface WeekdayStat {
weekday: string;
count: number;
}
export interface DayStat {
day: string;
label: string;
count: number;
}
export interface DayRevenueStat {
day: string;
label: string;
revenue: number;
}
export interface HourStat {
hour: number;
label: string;
count: number;
revenue: number;
}
export interface ProductStat {
product_id: number;
name: string;
quantity: number;
order_count: number;
revenue: number;
category: string;
category_color: string;
}
export interface QuantityStat {
quantity: number;
order_count: number;
total_sold: number;
revenue: number;
}
export interface ProductQuantityBreakdown {
product_id: number;
name: string;
category_color: string;
total_orders: number;
quantities: QuantityStat[];
}
export interface AdminStats {
summary: StatsSummary;
by_weekday: WeekdayStat[];
by_day_30: DayStat[];
by_day_revenue: DayRevenueStat[];
by_hour: HourStat[];
top_products: ProductStat[];
by_quantity: ProductQuantityBreakdown[];
}
export const getAdminStats = async (): Promise<AdminStats> => {
const { data } = await apiClient.get(`${V2}/admin/protected/stats`);
return data;
};
export const getAllClients = async (): Promise<ClientResponse[]> => {
const { data } = await apiClient.get(`${V2}/admin/protected/all/clients`);
return data.clients || [];
@@ -84,9 +151,6 @@ export const updateUserByAdmin = async (
return { success: true, message: data.message, user: data.user };
};
// ============================================
// COMMANDES
export const getAllCommands = async (status?: string, username?: string) => {
let url = `${V2}/admin/protected/orders`;
const params: string[] = [];
@@ -171,8 +235,11 @@ export const updateCommandAddress = async (
export const validateCommand = async (commandId: number) => {
const { data } = await apiClient.post(
`${V2}/admin/protected/orders/${commandId}/force-validate`,
{ command_id: commandId },
);
return { success: true, message: data.message };
const validated = (data.validated ?? []) as { command_id: number; 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 (
@@ -197,31 +264,22 @@ export const notifyClientToDescend = async (commandId: number) => {
};
};
export const confirmReceptionAdmin = async (commandId: number) => {
const { data } = await apiClient.post(
`${V2}/admin/protected/orders/${commandId}/confirm-reception`,
);
return {
success: true,
message: data.message,
points_earned: data.points_earned,
client_username: data.client_username,
};
};
// ============================================
// LIVREURS
// ============================================
export const getAvailableDeliveryPersons = async () => {
const { data } = await apiClient.get(
`${V2}/admin/protected/delivery-persons`,
);
return {
success: true,
livreurs: data.livreurs || [],
count: data.count || 0,
};
try {
const { data } = await apiClient.get(
`${V2}/admin/protected/delivery-persons`,
);
return {
success: true,
livreurs: data.livreurs || [],
count: data.count || 0,
};
} catch {
return { success: false, livreurs: [], count: 0 };
}
};
export const assignDeliveryPerson = async (
@@ -370,10 +428,6 @@ export const getDeliverymanLocationForCommand = async (commandId: number) => {
}
};
// ============================================
// PRODUITS
// ============================================
export const getAllProductsAdmin = async (): Promise<{
success: boolean;
data: Product[];
@@ -445,7 +499,7 @@ export const createUserByAdmin = async (data: {
role: string;
}) => {
const { data: res } = await apiClient.post(
`${V2}/admin/auth/register`,
`${V2}/admin/protected/users`,
data,
);
return {
@@ -710,6 +764,20 @@ export const deleteProductMediaAdmin = async (
return { success: true, message: data.message };
};
export const activateProductPrice = async (priceId: number) => {
const { data } = await apiClient.post(
`${V2}/admin/protected/active/product/price/${priceId}`,
);
return { success: true, message: data.message };
};
export const deactivateProductPrice = async (priceId: number) => {
const { data } = await apiClient.post(
`${V2}/admin/protected/desactive/product/price/${priceId}`,
);
return { success: true, message: data.message };
};
// ============================================
// ADDRESSES
// ============================================
@@ -849,6 +917,26 @@ export interface PointsTier {
points: number;
}
export interface RewardCategoryConfig {
category: string;
all_products: boolean;
product_ids: number[];
}
export interface RewardItem {
product_id: number;
quantity: number;
price: number;
}
export interface PointsReward {
threshold: number;
type: "free_product" | "half_price_product" | "custom";
description: string;
category_configs: RewardCategoryConfig[];
reward_items: RewardItem[];
}
export interface PointsPool {
key: string;
name: string;
@@ -947,6 +1035,7 @@ export interface AppSettings {
penalty_tiers: PenaltyTier[];
points_enabled: boolean;
points_pools: PointsPool[];
points_reward?: PointsReward | null;
referral_enabled: boolean;
delivery_schedule: DeliverySchedule;
postal_zones: PostalZone[];
@@ -958,7 +1047,10 @@ export interface AppSettings {
telegram_bot_token: string;
telegram_bot_username: string;
telegram_notifications_enabled: boolean;
telegram_2fa_enabled: boolean;
delivery_mode: DeliveryModeConfig;
shop_name: string;
contact_telegram: string;
}
export const getSettings = async (): Promise<{
+37 -13
View File
@@ -1,4 +1,7 @@
import apiClient, { API_BASE_URL } from "./client";
import apiClient from "./client";
import { API_BASE_URL } from "./client";
//@ts
import type {
OrderItem,
DeliveryPerson,
@@ -39,10 +42,6 @@ export const confirmReceptionCabine = async (commandId: number) => {
};
};
// ============================================
// PENALITES
// ============================================
export const applyClientPenalty = async (
clientUsername: string,
reason: string,
@@ -70,7 +69,6 @@ export const resetClientPenalties = async (clientUsername: string) => {
return { success: true, message: data.message };
};
// pool: index dans pool_names/pool_keys, -1 = reset tous les points
export const resetClientPoints = async (
clientUsername: string,
pool: number = -1,
@@ -96,10 +94,6 @@ export const getPenaltiesStats = async () => {
return { success: true, data: data.data };
};
// ============================================
// COMMANDES
// ============================================
export const getCancelledOrders = async () => {
const { data } = await apiClient.get(`${API}/commands/cancelled`);
return {
@@ -200,7 +194,7 @@ export const getAllDeliveryPersonsWithDetails = async (): Promise<{
users.map(async (u: any): Promise<DeliveryPerson> => {
try {
const { data: details } = await apiClient.get(
`${V2}/admin/protected/delivery-persons/${u.username}`,
`${API}/delivery-persons/${u.username}`,
);
const d = details.deliveryman || details;
const parsedStatus = parseStatus(d.status);
@@ -373,7 +367,7 @@ export const markCabineNotificationsRead = async (): Promise<void> => {
export const getPublicSettings = async (): Promise<PublicSettings> => {
try {
const { data } = await apiClient.get(
`https://5.181.0.112.nip.io/api/v1/app-settings`,
`${API_BASE_URL}/api/v1/app-settings`,
);
return {
penalties_enabled: data.penalties_enabled ?? true,
@@ -433,11 +427,41 @@ export const getAllAddresses = async (): Promise<
}));
};
// ============================================
// COMMANDES — CABINE
// ============================================
export const getCabineCommands = async (): Promise<{
success: boolean;
commands: any[];
count: number;
}> => {
try {
const { data } = await apiClient.get(`${API}/commands`);
return { success: true, commands: data.commands || [], count: data.count || 0 };
} catch {
return { success: false, commands: [], count: 0 };
}
};
// ============================================
// CLIENTS — CABINE
// ============================================
export const getCabineAllClients = async (): Promise<any[]> => {
try {
const { data } = await apiClient.get(`${API}/all/clients`);
return data.clients || [];
} catch {
return [];
}
};
// ============================================
// TELEGRAM — CABINE
// ============================================
const CABINE_API = "https://5.181.0.112.nip.io/api/v1/cabine";
const CABINE_API = `${API_BASE_URL}/api/v1/cabine`;
export const getCabineTelegramStatus = async (): Promise<{
linked: boolean;
+24 -13
View File
@@ -1,4 +1,5 @@
import apiClient, { API_BASE_URL } from "./client";
import apiClient from "./client";
import { API_BASE_URL } from "./client";
import type {
DeliveryStatus,
QueueInfo,
@@ -9,10 +10,6 @@ import type {
const API = `${API_BASE_URL}/api/v1/livreur`;
// ============================================
// STATUT
// ============================================
export const getMyStatus = async (): Promise<{
success: boolean;
status?: DeliveryStatus;
@@ -45,10 +42,6 @@ export const updateMyStatus = async (
}
};
// ============================================
// QUEUE
// ============================================
export const getMyQueue = async (): Promise<{
success: boolean;
queue_info?: QueueInfo;
@@ -65,10 +58,6 @@ export const getMyQueue = async (): Promise<{
}
};
// ============================================
// LIVRAISONS
// ============================================
export const getMyDeliveries = async (): Promise<{
success: boolean;
deliveries?: DeliveryItem[];
@@ -383,6 +372,28 @@ export const ISSUE_LABELS: Record<IssueType, string> = {
other: "Autre",
};
export type StatPoint = { label: string; count: number; revenue: number };
export const getMyStats = async (): Promise<{
success: boolean;
by_day?: StatPoint[];
by_week?: StatPoint[];
by_month?: StatPoint[];
error?: string;
}> => {
try {
const { data } = await apiClient.get(`${API}/stats`);
return {
success: true,
by_day: data.by_day || [],
by_week: data.by_week || [],
by_month: data.by_month || [],
};
} catch (error: any) {
return { success: false, error: error.response?.data?.error || "Erreur réseau" };
}
};
export const reportDeliveryIssue = async (
deliveryId: number,
issueType: IssueType,
-2
View File
@@ -12,7 +12,6 @@ const apiClient = axios.create({
},
});
// Request interceptor: attach JWT token
apiClient.interceptors.request.use(async (config) => {
const isAdminRoute =
config.url?.includes("/api/v2/") ||
@@ -27,7 +26,6 @@ apiClient.interceptors.request.use(async (config) => {
return config;
});
// Response interceptor: handle common errors
apiClient.interceptors.response.use(
(response) => response,
(error) => {
-5
View File
@@ -2,7 +2,6 @@ import axios from "axios";
const TOMTOM_API_KEY = "MERY8I7LMeYVSLKO5WuV73W9rKJpBLoB";
// ---- Types ----
export interface LatLng {
latitude: number;
longitude: number;
@@ -24,7 +23,6 @@ export interface NavigationInstruction {
isActive: boolean;
}
// ---- Maneuver translations (FR) ----
export const maneuverTranslations: Record<string, string> = {
TURN_LEFT: "Tournez à gauche",
TURN_RIGHT: "Tournez à droite",
@@ -48,7 +46,6 @@ export const maneuverTranslations: Record<string, string> = {
WAYPOINT_REACHED: "Point de passage atteint",
};
// Ionicons name per maneuver
export const maneuverIcons: Record<string, string> = {
TURN_LEFT: "arrow-back",
TURN_RIGHT: "arrow-forward",
@@ -79,7 +76,6 @@ function formatDistance(meters: number): string {
return `${(meters / 1000).toFixed(1)} km`;
}
// ---- Geocode address → coords ----
export async function geocodeAddress(address: string): Promise<LatLng | null> {
try {
const url = `https://api.tomtom.com/search/2/geocode/${encodeURIComponent(address)}.json?key=${TOMTOM_API_KEY}&limit=1`;
@@ -96,7 +92,6 @@ export async function geocodeAddress(address: string): Promise<LatLng | null> {
return null;
}
// ---- Calculate route ----
export async function calculateRoute(
origin: LatLng,
destination: LatLng,
+2 -1
View File
@@ -102,8 +102,9 @@ export interface Product {
category: string;
stock: number;
unit: string;
prices?: Array<{ quantity: number; price: number }>;
prices?: Array<{ id?: number; quantity: number; price: number; active_price?: boolean }>;
media?: Array<{ url: string; type: string; id?: number; created_at?: string }>;
coming_soon?: boolean;
created_at?: string;
updated_at?: string;
}