"use client" import { useState, useEffect, useCallback } from "react" import Link from "next/link" import { supabase } from "@/lib/supabase" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Shield, ArrowLeft, Plus, Loader2, Search, Trash2 } from "lucide-react" interface Business { business_id: number name: string slug: string created_at: string } interface AuthorizationRow { id: number business_id: number user_id: number authorized_by_admin_id: number account_identifier: string | null notes: string | null created_at: string business_name: string | null business_slug: string | null user_name: string | null user_email: string | null authorized_by_name: string | null authorized_by_email: string | null } async function getAuthHeaders(): Promise { const { data: { session }, } = await supabase.auth.getSession() const headers: HeadersInit = { "Content-Type": "application/json" } if (session?.access_token) { (headers as Record)["Authorization"] = `Bearer ${session.access_token}` } return headers } export default function AdminAuthorizationsPage() { const [businesses, setBusinesses] = useState([]) const [list, setList] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState("") const [filterBusinessId, setFilterBusinessId] = useState("") const [addOpen, setAddOpen] = useState(false) const [addBusinessId, setAddBusinessId] = useState("") const [lookupInput, setLookupInput] = useState("") const [lookupMode, setLookupMode] = useState<"email" | "username">("email") const [lookupResult, setLookupResult] = useState<{ found: boolean user?: { user_id: number; user_name: string; email: string } } | null>(null) const [lookupLoading, setLookupLoading] = useState(false) const [addUserId, setAddUserId] = useState(null) const [addSubmitting, setAddSubmitting] = useState(false) const [revokeId, setRevokeId] = useState(null) const loadBusinesses = useCallback(async () => { try { const res = await fetch("/api/admin/businesses", { headers: await getAuthHeaders() }) if (res.ok) { const data = await res.json() setBusinesses(data) } } catch { setBusinesses([]) } }, []) const loadList = useCallback(async () => { setLoading(true) setError("") try { const params = new URLSearchParams() if (filterBusinessId) params.set("business_id", filterBusinessId) const res = await fetch(`/api/admin/authorizations?${params}`, { headers: await getAuthHeaders(), }) if (!res.ok) { const data = await res.json().catch(() => ({})) throw new Error(data?.error || res.statusText) } const data = await res.json() setList(data) } catch (e) { setError(e instanceof Error ? e.message : "Failed to load authorizations") setList([]) } finally { setLoading(false) } }, [filterBusinessId]) useEffect(() => { loadBusinesses() }, [loadBusinesses]) useEffect(() => { loadList() }, [loadList]) const handleLookup = async (e: React.FormEvent) => { e.preventDefault() if (!lookupInput.trim()) return setLookupLoading(true) setLookupResult(null) try { const param = lookupMode === "email" ? `email=${encodeURIComponent(lookupInput.trim())}` : `username=${encodeURIComponent(lookupInput.trim())}` const res = await fetch(`/api/admin/users/lookup?${param}`, { headers: await getAuthHeaders(), }) const data = await res.json() if (res.status === 404) { setLookupResult({ found: false }) } else if (res.ok && data.found && data.user) { setLookupResult({ found: true, user: data.user }) } else { setLookupResult({ found: false }) } } catch { setLookupResult({ found: false }) } finally { setLookupLoading(false) } } const handleAddAuthorization = async (e: React.FormEvent) => { e.preventDefault() if (!addBusinessId || addUserId == null) return setAddSubmitting(true) try { const res = await fetch("/api/admin/authorizations", { method: "POST", headers: await getAuthHeaders(), body: JSON.stringify({ business_id: Number(addBusinessId), user_id: addUserId }), }) if (!res.ok) { const data = await res.json().catch(() => ({})) throw new Error(data?.error || res.statusText) } setAddOpen(false) setAddBusinessId("") setAddUserId(null) setLookupResult(null) setLookupInput("") loadList() } catch (e) { setError(e instanceof Error ? e.message : "Failed to add authorization") } finally { setAddSubmitting(false) } } const handleRevoke = async (id: number) => { if (!confirm("Revoke this authorization?")) return setRevokeId(id) try { const res = await fetch(`/api/admin/authorizations/${id}`, { method: "DELETE", headers: await getAuthHeaders(), }) if (!res.ok) { const data = await res.json().catch(() => ({})) throw new Error(data?.error || res.statusText) } loadList() } catch (e) { setError(e instanceof Error ? e.message : "Failed to revoke") } finally { setRevokeId(null) } } const openAddWithUser = (user: { user_id: number; user_name: string; email: string }) => { setAddUserId(user.user_id) setLookupResult({ found: true, user }) setAddOpen(true) } return (

Authorization checklist

Manage who is authorized for which business. Look up users and grant or revoke access.

{error && (
{error}
)} {/* User lookup */} Check user exists Look up by email or username to see if a user exists. You can then add them to the authorization list.
setLookupInput(e.target.value)} placeholder={lookupMode === "email" ? "user@example.com" : "username"} disabled={lookupLoading} />
{lookupResult !== null && (
{lookupResult.found && lookupResult.user ? (

User exists

ID: {lookupResult.user.user_id} · {lookupResult.user.user_name} · {lookupResult.user.email}

) : (

User not found.

)}
)}
{/* Checklist table */} Authorizations Users authorized per business. Revoke to remove access.
{loading ? (
) : list.length === 0 ? (

No authorizations yet. Add one or create businesses first.

) : (
{list.map((row) => ( ))}
Business User Authorized by Date Actions
{row.business_name ?? row.business_id} {row.user_name ?? row.user_email ?? `User #${row.user_id}`} {row.user_email && ( {row.user_email} )} {row.authorized_by_name ?? row.authorized_by_email ?? `Admin #${row.authorized_by_admin_id}`} {new Date(row.created_at).toLocaleDateString()}
)}
{/* Add authorization dialog */} Add authorization Choose a business and a user to authorize. Use the lookup above to find a user, or enter user ID if you know it.
{addUserId != null ? (
Authorizing user ID: {addUserId}
) : (
{ const v = e.target.value ? parseInt(e.target.value, 10) : null setAddUserId(Number.isNaN(v as number) ? null : v) }} />
)}
) }