From 581a275bc0df59566d593ecd4a284dbfe129da1d Mon Sep 17 00:00:00 2001 From: root Date: Thu, 28 May 2026 10:11:57 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20action=20log=20=E2=80=94=20readable=20dr?= =?UTF-8?q?iver=20names,=20no=20duplicate=20columns,=20meaningful=20descri?= =?UTF-8?q?ptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/admin/ActionLogPanel.jsx | 96 ++++++++++--------- src/services/supabase/orderGroupRepository.js | 9 +- 2 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/components/admin/ActionLogPanel.jsx b/src/components/admin/ActionLogPanel.jsx index 31c05cd..3191249 100644 --- a/src/components/admin/ActionLogPanel.jsx +++ b/src/components/admin/ActionLogPanel.jsx @@ -33,30 +33,11 @@ const ACTION_TONES = { invitation_created: "accent", }; -const formatMSK = (isoStr) => { - if (!isoStr) return "—"; - try { - const d = new Date(isoStr); - if (isNaN(d.getTime())) return isoStr; - const day = String(d.getDate()).padStart(2, "0"); - const month = String(d.getMonth() + 1).padStart(2, "0"); - const year = d.getFullYear(); - const hours = String(d.getUTCHours() + 3).padStart(2, "0"); // UTC+3 - const mins = String(d.getUTCMinutes()).padStart(2, "0"); - const h = parseInt(hours, 10); - const adjustedHours = h >= 24 ? String(h - 24).padStart(2, "0") : hours; - return `${day}.${month}.${year} ${adjustedHours}:${mins}`; - } catch { - return isoStr; - } -}; - const formatMSKCorrect = (isoStr) => { if (!isoStr) return "—"; try { const d = new Date(isoStr); if (isNaN(d.getTime())) return isoStr; - // Format in Moscow timezone const msk = new Date(d.getTime() + 3 * 60 * 60 * 1000); const day = String(msk.getUTCDate()).padStart(2, "0"); const month = String(msk.getUTCMonth() + 1).padStart(2, "0"); @@ -77,6 +58,36 @@ const ROLE_LABELS = { driver: "Водитель", }; +/** Human-readable description of what happened */ +const getActionDescription = (log) => { + switch (log.action) { + case "status_change": + return `${log.old_value || "—"} → ${log.new_value || "—"}`; + case "driver_assigned": + return `Назначен: ${log.details?.driver_name || log.new_value || "водитель"}`; + case "driver_removed": + return `Снят: ${log.details?.driver_name || log.old_value || "водитель"}`; + case "date_assigned": + return `Дата: ${log.new_value || "—"}`; + case "client_confirmed": + return `Клиент подтвердил`; + case "client_cancelled": + return `Клиент отменил`; + case "cancelled": + return `Отменено`; + case "manual_confirmation": + return `Ручное подтверждение`; + case "paid_storage": + return `Платное хранение`; + case "sms_sent": + return `SMS отправлено`; + case "invitation_created": + return `Приглашение создано`; + default: + return log.new_value || getActionLabel(log.action); + } +}; + export const ActionLogPanel = ({ orderGroupId = null }) => { const { user } = useAuth(); const navigate = useNavigate(); @@ -125,7 +136,9 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { (getActionLabel(log.action) || "").toLowerCase().includes(q) || (log.old_value || "").toLowerCase().includes(q) || (log.new_value || "").toLowerCase().includes(q) || - (log.order_group_id || "").toLowerCase().includes(q) + (log.order_group_id || "").toLowerCase().includes(q) || + (getActionDescription(log) || "").toLowerCase().includes(q) || + (log.details?.driver_name || "").toLowerCase().includes(q) ); }, [logs, filterSearch]); @@ -196,16 +209,14 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { Дата/Время Сотрудник Действие - Действие - Было - Стало - {!orderGroupId && Группа доставки} + Описание + {!orderGroupId && Группа} {filteredLogs.length === 0 && !loading && ( - + Нет записей @@ -227,16 +238,10 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { {getActionLabel(log.action)} -
- {log.action === "status_change" && (log.new_value || "")} - {log.action === "driver_assigned" && "→ " + (log.new_value || "водитель")} - {log.action === "driver_removed" && "← " + (log.old_value || "водитель")} - {log.action === "date_assigned" && (log.new_value || "")} - {log.action === "paid_storage" && (log.new_value || "")} -
- {log.old_value || "—"} - {log.new_value || "—"} + + {getActionDescription(log)} + {!orderGroupId && ( {log.order_group_id ? ( @@ -251,9 +256,9 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { )} - {expandedId === log.id && (log.details || log.old_value?.length > 40 || log.new_value?.length > 40) && ( + {expandedId === log.id && ( - +
{log.old_value && (
Было: {log.old_value}
@@ -263,16 +268,20 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { )} {log.details && typeof log.details === "object" && (
- {Object.entries(log.details).map(([k, v]) => ( -
{k}: {String(v)}
+ {Object.entries(log.details) + .filter(([k]) => k !== "source") + .map(([k, v]) => ( +
+ + {{driver_name: "Водитель", driver_id: "ID водителя", problem_type: "Тип проблемы"}[k] || k}: + {String(v)} +
))}
)} - {log.details && typeof log.details === "string" && ( -
Детали: {log.details}
- )} {log.order_group_id && ( -
Группа:{" "} +
+ Группа:{" "} { e.preventDefault(); navigate(`/dashboard/group/${log.order_group_id}`); }} @@ -292,5 +301,4 @@ export const ActionLogPanel = ({ orderGroupId = null }) => { {loading &&
Загрузка...
} ); -}; - +}; \ No newline at end of file diff --git a/src/services/supabase/orderGroupRepository.js b/src/services/supabase/orderGroupRepository.js index 6b342ac..a0ce834 100644 --- a/src/services/supabase/orderGroupRepository.js +++ b/src/services/supabase/orderGroupRepository.js @@ -229,7 +229,7 @@ export const assignDriverToOrderGroup = async ({ // Direct UPDATE — RLS allows manager/logistician/admin const { data: currentGroup, error: fetchCurrentError } = await client .from("order_groups") - .select("delivery_status") + .select("delivery_status, assigned_driver:users!order_groups_assigned_driver_id_fkey(id, name)") .eq("id", orderGroupId) .single(); @@ -271,7 +271,12 @@ export const assignDriverToOrderGroup = async ({ throw error; } - await logAction({ orderGroupId, action: driverId ? "driver_assigned" : "driver_removed", newValue: driverId || "removed", details: { driver_id: driverId } }).catch(() => {}); + const driverName = data?.assigned_driver?.name || driverId || "—"; + const oldDriverName = currentGroup?.assigned_driver?.name || currentGroup?.assigned_driver_id || ""; + const logPayload = driverId + ? { orderGroupId, action: "driver_assigned", newValue: driverName, details: { driver_id: driverId, driver_name: driverName } } + : { orderGroupId, action: "driver_removed", oldValue: oldDriverName, newValue: "Снят", details: { driver_name: oldDriverName } }; + await logAction(logPayload).catch(() => {}); return mapOrderGroupRowToDeliveryGroup(data); }, "Ошибка назначения водителя");