EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
page.tsx
Go to the documentation of this file.
1"use client";
2import { useState, useEffect } from "react";
3import { Icon } from '@/contexts/IconContext';
4
5interface AuditEntry {
6 id: string;
7 timestamp: Date;
8 user: string;
9 action: string;
10 resource: string;
11 details: string;
12 status: "success" | "error" | "warning";
13}
14
15export default function AuditPage() {
16 const [auditLog, setAuditLog] = useState<AuditEntry[]>([]);
17 const [loading, setLoading] = useState(true);
18 const [filter, setFilter] = useState<string>("all");
19 const [searchTerm, setSearchTerm] = useState("");
20
21 useEffect(() => {
22 // Simulate loading audit log
23 // In production, this would fetch from an API
24 const mockData: AuditEntry[] = [
25 {
26 id: "1",
27 timestamp: new Date("2024-12-24T10:30:00"),
28 user: "admin@everydaypos.com",
29 action: "LOGIN",
30 resource: "Authentication",
31 details: "User logged in successfully",
32 status: "success"
33 },
34 {
35 id: "2",
36 timestamp: new Date("2024-12-24T10:35:00"),
37 user: "admin@everydaypos.com",
38 action: "STOCK_ADJUSTMENT",
39 resource: "Products",
40 details: "Adjusted stock for Product ID 12345 by +10",
41 status: "success"
42 },
43 {
44 id: "3",
45 timestamp: new Date("2024-12-24T10:40:00"),
46 user: "admin@everydaypos.com",
47 action: "SALE_CREATED",
48 resource: "Sales",
49 details: "Created sale SID 98765 for $125.50",
50 status: "success"
51 },
52 {
53 id: "4",
54 timestamp: new Date("2024-12-24T10:45:00"),
55 user: "admin@everydaypos.com",
56 action: "API_ERROR",
57 resource: "Fieldpine API",
58 details: "Failed to connect to Fieldpine server - timeout",
59 status: "error"
60 },
61 {
62 id: "5",
63 timestamp: new Date("2024-12-24T10:50:00"),
64 user: "admin@everydaypos.com",
65 action: "PRODUCT_UPDATE",
66 resource: "Products",
67 details: "Updated price for Product ID 67890",
68 status: "success"
69 }
70 ];
71
72 setTimeout(() => {
73 setAuditLog(mockData);
74 setLoading(false);
75 }, 500);
76 }, []);
77
78 const filteredLog = auditLog.filter(entry => {
79 const matchesFilter = filter === "all" || entry.status === filter;
80 const matchesSearch =
81 entry.action.toLowerCase().includes(searchTerm.toLowerCase()) ||
82 entry.resource.toLowerCase().includes(searchTerm.toLowerCase()) ||
83 entry.details.toLowerCase().includes(searchTerm.toLowerCase()) ||
84 entry.user.toLowerCase().includes(searchTerm.toLowerCase());
85 return matchesFilter && matchesSearch;
86 });
87
88 const getStatusColor = (status: string) => {
89 switch (status) {
90 case "success":
91 return "bg-success/10 text-success border-success/30";
92 case "error":
93 return "bg-danger/10 text-danger border-danger/30";
94 case "warning":
95 return "bg-warn/10 text-warn border-warn/30";
96 default:
97 return "bg-surface-2 text-muted border-border";
98 }
99 };
100
101 const getStatusIcon = (status: string) => {
102 switch (status) {
103 case "success":
104 return "✓";
105 case "error":
106 return "✗";
107 case "warning":
108 return "⚠";
109 default:
110 return "•";
111 }
112 };
113
114 return (
115 <div className="min-h-screen bg-bg">
116 <div className="max-w-7xl mx-auto p-6">
117 {/* Header */}
118 <div className="mb-8">
119 <h1 className="text-3xl font-bold text-text mb-2 flex items-center gap-3">
120 <Icon name="receipt_long" size={32} />
121 Transaction Log
122 </h1>
123 <p className="text-muted">Audit trail of system activities and API transactions</p>
124 </div>
125
126 {/* Filters */}
127 <div className="bg-surface rounded-lg shadow-sm border border-border p-4 mb-6">
128 <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
129 <div>
130 <label className="block text-sm font-medium text-text mb-2">
131 Search
132 </label>
133 <input
134 type="text"
135 value={searchTerm}
136 onChange={(e) => setSearchTerm(e.target.value)}
137 placeholder="Search actions, resources, or details..."
138 className="w-full px-3 py-2 border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-brand"
139 />
140 </div>
141 <div>
142 <label className="block text-sm font-medium text-text mb-2">
143 Filter by Status
144 </label>
145 <select
146 value={filter}
147 onChange={(e) => setFilter(e.target.value)}
148 className="w-full px-3 py-2 border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-brand"
149 >
150 <option value="all">All Status</option>
151 <option value="success">Success</option>
152 <option value="error">Error</option>
153 <option value="warning">Warning</option>
154 </select>
155 </div>
156 </div>
157 </div>
158
159 {/* Stats */}
160 <div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
161 <div className="bg-surface rounded-lg shadow-sm border border-border p-4">
162 <div className="text-sm text-muted mb-1">Total Events</div>
163 <div className="text-2xl font-bold text-text">{auditLog.length}</div>
164 </div>
165 <div className="bg-green-50 rounded-lg shadow-sm border border-green-200 p-4">
166 <div className="text-sm text-green-600 mb-1">Success</div>
167 <div className="text-2xl font-bold text-green-900">
168 {auditLog.filter(e => e.status === "success").length}
169 </div>
170 </div>
171 <div className="bg-red-50 rounded-lg shadow-sm border border-red-200 p-4">
172 <div className="text-sm text-red-600 mb-1">Errors</div>
173 <div className="text-2xl font-bold text-red-900">
174 {auditLog.filter(e => e.status === "error").length}
175 </div>
176 </div>
177 <div className="bg-yellow-50 rounded-lg shadow-sm border border-yellow-200 p-4">
178 <div className="text-sm text-yellow-600 mb-1">Warnings</div>
179 <div className="text-2xl font-bold text-yellow-900">
180 {auditLog.filter(e => e.status === "warning").length}
181 </div>
182 </div>
183 </div>
184
185 {/* Audit Log Table */}
186 <div className="bg-surface rounded-lg shadow-sm border border-border overflow-hidden">
187 {loading ? (
188 <div className="p-12 text-center text-muted">
189 Loading audit log...
190 </div>
191 ) : filteredLog.length === 0 ? (
192 <div className="p-12 text-center text-muted">
193 {searchTerm ? `No events match "${searchTerm}"` : "No events found"}
194 </div>
195 ) : (
196 <div className="overflow-x-auto">
197 <table className="min-w-full divide-y divide-border">
198 <thead className="bg-[var(--brand)] text-surface">
199 <tr>
200 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
201 Timestamp
202 </th>
203 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
204 User
205 </th>
206 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
207 Action
208 </th>
209 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
210 Resource
211 </th>
212 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
213 Details
214 </th>
215 <th className="px-6 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider">
216 Status
217 </th>
218 </tr>
219 </thead>
220 <tbody className="bg-surface divide-y divide-border">
221 {filteredLog.map((entry) => (
222 <tr key={entry.id} className="hover:bg-surface-2">
223 <td className="px-6 py-4 whitespace-nowrap text-sm text-text">
224 {entry.timestamp.toLocaleString()}
225 </td>
226 <td className="px-6 py-4 whitespace-nowrap text-sm text-muted">
227 {entry.user}
228 </td>
229 <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-text">
230 {entry.action}
231 </td>
232 <td className="px-6 py-4 whitespace-nowrap text-sm text-muted">
233 {entry.resource}
234 </td>
235 <td className="px-6 py-4 text-sm text-muted">
236 {entry.details}
237 </td>
238 <td className="px-6 py-4 whitespace-nowrap">
239 <span
240 className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium border ${getStatusColor(
241 entry.status
242 )}`}
243 >
244 <span className="mr-1">{getStatusIcon(entry.status)}</span>
245 {entry.status.toUpperCase()}
246 </span>
247 </td>
248 </tr>
249 ))}
250 </tbody>
251 </table>
252 </div>
253 )}
254 </div>
255
256 {/* Info Box */}
257 <div className="mt-6 bg-info/10 border border-info/30 rounded-lg p-4">
258 <h3 className="font-semibold text-info mb-2">About the Audit Log</h3>
259 <p className="text-info/90 text-sm mb-2">
260 The transaction log tracks all system activities including user actions, API calls,
261 and system events. This helps with:
262 </p>
263 <ul className="list-disc list-inside text-info/90 text-sm space-y-1 ml-2">
264 <li>Security monitoring and compliance</li>
265 <li>Debugging and troubleshooting</li>
266 <li>Performance analysis</li>
267 <li>User activity tracking</li>
268 </ul>
269 <p className="text-info/80 text-xs mt-3">
270 <strong>Note:</strong> Currently showing mock data. Production will log real transactions.
271 </p>
272 </div>
273 </div>
274 </div>
275 );
276}