import { DashboardLayout } from '@/frontend/components/DashboardLayout' import { API_URLS } from '@/frontend/config/api' import { Accordion, Avatar, Badge, Box, Button, Code, Collapse, Container, Group, Image, Loader, Modal, Pagination, Paper, Select, SimpleGrid, Stack, Text, ThemeIcon, TextInput, Textarea, Title, Timeline, } from '@mantine/core' import { useQuery } from '@tanstack/react-query' import { createFileRoute } from '@tanstack/react-router' import { useState } from 'react' import { useDisclosure } from '@mantine/hooks' import { notifications } from '@mantine/notifications' import { TbAlertTriangle, TbBug, TbDeviceDesktop, TbDeviceMobile, TbFilter, TbSearch, TbHistory, TbPhoto, TbPlus, TbCircleCheck, TbCircleX, } from 'react-icons/tb' export const Route = createFileRoute('/bug-reports')({ component: ListErrorsPage, }) function ListErrorsPage() { const [page, setPage] = useState(1) const [search, setSearch] = useState('') const [app, setApp] = useState('all') const [status, setStatus] = useState('all') const [showLogs, setShowLogs] = useState>({}) const toggleLogs = (bugId: string) => { setShowLogs((prev) => ({ ...prev, [bugId]: !prev[bugId] })) } const { data, isLoading, refetch } = useQuery({ queryKey: ['bugs', { page, search, app, status }], queryFn: () => fetch(API_URLS.getBugs(page, search, app, status)).then((r) => r.json()), }) // Create Bug Modal Logic const [opened, { open, close }] = useDisclosure(false) const [isSubmitting, setIsSubmitting] = useState(false) const [createForm, setCreateForm] = useState({ description: '', app: 'desa-plus', status: 'OPEN', source: 'USER', affectedVersion: '', device: '', os: '', stackTrace: '', imageUrl: '', }) // Update Status Modal Logic const [updateModalOpened, { open: openUpdateModal, close: closeUpdateModal }] = useDisclosure(false) const [isUpdating, setIsUpdating] = useState(false) const [selectedBugId, setSelectedBugId] = useState(null) const [updateForm, setUpdateForm] = useState({ status: '', description: '', }) // Feedback Modal Logic const [feedbackModalOpened, { open: openFeedbackModal, close: closeFeedbackModal }] = useDisclosure(false) const [isUpdatingFeedback, setIsUpdatingFeedback] = useState(false) const [feedbackForm, setFeedbackForm] = useState({ feedBack: '', }) const handleUpdateFeedback = async () => { if (!selectedBugId || !feedbackForm.feedBack) return setIsUpdatingFeedback(true) try { const res = await fetch(API_URLS.updateBugFeedback(selectedBugId), { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(feedbackForm), }) if (res.ok) { notifications.show({ title: 'Success', message: 'Feedback has been updated.', color: 'teal', icon: , }) refetch() closeFeedbackModal() setFeedbackForm({ feedBack: '' }) } else { throw new Error('Failed to update feedback') } } catch (e) { notifications.show({ title: 'Error', message: 'Something went wrong.', color: 'red', icon: , }) } finally { setIsUpdatingFeedback(false) } } const handleUpdateStatus = async () => { if (!selectedBugId || !updateForm.status) return setIsUpdating(true) try { const res = await fetch(API_URLS.updateBugStatus(selectedBugId), { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updateForm), }) if (res.ok) { notifications.show({ title: 'Success', message: 'Status has been updated.', color: 'teal', icon: , }) refetch() closeUpdateModal() setUpdateForm({ status: '', description: '' }) } else { throw new Error('Failed to update status') } } catch (e) { notifications.show({ title: 'Error', message: 'Something went wrong.', color: 'red', icon: , }) } finally { setIsUpdating(false) } } const handleCreateBug = async () => { if (!createForm.description || !createForm.affectedVersion || !createForm.device || !createForm.os) { notifications.show({ title: 'Validation Error', message: 'Please fill in all required fields.', color: 'red', }) return } setIsSubmitting(true) try { const res = await fetch(API_URLS.createBug(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(createForm), }) if (res.ok) { await fetch(API_URLS.createLog(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'CREATE', message: `Report error baru ditambahkan: ${createForm.description.substring(0, 50)}${createForm.description.length > 50 ? '...' : ''}` }) }).catch(console.error) notifications.show({ title: 'Success', message: 'Error report has been created.', color: 'teal', icon: , }) refetch() close() setCreateForm({ description: '', app: 'desa-plus', status: 'OPEN', source: 'USER', affectedVersion: '', device: '', os: '', stackTrace: '', imageUrl: '', }) } else { throw new Error('Failed to create error report') } } catch (e) { notifications.show({ title: 'Error', message: 'Something went wrong.', color: 'red', icon: , }) } finally { setIsSubmitting(false) } } const bugs = data?.data || [] const totalPages = data?.totalPages || 1 return ( Error Reports Centralized error tracking and analysis for all applications. {/* */} Update Bug Status} radius="xl" overlayProps={{ backgroundOpacity: 0.55, blur: 3 }} >