From 199715d5b6a1a4cec19ce9439c281717ddd2aa73 Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Fri, 17 Apr 2026 16:03:34 -0400 Subject: [PATCH] Add Verify & Close button and verified banner to dispatch detail - Verify & Close button at bottom of dispatch modal - Disabled with tooltip showing missing items (checklist, signoffs) - Green verified banner after verification with verifier name + timestamp - Verified status badge (dark green) - Added Verified to DISPATCH_STATUSES constant - verifyDispatch API function --- src/pages/workorders/api.js | 4 ++ .../workorders/view/WorkOrderViewPage.css | 29 ++++++++++++ .../workorders/view/WorkOrderViewPage.js | 47 ++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/pages/workorders/api.js b/src/pages/workorders/api.js index 49b034e4..c0c92e23 100644 --- a/src/pages/workorders/api.js +++ b/src/pages/workorders/api.js @@ -134,6 +134,10 @@ export const addChecklistItem = async (dispatchId, itemText, workOrderId) => { return post(`${API_URL}/WorkOrder/AddChecklistItem`, { DispatchId: dispatchId, ItemText: itemText, WorkOrderId: workOrderId }); }; +export const verifyDispatch = async (dispatchId) => { + return post(`${API_URL}/WorkOrder/VerifyDispatch?dispatchId=${dispatchId}`); +}; + export const addDispatchSignoff = async (dispatchId, signoffType, name, signature, signatureMethod) => { return post(`${API_URL}/WorkOrder/AddDispatchSignoff`, { DispatchId: dispatchId, diff --git a/src/pages/workorders/view/WorkOrderViewPage.css b/src/pages/workorders/view/WorkOrderViewPage.css index c39ee98a..0a1f86b7 100644 --- a/src/pages/workorders/view/WorkOrderViewPage.css +++ b/src/pages/workorders/view/WorkOrderViewPage.css @@ -629,6 +629,7 @@ .woDispatchStatus.acknowledged { background: #ffc107; color: #333; } .woDispatchStatus.completed { background: #28a745; } .woDispatchStatus.cancelled { background: #dc3545; } +.woDispatchStatus.verified { background: #155724; } .dispatchClickRow { cursor: pointer; @@ -748,6 +749,34 @@ font-weight: 600; } +.dispatchVerifiedBanner { + padding: 12px 20px; + background: #d4edda; + color: #155724; + font-size: 13px; + font-weight: 600; + text-align: center; + border-top: 1px solid #c3e6cb; + flex-shrink: 0; +} + +.dispatchVerifyFooter { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 12px; + padding: 12px 20px; + border-top: 1px solid #eee; + background: #fafafa; + flex-shrink: 0; +} + +.dispatchVerifyMissing { + font-size: 12px; + color: #999; + flex: 1; +} + .dispatchSignoffs { display: flex; gap: 16px; diff --git a/src/pages/workorders/view/WorkOrderViewPage.js b/src/pages/workorders/view/WorkOrderViewPage.js index 2382208e..456b07ac 100644 --- a/src/pages/workorders/view/WorkOrderViewPage.js +++ b/src/pages/workorders/view/WorkOrderViewPage.js @@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react"; import ReactDOM from "react-dom"; import { useParams, useNavigate } from "react-router"; import { toast } from "react-toastify"; -import { getWorkOrderById, addComment, changeWorkOrderStatus, fetchUsers, changeWorkOrderAssignment, fetchVendorsDropdown, dispatchToVendor, getDispatchById, updateDispatch, addDispatchComment, fetchTaskTemplates, updateChecklistItem, addChecklistItem, addDispatchSignoff } from "../api"; +import { getWorkOrderById, addComment, changeWorkOrderStatus, fetchUsers, changeWorkOrderAssignment, fetchVendorsDropdown, dispatchToVendor, getDispatchById, updateDispatch, addDispatchComment, fetchTaskTemplates, updateChecklistItem, addChecklistItem, addDispatchSignoff, verifyDispatch } from "../api"; import { getCurrentUser } from "../../../services/authService"; import { timeSince, timeBetween, waitTimeColor } from "../../../utils/timeSince"; import SignatureCapture from "../../../components/SignatureCapture"; @@ -164,7 +164,7 @@ function AuditTimeline({ entries }) { ); } -const DISPATCH_STATUSES = ["Sent", "Acknowledged", "In Progress", "Completed", "Cancelled"]; +const DISPATCH_STATUSES = ["Sent", "Acknowledged", "In Progress", "Completed", "Verified", "Cancelled"]; function DispatchDetailModal({ dispatchId, onClose, onUpdated }) { const [dispatch, setDispatch] = useState(null); @@ -468,6 +468,49 @@ function DispatchDetailModal({ dispatchId, onClose, onUpdated }) { + + {dispatch.verifiedAt ? ( +