"use client"; import { FormEvent, useCallback, useEffect, useState } from "react"; import { Nav, useAuth } from "@/components/Nav"; type Device = { id: string; name: string; platform: string; lastSeenAt: string | null; createdAt: string; }; type GooglePlaySyncStatus = | "NOT_ENABLED" | "PENDING_ADD" | "ACTIVE" | "PENDING_REMOVE" | "REMOVED" | "ERROR"; type Viewer = { id: string; email: string; name: string | null; enabled: boolean; appAccess: boolean; googlePlayEmail: string | null; googlePlayAccess: boolean; googlePlayMembershipId: string | null; googlePlaySyncStatus: GooglePlaySyncStatus; googlePlayLastSyncedAt: string | null; googlePlaySyncError: string | null; googlePlayResolvedEmail: string; createdAt: string; deviceCount: number; devices: Device[]; }; type PlayConfig = { configured: boolean; groupEmail: string | null; groupId: string | null; optInUrl: string | null; }; const SYNC_LABELS: Record = { NOT_ENABLED: "Niet ingeschakeld", PENDING_ADD: "Bezig met toevoegen…", ACTIVE: "Actief", PENDING_REMOVE: "Bezig met verwijderen…", REMOVED: "Verwijderd", ERROR: "Fout", }; export default function ViewersPage() { useAuth(); const [viewers, setViewers] = useState([]); const [playConfig, setPlayConfig] = useState(null); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [name, setName] = useState(""); const [busy, setBusy] = useState(false); const [msg, setMsg] = useState(null); const [err, setErr] = useState(null); const [playEmails, setPlayEmails] = useState>({}); const load = useCallback(() => { fetch("/api/v1/admin/viewers", { credentials: "include" }) .then((r) => r.json()) .then((d) => { const list: Viewer[] = d.viewers ?? []; setViewers(list); setPlayEmails((prev) => { const next = { ...prev }; for (const v of list) { if (next[v.id] === undefined) { next[v.id] = v.googlePlayEmail ?? ""; } } return next; }); }) .catch(() => setErr("Kon kijkers niet laden")); }, []); useEffect(() => { load(); fetch("/api/v1/admin/google-play-access/config", { credentials: "include" }) .then((r) => r.json()) .then((d) => setPlayConfig(d.config ?? null)) .catch(() => undefined); }, [load]); async function createViewer(e: FormEvent) { e.preventDefault(); setBusy(true); setMsg(null); setErr(null); try { const res = await fetch("/api/v1/admin/viewers", { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password, name: name || undefined, appAccess: true }), }); const data = await res.json().catch(() => ({})); if (!res.ok) { setErr(data.error?.message ?? "Aanmaken mislukt"); return; } setMsg(`Kijker ${data.viewer.email} aangemaakt`); setEmail(""); setPassword(""); setName(""); load(); } finally { setBusy(false); } } async function toggle(v: Viewer, field: "enabled" | "appAccess") { await fetch(`/api/v1/admin/viewers/${v.id}`, { method: "PATCH", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ [field]: !v[field] }), }); load(); } async function setPlayAccess(v: Viewer, enabled: boolean) { setMsg(null); setErr(null); const res = await fetch(`/api/v1/admin/viewers/${v.id}/google-play-access`, { method: "PATCH", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ enabled, email: playEmails[v.id]?.trim() || null, }), }); const data = await res.json().catch(() => ({})); if (!res.ok) { setErr(data.error?.message ?? "Google Play-toegang bijwerken mislukt"); } else { setMsg(data.message ?? (enabled ? "Google Play access enabled." : "Google Play access removed.")); if (data.syncError) setErr(data.syncError); } load(); } async function retryPlaySync(v: Viewer) { setMsg(null); setErr(null); const res = await fetch(`/api/v1/admin/viewers/${v.id}/google-play-access/retry`, { method: "POST", credentials: "include", }); const data = await res.json().catch(() => ({})); if (!res.ok) { setErr(data.error?.message ?? "Synchronisatie mislukt"); } else { setMsg(data.message ?? "Synchronization completed."); if (data.syncError) setErr(data.syncError); } load(); } async function bulkAction(path: "sync-all" | "reconcile") { setMsg(null); setErr(null); const res = await fetch(`/api/v1/admin/google-play-access/${path}`, { method: "POST", credentials: "include", }); const data = await res.json().catch(() => ({})); if (!res.ok) { setErr(data.error?.message ?? "Actie mislukt"); return; } const s = data.summary; setMsg( `Scanned: ${s.scanned} · Correct: ${s.correct} · Added: ${s.added} · Removed: ${s.removed} · Errors: ${s.errors}` ); load(); } async function revokeDevice(deviceId: string) { if (!confirm("Apparaat intrekken?")) return; await fetch(`/api/v1/admin/viewers/devices/${deviceId}/revoke`, { method: "POST", credentials: "include", }); load(); } return ( <>