Yaltopia-Ticket-Admin/src/pages/admin/audit/index.tsx

106 lines
3.6 KiB
TypeScript

import { useState } from "react"
import { useQuery } from "@tanstack/react-query"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { Search, Eye } from "lucide-react"
import { auditService } from "@/services"
import { format } from "date-fns"
export default function AuditPage() {
const [page] = useState(1)
const [limit] = useState(50)
const [search, setSearch] = useState("")
const { data: auditData, isLoading } = useQuery({
queryKey: ['admin', 'audit', 'logs', page, limit, search],
queryFn: async () => {
const params: any = { page, limit }
if (search) params.search = search
return await auditService.getAuditLogs(params)
},
})
return (
<div className="space-y-6">
<h2 className="text-3xl font-bold">Audit Logs</h2>
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>All Audit Logs</CardTitle>
<div className="flex items-center gap-4">
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
<Input
placeholder="Search audit logs..."
className="pl-10 w-64"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
</div>
</div>
</CardHeader>
<CardContent>
{isLoading ? (
<div className="text-center py-8">Loading audit logs...</div>
) : (
<>
<Table>
<TableHeader>
<TableRow>
<TableHead>Action</TableHead>
<TableHead>Resource Type</TableHead>
<TableHead>Resource ID</TableHead>
<TableHead>User</TableHead>
<TableHead>IP Address</TableHead>
<TableHead>Date</TableHead>
<TableHead>Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{auditData?.data?.map((log: any) => (
<TableRow key={log.id}>
<TableCell>
<Badge>{log.action}</Badge>
</TableCell>
<TableCell>{log.resourceType}</TableCell>
<TableCell className="font-mono text-sm">{log.resourceId}</TableCell>
<TableCell>{log.userId || 'N/A'}</TableCell>
<TableCell>{log.ipAddress || 'N/A'}</TableCell>
<TableCell>
{format(new Date(log.createdAt), 'MMM dd, yyyy HH:mm')}
</TableCell>
<TableCell>
<Button variant="ghost" size="icon">
<Eye className="w-4 h-4" />
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{auditData?.data?.length === 0 && (
<div className="text-center py-8 text-muted-foreground">
No audit logs found
</div>
)}
</>
)}
</CardContent>
</Card>
</div>
)
}