upd: tampilan
This commit is contained in:
195
src/frontend/components/ErrorDataTable.tsx
Normal file
195
src/frontend/components/ErrorDataTable.tsx
Normal file
@@ -0,0 +1,195 @@
|
||||
import {
|
||||
Table,
|
||||
Badge,
|
||||
Text,
|
||||
Paper,
|
||||
Group,
|
||||
Drawer,
|
||||
Stack,
|
||||
Divider,
|
||||
Code,
|
||||
Button,
|
||||
Box,
|
||||
ScrollArea,
|
||||
Title
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { useState } from 'react'
|
||||
import { TbMessageReport, TbHistory, TbExternalLink, TbBug } from 'react-icons/tb'
|
||||
|
||||
const mockErrors = [
|
||||
{
|
||||
id: 1,
|
||||
message: 'NullPointerException at village_sync.dart:45',
|
||||
village: 'Sukatani',
|
||||
version: 'v1.2.0',
|
||||
timestamp: '2026-04-01 14:30:15',
|
||||
severity: 'critical',
|
||||
stackTrace: 'at com.desa.sync.VillageManager.sync(VillageManager.java:45)\nat com.desa.sync.SyncService.onHandleIntent(SyncService.java:120)'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
message: 'Failed to load citizen record session',
|
||||
village: 'Sukamaju',
|
||||
version: 'v1.1.8',
|
||||
timestamp: '2026-04-01 14:15:22',
|
||||
severity: 'high',
|
||||
stackTrace: 'Error: Connection timeout reaching upstream citizen-db\n at HttpClient.get (network.dart:88)'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
message: 'SocketException: Connection timed out',
|
||||
village: 'Cikini',
|
||||
version: 'v1.2.0',
|
||||
timestamp: '2026-04-01 13:55:10',
|
||||
severity: 'medium',
|
||||
stackTrace: 'SocketException: OS Error: Connection timed out, errno = 110, address = 10.0.2.2, port = 54332'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
message: 'UI Thread blocking > 500ms',
|
||||
village: 'Beji',
|
||||
version: 'v1.1.2',
|
||||
timestamp: '2026-04-01 13:40:00',
|
||||
severity: 'low',
|
||||
stackTrace: 'ANR (Application Not Responding) detected in main thread.'
|
||||
},
|
||||
]
|
||||
|
||||
export function ErrorDataTable() {
|
||||
const [opened, { open, close }] = useDisclosure(false)
|
||||
const [selectedError, setSelectedError] = useState<any>(null)
|
||||
|
||||
const handleRowClick = (error: any) => {
|
||||
setSelectedError(error)
|
||||
open()
|
||||
}
|
||||
|
||||
const getSeverityColor = (sev: string) => {
|
||||
switch(sev) {
|
||||
case 'critical': return 'red'
|
||||
case 'high': return 'orange'
|
||||
case 'medium': return 'yellow'
|
||||
default: return 'gray'
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Paper withBorder radius="2xl" className="glass overflow-hidden">
|
||||
<Box p="xl" style={{ borderBottom: '1px solid rgba(255, 255, 255, 0.08)' }}>
|
||||
<Group justify="space-between">
|
||||
<Group gap="sm">
|
||||
<ThemeIcon variant="light" color="red" size="lg" radius="md">
|
||||
<TbBug size={20} />
|
||||
</ThemeIcon>
|
||||
<Text fw={700}>LATEST ERROR REPORTS</Text>
|
||||
</Group>
|
||||
<Button variant="subtle" size="compact-xs" color="blue" rightSection={<TbExternalLink size={14} />}>
|
||||
View All Reports
|
||||
</Button>
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
<ScrollArea>
|
||||
<Table verticalSpacing="md" highlightOnHover className="data-table">
|
||||
<Table.Thead bg="rgba(0,0,0,0.1)">
|
||||
<Table.Tr>
|
||||
<Table.Th px="xl">Error Message</Table.Th>
|
||||
<Table.Th>Village</Table.Th>
|
||||
<Table.Th>App Version</Table.Th>
|
||||
<Table.Th>Timestamp</Table.Th>
|
||||
<Table.Th pr="xl">Severity</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{mockErrors.map((error) => (
|
||||
<Table.Tr
|
||||
key={error.id}
|
||||
onClick={() => handleRowClick(error)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<Table.Td px="xl">
|
||||
<Text size="sm" fw={600} lineClamp={1}>{error.message}</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge variant="dot" color="brand-blue" radius="sm">{error.village}</Badge>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="xs" fw={700} c="dimmed">{error.version}</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Group gap={6}>
|
||||
<TbHistory size={12} color="gray" />
|
||||
<Text size="xs" c="dimmed">{error.timestamp}</Text>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
<Table.Td pr="xl">
|
||||
<Badge color={getSeverityColor(error.severity)} variant="light" size="sm">
|
||||
{error.severity.toUpperCase()}
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</Paper>
|
||||
|
||||
<Drawer
|
||||
opened={opened}
|
||||
onClose={close}
|
||||
position="right"
|
||||
size="md"
|
||||
title={
|
||||
<Group gap="xs">
|
||||
<TbMessageReport color="#ef4444" size={24} />
|
||||
<Title order={4}>Error Investigation</Title>
|
||||
</Group>
|
||||
}
|
||||
styles={{
|
||||
header: { padding: '24px', borderBottom: '1px solid rgba(255,255,255,0.1)' },
|
||||
content: { background: 'rgba(15, 23, 42, 0.95)', backdropFilter: 'blur(12px)' }
|
||||
}}
|
||||
>
|
||||
{selectedError && (
|
||||
<Stack p="lg" gap="xl">
|
||||
<Box>
|
||||
<Text size="xs" fw={700} c="dimmed" mb={4}>MESSAGE</Text>
|
||||
<Text fw={700} size="lg" color="red">{selectedError.message}</Text>
|
||||
</Box>
|
||||
|
||||
<SimpleGrid cols={2} spacing="lg">
|
||||
<Box>
|
||||
<Text size="xs" fw={700} c="dimmed" mb={4}>VILLAGE</Text>
|
||||
<Text fw={600}>{selectedError.village}</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text size="xs" fw={700} c="dimmed" mb={4}>APP VERSION</Text>
|
||||
<Badge variant="outline">{selectedError.version}</Badge>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
|
||||
<Divider opacity={0.1} />
|
||||
|
||||
<Box>
|
||||
<Text size="xs" fw={700} c="dimmed" mb="sm">STACK TRACE</Text>
|
||||
<Paper p="md" radius="md" bg="dark.8" style={{ border: '1px solid rgba(255,255,255,0.1)' }}>
|
||||
<Code block color="red" bg="transparent" style={{ whiteSpace: 'pre-wrap', lineHeight: 1.6 }}>
|
||||
{selectedError.stackTrace}
|
||||
</Code>
|
||||
</Paper>
|
||||
</Box>
|
||||
|
||||
<Group justify="flex-end" mt="xl">
|
||||
<Button variant="light" color="gray" onClick={close}>Dismiss</Button>
|
||||
<Button variant="gradient" gradient={{ from: 'red', to: 'orange' }}>Assign Technician</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
)}
|
||||
</Drawer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
import { SimpleGrid, ThemeIcon } from '@mantine/core'
|
||||
Reference in New Issue
Block a user