import { useQuery } from '@tanstack/react-query' import { VillageActivityLineChart, VillageComparisonBarChart } from '@/frontend/components/DashboardCharts' import { ErrorDataTable } from '@/frontend/components/ErrorDataTable' import { SummaryCard } from '@/frontend/components/SummaryCard' import { useSession } from '@/frontend/hooks/useAuth' import { Badge, Button, Group, Modal, SimpleGrid, Stack, Switch, Text, Textarea, TextInput, Title } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' import { notifications } from '@mantine/notifications' import { createFileRoute, useNavigate, useParams } from '@tanstack/react-router' import { useEffect, useState } from 'react' import { TbActivity, TbAlertTriangle, TbBuildingCommunity, TbVersions } from 'react-icons/tb' import useSWR from 'swr' import { API_URLS } from '../config/api' export const Route = createFileRoute('/apps/$appId/')({ component: AppOverviewPage, }) const fetcher = (url: string) => fetch(url).then((res) => res.json()) function AppOverviewPage() { const { appId } = useParams({ from: '/apps/$appId/' }) const navigate = useNavigate() const isDesaPlus = appId === 'desa-plus' const [versionModalOpened, { open: openVersionModal, close: closeVersionModal }] = useDisclosure(false) const { data: session } = useSession() const isDeveloper = session?.user?.role === 'DEVELOPER' // Form State const [latestVersion, setLatestVersion] = useState('') const [minVersion, setMinVersion] = useState('') const [messageUpdate, setMessageUpdate] = useState('') const [maintenance, setMaintenance] = useState(false) const [isSaving, setIsSaving] = useState(false) // Data Fetching const { data: gridRes, isLoading: gridLoading, mutate: mutateGrid } = useSWR(isDesaPlus ? API_URLS.getGridOverview() : null, fetcher) const { data: dailyRes, isLoading: dailyLoading, mutate: mutateDaily } = useSWR(isDesaPlus ? API_URLS.getDailyActivity() : null, fetcher) const { data: comparisonRes, isLoading: comparisonLoading, mutate: mutateComparison } = useSWR(isDesaPlus ? API_URLS.getComparisonActivity() : null, fetcher) const { data: appData, isLoading: appLoading } = useQuery({ queryKey: ['apps', appId], queryFn: () => fetch(`/api/apps/${appId}`).then((r) => r.json()), }) const grid = gridRes?.data const dailyData = dailyRes?.data || [] const comparisonData = comparisonRes?.data || [] // Initialize form when data loads or modal opens useEffect(() => { if (grid?.version && versionModalOpened) { setLatestVersion(grid.version.mobile_latest_version || '') setMinVersion(grid.version.mobile_minimum_version || '') setMessageUpdate(grid.version.mobile_message_update || '') setMaintenance(grid.version.mobile_maintenance === 'true') } }, [grid, versionModalOpened]) const handleRefresh = () => { mutateGrid() mutateDaily() mutateComparison() } const handleSaveVersion = async () => { setIsSaving(true) try { const response = await fetch(API_URLS.postVersionUpdate(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mobile_latest_version: latestVersion, mobile_minimum_version: minVersion, mobile_maintenance: maintenance, mobile_message_update: messageUpdate, }), }) if (response.ok) { await fetch(API_URLS.createLog(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: 'UPDATE', message: `Update version information: ${JSON.stringify({ latestVersion, minVersion, maintenance, messageUpdate })}` }) }).catch(console.error) notifications.show({ title: 'Update Successful', message: 'Application version information has been updated.', color: 'teal', }) mutateGrid() closeVersionModal() } else { notifications.show({ title: 'Update Failed', message: 'Failed to update version information. Please check your data.', color: 'red', }) } } catch (error) { notifications.show({ title: 'Network Error', message: 'Could not connect to the server. Please try again later.', color: 'red', }) } finally { setIsSaving(false) } } return ( <> setLatestVersion(e.currentTarget.value)} /> setMinVersion(e.currentTarget.value)} />