fix: driver delivery UX — remove Загружено status, fix checkbox reset, fix confirmed label

1. Remove "Загружено" status from driver workflow — driver goes directly
   Назначен водитель → Доставлено (or Проблема)
2. Driver can undo "Доставлено" → "Вернуть в работу" (back to Назначен водитель)
3. Fix checkbox reset: shippedItems only resets when order ID changes,
   not on every order data refetch — driver can toggle items freely
4. Fix "confirmed" showing in SMS status card — add Russian label
5. onResetStatus resets to driver_assigned, not loaded
6. ShipmentPanel "Сбросить" works for all active statuses
This commit is contained in:
root 2026-07-13 11:51:56 +00:00
parent 1766ccb897
commit fbfcb71d61
6 changed files with 31 additions and 27 deletions

View File

@ -74,21 +74,18 @@ export const DriverDeliveryDetail = ({ order, onStatusChange }) => {
const orderItems = Array.isArray(order.items) ? order.items.map(splitItem) : []; const orderItems = Array.isArray(order.items) ? order.items.map(splitItem) : [];
const currentStatus = order.status; const currentStatus = order.status;
const IN_TRANSIT_STATUSES = ["Загружен", "В пути"];
const isOnRoute = IN_TRANSIT_STATUSES.includes(currentStatus);
let actionButtons = []; let actionButtons = [];
if (currentStatus === "Назначен водитель") { if (currentStatus === "Назначен водитель") {
actionButtons = [
{ value: "Загружен", label: "Загружено" },
{ value: "Проблема доставки", label: "Проблема" },
];
} else if (isOnRoute) {
actionButtons = [ actionButtons = [
{ value: "Доставлен", label: "Доставлено" }, { value: "Доставлен", label: "Доставлено" },
{ value: "Проблема доставки", label: "Проблема" }, { value: "Проблема доставки", label: "Проблема" },
]; ];
} else if (currentStatus === "Доставлен" || currentStatus === "Вывезено" || currentStatus === "Проблема доставки" || currentStatus === "Закрыт" || currentStatus === "Отменён") { } else if (currentStatus === "Доставлен") {
actionButtons = [
{ value: "Назначен водитель", label: "Вернуть в работу" },
];
} else if (currentStatus === "Проблема доставки" || currentStatus === "Закрыт" || currentStatus === "Отменён") {
actionButtons = []; actionButtons = [];
} else { } else {
actionButtons = availableTransitions.map((status) => ({ actionButtons = availableTransitions.map((status) => ({

View File

@ -138,11 +138,17 @@ export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, i
const [comments, setComments] = React.useState(initialComments); const [comments, setComments] = React.useState(initialComments);
const [commentInput, setCommentInput] = React.useState(""); const [commentInput, setCommentInput] = React.useState("");
// Sync state when order data changes (e.g. after save) // Sync state ONLY when order ID changes (navigating to different order), not on every order data update
const orderId = order?.id;
const prevOrderId = React.useRef(orderId);
React.useEffect(() => { React.useEffect(() => {
setShippedItems(initialShippedIds); if (prevOrderId.current !== orderId) {
setComments(initialComments); prevOrderId.current = orderId;
}, [initialShippedIds, initialComments]); setShippedItems(initialShippedIds);
setComments(initialComments);
setJustSaved(false);
}
}, [orderId, initialShippedIds, initialComments]);
// Track last saved shipment data for visual display // Track last saved shipment data for visual display
React.useEffect(() => { React.useEffect(() => {
@ -170,7 +176,7 @@ export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, i
}; };
const currentDeliveryStatus = order?.deliveryStatus || order?.delivery_status; const currentDeliveryStatus = order?.deliveryStatus || order?.delivery_status;
const isStatusFinal = ["delivered", "problem", "picked_up"].includes(currentDeliveryStatus); const isStatusFinal = ["delivered", "problem", "picked_up", "loaded", "on_route", "driver_assigned"].includes(currentDeliveryStatus);
const unshipAll = () => { const unshipAll = () => {
if (isStatusFinal && onResetStatus) { if (isStatusFinal && onResetStatus) {
@ -250,7 +256,7 @@ export const DriverShipmentPanel = ({ order, onShipmentChange, onSaveShipment, i
Отгрузить всё Отгрузить всё
</Button> </Button>
<Button variant="ghost" size="sm" onClick={unshipAll} disabled={shippedCount === 0 && !isStatusFinal}> <Button variant="ghost" size="sm" onClick={unshipAll} disabled={shippedCount === 0 && !isStatusFinal}>
Сбросить Сбросить отгрузку
</Button> </Button>
</div> </div>

View File

@ -1102,7 +1102,7 @@ export const OrderDetailPanel = ({
if (onChangeDeliveryStatus) { if (onChangeDeliveryStatus) {
onChangeDeliveryStatus({ onChangeDeliveryStatus({
orderGroupId: order.id, orderGroupId: order.id,
status: "loaded", status: "driver_assigned",
}).then((response) => { }).then((response) => {
if (!response.success) { if (!response.success) {
setFormMessage(response.error || "Не удалось сбросить статус"); setFormMessage(response.error || "Не удалось сбросить статус");
@ -1136,15 +1136,15 @@ export const OrderDetailPanel = ({
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{(() => { {(() => {
const currentStatus = order.deliveryStatus || order.delivery_status; const currentStatus = order.deliveryStatus || order.delivery_status;
const IN_TRANSIT_STATUSES = ["loaded", "on_route"];
const isOnRoute = IN_TRANSIT_STATUSES.includes(currentStatus);
const isPickup = (order.deliveryType || order.delivery_type) === "pickup" || currentStatus === "pickup"; const isPickup = (order.deliveryType || order.delivery_type) === "pickup" || currentStatus === "pickup";
let statusOptions = []; let statusOptions = [];
if (currentStatus === "delivered" || currentStatus === "picked_up" || currentStatus === "problem" || currentStatus === "cancelled" || currentStatus === "paid_storage") { if (currentStatus === "delivered" || currentStatus === "picked_up" || currentStatus === "problem") {
// Final statuses show "Return to work" instead
statusOptions = [];
} else if (currentStatus === "cancelled" || currentStatus === "paid_storage") {
statusOptions = []; statusOptions = [];
} else { } else {
// Primary button matches delivery type, secondary requires confirmation
if (isPickup) { if (isPickup) {
statusOptions = [ statusOptions = [
{ value: "picked_up", label: "Вывезено", mismatch: false }, { value: "picked_up", label: "Вывезено", mismatch: false },
@ -1160,7 +1160,6 @@ export const OrderDetailPanel = ({
} }
} }
// "Return to work" button for final statuses
const canReturn = ["delivered", "picked_up", "problem"].includes(currentStatus); const canReturn = ["delivered", "picked_up", "problem"].includes(currentStatus);
if (statusOptions.length === 0 && !canReturn) return null; if (statusOptions.length === 0 && !canReturn) return null;
@ -1201,7 +1200,7 @@ export const OrderDetailPanel = ({
disabled={isSavingStatusChange} disabled={isSavingStatusChange}
onClick={() => { onClick={() => {
setPendingStatus({ setPendingStatus({
value: "loaded", value: "driver_assigned",
label: "Вернуть в работу", label: "Вернуть в работу",
mismatch: false, mismatch: false,
deliveryType: "delivery", deliveryType: "delivery",

View File

@ -22,6 +22,7 @@ const NOTIF_LABELS = {
paid_storage_sending: "Отправляется…", paid_storage_sending: "Отправляется…",
paid_storage_sent: "Платное хранение: отправлено", paid_storage_sent: "Платное хранение: отправлено",
draft: "Черновик", draft: "Черновик",
confirmed: "Согласовано",
}; };
const NOTIF_TONES = { const NOTIF_TONES = {
@ -36,6 +37,7 @@ const NOTIF_TONES = {
paid_storage_sending: "info", paid_storage_sending: "info",
paid_storage_sent: "accent", paid_storage_sent: "accent",
draft: "neutral", draft: "neutral",
confirmed: "accent",
}; };
// Helpers // Helpers

View File

@ -240,10 +240,10 @@ export const ORDER_STATUS_TRANSITIONS = {
"Ожидает согласования доставки": ["Доставка согласована", "Самовывоз", "Требуется адрес", "Проблема доставки", "Отменён"], "Ожидает согласования доставки": ["Доставка согласована", "Самовывоз", "Требуется адрес", "Проблема доставки", "Отменён"],
"Доставка согласована": ["Назначен водитель", "Ожидает согласования доставки", "Проблема доставки", "Самовывоз", "Требуется адрес"], "Доставка согласована": ["Назначен водитель", "Ожидает согласования доставки", "Проблема доставки", "Самовывоз", "Требуется адрес"],
"Передан логисту": ["Доставка согласована", "Платное хранение", "Проблема доставки", "Отменён"], "Передан логисту": ["Доставка согласована", "Платное хранение", "Проблема доставки", "Отменён"],
"Назначен водитель": ["Загружен", "Проблема доставки"], "Назначен водитель": ["Доставлен", "Проблема доставки"],
Загружен: ["Доставлен", "Проблема доставки"], Загружен: ["Доставлен", "Проблема доставки"],
"В пути": ["Доставлен", "Проблема доставки"], "В пути": ["Доставлен", "Проблема доставки"],
Доставлен: ["Закрыт"], Доставлен: ["Закрыт", "Назначен водитель"],
"Проблема доставки": ["Ожидает согласования доставки", "Назначен водитель", "Отменён", "Закрыт"], "Проблема доставки": ["Ожидает согласования доставки", "Назначен водитель", "Отменён", "Закрыт"],
"Платное хранение": ["Доставка согласована", "Отменён", "Закрыт"], "Платное хранение": ["Доставка согласована", "Отменён", "Закрыт"],
"Самовывоз": ["Доставка согласована", "Закрыт", "Отменён", "Платное хранение"], "Самовывоз": ["Доставка согласована", "Закрыт", "Отменён", "Платное хранение"],
@ -270,7 +270,7 @@ export const ROLE_TRANSITION_TARGETS = {
"Закрыт", "Закрыт",
"Отменён", "Отменён",
], ],
driver: ["Загружен", "Доставлен", "Проблема доставки"], driver: ["Доставлен", "Проблема доставки"],
admin: ORDER_STATUSES, admin: ORDER_STATUSES,
}; };
@ -291,7 +291,7 @@ export const LOGISTICS_STATUSES = [
"Проблема доставки", "Проблема доставки",
]; ];
export const DRIVER_STATUSES = ["Назначен водитель", "Загружен", "Доставлен"]; export const DRIVER_STATUSES = ["Назначен водитель", "Доставлен"];
export const getOrderStatusComment = (status) => ORDER_STATUS_META[status]?.comment || "Комментарий не задан."; export const getOrderStatusComment = (status) => ORDER_STATUS_META[status]?.comment || "Комментарий не задан.";

View File

@ -39,7 +39,7 @@ export const DRIVER_VISIBLE_DELIVERY_STATUSES = [
"paid_storage", "paid_storage",
]; ];
export const DRIVER_ACTIVE_DELIVERY_STATUSES = ["driver_assigned", "loaded", "on_route", "problem"]; export const DRIVER_ACTIVE_DELIVERY_STATUSES = ["driver_assigned", "problem"];
const HALF_DAY_LABELS = { const HALF_DAY_LABELS = {
morning: "Первая половина дня", morning: "Первая половина дня",