import { IconDatabaseExport, IconServer2, IconShieldLock, } from "@tabler/icons-react"; import { desc, eq } from "drizzle-orm"; import { redirect } from "next/navigation"; import { Suspense } from "react"; import { TmdbLogo } from "@/components/tmdb-logo"; import { Card } from "@/components/ui/card"; import { getSession } from "@/lib/auth/session"; import { db } from "@/lib/db/client"; import { integrationEvents, integrations } from "@/lib/db/schema"; import { listBackups } from "@/lib/services/backup"; import { getSetting } from "@/lib/services/settings"; import { getSystemHealth } from "@/lib/services/system-health"; import { getCachedUpdateCheck, isUpdateCheckEnabled, } from "@/lib/services/update-check"; import { AccountSection } from "./_components/account-section"; import { BackupRestoreSection } from "./_components/backup-restore-section"; import { BackupScheduleSection } from "./_components/backup-schedule-section"; import { BackupSection } from "./_components/backup-section"; import { IntegrationsSection } from "./_components/integrations-section"; import { RegistrationSection } from "./_components/registration-section"; import { SettingsShell } from "./_components/settings-shell"; import { SkeletonCards, SystemHealthCards, } from "./_components/system-health-section"; import { UpdateCheckSection } from "./_components/update-check-section"; export default async function SettingsPage() { const session = await getSession(); if (!session?.user) redirect("/login"); const isAdmin = session.user.role === "admin"; const connRows = db .select() .from(integrations) .where(eq(integrations.userId, session.user.id)) .all(); const connIds = connRows.map((c) => c.id); // Fetch only the 10 most recent events per connection (index-optimized) const eventsByConn = new Map< string, (typeof integrationEvents.$inferSelect)[] >(); for (const connId of connIds) { const events = db .select() .from(integrationEvents) .where(eq(integrationEvents.integrationId, connId)) .orderBy(desc(integrationEvents.receivedAt)) .limit(10) .all(); eventsByConn.set(connId, events); } const connections = connRows.map((conn) => ({ id: conn.id, provider: conn.provider, type: conn.type, token: conn.token, enabled: conn.enabled, lastEventAt: conn.lastEventAt?.toISOString() ?? null, recentEvents: (eventsByConn.get(conn.id) ?? []).map((e) => ({ id: e.id, eventType: e.eventType, mediaType: e.mediaType, mediaTitle: e.mediaTitle, status: e.status, receivedAt: e.receivedAt.toISOString(), })), })); const registrationOpen = isAdmin ? getSetting("registrationOpen") === "true" : false; const backups = isAdmin ? await listBackups() : []; const scheduledBackupsEnabled = isAdmin ? getSetting("scheduledBackups") === "true" : false; const maxBackupRetention = isAdmin ? Number.parseInt(getSetting("maxBackupRetention") ?? "7", 10) : 7; const backupFrequency = isAdmin ? (getSetting("backupScheduleFrequency") ?? "1d") : "1d"; const backupTime = isAdmin ? (getSetting("backupScheduleTime") ?? "02:00") : "02:00"; const backupDow = isAdmin ? Number.parseInt(getSetting("backupScheduleDow") ?? "0", 10) : 0; const updateCheckEnabled = isAdmin ? isUpdateCheckEnabled() : true; const updateCheck = isAdmin && updateCheckEnabled ? getCachedUpdateCheck() : null; const GITHUB_REPO = "jakejarvis/sofa"; const APP_VERSION = process.env.APP_VERSION || "0.0.0"; const GIT_COMMIT_SHA = process.env.GIT_COMMIT_SHA?.slice(0, 7) || ""; return (

Sofa {" "} v{APP_VERSION} {GIT_COMMIT_SHA && ( <> {" "} ( {GIT_COMMIT_SHA} ) )} {updateCheck?.updateAvailable && ( v{updateCheck.latestVersion} available )}

This product uses the TMDB API but is not endorsed or certified by TMDB.

} > {isAdmin && ( <> {/* Server health */}

Server

Admin only
}>
{/* Security */}

Security

Admin only
{/* Backups */}

Backups

Admin only
)}
); } async function SystemHealthLoader() { const data = await getSystemHealth(); return ; }