supersam/src/hooks/useOrderGroups.js

256 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import { assignDriverToOrderGroup, fetchOrderGroups, saveShipmentData, updateDeliveryStatus, updateOrderGroupDeliveryChoice } from "../services/supabase/orderGroupRepository";
import {
buildOrderGroupBuckets,
filterOrderGroups,
groupOrderGroupsByDate,
ORDER_GROUP_DISPLAY_STATUS_OPTIONS,
getOrderGroupDisplayStatusValue,
} from "../services/orderGroupViews";
import { getErrorMessage } from "../utils/deliveryUtils";
export const useOrderGroups = () => {
const [orderGroups, setOrderGroups] = React.useState(() => []);
const [filters, setFilters] = React.useState({
query: "",
displayStatus: "all",
deliveryType: "",
});
const [selectedOrderGroupId, setSelectedOrderGroupId] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(true);
const [loadError, setLoadError] = React.useState("");
const [isSavingDeliveryChoice, setIsSavingDeliveryChoice] = React.useState(false);
const [isSavingDriverAssignment, setIsSavingDriverAssignment] = React.useState(false);
const [isSavingStatusChange, setIsSavingStatusChange] = React.useState(false);
const loadLiveData = React.useCallback(async (showLoading = true) => {
if (showLoading) {
setIsLoading(true);
}
setLoadError("");
const groupsResult = await fetchOrderGroups();
if (!groupsResult) {
return;
}
if (groupsResult.error) {
setLoadError(groupsResult.error?.message || "Не удалось загрузить группы доставки");
setOrderGroups([]);
setIsLoading(false);
return;
}
setOrderGroups(groupsResult.data || []);
setIsLoading(false);
}, []);
// Initial load
React.useEffect(() => {
let cancelled = false;
const doLoad = async () => {
setIsLoading(true);
await loadLiveData(true);
if (cancelled) return;
};
doLoad();
return () => { cancelled = true; };
}, [loadLiveData]);
// Refetch on window focus to keep data fresh across tabs/pages
React.useEffect(() => {
const handleFocus = () => {
loadLiveData(false); // silent refetch, no loading spinner
};
window.addEventListener("focus", handleFocus);
return () => window.removeEventListener("focus", handleFocus);
}, [loadLiveData]);
React.useEffect(() => {
if (!orderGroups.length) {
setSelectedOrderGroupId(null);
return;
}
if (!selectedOrderGroupId || !orderGroups.some((group) => group.id === selectedOrderGroupId)) {
setSelectedOrderGroupId(orderGroups[0].id);
}
}, [orderGroups, selectedOrderGroupId]);
const statusCounts = React.useMemo(() => {
const counts = {};
orderGroups.forEach((group) => {
const status = getOrderGroupDisplayStatusValue(group);
counts[status] = (counts[status] || 0) + 1;
});
return counts;
}, [orderGroups]);
const statusOptions = React.useMemo(() =>
ORDER_GROUP_DISPLAY_STATUS_OPTIONS.map((opt) => ({
...opt,
count: opt.value === "all" ? orderGroups.length : (statusCounts[opt.value] || 0),
})),
[statusCounts, orderGroups]
);
const filteredOrderGroups = React.useMemo(
() => filterOrderGroups(orderGroups, filters),
[filters, orderGroups],
);
const visibleOrderGroups = filteredOrderGroups;
const selectedOrderGroup =
visibleOrderGroups.find((group) => group.id === selectedOrderGroupId) ||
orderGroups.find((group) => group.id === selectedOrderGroupId) ||
visibleOrderGroups[0] ||
null;
const orderGroupsByDate = React.useMemo(() => groupOrderGroupsByDate(orderGroups), [orderGroups]);
const deliveryGroupBuckets = React.useMemo(() => buildOrderGroupBuckets(orderGroups), [orderGroups]);
const saveManualDeliveryChoice = React.useCallback(async ({
orderGroupId,
deliveryDate,
deliveryTime,
deliveryType,
deliveryAddress,
pickupDate,
pickupTimeSlot,
}) => {
setIsSavingDeliveryChoice(true);
try {
/* Demo mode removed */
const result = await updateOrderGroupDeliveryChoice({
orderGroupId,
deliveryDate,
deliveryTime,
deliveryType,
deliveryAddress,
pickupDate,
pickupTimeSlot,
});
if (result.error) {
return {
success: false,
error: getErrorMessage(result.error, "Не удалось сохранить согласование доставки"),
};
}
setOrderGroups((currentGroups) =>
currentGroups.map((group) => (group.id === orderGroupId ? result.data : group)),
);
return { success: true, data: result.data };
} catch (error) {
return {
success: false,
error: getErrorMessage(error, "Не удалось сохранить согласование доставки"),
};
} finally {
setIsSavingDeliveryChoice(false);
}
}, []);
const assignDriver = React.useCallback(async ({ orderGroupId, driverId }) => {
setIsSavingDriverAssignment(true);
try {
const result = await assignDriverToOrderGroup({ orderGroupId, driverId });
if (result.error) {
return {
success: false,
error: getErrorMessage(result.error, "Не удалось назначить водителя"),
};
}
setOrderGroups((currentGroups) =>
currentGroups.map((group) => (group.id === orderGroupId ? result.data : group)),
);
return { success: true, data: result.data };
} catch (error) {
return {
success: false,
error: getErrorMessage(error, "Не удалось назначить водителя"),
};
} finally {
setIsSavingDriverAssignment(false);
}
}, []);
const changeDeliveryStatus = React.useCallback(async ({ orderGroupId, status, details, shipmentData }) => {
setIsSavingStatusChange(true);
try {
const result = await updateDeliveryStatus({ orderGroupId, status, details, shipmentData });
if (result.error) {
return {
success: false,
error: getErrorMessage(result.error, "Не удалось обновить статус"),
};
}
setOrderGroups((currentGroups) =>
currentGroups.map((group) => (group.id === orderGroupId ? result.data : group)),
);
return { success: true, data: result.data };
} catch (error) {
return {
success: false,
error: getErrorMessage(error, "Не удалось обновить статус"),
};
} finally {
setIsSavingStatusChange(false);
}
}, []);
const onSaveShipmentData = React.useCallback(async ({ orderGroupId, shipmentData }) => {
try {
const result = await saveShipmentData({ orderGroupId, shipmentData });
if (result.error) {
return {
success: false,
error: getErrorMessage(result.error, "Не удалось сохранить данные отгрузки"),
};
}
setOrderGroups((currentGroups) =>
currentGroups.map((group) => (group.id === orderGroupId ? result.data : group)),
);
return { success: true, data: result.data };
} catch (error) {
return {
success: false,
error: getErrorMessage(error, "Не удалось сохранить данные отгрузки"),
};
}
}, []);
return {
orderGroups,
allOrderGroups: orderGroups,
filteredOrderGroups,
visibleOrderGroups,
selectedOrderGroup,
selectedOrderGroupId,
setSelectedOrderGroupId,
filters,
setFilters,
statusOptions,
orderGroupsByDate,
deliveryGroupBuckets,
saveManualDeliveryChoice,
assignDriver,
changeDeliveryStatus,
saveShipmentData: onSaveShipmentData,
isSavingDeliveryChoice,
isSavingDriverAssignment,
isSavingStatusChange,
isLoading,
loadError,
refetch: loadLiveData,
};
};