124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
import {
|
|
Badge,
|
|
Container,
|
|
Group,
|
|
Stack,
|
|
Text,
|
|
Title,
|
|
Paper,
|
|
Table,
|
|
TextInput,
|
|
Select,
|
|
ActionIcon,
|
|
Tooltip,
|
|
Avatar,
|
|
Code,
|
|
Button
|
|
} from '@mantine/core'
|
|
import { createFileRoute, useParams } from '@tanstack/react-router'
|
|
import { TbSearch, TbFilter, TbDownload, TbCalendar } from 'react-icons/tb'
|
|
|
|
export const Route = createFileRoute('/apps/$appId/logs')({
|
|
component: AppLogsPage,
|
|
})
|
|
|
|
const mockLogs = [
|
|
{ id: 1, type: 'DOCUMENT', village: 'Sukatani', activity: 'GENERATE_SURAT_DOMISILI', operator: 'Budi Santoso', time: '2 mins ago', status: 'SUCCESS' },
|
|
{ id: 2, type: 'FINANCE', village: 'Sukamaju', activity: 'UPLOAD_LAPORAN_REALISASI_Q1', operator: 'Siti Aminah', time: '15 mins ago', status: 'SUCCESS' },
|
|
{ id: 3, type: 'SYNC', village: 'Cikini', activity: 'SYNC_DATA_PENDUDUK_SIAK', operator: 'System', time: '1 hour ago', status: 'WARNING' },
|
|
{ id: 4, type: 'SECURITY', village: 'Bojong Gede', activity: 'LOGIN_ADMIN_DESA', operator: 'Rahmat Hidayat', time: '2 hours ago', status: 'SUCCESS' },
|
|
{ id: 5, type: 'DOCUMENT', village: 'Tapos', activity: 'VERIFIKASI_SURAT_KEMATIAN', operator: 'Agus Setiawan', time: '4 hours ago', status: 'SUCCESS' },
|
|
]
|
|
|
|
function AppLogsPage() {
|
|
const { appId } = useParams({ from: '/apps/$appId/logs' })
|
|
const isDesaPlus = appId === 'desa-plus'
|
|
|
|
return (
|
|
<Stack gap="xl">
|
|
<Group justify="space-between" align="center">
|
|
<Stack gap={0}>
|
|
<Title order={3}>{isDesaPlus ? 'Desa+ Service Logs' : 'Application Activity Logs'}</Title>
|
|
<Text size="sm" c="dimmed">Detailed audit trail of all actions performed within the application instances.</Text>
|
|
</Stack>
|
|
<Group gap="xs">
|
|
<Button variant="light" leftSection={<TbDownload size={16} />} radius="md">Export XLS</Button>
|
|
</Group>
|
|
</Group>
|
|
|
|
<Paper withBorder radius="2xl" className="glass" p="md">
|
|
<Group mb="md" grow>
|
|
<TextInput
|
|
placeholder="Search activity, village, or operator..."
|
|
leftSection={<TbSearch size={16} />}
|
|
radius="md"
|
|
/>
|
|
<Select
|
|
placeholder="All Service Types"
|
|
data={['DOCUMENT', 'FINANCE', 'SYNC', 'SECURITY']}
|
|
leftSection={<TbFilter size={16} />}
|
|
radius="md"
|
|
clearable
|
|
/>
|
|
</Group>
|
|
|
|
<Table verticalSpacing="sm" highlightOnHover>
|
|
<Table.Thead>
|
|
<Table.Tr>
|
|
<Table.Th>Type</Table.Th>
|
|
<Table.Th>Village / Instance</Table.Th>
|
|
<Table.Th>Activity Name</Table.Th>
|
|
<Table.Th>Operator</Table.Th>
|
|
<Table.Th>Timestamp</Table.Th>
|
|
<Table.Th>Status</Table.Th>
|
|
</Table.Tr>
|
|
</Table.Thead>
|
|
<Table.Tbody>
|
|
{mockLogs.map((log) => (
|
|
<Table.Tr key={log.id}>
|
|
<Table.Td>
|
|
<Badge
|
|
variant="light"
|
|
color={
|
|
log.type === 'DOCUMENT' ? 'blue' :
|
|
log.type === 'FINANCE' ? 'teal' :
|
|
log.type === 'SYNC' ? 'orange' : 'gray'
|
|
}
|
|
size="xs"
|
|
>
|
|
{log.type}
|
|
</Badge>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Text size="sm" fw={600}>{log.village}</Text>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Code color="brand-blue" bg="transparent" fw={800} style={{ fontSize: '11px' }}>{log.activity}</Code>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Group gap="xs">
|
|
<Avatar size="xs" radius="xl" color="brand-blue">{log.operator[0]}</Avatar>
|
|
<Text size="xs" fw={500}>{log.operator}</Text>
|
|
</Group>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Text size="xs" c="dimmed">{log.time}</Text>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Badge
|
|
size="xs"
|
|
variant="dot"
|
|
color={log.status === 'SUCCESS' ? 'teal' : 'orange'}
|
|
>
|
|
{log.status}
|
|
</Badge>
|
|
</Table.Td>
|
|
</Table.Tr>
|
|
))}
|
|
</Table.Tbody>
|
|
</Table>
|
|
</Paper>
|
|
</Stack>
|
|
)
|
|
}
|