diff --git a/src/components/transactions/AuditModal.tsx b/src/components/transactions/AuditModal.tsx new file mode 100644 index 0000000..bba20e3 --- /dev/null +++ b/src/components/transactions/AuditModal.tsx @@ -0,0 +1,254 @@ +import React, { useState } from "react"; +import { + FiX, + FiCheckCircle, + FiXCircle, + FiClock, + FiUser, + FiCalendar, + FiFileText, + FiAlertTriangle, + FiTruck, + FiUserCheck, + FiUserX, + FiPackage, + FiMapPin, + FiEye, + FiRotateCcw +} from "react-icons/fi"; + +interface AuditModalProps { + closeModal: () => void; +} + +const AuditModal: React.FC = ({ closeModal }) => { + const [activeTab, setActiveTab] = useState<'status' | 'audit'>('status'); + + const statusHistory = [ + { + id: 1, + title: "The Accrual status has been successfully changed to Approved.", + author: "Alexander Turner", + role: "Analyst Perspective on Transaction", + time: "34m ago", + fromStatus: "Ready to Review", + toStatus: "Approved", + icon: , + statusColor: "text-green-600" + }, + { + id: 2, + title: "The Accrual has been updated to reflect a status of Reject.", + author: "Alexander Turner", + time: "3h ago", + fromStatus: "Ready to Review", + toStatus: "Rejected", + icon: , + statusColor: "text-red-600" + }, + { + id: 3, + title: "The Accrual has been revised for accuracy.", + author: "Alex Turner", + role: "Manager View Transaction State", + time: "7d ago", + fromStatus: "Rejected", + toStatus: "Reviewed", + icon: , + statusColor: "text-yellow-600" + }, + { + id: 4, + title: "The Accrual state has been updated from 'ready' to 'under review'.", + author: "Alexander Turner", + role: "Analyst Perspective on Transaction", + time: "34m ago", + fromStatus: "Ready to Review", + toStatus: "Reviewed", + icon: , + statusColor: "text-blue-600" + }, + { + id: 5, + title: "The Accrual has been updated from rejected to reviewed.", + author: "Alex Turner", + role: "Analyst View Transaction", + time: "34m ago", + fromStatus: "Rejected", + toStatus: "Reviewed", + icon: , + statusColor: "text-blue-600" + } + ]; + + const auditTrail = [ + { + id: 1, + title: "Batch 11317 Pickup Request Created", + author: "Sandra Darlington", + location: "Lagos General Hospital Gbagada", + time: "11 Aug, 2023 09:23 AM", + icon: , + type: "created" + }, + { + id: 2, + title: "Batch 11317 Pickup Request", + author: "Oladejo Israel", + location: "Institute of Human Virology H3Africa BioRepository", + time: "12 Aug, 2023 11:19 AM", + status: "Approved", + icon: , + type: "approved" + }, + { + id: 3, + title: "Batch 11317 was Initiated", + author: "Sandra Darlington", + location: "Lagos General Hospital Gbagada", + time: "12 Aug, 2023 11:19 AM", + icon: , + type: "initiated" + }, + { + id: 4, + title: "Sandra Darlington Assigned batch 11317", + assignee: "Yusuf Ahmed", + time: "12 Aug, 2023 11:20 AM", + icon: , + type: "assigned" + }, + { + id: 5, + title: "Batch 11317 was rejected by Yusuf Ahmed", + reason: "due to faulty vehicle", + time: "12 Aug, 2023 11:20 AM", + icon: , + type: "rejected" + }, + { + id: 6, + title: "Sandra Darlington Assigned batch 11317", + assignee: "Kolado Jolade", + time: "12 Aug, 2023 11:20 AM", + icon: , + type: "assigned" + }, + { + id: 7, + title: "Logger Synced", + deviceId: "ID: LGR-0421", + status: "95% remaining", + time: "12 Aug, 2023 11:25 AM", + icon: , + type: "synced" + }, + { + id: 8, + title: "Logger Disconnected", + deviceId: "ID: LGR-0421", + time: "12 Aug, 2023 11:25 AM", + icon: , + type: "disconnected" + } + ]; + + const getStatusBadge = (status: string) => { + const statusClasses = { + 'Approved': 'bg-green-100 text-green-800', + 'Rejected': 'bg-red-100 text-red-800', + 'Reviewed': 'bg-yellow-100 text-yellow-800', + 'Ready to Review': 'bg-blue-100 text-blue-800' + }; + return statusClasses[status as keyof typeof statusClasses] || 'bg-gray-100 text-gray-800'; + }; + + const getAuditTypeColor = (type: string) => { + const colors = { + 'created': 'text-blue-600', + 'approved': 'text-green-600', + 'initiated': 'text-purple-600', + 'assigned': 'text-indigo-600', + 'rejected': 'text-red-600', + 'synced': 'text-green-600', + 'disconnected': 'text-orange-600' + }; + return colors[type as keyof typeof colors] || 'text-gray-600'; + }; + + return ( +
+
+ {/* Header */} +
+
+

+ Audit Status +

+
+ +
+ + {/* Content */} +
+ +
+
TODAY
+ + {statusHistory.slice(0, 2).map((item) => ( +
+
+ {item.icon} +
+
+

{item.title}

+
+ By {item.author} + {item.role && ( + <> + • + ({item.role}) + + )} +
+
+ {item.time} +
+ + {item.fromStatus} + + → + + {item.toStatus} + +
+
+
+
+ ))} + + +
+ +
+ + {/* Footer */} +
+ +
+
+
+ ); +}; + +export default AuditModal; diff --git a/src/components/transactions/TransactionView.tsx b/src/components/transactions/TransactionView.tsx index b31dc69..dfb154c 100644 --- a/src/components/transactions/TransactionView.tsx +++ b/src/components/transactions/TransactionView.tsx @@ -1,5 +1,5 @@ import { AiFillSignature } from 'react-icons/ai'; -import { Link, useNavigate, useParams } from 'react-router-dom'; +import { Link, useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { LuGitGraph } from 'react-icons/lu'; import AccountNav from '../accounts/AccountNav'; import { useEffect, useState } from 'react'; @@ -10,6 +10,7 @@ import { MdEditDocument } from "react-icons/md"; import { useSelector } from 'react-redux'; import { RootState } from '../../store/store'; import { SignTypeEnum } from '../../utlity/types'; +import AuditModal from './AuditModal'; // Sample recipient data — you can replace this with actual API data later const recipients = [ @@ -44,6 +45,35 @@ const TransactionView = () => { const [transactionDetails, setTransactionDetails] = useState(null); const [signingOrderModal, setSigningOrderModal] = useState({ open: false }); const user = useSelector((state: RootState) => state.user) + const location = useLocation(); + const [isModalOpen, setIsModalOpen] = useState(false); + + useEffect(() => { + // update whenever location changes + setIsModalOpen(location.search.includes("auditStatus")); + }, [location]); + + const handleOpenAuditModal = () => { + const { pathname, search } = location; + let newSearch = search + ? search.includes("auditStatus") + ? search + : `${search}&auditStatus` + : "?auditStatus"; + + window.history.pushState({}, "", pathname + newSearch); + setIsModalOpen(true); // ✅ update state immediately + }; + + const closeModal = () => { + let search = location.search + .replace(/[?&]auditStatus\b/, "") + .replace(/^&/, "?") + .replace(/\?$/, ""); + + window.history.pushState({}, "", location.pathname + search); + setIsModalOpen(false); // ✅ update state immediately + }; console.log(transactionDetails, "line 37"); @@ -99,9 +129,13 @@ const TransactionView = () => { More - + {/* Edit - + */} + +
@@ -138,7 +172,7 @@ const TransactionView = () => { {recipient.email === user.email && recipient.status !== "COMPLETED" &&

handleNavigateToSign(recipient.id)} + onClick={() => handleNavigateToSign(recipient.id)} className='text-white rounded-sm bg-[var(--primary)] px-3 py-1 font-semibold cursor-pointer'> Sign

} @@ -207,6 +241,8 @@ const TransactionView = () => { } + + {isModalOpen && } }