diff --git a/src/frontend/routes/apps.$appId.villages.$villageId.tsx b/src/frontend/routes/apps.$appId.villages.$villageId.tsx index 970fc52..c695c99 100644 --- a/src/frontend/routes/apps.$appId.villages.$villageId.tsx +++ b/src/frontend/routes/apps.$appId.villages.$villageId.tsx @@ -8,7 +8,9 @@ import { Group, Loader, Modal, + Pagination, Paper, + ScrollArea, SegmentedControl, SimpleGrid, Stack, @@ -40,6 +42,7 @@ import { TbPower, TbTestPipe, TbUser, + TbUserOff, TbUsers, TbUsersGroup, TbWifi @@ -321,6 +324,116 @@ function RecentVillageLogs({ villageId }: { villageId: string }) { ) } +// ── Inactive Users ──────────────────────────────────────────────────────────── + +function InactiveVillageUsers({ villageId }: { villageId: string }) { + const [days, setDays] = useState<7 | 14 | 30>(7) + const [page, setPage] = useState(1) + + const { data: response, isLoading } = useSWR( + API_URLS.getInactiveUsers(days, villageId, page), + fetcher + ) + + const users: any[] = response?.data?.users || [] + const totalPages: number = response?.data?.totalPage ?? 0 + const total: number = response?.data?.total ?? 0 + + return ( + + + + + + + + Inactive Users + + {isLoading ? 'Loading...' : `${total} users with no activity in the last ${days} days`} + + + + { setDays(Number(v) as 7 | 14 | 30); setPage(1) }} + data={[ + { label: '7D', value: '7' }, + { label: '14D', value: '14' }, + { label: '30D', value: '30' }, + ]} + /> + + + {isLoading ? ( + + + + ) : users.length === 0 ? ( + + + No inactive users in this period. + + ) : ( + + + + + + Name + Role + Group / Position + Status + Last Activity + + + + {users.map((u: any) => ( + + + + {u.name} + {u.email} + + + + + {u.role} + + + + {u.group}{u.position ? ` · ${u.position}` : ''} + + + + {u.isActive ? 'Active' : 'Inactive'} + + + + {u.daysSince === null ? ( + Never + ) : ( + 30 ? 'red.5' : u.daysSince > 7 ? 'yellow.5' : 'dimmed'}> + {u.daysSince}d ago + + )} + + + ))} + +
+
+ {totalPages > 1 && ( + + + + )} +
+ )} +
+ ) +} + // ── Main Page ───────────────────────────────────────────────────────────────── function VillageDetailPage() { @@ -671,6 +784,9 @@ function VillageDetailPage() { + {/* ── Inactive Users ── */} + + {/* ── Confirmation Modal ── */}