diff --git a/src/frontend/components/DashboardCharts.tsx b/src/frontend/components/DashboardCharts.tsx
index c2ddf93..bd67156 100644
--- a/src/frontend/components/DashboardCharts.tsx
+++ b/src/frontend/components/DashboardCharts.tsx
@@ -11,25 +11,12 @@ import {
import { LineChart, BarChart } from '@mantine/charts'
import { TbTimeline, TbChartBar, TbArrowUpRight } from 'react-icons/tb'
-const activityData = [
- { date: 'Mar 26', logs: 1200 },
- { date: 'Mar 27', logs: 1900 },
- { date: 'Mar 28', logs: 1540 },
- { date: 'Mar 29', logs: 2400 },
- { date: 'Mar 30', logs: 2100 },
- { date: 'Mar 31', logs: 3200 },
- { date: 'Apr 01', logs: 3800 },
-]
+interface ChartProps {
+ data?: any[]
+ isLoading?: boolean
+}
-const villageComparisonData = [
- { village: 'Sukatani', activity: 4500 },
- { village: 'Sukamaju', activity: 3800 },
- { village: 'Bojong Gede', activity: 3200 },
- { village: 'Beji', activity: 2800 },
- { village: 'Tapos', activity: 2400 },
-]
-
-export function VillageActivityLineChart() {
+export function VillageActivityLineChart({ data = [], isLoading }: ChartProps) {
const theme = useMantineTheme()
return (
@@ -46,14 +33,14 @@ export function VillageActivityLineChart() {
}>
- Growing
+ {isLoading ? '...' : 'Live'}
USAGE COMPARISON BETWEEN VILLAGES
- Top 5 most active village deployments
+ Most active village deployments
@@ -97,7 +84,7 @@ export function VillageComparisonBarChart() {
- {/* Custom SVG Gradient definitions for Premium SaaS look */}
diff --git a/src/frontend/config/api.ts b/src/frontend/config/api.ts
index 1cb70e3..0302546 100644
--- a/src/frontend/config/api.ts
+++ b/src/frontend/config/api.ts
@@ -13,4 +13,7 @@ export const API_URLS = {
`${API_BASE_URL}/api/monitoring/user?page=${page}&search=${encodeURIComponent(search)}`,
getLogsAllVillages: (page: number, search: string) =>
`${API_BASE_URL}/api/monitoring/log-all-villages?page=${page}&search=${encodeURIComponent(search)}`,
+ getGridOverview: () => `${API_BASE_URL}/api/monitoring/grid-overview`,
+ getDailyActivity: () => `${API_BASE_URL}/api/monitoring/daily-activity`,
+ getComparisonActivity: () => `${API_BASE_URL}/api/monitoring/comparison-activity`,
}
diff --git a/src/frontend/routes/apps.$appId.index.tsx b/src/frontend/routes/apps.$appId.index.tsx
index 4112379..6c737c8 100644
--- a/src/frontend/routes/apps.$appId.index.tsx
+++ b/src/frontend/routes/apps.$appId.index.tsx
@@ -13,10 +13,12 @@ import {
TextInput,
Switch,
Badge,
- Textarea
+ Textarea,
+ Skeleton
} from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { createFileRoute, useParams, useNavigate } from '@tanstack/react-router'
+import useSWR from 'swr'
import {
TbActivity,
TbAlertTriangle,
@@ -24,125 +26,131 @@ import {
TbRefresh,
TbVersions
} from 'react-icons/tb'
+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)
+ // 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 grid = gridRes?.data
+ const dailyData = dailyRes?.data || []
+ const comparisonData = comparisonRes?.data || []
+
+ const handleRefresh = () => {
+ mutateGrid()
+ mutateDaily()
+ mutateComparison()
+ }
+
return (
<>
-
-
+
+
-
+
- {/* 🔝 HEADER SECTION */}
- {/* */}
-
-
- Overview
- Last updated: Just now
-
+
+
+ Overview
+ Detailed metrics for {isDesaPlus ? 'Desa+' : appId}
+
-
- {/* }
- radius="md"
- w={140}
- /> */}
-
-
-
- {/* }
- >
- Add Filter
- */}
+
+
+
+
+
-
- {/* */}
- {/* 📊 1. SUMMARY CARDS */}
-
-
-
-
- Min. Version
- v1.0.0
-
-
- Maintenance
- False
-
-
-
-
- navigate({ to: `/apps/${appId}/villages` })}
- >
-
- Nonactive Villages
- 24
-
-
-
-
+
+
+
+
+ Min. Version
+ {grid?.version?.mobile_minimum_version || '-'}
+
+
+ Maintenance
+
+ {grid?.version?.mobile_maintenance?.toUpperCase() || 'FALSE'}
+
+
+
+
- {/* 📈 📊 2 & 3. CHARTS GRID */}
-
-
-
-
+ 0 } : undefined}
+ />
- {/* 🐞 4. LATEST ERROR REPORTS */}
-
-
+ navigate({ to: `/apps/${appId}/villages` })}
+ >
+
+ Nonactive Villages
+ {grid?.village?.inactive || 0}
+
+
+
+
+
+
+
+
+
+
+
+
+
>
)
}