diff --git a/src/components/transactions/AuditModal.tsx b/src/components/transactions/AuditModal.tsx
index bba20e3..f7dbcb2 100644
--- a/src/components/transactions/AuditModal.tsx
+++ b/src/components/transactions/AuditModal.tsx
@@ -1,254 +1,320 @@
-import React, { useState } from "react";
-import {
- FiX,
- FiCheckCircle,
- FiXCircle,
- FiClock,
- FiUser,
- FiCalendar,
- FiFileText,
- FiAlertTriangle,
- FiTruck,
- FiUserCheck,
- FiUserX,
- FiPackage,
- FiMapPin,
- FiEye,
- FiRotateCcw
+import React, { useEffect, useState } from "react";
+import {
+ FiX,
+ FiCheckCircle,
+ FiXCircle,
+ FiClock,
+ FiUser,
+ FiCalendar,
+ FiFileText,
+ FiAlertTriangle,
+ FiTruck,
+ FiUserCheck,
+ FiUserX,
+ FiPackage,
+ FiMapPin,
+ FiEye,
+ FiRotateCcw,
+ FiSend,
+ FiMail,
+ FiActivity,
+ FiRefreshCw,
+ FiLock,
+ FiUnlock,
+ FiUserPlus,
+ FiEdit
} from "react-icons/fi";
+import api from "../../config/api";
+import { useParams } from "react-router-dom";
+import logoRecord from '../../assets/record.svg'
+import LoaderUi from "../../helper/LoaderUi";
+import { FaRegEyeSlash } from "react-icons/fa";
+import { MdAccessTime, MdCancel } from "react-icons/md";
interface AuditModalProps {
- closeModal: () => void;
+ closeModal: () => void;
}
const AuditModal: React.FC
= ({ closeModal }) => {
- const [activeTab, setActiveTab] = useState<'status' | 'audit'>('status');
+ const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
- 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"
+ if (!accountId || !transactionId) {
+ window.location.href = "/";
+ return null;
}
- ];
- 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"
+ let [auditStatus, setAuditStatus] = useState([])
+ let [loading, setLoading] = useState(false)
+ const getAuditDetails = async () => {
+ setLoading(true)
+ try {
+ let res = await api.get(`/api/accounts/${accountId}/transactions/${transactionId}/audit`)
+ if (res?.status === 200) {
+ // console.log(res?.data?.events)
+ let auditResponse = res?.data?.events
+ setAuditStatus(auditResponse)
+ }
+ } catch (error) {
+ console.log(error)
+ } finally {
+ setLoading(false)
+ }
}
- ];
- 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'
+ useEffect(() => {
+ if (accountId && transactionId) {
+ getAuditDetails()
+ }
+ }, [accountId, transactionId])
+
+
+ const statusHistory = [
+ {
+ "action": "SENT",
+ "message": "Transaction Sent by John Doe ",
+ "status": "SENT",
+ "eventData": {
+ "ip": "192.168.1.1",
+ "longitude": "3.3792",
+ "latitude": "6.5244",
+ "timezone": "WAT"
+ },
+ "timestamp": "2025-01-15T10:30:00Z",
+ "language": "en"
+ },
+ {
+ "action": "INVITED",
+ "message": "Invitation Sent to Jane Smith to sign documents",
+ "status": "SENT",
+ "eventData": {
+ "ip": "0.0.0.0",
+ "longitude": "11",
+ "latitude": "12",
+ "timezone": ""
+ },
+ "timestamp": "2025-01-15T11:45:00Z",
+ "language": "es"
+ },
+ {
+ "action": "VIEWED",
+ "message": "Document viewed by recipient Alice Johnson ",
+ "status": "VIEWED",
+ "eventData": {
+ "ip": "203.0.113.5",
+ "longitude": "-74.0059",
+ "latitude": "40.7128",
+ "timezone": "EST"
+ },
+ "timestamp": "2025-01-15T14:20:00Z",
+ "language": "en"
+ },
+ {
+ "action": "SIGNED",
+ "message": "Document signed by Bob Wilson ",
+ "status": "COMPLETED",
+ "eventData": {
+ "ip": "198.51.100.10",
+ "longitude": "-122.4194",
+ "latitude": "37.7749",
+ "timezone": "PST"
+ },
+ "timestamp": "2025-01-15T16:10:00Z",
+ "language": "en"
+ }
+ ];
+
+ const getActionIcon = (action: string) => {
+ const icons = {
+ 'CREATED': ,
+ 'SENT': ,
+ 'INVITED': ,
+ 'COMPLETED': ,
+ 'RE_SENT_INVITATION': ,
+ 'RE_SENT_EXPIRED_INVITATION': ,
+ 'VIEWED': ,
+ 'VIEWED_IN_PERSON': , // Slightly different eye icon
+ 'AUTH_FAILED': ,
+ 'ACCESS_CODE_FAILED': ,
+ 'ACCESS_CODE_VALIDATED': ,
+ 'AUTH_VALIDATED': ,
+ 'SIGNED': ,
+ 'EXPIRED': ,
+ 'CANCELLED': ,
+ 'DECLINED': ,
+ 'PENDING': ,
+ 'ASSIGNED': ,
+ 'REASSIGNED': ,
+ 'EDITED': ,
+ };
+
+ return icons[action as keyof typeof icons] || ;
};
- 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'
+ const getActionColor = (action: string, status: string) => {
+ if (status === 'COMPLETED') return 'text-green-600';
+ if (status === 'FAILED' || status === 'REJECTED') return 'text-red-600';
+ if (status === 'PENDING') return 'text-yellow-600';
+
+ const colors = {
+ 'SENT': 'text-blue-600',
+ 'INVITED': 'text-indigo-600',
+ 'VIEWED': 'text-purple-600',
+ 'SIGNED': 'text-green-600',
+ 'REJECTED': 'text-red-600'
+ };
+ return colors[action as keyof typeof colors] || 'text-gray-600';
};
- return colors[type as keyof typeof colors] || 'text-gray-600';
- };
- return (
-
-
- {/* Header */}
-
-
-
- Audit Status
-
-
-
-
+ const getStatusBadge = (status: string) => {
+ const statusClasses = {
+ 'SENT': 'bg-blue-100 text-blue-800',
+ 'COMPLETED': 'bg-green-100 text-green-800',
+ 'FAILED': 'bg-red-100 text-red-800',
+ 'PENDING': 'bg-yellow-100 text-yellow-800',
+ 'VIEWED': 'bg-purple-100 text-purple-800',
+ 'REJECTED': 'bg-red-100 text-red-800'
+ };
+ return statusClasses[status as keyof typeof statusClasses] || 'bg-gray-100 text-gray-800';
+ };
- {/* Content */}
-
-
-
-
TODAY
-
- {statusHistory.slice(0, 2).map((item) => (
-
-
- {item.icon}
-
-
-
{item.title}
-
-
By {item.author}
- {item.role && (
- <>
-
•
-
({item.role})
- >
- )}
+ const formatTimestamp = (timestamp: string) => {
+ try {
+ const date = new Date(timestamp);
+ if (isNaN(date.getTime())) {
+ return timestamp;
+ }
+
+ const now = new Date();
+ const diffMs = now.getTime() - date.getTime();
+ const diffMins = Math.floor(diffMs / (1000 * 60));
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
+
+ if (diffMins < 60) {
+ return `${diffMins}m ago`;
+ } else if (diffHours < 24) {
+ return `${diffHours}h ago`;
+ } else if (diffDays < 7) {
+ return `${diffDays}d ago`;
+ } else {
+ return date.toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit'
+ });
+ }
+ } catch (error) {
+ return timestamp;
+ }
+ };
+
+ const extractEmailFromMessage = (message: string) => {
+ const emailMatch = message.match(/<([^>]+)>/);
+ return emailMatch ? emailMatch[1] : '';
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+
+ Audit Status
+
-
-
{item.time}
-
-
- {item.fromStatus}
-
- →
-
- {item.toStatus}
-
-
-
-
+
- ))}
-
+ {/* Content */}
+
+ {/* {loading ?
: ""} */}
+ {auditStatus.length ?
+
+ {/*
TODAY
*/}
+ {auditStatus.map((item, index) => (
+
+
+ {getActionIcon(item.action)}
+
+
+
{item.message}
+
+
+ Action: {item.action}
+ {extractEmailFromMessage(item.message) && (
+ <>
+ •
+ {extractEmailFromMessage(item.message)}
+ >
+ )}
+
+
+
+ Status:
+ {item.status}
+
+ {formatTimestamp(item.timestamp)}
+ {item.language && (
+ {item.language}
+ )}
+
+
+ {/* Event Data Details */}
+ {/*
+ {item.eventData.ip && (
+
+ IP: {item.eventData.ip}
+
+ )}
+ {item.eventData.timezone && (
+
+ Timezone: {item.eventData.timezone}
+
+ )}
+ {item.eventData.latitude && item.eventData.longitude && (
+
+ Location:
+ Lat: {item.eventData.latitude}, Lng: {item.eventData.longitude}
+
+ )}
+
*/}
+
+
+ ))}
+
:
+
+

+
+ }
+
+
+ {/* Footer */}
+
+
+ Showing {auditStatus.length} event{auditStatus.length !== 1 ? 's' : ''}
+
+
+
-
-
- {/* Footer */}
-
-
-
-
-
- );
+ );
};
-export default AuditModal;
+export default AuditModal;
\ No newline at end of file