159 lines
4.4 KiB
JavaScript
159 lines
4.4 KiB
JavaScript
const ACTIVE_DRIVER_STATUSES = new Set(["Назначен водитель", "Загружен", "В пути"]);
|
||
const COMPLETED_DRIVER_STATUSES = new Set(["Доставлен", "Закрыт"]);
|
||
const PROBLEM_DRIVER_STATUSES = new Set(["Проблема доставки"]);
|
||
const DRIVER_KANBAN_COLUMNS = [
|
||
{
|
||
key: "assigned",
|
||
title: "Назначен",
|
||
statuses: ["Назначен водитель"],
|
||
dropStatus: "Назначен водитель",
|
||
},
|
||
{
|
||
key: "loaded",
|
||
title: "Загружен",
|
||
statuses: ["Загружен"],
|
||
dropStatus: "Загружен",
|
||
},
|
||
{
|
||
key: "on_route",
|
||
title: "В пути",
|
||
statuses: ["В пути"],
|
||
dropStatus: "В пути",
|
||
},
|
||
{
|
||
key: "delivered",
|
||
title: "Доставлен",
|
||
statuses: ["Доставлен", "Закрыт"],
|
||
dropStatus: "Доставлен",
|
||
},
|
||
{
|
||
key: "problem",
|
||
title: "Проблема",
|
||
statuses: ["Проблема доставки"],
|
||
dropStatus: "Проблема доставки",
|
||
},
|
||
];
|
||
|
||
export const getDeliveryDay = (order) =>
|
||
order.deliverySlots?.[0]?.date || order.scheduledDelivery?.slice(0, 10) || "";
|
||
|
||
export const getDeliveryCity = (order) =>
|
||
order.customer.address?.split(",")[0]?.trim() || "Без города";
|
||
|
||
export const getDeliveryHalfDay = (order) => {
|
||
if (order.deliverySlots?.[0]?.time) {
|
||
return order.deliverySlots[0].time;
|
||
}
|
||
|
||
const deliveryHour = Number(order.scheduledDelivery?.slice(11, 13) || 0);
|
||
return deliveryHour >= 12 ? "Вторая половина дня" : "Первая половина дня";
|
||
};
|
||
|
||
const isWithinDateRange = (order, dateFrom, dateTo) => {
|
||
const deliveryDay = getDeliveryDay(order);
|
||
|
||
if (dateFrom && deliveryDay < dateFrom) {
|
||
return false;
|
||
}
|
||
|
||
if (dateTo && deliveryDay > dateTo) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
const isIncludedByView = (order, viewMode, showCompleted) => {
|
||
if (viewMode === "all") {
|
||
return showCompleted || !COMPLETED_DRIVER_STATUSES.has(order.status);
|
||
}
|
||
|
||
if (viewMode === "active") {
|
||
return ACTIVE_DRIVER_STATUSES.has(order.status) || (showCompleted && COMPLETED_DRIVER_STATUSES.has(order.status));
|
||
}
|
||
|
||
if (viewMode === "problems") {
|
||
return PROBLEM_DRIVER_STATUSES.has(order.status);
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
export const filterDriverDeliveries = (orders, filters) => {
|
||
const {
|
||
dateFrom = "",
|
||
dateTo = "",
|
||
city = "all",
|
||
timeSlot = "all",
|
||
viewMode = "active",
|
||
showCompleted = false,
|
||
} = filters;
|
||
|
||
return orders.filter((order) => {
|
||
if (!isWithinDateRange(order, dateFrom, dateTo)) {
|
||
return false;
|
||
}
|
||
|
||
if (city !== "all" && getDeliveryCity(order) !== city) {
|
||
return false;
|
||
}
|
||
|
||
if (timeSlot !== "all" && getDeliveryHalfDay(order) !== timeSlot) {
|
||
return false;
|
||
}
|
||
|
||
return isIncludedByView(order, viewMode, showCompleted);
|
||
});
|
||
};
|
||
|
||
const compareByRouteOrder = (left, right) => {
|
||
const leftOrder = left.driverRouteOrder ?? Number.MAX_SAFE_INTEGER;
|
||
const rightOrder = right.driverRouteOrder ?? Number.MAX_SAFE_INTEGER;
|
||
|
||
if (leftOrder !== rightOrder) {
|
||
return leftOrder - rightOrder;
|
||
}
|
||
|
||
return new Date(left.scheduledDelivery) - new Date(right.scheduledDelivery);
|
||
};
|
||
|
||
export const groupDriverDeliveriesByDate = (orders) => {
|
||
const grouped = orders.reduce((accumulator, order) => {
|
||
const date = getDeliveryDay(order);
|
||
accumulator[date] = accumulator[date] || [];
|
||
accumulator[date].push(order);
|
||
return accumulator;
|
||
}, {});
|
||
|
||
return Object.entries(grouped)
|
||
.sort(([leftDate], [rightDate]) => leftDate.localeCompare(rightDate))
|
||
.map(([date, items]) => ({
|
||
date,
|
||
items: [...items].sort(compareByRouteOrder),
|
||
}));
|
||
};
|
||
|
||
export const reorderDriverDeliveries = (orders, orderedIds) => {
|
||
const routeIndexMap = new Map(orderedIds.map((id, index) => [id, index + 1]));
|
||
|
||
return orders.map((order) =>
|
||
routeIndexMap.has(order.id)
|
||
? {
|
||
...order,
|
||
driverRouteOrder: routeIndexMap.get(order.id),
|
||
}
|
||
: order,
|
||
);
|
||
};
|
||
|
||
export const getDriverCities = (orders) =>
|
||
[...new Set(orders.map((order) => getDeliveryCity(order)).filter(Boolean))].sort((left, right) =>
|
||
left.localeCompare(right),
|
||
);
|
||
|
||
export const buildDriverKanbanColumns = (orders) =>
|
||
DRIVER_KANBAN_COLUMNS.map((column) => ({
|
||
...column,
|
||
items: orders.filter((order) => column.statuses.includes(order.status)).sort(compareByRouteOrder),
|
||
}));
|