"use client"; import { useEffect, useState } from "react"; import { IconExternalLink, IconPlus } from "@tabler/icons-react"; import { Button } from "@kandev/ui/button"; import { Spinner } from "@kandev/ui/spinner"; import { useToast } from "@/components/toast-provider"; import { useGitHubAppRegistrations } from "@/hooks/domains/github/use-github-app-registrations"; import { GitHubAppCreateForm } from "./github-app-create-form"; import { GitHubAppImportForm } from "./github-app-import-form"; import { GitHubAppRegistrationList } from "./github-app-registration-list"; import { useTranslation } from "react-i18next"; type AppView = "choose" | "import" | "create"; type RegistrationHook = ReturnType; export function GitHubAppConnectionPanel({ workspaceId }: { workspaceId: string }) { const { t } = useTranslation(); const registrations = useGitHubAppRegistrations(workspaceId); const [view, setView] = useState("choose"); const { selectedId, setSelectedId, selectedRegistration } = useAppRegistrationSelection( workspaceId, registrations, ); const { toast } = useToast(); useEffect(() => { setView("choose"); }, [workspaceId]); async function install() { if (!selectedRegistration || selectedRegistration.status !== "active") return; try { const response = await registrations.startInstall(selectedRegistration.id); const url = response.url ?? response.URL; // Surfaced to the user by the catch below, so it is copy. if (!url) throw new Error(t("github:githubDidNotReturnAnInstallationUrl")); window.location.assign(url); } catch (error) { toast({ description: error instanceof Error ? error.message : t("github:appInstallationFailed"), variant: "error", }); } } if (view === "import") { return (
setView("choose")} /> { setSelectedId(registrationId); setView("choose"); }} />
); } if (view === "create") { return (
setView("choose")} />
); } return (

{t("github:chooseAGithubApp")}

{t("github:useAnAppWhenAutomationNeeds")}

{registrations.loading ? (
{t("github:loadingRegisteredApps")}
) : ( )} {registrations.error &&

{registrations.error}

}

{t("github:aRegistrationCanBeReusedAcross")}

); } function useAppRegistrationSelection(workspaceId: string, registrations: RegistrationHook) { const [selectedId, setSelectedId] = useState(""); useEffect(() => setSelectedId(""), [workspaceId]); useEffect(() => { if (!registrations.loaded) return; setSelectedId((current) => { const currentRegistration = registrations.registrations.find(({ id }) => id === current); if (currentRegistration?.status === "active") return current; if (registrations.selected?.status === "active") return registrations.selected.id; return registrations.registrations.find(({ status }) => status === "active")?.id ?? ""; }); }, [registrations.loaded, registrations.registrations, registrations.selected]); const selectedRegistration = registrations.registrations.find(({ id }) => id === selectedId); return { selectedId, setSelectedId, selectedRegistration }; } function BackButton({ onClick }: { onClick: () => void }) { const { t } = useTranslation(); return ( ); }