feat: integrate dynamic audit logs and dashboard quick tasks from API
All checks were successful
Beta CI/CD Pipeline / build-and-test (push) Successful in 15s
Beta CI/CD Pipeline / deploy-beta (push) Successful in 6s

This commit is contained in:
vickytechkey 2026-08-16 10:32:48 +05:30
parent 13bc5f9078
commit 84674ea206
2 changed files with 100 additions and 77 deletions

View file

@ -1,56 +1,87 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { API_BASE_URL } from '../config';
import { useAuth } from '../context/AuthContext';
const AuditLogs = () => {
const [logs] = useState([
{ id: 221, admin: 'admin', action: 'approve_seller', target: 'Seller #2', details: 'KYC verified for ElectroHub', time: '2026-08-15 15:30:22' },
{ id: 220, admin: 'admin', action: 'issue_refund', target: 'Order #ORD88761', details: '₹2,499.00 processed via PhonePe', time: '2026-08-15 14:15:10' },
{ id: 219, admin: 'moderator', action: 'create_return', target: 'Order #ORD88120', details: 'Shadowfax AWB SF_RET_AWB_776152', time: '2026-08-14 11:22:45' },
{ id: 218, admin: 'admin', action: 'hold_product', target: 'Product #101', details: 'Held: Stock verification pending', time: '2026-08-12 09:05:00' },
]);
const { token } = useAuth();
const [logs, setLogs] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchLogs = async () => {
try {
setLoading(true);
const res = await fetch(`${API_BASE_URL}/audit-logs/`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!res.ok) throw new Error('Failed to fetch system audit logs');
const data = await res.json();
setLogs(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchLogs();
}, [token]);
return (
<div>
<h1 className="page-title">Admin System Audit Logs</h1>
<div className="glass-card">
<div className="table-container">
<table className="custom-table">
<thead>
<tr>
<th>Log ID</th>
<th>Admin User</th>
<th>Action</th>
<th>Target Object</th>
<th>Operation Details</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
{logs.map(log => (
<tr key={log.id}>
<td>#{log.id}</td>
<td><span style={{ fontFamily: 'monospace' }}>{log.admin}</span></td>
<td>
<span style={{
display: 'inline-block',
background: 'rgba(139, 92, 246, 0.1)',
color: 'var(--accent-hover)',
padding: '2px 8px',
borderRadius: '4px',
fontSize: '12px',
fontWeight: '600'
}}>
{log.action}
</span>
</td>
<td style={{ fontWeight: '500' }}>{log.target}</td>
<td>{log.details}</td>
<td style={{ color: 'var(--text-secondary)' }}>{log.time}</td>
{loading ? (
<div style={{ padding: '40px', textAlign: 'center' }}>Loading audit trail logs...</div>
) : error ? (
<div style={{ padding: '20px', color: 'var(--color-danger)', textAlign: 'center' }}>Error: {error}</div>
) : (
<div className="table-container">
<table className="custom-table">
<thead>
<tr>
<th>Log ID</th>
<th>Admin User</th>
<th>Action</th>
<th>Target Object</th>
<th>Operation Details</th>
<th>Timestamp</th>
</tr>
))}
</tbody>
</table>
</div>
</thead>
<tbody>
{logs.map(log => (
<tr key={log.id}>
<td>#{log.id}</td>
<td><span style={{ fontFamily: 'monospace', fontWeight: 'bold' }}>{log.admin_username || log.admin || 'system'}</span></td>
<td>
<span style={{
display: 'inline-block',
background: 'rgba(139, 92, 246, 0.1)',
color: 'var(--accent-hover)',
padding: '2px 8px',
borderRadius: '4px',
fontSize: '12px',
fontWeight: '600'
}}>
{log.action}
</span>
</td>
<td style={{ fontWeight: '500' }}>
{log.target_type} #{log.target_id || ''}
</td>
<td>{typeof log.details === 'object' ? JSON.stringify(log.details) : log.details}</td>
<td style={{ color: 'var(--text-secondary)' }}>
{log.performed_at ? new Date(log.performed_at).toLocaleString() : log.time}
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
</div>
);

View file

@ -13,7 +13,10 @@ const Dashboard = () => {
pending_approvals: 0,
total_revenue: 0,
active_products: 0,
refunds_issued: 0
refunds_issued: 0,
chart_labels: [],
chart_sales: [],
quick_tasks: []
});
const [loading, setLoading] = useState(true);
@ -47,11 +50,11 @@ const Dashboard = () => {
];
const chartData = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
labels: stats.chart_labels.length > 0 ? stats.chart_labels : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
datasets: [
{
label: 'Platform Sales (₹ Lakhs)',
data: [2.5, 3.8, 3.2, 5.4, 6.1, 7.8, 9.2, stats.total_revenue / 100000],
data: stats.chart_sales.length > 0 ? stats.chart_sales : [0, 0, 0, 0, 0, 0, 0, 0],
borderColor: '#8b5cf6',
backgroundColor: 'rgba(139, 92, 246, 0.2)',
tension: 0.4,
@ -115,36 +118,25 @@ const Dashboard = () => {
<div className="glass-card" style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
<h3 className="section-title">Quick Tasks</h3>
<div style={{
padding: '12px',
background: 'rgba(255,255,255,0.02)',
border: '1px solid var(--glass-border)',
borderRadius: 'var(--border-radius)',
fontSize: '14px'
}}>
<div style={{ fontWeight: '600', marginBottom: '4px' }}>Validate New Sellers</div>
<p style={{ color: 'var(--text-secondary)', fontSize: '12px' }}>Verify uploaded KYC Aadhar and PAN records.</p>
</div>
<div style={{
padding: '12px',
background: 'rgba(255,255,255,0.02)',
border: '1px solid var(--glass-border)',
borderRadius: 'var(--border-radius)',
fontSize: '14px'
}}>
<div style={{ fontWeight: '600', marginBottom: '4px' }}>Pending Withdrawal Requests</div>
<p style={{ color: 'var(--text-secondary)', fontSize: '12px' }}>Approve wallet transfers and input Bank UTR details.</p>
</div>
<div style={{
padding: '12px',
background: 'rgba(255,255,255,0.02)',
border: '1px solid var(--glass-border)',
borderRadius: 'var(--border-radius)',
fontSize: '14px'
}}>
<div style={{ fontWeight: '600', marginBottom: '4px' }}>Shadowfax Reverse Log</div>
<p style={{ color: 'var(--text-secondary)', fontSize: '12px' }}>Check failed doorstep quality check (QC) status.</p>
</div>
{stats.quick_tasks && stats.quick_tasks.length > 0 ? (
stats.quick_tasks.map((task, idx) => (
<div key={idx} style={{
padding: '12px',
background: 'rgba(255,255,255,0.02)',
border: '1px solid var(--glass-border)',
borderRadius: 'var(--border-radius)',
fontSize: '14px'
}}>
<div style={{ fontWeight: '600', marginBottom: '4px', display: 'flex', justifyContent: 'space-between' }}>
<span>{task.title}</span>
{task.count > 0 && <span style={{ color: 'var(--color-warning)', fontWeight: 'bold' }}>⚠️</span>}
</div>
<p style={{ color: 'var(--text-secondary)', fontSize: '12px', margin: 0 }}>{task.desc}</p>
</div>
))
) : (
<div style={{ padding: '20px', textAlign: 'center', color: 'var(--text-muted)' }}>No pending tasks!</div>
)}
</div>
</div>
</div>