fix: StatusActionPanel smart hints + driver name lookup + logistician can edit shipment + completed label
1. StatusActionPanel: all buttons clickable (no more manual:false blocking)
- Click on current status shows actual state: "Водитель уже назначен: Иван"
- "Назначен водитель" clickable even if already assigned
- "Согласовано" clickable even if already agreed
2. Status indicators: green badges ✓ Дата согласована / ✓ Водитель: имя
+ warning badges if missing
3. DriverAssignmentPanel: look up driver name from drivers list if
assignedDriverName is empty (Supabase join failed)
4. DriverShipmentPanel: now visible to logistician/admin too — can edit
shipment data (fix wrong driver checkboxes)
5. SmsStatusCard: add completed label ("Завершено")
This commit is contained in:
parent
17f93a65ae
commit
755385cf0e
|
|
@ -122,7 +122,7 @@ const DriverAssignmentPanel = ({
|
|||
Водитель назначен
|
||||
</p>
|
||||
<p className="mt-1 text-lg font-semibold">
|
||||
{order.assignedDriverName || "Водитель назначен"}
|
||||
{order.assignedDriverName || drivers.find((d) => d.id === order.assignedDriverId)?.name || "Водитель назначен"}
|
||||
</p>
|
||||
</div>
|
||||
<Badge tone="accent">Назначен</Badge>
|
||||
|
|
|
|||
|
|
@ -1110,7 +1110,7 @@ export const OrderDetailPanel = ({
|
|||
/>
|
||||
) : null}
|
||||
|
||||
{userRole === "driver" && order ? (
|
||||
{["driver", "logistician", "admin", "mega_admin"].includes(userRole) && order ? (
|
||||
<DriverShipmentPanel
|
||||
order={order}
|
||||
onShipmentChange={handleShipmentChange}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ const NOTIF_LABELS = {
|
|||
paid_storage_sent: "Платное хранение: отправлено",
|
||||
draft: "Черновик",
|
||||
confirmed: "Клиент согласовал дату",
|
||||
completed: "Завершено",
|
||||
};
|
||||
|
||||
const NOTIF_TONES = {
|
||||
|
|
@ -38,6 +39,7 @@ const NOTIF_TONES = {
|
|||
paid_storage_sent: "accent",
|
||||
draft: "neutral",
|
||||
confirmed: "accent",
|
||||
completed: "neutral",
|
||||
};
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import { Button } from "../UI/Button";
|
|||
import { Panel } from "../UI/Panel";
|
||||
import { DELIVERY_GROUP_STATUS_LABELS } from "../../services/orderGroupViews";
|
||||
|
||||
const STATUS_LABELS = DELIVERY_GROUP_STATUS_LABELS;
|
||||
|
||||
const StatusActionPanel = ({
|
||||
order,
|
||||
userRole,
|
||||
|
|
@ -20,32 +18,45 @@ const StatusActionPanel = ({
|
|||
const currentStatus = order.deliveryStatus || order.delivery_status;
|
||||
const isPickup = (order.deliveryType || order.delivery_type) === "pickup" || currentStatus === "pickup";
|
||||
|
||||
// Check if delivery date and half-day are set
|
||||
// Check delivery schedule
|
||||
const hasDeliveryDate = !!(order.deliveryDate || order.customerDate);
|
||||
const hasDeliveryHalfDay = !!(order.deliveryTime || order.deliveryHalfDay || order.delivery_time || order.delivery_half_day);
|
||||
const hasDeliverySchedule = hasDeliveryDate && hasDeliveryHalfDay;
|
||||
const hasDriver = !!order.assignedDriverId;
|
||||
|
||||
// Smart hints: show actual state instead of generic "do X"
|
||||
const getHint = (statusValue) => {
|
||||
if (statusValue === "agreed") {
|
||||
if (hasDeliverySchedule) return "Дата доставки уже согласована";
|
||||
return "Согласуйте дату доставки выше";
|
||||
}
|
||||
if (statusValue === "driver_assigned") {
|
||||
if (hasDriver) return `Водитель уже назначен: ${order.assignedDriverName || ""}`.trim();
|
||||
return "Назначьте водителя из списка выше";
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
// Build status options — no "Загружено", "Доставлено"/"Вывезено" require date+half-day
|
||||
const allStatuses = isPickup
|
||||
? [
|
||||
{ value: "pending_confirmation", label: "Ожидает согласования", manual: true },
|
||||
{ value: "agreed", label: "Согласовано", manual: false, hint: "Согласуйте дату доставки выше" },
|
||||
{ value: "driver_assigned", label: "Назначен водитель", manual: false, hint: "Назначьте водителя из списка" },
|
||||
{ value: "picked_up", label: "Вывезено", manual: true, primary: true, requiresSchedule: true },
|
||||
{ value: "delivered", label: "Доставлено", manual: true, mismatch: true, requiresSchedule: true },
|
||||
{ value: "requires_address", label: "Требуется адрес", manual: true },
|
||||
{ value: "problem", label: "Проблема", manual: true },
|
||||
{ value: "cancelled", label: "Отменено", manual: true },
|
||||
{ value: "pending_confirmation", label: "Ожидает согласования" },
|
||||
{ value: "agreed", label: "Согласовано" },
|
||||
{ value: "driver_assigned", label: "Назначен водитель" },
|
||||
{ value: "picked_up", label: "Вывезено", primary: true, requiresSchedule: true },
|
||||
{ value: "delivered", label: "Доставлено", mismatch: true, requiresSchedule: true },
|
||||
{ value: "requires_address", label: "Требуется адрес" },
|
||||
{ value: "problem", label: "Проблема" },
|
||||
{ value: "cancelled", label: "Отменено" },
|
||||
]
|
||||
: [
|
||||
{ value: "pending_confirmation", label: "Ожидает согласования", manual: true },
|
||||
{ value: "agreed", label: "Согласовано", manual: false, hint: "Согласуйте дату доставки выше" },
|
||||
{ value: "driver_assigned", label: "Назначен водитель", manual: false, hint: "Назначьте водителя из списка" },
|
||||
{ value: "delivered", label: "Доставлено", manual: true, primary: true, requiresSchedule: true },
|
||||
{ value: "picked_up", label: "Вывезено", manual: true, mismatch: true, requiresSchedule: true },
|
||||
{ value: "requires_address", label: "Требуется адрес", manual: true },
|
||||
{ value: "problem", label: "Проблема", manual: true },
|
||||
{ value: "cancelled", label: "Отменено", manual: true },
|
||||
{ value: "pending_confirmation", label: "Ожидает согласования" },
|
||||
{ value: "agreed", label: "Согласовано" },
|
||||
{ value: "driver_assigned", label: "Назначен водитель" },
|
||||
{ value: "delivered", label: "Доставлено", primary: true, requiresSchedule: true },
|
||||
{ value: "picked_up", label: "Вывезено", mismatch: true, requiresSchedule: true },
|
||||
{ value: "requires_address", label: "Требуется адрес" },
|
||||
{ value: "problem", label: "Проблема" },
|
||||
{ value: "cancelled", label: "Отменено" },
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -56,20 +67,33 @@ const StatusActionPanel = ({
|
|||
Измените статус, если водитель забыл обновить или нужна корректировка.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Status indicators: show current state clearly */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{hasDeliverySchedule && (
|
||||
<Badge tone="accent">✓ Дата согласована</Badge>
|
||||
)}
|
||||
{hasDriver && (
|
||||
<Badge tone="accent">✓ Водитель: {order.assignedDriverName || "назначен"}</Badge>
|
||||
)}
|
||||
{!hasDeliverySchedule && (
|
||||
<Badge tone="warning">⚠ Дата не указана</Badge>
|
||||
)}
|
||||
{!hasDriver && (
|
||||
<Badge tone="warning">⚠ Водитель не назначен</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{allStatuses.map((statusOption) => {
|
||||
const isCurrent = currentStatus === statusOption.value;
|
||||
const isClickable = (statusOption.manual !== false || currentStatus === 'problem') && !isCurrent;
|
||||
const blockedBySchedule = statusOption.requiresSchedule && !hasDeliverySchedule;
|
||||
const hint = getHint(statusOption.value);
|
||||
return (
|
||||
<div key={statusOption.value} className="relative group">
|
||||
<Button
|
||||
key={statusOption.value}
|
||||
variant={isCurrent ? "primary" : (statusOption.mismatch ? "ghost" : "secondary")}
|
||||
onClick={() => {
|
||||
if (!isClickable) {
|
||||
onConfirmStatus?.({ type: "hint", hint: statusOption.hint || "" });
|
||||
return;
|
||||
}
|
||||
if (blockedBySchedule) {
|
||||
onConfirmStatus?.({
|
||||
type: "hint",
|
||||
|
|
@ -77,6 +101,10 @@ const StatusActionPanel = ({
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (isCurrent && hint) {
|
||||
onConfirmStatus?.({ type: "hint", hint });
|
||||
return;
|
||||
}
|
||||
onConfirmStatus?.({
|
||||
type: "status",
|
||||
status: statusOption.value,
|
||||
|
|
@ -90,7 +118,6 @@ const StatusActionPanel = ({
|
|||
>
|
||||
{statusOption.label}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue