'use client' import { useEffect, useState } from 'react' import { useParams, useRouter } from 'next/navigation' import { authFetch, clearToken, getApiBase, getToken } from '../../lib/auth' import AdminShell from '../../ui/AdminShell' type UserStats = { total: number ready: number pending: number approved: number working: number partial: number declined: number in_progress: number last_request_at?: string | null } type AdminUser = { id?: number username: string role: string auth_provider?: string | null last_login_at?: string | null is_blocked?: boolean jellyseerr_user_id?: number | null } const formatDateTime = (value?: string | null) => { if (!value) return 'Never' const date = new Date(value) if (Number.isNaN(date.valueOf())) return value return date.toLocaleString() } const normalizeStats = (stats: any): UserStats => ({ total: Number(stats?.total ?? 0), ready: Number(stats?.ready ?? 0), pending: Number(stats?.pending ?? 0), approved: Number(stats?.approved ?? 0), working: Number(stats?.working ?? 0), partial: Number(stats?.partial ?? 0), declined: Number(stats?.declined ?? 0), in_progress: Number(stats?.in_progress ?? 0), last_request_at: stats?.last_request_at ?? null, }) export default function UserDetailPage() { const params = useParams() const router = useRouter() const idParam = Array.isArray(params?.id) ? params.id[0] : params?.id const [user, setUser] = useState(null) const [stats, setStats] = useState(null) const [error, setError] = useState(null) const [loading, setLoading] = useState(true) const loadUser = async () => { if (!idParam) return try { const baseUrl = getApiBase() const response = await authFetch( `${baseUrl}/admin/users/id/${encodeURIComponent(idParam)}` ) if (!response.ok) { if (response.status === 401) { clearToken() router.push('/login') return } if (response.status === 403) { router.push('/') return } if (response.status === 404) { setError('User not found.') return } throw new Error('Could not load user.') } const data = await response.json() setUser(data?.user ?? null) setStats(normalizeStats(data?.stats)) setError(null) } catch (err) { console.error(err) setError('Could not load user.') } finally { setLoading(false) } } const toggleUserBlock = async (blocked: boolean) => { if (!user) return try { const baseUrl = getApiBase() const response = await authFetch( `${baseUrl}/admin/users/${encodeURIComponent(user.username)}/${blocked ? 'block' : 'unblock'}`, { method: 'POST' } ) if (!response.ok) { throw new Error('Update failed') } await loadUser() } catch (err) { console.error(err) setError('Could not update user access.') } } const updateUserRole = async (role: string) => { if (!user) return try { const baseUrl = getApiBase() const response = await authFetch( `${baseUrl}/admin/users/${encodeURIComponent(user.username)}/role`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ role }), } ) if (!response.ok) { throw new Error('Update failed') } await loadUser() } catch (err) { console.error(err) setError('Could not update user role.') } } useEffect(() => { if (!getToken()) { router.push('/login') return } void loadUser() }, [router, idParam]) if (loading) { return
Loading user...
} return ( router.push('/users')}> Back to users } >
{error &&
{error}
} {!user ? (
No user data found.
) : ( <>
{user.username}
Jellyseerr ID: {user.jellyseerr_user_id ?? user.id ?? 'Unknown'} Role: {user.role} Login type: {user.auth_provider || 'local'} Last login: {formatDateTime(user.last_login_at)}
Total {stats?.total ?? 0}
Ready {stats?.ready ?? 0}
Pending {stats?.pending ?? 0}
Approved {stats?.approved ?? 0}
Working {stats?.working ?? 0}
Partial {stats?.partial ?? 0}
Declined {stats?.declined ?? 0}
In progress {stats?.in_progress ?? 0}
Last request {formatDateTime(stats?.last_request_at)}
)}
) }