Files
teatea-pension/modules/settings/components/GlobalSettingsClient.tsx

170 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { FormEvent, useState } from "react";
import { Globe2, Save, ShieldCheck } from "lucide-react";
import { useRouter } from "next/navigation";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import type { ApiResult } from "@/modules/core/server/api";
import type { SystemSettings } from "@/modules/core/types";
type GlobalSettingsClientProps = {
settings: SystemSettings;
};
export function GlobalSettingsClient({ settings }: GlobalSettingsClientProps): React.ReactElement {
const router = useRouter();
const [message, setMessage] = useState("");
const [isPending, setIsPending] = useState(false);
async function handleSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
event.preventDefault();
setMessage("");
setIsPending(true);
const formData = new FormData(event.currentTarget);
const response = await fetch("/api/settings/global", {
method: "PATCH",
headers: { "content-type": "application/json" },
body: JSON.stringify({
registrationEnabled: formData.get("registrationEnabled") === "on",
oidcEnabled: formData.get("oidcEnabled") === "on",
oidcIssuerUrl: String(formData.get("oidcIssuerUrl") ?? ""),
oidcClientId: String(formData.get("oidcClientId") ?? ""),
oidcClientSecret: String(formData.get("oidcClientSecret") ?? ""),
oidcScopes: String(formData.get("oidcScopes") ?? ""),
oidcRedirectUri: String(formData.get("oidcRedirectUri") ?? ""),
oidcAvatarClaim: String(formData.get("oidcAvatarClaim") ?? ""),
oidcAutoProvision: formData.get("oidcAutoProvision") === "on",
}),
});
const result = (await response.json()) as ApiResult<{ settings: SystemSettings }>;
setIsPending(false);
if (!result.success) {
setMessage(result.reason);
return;
}
setMessage(result.reason);
router.refresh();
}
return (
<form className="grid gap-5 xl:grid-cols-[0.9fr_1.1fr]" onSubmit={handleSubmit}>
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<Globe2 className="size-5 text-primary" aria-hidden="true" />
<CardTitle></CardTitle>
</div>
<CardDescription> OIDC </CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<div className="rounded-md border p-3 text-sm">
<Checkbox
controlFirst={false}
defaultChecked={settings.registrationEnabled}
label={
<span className="min-w-0">
<span className="block font-medium"></span>
<span className="block text-xs text-muted-foreground">使</span>
</span>
}
name="registrationEnabled"
/>
</div>
<div className="rounded-md border p-3 text-sm">
<Checkbox
controlFirst={false}
defaultChecked={settings.oidcEnabled}
label={
<span className="min-w-0">
<span className="block font-medium"> OIDC </span>
<span className="block text-xs text-muted-foreground"> OIDC </span>
</span>
}
name="oidcEnabled"
/>
</div>
<div className="rounded-md border p-3 text-sm">
<Checkbox
controlFirst={false}
defaultChecked={settings.oidcAutoProvision}
label={
<span className="min-w-0">
<span className="block font-medium">OIDC </span>
<span className="block text-xs text-muted-foreground"> OIDC </span>
</span>
}
name="oidcAutoProvision"
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<ShieldCheck className="size-5 text-primary" aria-hidden="true" />
<CardTitle>OIDC </CardTitle>
</div>
<CardDescription> OIDC issuerclientscope claim</CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-3 md:grid-cols-2">
<Input
defaultValue={settings.oidcIssuerUrl}
label="Issuer URL"
name="oidcIssuerUrl"
placeholder="https://idp.example.com"
/>
<Input defaultValue={settings.oidcClientId} label="Client ID" name="oidcClientId" />
</div>
<Input
label="Client Secret"
name="oidcClientSecret"
placeholder={settings.oidcHasClientSecret ? "已配置,留空则不修改" : "未配置"}
type="password"
/>
<div className="grid gap-3 md:grid-cols-2">
<Input defaultValue={settings.oidcScopes} label="Scopes" name="oidcScopes" placeholder="openid profile email" />
<Input
defaultValue={settings.oidcRedirectUri}
label="Redirect URI"
name="oidcRedirectUri"
placeholder="/api/auth/oidc/callback"
/>
</div>
<Input defaultValue={settings.oidcAvatarClaim} label="Avatar Claim" name="oidcAvatarClaim" placeholder="picture" />
{message ? (
<p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
{message}
</p>
) : null}
<div className="flex items-center justify-between gap-3 border-t pt-4">
<Badge variant={settings.oidcEnabled ? "success" : "secondary"}>
{settings.oidcEnabled ? "OIDC 已启用" : "OIDC 未启用"}
</Badge>
<Button disabled={isPending} type="submit">
<Save className="size-4" aria-hidden="true" />
</Button>
</div>
</CardContent>
</Card>
</form>
);
}