From 7283a9b655275e2bbe2852eab9e1b686d58f1c8c Mon Sep 17 00:00:00 2001 From: TronoSfera <119615520+TronoSfera@users.noreply.github.com> Date: Mon, 2 Mar 2026 22:30:19 +0300 Subject: [PATCH] fix user UI 4 --- app/web/admin.css | 15 +++++++ .../features/requests/RequestWorkspace.jsx | 43 ++++++++++++++++++- app/web/client.jsx | 2 - 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/app/web/admin.css b/app/web/admin.css index 9561153..3e604f2 100644 --- a/app/web/admin.css +++ b/app/web/admin.css @@ -2296,6 +2296,21 @@ opacity: 0.85; } + .route-item.important-date .route-dot { + background: #c9973f; + box-shadow: 0 0 0 1px rgba(201, 151, 63, 0.45); + } + + .route-item.important-date::before { + background: #c9973f; + opacity: 0.8; + } + + .route-item.important-date .route-body b { + color: #ffe3b2; + letter-spacing: 0.02em; + } + .route-body b { display: block; font-size: 1.02rem; diff --git a/app/web/admin/features/requests/RequestWorkspace.jsx b/app/web/admin/features/requests/RequestWorkspace.jsx index 2464239..1fed826 100644 --- a/app/web/admin/features/requests/RequestWorkspace.jsx +++ b/app/web/admin/features/requests/RequestWorkspace.jsx @@ -1142,12 +1142,47 @@ export function RequestWorkspace({ return () => window.cancelAnimationFrame(raf); }, [chatTab, localActivityCursor]); - const routeNodes = + const baseRouteNodes = Array.isArray(statusRouteNodes) && statusRouteNodes.length ? statusRouteNodes : row?.status_code ? [{ code: row.status_code, name: statusLabel(row.status_code), state: "current", note: "Текущий этап обработки заявки" }] : []; + const upcomingImportantDate = useMemo(() => { + const source = String(currentImportantDateAt || row?.important_date_at || "").trim(); + if (!source) return ""; + const timestamp = new Date(source).getTime(); + if (!Number.isFinite(timestamp) || timestamp <= Date.now()) return ""; + return new Date(timestamp).toISOString(); + }, [currentImportantDateAt, row?.important_date_at]); + const routeNodes = useMemo(() => { + if (viewerRoleCode !== "CLIENT" || !upcomingImportantDate) return baseRouteNodes; + if (!Array.isArray(baseRouteNodes) || !baseRouteNodes.length) { + return [ + { + code: "__IMPORTANT_DATE__", + name: "Важная дата", + state: "pending", + changed_at: upcomingImportantDate, + note: "Контрольный срок", + }, + ]; + } + const hasVirtualNode = baseRouteNodes.some((node) => String(node?.code || "").trim() === "__IMPORTANT_DATE__"); + if (hasVirtualNode) return baseRouteNodes; + const currentIndex = baseRouteNodes.findIndex((node) => String(node?.state || "").trim().toLowerCase() === "current"); + const virtualNode = { + code: "__IMPORTANT_DATE__", + name: "Важная дата", + state: "pending", + changed_at: upcomingImportantDate, + note: "Контрольный срок", + }; + if (currentIndex < 0) return [...baseRouteNodes, virtualNode]; + const next = [...baseRouteNodes]; + next.splice(currentIndex + 1, 0, virtualNode); + return next; + }, [baseRouteNodes, upcomingImportantDate, viewerRoleCode]); const AttachmentPreviewModal = AttachmentPreviewModalComponent; const StatusLine = StatusLineComponent; @@ -1338,7 +1373,11 @@ export function RequestWorkspace({ const note = String(node?.note || "").trim(); const changedAtSource = String(node?.changed_at || "").trim() || (index === 0 ? String(row?.created_at || "").trim() : ""); const changedAt = changedAtSource ? fmtDate(changedAtSource) : ""; - const className = "route-item " + (state === "current" ? "current" : state === "completed" ? "completed" : "pending"); + const isImportantDateNode = code === "__IMPORTANT_DATE__"; + const className = + "route-item " + + (state === "current" ? "current" : state === "completed" ? "completed" : "pending") + + (isImportantDateNode ? " important-date" : ""); return (
  • diff --git a/app/web/client.jsx b/app/web/client.jsx index c108a99..5df769a 100644 --- a/app/web/client.jsx +++ b/app/web/client.jsx @@ -609,7 +609,6 @@ import { detectAttachmentPreviewKind, fmtShortDateTime, statusLabel } from "./ad ? String(preferredTrack || "").trim().toUpperCase() : tracks[0]; await loadRequestWorkspace(selected, true); - setPageStatus("Открыта заявка: " + selected, "ok"); }, [loadRequestWorkspace, refreshRequestsList, setPageStatus] ); @@ -644,7 +643,6 @@ import { detectAttachmentPreviewKind, fmtShortDateTime, statusLabel } from "./ad try { await loadRequestWorkspace(track, true); await refreshRequestsList(); - setPageStatus("Открыта заявка: " + track, "ok"); setRequestPickerModal({ open: false, loading: false }); } catch (error) { setRequestPickerModal((prev) => ({ ...prev, loading: false }));