// SPDX-FileCopyrightText: 2026 Progmasoft // SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 "use client"; import { useEffect, useState } from "react"; import { callOAuthApi, type ApplicationCredentials, type ApplicationView, } from "@/lib/credentials"; import { format, getCredentialsMessages } from "@/lib/credentials-messages"; import type { Locale } from "@/lib/localization"; import { AccountSignInNotice } from "./AccountSignInNotice"; import { ApplicationForm } from "./ApplicationForm"; import { CredentialsCard } from "./CredentialsCard"; type DetailsState = | { kind: "loading" } | { kind: "signedOut" } | { kind: "notFound" } | { kind: "failed" } | { kind: "ready"; application: ApplicationView }; /** One application of the signed-in account: its settings, its secret and its deletion. */ export function ApplicationDetails({ locale, clientId, }: { locale: Locale; clientId: string; }) { const { common, details, form, kinds } = getCredentialsMessages(locale); const [state, setState] = useState({ kind: "loading" }); const [saved, setSaved] = useState(false); const [secret, setSecret] = useState(null); const path = `/applications/${encodeURIComponent(clientId)}`; useEffect(() => { const controller = new AbortController(); void callOAuthApi( `/applications/${encodeURIComponent(clientId)}`, { signal: controller.signal }, ).then((result) => { if (result.kind === "signedOut") { setState({ kind: "signedOut" }); } else if (result.kind === "ok") { setState({ kind: "ready", application: result.value }); } else { setState({ kind: result.kind === "notFound" ? "notFound" : "failed" }); } }); return () => controller.abort(); }, [clientId]); if (state.kind === "loading") { return

{common.loading}

; } if (state.kind === "signedOut") { return ; } if (state.kind !== "ready") { return (

{state.kind === "notFound" ? common.notFound : common.unreachable}

); } const { application } = state; async function rotate() { const result = await callOAuthApi( `${path}/secret`, { method: "POST" }, ); if (result.kind === "ok") { setSecret(result.value); } else if (result.kind === "signedOut") { setState({ kind: "signedOut" }); } } async function remove() { if (!window.confirm(details.confirmDelete)) { return; } const result = await callOAuthApi(path, { method: "DELETE" }); if (result.kind === "ok" || result.kind === "notFound") { window.location.replace("/credentials"); } else if (result.kind === "signedOut") { setState({ kind: "signedOut" }); } } return ( <>

{kinds[application.kind].title} {application.clientId} {format(details.created, { date: new Date(application.createdAt).toLocaleDateString(locale), })}

{saved && (
{form.saved}
)}
{ setSaved(false); const result = await callOAuthApi(path, { method: "PUT", body: submission, }); switch (result.kind) { case "ok": setState({ kind: "ready", application: result.value }); setSaved(true); return null; case "signedOut": setState({ kind: "signedOut" }); return null; case "refused": return result.errors; default: return { form: common.unreachable }; } }} /> {secret ? ( ) : (

{details.secretHeading}

{application.isPublic ? (

{details.noSecret}

) : ( <>

{details.rotateNote}

)}
)}

{details.deleteHeading}

{details.deleteNote}

); }