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 ── */}