♻️ separate create form into multiple ones

This commit is contained in:
Fred KISSIE
2026-03-05 19:45:13 +01:00
parent c5fc49b4fa
commit 642999c8b1
5 changed files with 392 additions and 276 deletions

View File

@@ -14,7 +14,7 @@ import { useTranslations } from "next-intl";
import z from "zod"; import z from "zod";
import { type PolicyFormValues } from "."; import { createPolicySchema, type PolicyFormValues } from ".";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
@@ -46,7 +46,7 @@ import {
import { cn } from "@app/lib/cn"; import { cn } from "@app/lib/cn";
import { Binary, Bot, Key, Plus } from "lucide-react"; import { Binary, Bot, Key, Plus } from "lucide-react";
import { useState } from "react"; import { useEffect, useState } from "react";
import { type UseFormReturn, useForm, useWatch } from "react-hook-form"; import { type UseFormReturn, useForm, useWatch } from "react-hook-form";
// ─── CreatePolicyAuthMethodsSectionForm ─────────────────────────────────────── // ─── CreatePolicyAuthMethodsSectionForm ───────────────────────────────────────
@@ -70,7 +70,7 @@ export type CreatePolicyAuthMethodsSectionFormProps = {
}; };
export function CreatePolicyAuthMethodsSectionForm({ export function CreatePolicyAuthMethodsSectionForm({
form form: parentForm
}: CreatePolicyAuthMethodsSectionFormProps) { }: CreatePolicyAuthMethodsSectionFormProps) {
const t = useTranslations(); const t = useTranslations();
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
@@ -78,6 +78,30 @@ export function CreatePolicyAuthMethodsSectionForm({
const [isSetPincodeOpen, setIsSetPincodeOpen] = useState(false); const [isSetPincodeOpen, setIsSetPincodeOpen] = useState(false);
const [isSetHeaderAuthOpen, setIsSetHeaderAuthOpen] = useState(false); const [isSetHeaderAuthOpen, setIsSetHeaderAuthOpen] = useState(false);
const form = useForm({
resolver: zodResolver(
createPolicySchema.pick({
password: true,
pincode: true,
headerAuth: true
})
),
defaultValues: {
password: null,
pincode: null,
headerAuth: null
}
});
useEffect(() => {
const subscription = form.watch((values) => {
parentForm.setValue("password", values.password as any);
parentForm.setValue("pincode", values.pincode as any);
parentForm.setValue("headerAuth", values.headerAuth as any);
});
return () => subscription.unsubscribe();
}, [form, parentForm]);
const password = useWatch({ const password = useWatch({
control: form.control, control: form.control,
name: "password" name: "password"

View File

@@ -43,7 +43,7 @@ import {
} from "@app/components/ui/form"; } from "@app/components/ui/form";
import { Input } from "@app/components/ui/input"; import { Input } from "@app/components/ui/input";
import { useMemo, useActionState } from "react"; import { useMemo, useTransition } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { CreatePolicyUsersRolesSectionForm } from "./CreatePolicyUserRolesSectionForm"; import { CreatePolicyUsersRolesSectionForm } from "./CreatePolicyUserRolesSectionForm";
import { CreatePolicyAuthMethodsSectionForm } from "./CreatePolicyAuthMethodsSectionForm"; import { CreatePolicyAuthMethodsSectionForm } from "./CreatePolicyAuthMethodsSectionForm";
@@ -59,7 +59,7 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
const t = useTranslations(); const t = useTranslations();
const { env } = useEnvContext(); const { env } = useEnvContext();
const api = createApiClient({ env }); const api = createApiClient({ env });
const [, formAction, isSubmitting] = useActionState(onSubmit, null); const [isSubmitting, startTransition] = useTransition();
const { isPaidUser } = usePaidStatus(); const { isPaidUser } = usePaidStatus();
const router = useRouter(); const router = useRouter();
@@ -202,8 +202,7 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
return ( return (
<Form {...form}> <Form {...form}>
<form action={formAction}> <SettingsContainer>
<SettingsContainer>
{/* Name */} {/* Name */}
<SettingsSection> <SettingsSection>
<SettingsSectionHeader> <SettingsSectionHeader>
@@ -258,14 +257,14 @@ export function CreatePolicyForm({}: CreatePolicyFormProps) {
<div className="flex py-6 justify-end"> <div className="flex py-6 justify-end">
<Button <Button
type="submit" type="button"
onClick={() => startTransition(onSubmit)}
loading={isSubmitting} loading={isSubmitting}
disabled={isSubmitting} disabled={isSubmitting}
> >
{t("resourcePoliciesCreate")} {t("resourcePoliciesCreate")}
</Button> </Button>
</div> </div>
</form>
</Form> </Form>
); );
} }

View File

@@ -9,30 +9,31 @@ import {
SettingsSectionTitle SettingsSectionTitle
} from "@app/components/Settings"; } from "@app/components/Settings";
import { zodResolver } from "@hookform/resolvers/zod";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import z from "zod"; import z from "zod";
import { type PolicyFormValues } from "."; import { createPolicySchema, type PolicyFormValues } from ".";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
import { Tag, TagInput } from "@app/components/tags/tag-input"; import { Tag, TagInput } from "@app/components/tags/tag-input";
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert"; import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { import {
Form,
FormControl, FormControl,
FormDescription, FormDescription,
FormField, FormField,
FormItem, FormItem,
FormLabel, FormLabel
FormMessage
} from "@app/components/ui/form"; } from "@app/components/ui/form";
import { InfoPopup } from "@app/components/ui/info-popup"; import { InfoPopup } from "@app/components/ui/info-popup";
import { InfoIcon, Plus } from "lucide-react"; import { InfoIcon, Plus } from "lucide-react";
import { useState } from "react"; import { useEffect, useState } from "react";
import { type UseFormReturn } from "react-hook-form"; import { type UseFormReturn, useForm, useWatch } from "react-hook-form";
// ─── CreatePolicyOtpEmailSectionForm ────────────────────────────────────────── // ─── CreatePolicyOtpEmailSectionForm ──────────────────────────────────────────
@@ -42,16 +43,44 @@ export type CreatePolicyOtpEmailSectionFormProps = {
}; };
export function CreatePolicyOtpEmailSectionForm({ export function CreatePolicyOtpEmailSectionForm({
form, form: parentForm,
emailEnabled emailEnabled
}: CreatePolicyOtpEmailSectionFormProps) { }: CreatePolicyOtpEmailSectionFormProps) {
const t = useTranslations(); const t = useTranslations();
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
const [whitelistEnabled, setWhitelistEnabled] = useState(false);
const [activeEmailTagIndex, setActiveEmailTagIndex] = useState< const [activeEmailTagIndex, setActiveEmailTagIndex] = useState<
number | null number | null
>(null); >(null);
const form = useForm({
resolver: zodResolver(
createPolicySchema.pick({
emailWhitelistEnabled: true,
emails: true
})
),
defaultValues: {
emailWhitelistEnabled: false,
emails: []
}
});
useEffect(() => {
const subscription = form.watch((values) => {
parentForm.setValue(
"emailWhitelistEnabled",
values.emailWhitelistEnabled as boolean
);
parentForm.setValue("emails", values.emails as [Tag, ...Tag[]]);
});
return () => subscription.unsubscribe();
}, [form, parentForm]);
const whitelistEnabled = useWatch({
control: form.control,
name: "emailWhitelistEnabled"
});
if (!isExpanded) { if (!isExpanded) {
return ( return (
<SettingsSection> <SettingsSection>
@@ -78,100 +107,107 @@ export function CreatePolicyOtpEmailSectionForm({
} }
return ( return (
<SettingsSection> <Form {...form}>
<SettingsSectionHeader> <SettingsSection>
<SettingsSectionTitle> <SettingsSectionHeader>
{t("otpEmailTitle")} <SettingsSectionTitle>
</SettingsSectionTitle> {t("otpEmailTitle")}
<SettingsSectionDescription> </SettingsSectionTitle>
{t("otpEmailTitleDescription")} <SettingsSectionDescription>
</SettingsSectionDescription> {t("otpEmailTitleDescription")}
</SettingsSectionHeader> </SettingsSectionDescription>
<SettingsSectionBody> </SettingsSectionHeader>
<SettingsSectionForm> <SettingsSectionBody>
{!emailEnabled && ( <SettingsSectionForm>
<Alert variant="neutral" className="mb-4"> {!emailEnabled && (
<InfoIcon className="h-4 w-4" /> <Alert variant="neutral" className="mb-4">
<AlertTitle className="font-semibold"> <InfoIcon className="h-4 w-4" />
{t("otpEmailSmtpRequired")} <AlertTitle className="font-semibold">
</AlertTitle> {t("otpEmailSmtpRequired")}
<AlertDescription> </AlertTitle>
{t("otpEmailSmtpRequiredDescription")} <AlertDescription>
</AlertDescription> {t("otpEmailSmtpRequiredDescription")}
</Alert> </AlertDescription>
)} </Alert>
<SwitchInput )}
id="whitelist-toggle" <SwitchInput
label={t("otpEmailWhitelist")} id="whitelist-toggle"
defaultChecked={false} label={t("otpEmailWhitelist")}
onCheckedChange={(val) => { defaultChecked={false}
setWhitelistEnabled(val); onCheckedChange={(val) => {
form.setValue("emailWhitelistEnabled", val); form.setValue("emailWhitelistEnabled", val);
}} }}
disabled={!emailEnabled} disabled={!emailEnabled}
/>
{whitelistEnabled && emailEnabled && (
<FormField
control={form.control}
name="emails"
render={({ field }) => (
<FormItem>
<FormLabel>
<InfoPopup
text={t("otpEmailWhitelistList")}
info={t(
"otpEmailWhitelistListDescription"
)}
/>
</FormLabel>
<FormControl>
{/* @ts-ignore */}
<TagInput
{...field}
activeTagIndex={activeEmailTagIndex}
size="sm"
validateTag={(tag) => {
return z
.email()
.or(
z
.string()
.regex(
/^\*@[\w.-]+\.[a-zA-Z]{2,}$/,
{
message: t(
"otpEmailErrorInvalid"
)
}
)
)
.safeParse(tag).success;
}}
setActiveTagIndex={
setActiveEmailTagIndex
}
placeholder={t("otpEmailEnter")}
tags={form.getValues().emails}
setTags={(newEmails) => {
form.setValue(
"emails",
newEmails as [Tag, ...Tag[]]
);
}}
allowDuplicates={false}
sortTags={true}
/>
</FormControl>
<FormDescription>
{t("otpEmailEnterDescription")}
</FormDescription>
</FormItem>
)}
/> />
)}
</SettingsSectionForm> {whitelistEnabled && emailEnabled && (
</SettingsSectionBody> <FormField
</SettingsSection> control={form.control}
name="emails"
render={({ field }) => (
<FormItem>
<FormLabel>
<InfoPopup
text={t("otpEmailWhitelistList")}
info={t(
"otpEmailWhitelistListDescription"
)}
/>
</FormLabel>
<FormControl>
{/* @ts-ignore */}
<TagInput
{...field}
activeTagIndex={
activeEmailTagIndex
}
size="sm"
validateTag={(tag) => {
return z
.email()
.or(
z
.string()
.regex(
/^\*@[\w.-]+\.[a-zA-Z]{2,}$/,
{
message:
t(
"otpEmailErrorInvalid"
)
}
)
)
.safeParse(tag).success;
}}
setActiveTagIndex={
setActiveEmailTagIndex
}
placeholder={t("otpEmailEnter")}
tags={form.getValues().emails}
setTags={(newEmails) => {
form.setValue(
"emails",
newEmails as [
Tag,
...Tag[]
]
);
}}
allowDuplicates={false}
sortTags={true}
/>
</FormControl>
<FormDescription>
{t("otpEmailEnterDescription")}
</FormDescription>
</FormItem>
)}
/>
)}
</SettingsSectionForm>
</SettingsSectionBody>
</SettingsSection>
</Form>
); );
} }

View File

@@ -13,7 +13,7 @@ import { useTranslations } from "next-intl";
import z from "zod"; import z from "zod";
import { type PolicyFormValues } from "."; import { createPolicySchema, type PolicyFormValues } from ".";
import { toast } from "@app/hooks/useToast"; import { toast } from "@app/hooks/useToast";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
@@ -81,8 +81,8 @@ import {
Plus Plus
} from "lucide-react"; } from "lucide-react";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { type UseFormReturn, useForm } from "react-hook-form"; import { type UseFormReturn, useForm, useWatch } from "react-hook-form";
// ─── CreatePolicyRulesSectionForm ───────────────────────────────────────────── // ─── CreatePolicyRulesSectionForm ─────────────────────────────────────────────
@@ -111,18 +111,43 @@ export type CreatePolicyRulesSectionFormProps = {
}; };
export function CreatePolicyRulesSectionForm({ export function CreatePolicyRulesSectionForm({
form, form: parentForm,
isMaxmindAvailable, isMaxmindAvailable,
isMaxmindAsnAvailable isMaxmindAsnAvailable
}: CreatePolicyRulesSectionFormProps) { }: CreatePolicyRulesSectionFormProps) {
const t = useTranslations(); const t = useTranslations();
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
const [rules, setRules] = useState<LocalRule[]>([]); const [rules, setRules] = useState<LocalRule[]>([]);
const [rulesEnabled, setRulesEnabled] = useState(false);
const [openAddRuleCountrySelect, setOpenAddRuleCountrySelect] = const [openAddRuleCountrySelect, setOpenAddRuleCountrySelect] =
useState(false); useState(false);
const [openAddRuleAsnSelect, setOpenAddRuleAsnSelect] = useState(false); const [openAddRuleAsnSelect, setOpenAddRuleAsnSelect] = useState(false);
const form = useForm({
resolver: zodResolver(
createPolicySchema.pick({
applyRules: true,
rules: true
})
),
defaultValues: {
applyRules: false,
rules: []
}
});
useEffect(() => {
const subscription = form.watch((values) => {
parentForm.setValue("applyRules", values.applyRules as boolean);
parentForm.setValue("rules", values.rules as any);
});
return () => subscription.unsubscribe();
}, [form, parentForm]);
const rulesEnabled = useWatch({
control: form.control,
name: "applyRules"
});
const addRuleForm = useForm({ const addRuleForm = useForm({
resolver: zodResolver(addRuleSchema), resolver: zodResolver(addRuleSchema),
defaultValues: { defaultValues: {
@@ -656,7 +681,6 @@ export function CreatePolicyRulesSectionForm({
label={t("rulesEnable")} label={t("rulesEnable")}
defaultChecked={false} defaultChecked={false}
onCheckedChange={(val) => { onCheckedChange={(val) => {
setRulesEnabled(val);
form.setValue("applyRules", val); form.setValue("applyRules", val);
}} }}
/> />

View File

@@ -9,9 +9,11 @@ import {
SettingsSectionTitle SettingsSectionTitle
} from "@app/components/Settings"; } from "@app/components/Settings";
import { zodResolver } from "@hookform/resolvers/zod";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
import { Tag, TagInput } from "@app/components/tags/tag-input"; import { Tag, TagInput } from "@app/components/tags/tag-input";
import { import {
Form,
FormControl, FormControl,
FormDescription, FormDescription,
FormField, FormField,
@@ -26,10 +28,10 @@ import {
SelectTrigger, SelectTrigger,
SelectValue SelectValue
} from "@app/components/ui/select"; } from "@app/components/ui/select";
import { type PolicyFormValues } from "."; import { createPolicySchema, type PolicyFormValues } from ".";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useState } from "react"; import { useEffect, useState } from "react";
import { type UseFormReturn, useWatch } from "react-hook-form"; import { type UseFormReturn, useForm, useWatch } from "react-hook-form";
// ─── CreatePolicyUsersRolesSectionForm ──────────────────────────────────────── // ─── CreatePolicyUsersRolesSectionForm ────────────────────────────────────────
@@ -41,12 +43,40 @@ export type CreatePolicyUsersRolesSectionFormProps = {
}; };
export function CreatePolicyUsersRolesSectionForm({ export function CreatePolicyUsersRolesSectionForm({
form, form: parentForm,
allRoles, allRoles,
allUsers, allUsers,
allIdps allIdps
}: CreatePolicyUsersRolesSectionFormProps) { }: CreatePolicyUsersRolesSectionFormProps) {
const t = useTranslations(); const t = useTranslations();
const form = useForm({
resolver: zodResolver(
createPolicySchema.pick({
sso: true,
skipToIdpId: true,
roles: true,
users: true
})
),
defaultValues: {
sso: true,
skipToIdpId: null,
roles: [],
users: []
}
});
useEffect(() => {
const subscription = form.watch((values) => {
parentForm.setValue("sso", values.sso as boolean);
parentForm.setValue("skipToIdpId", values.skipToIdpId as number | null);
parentForm.setValue("roles", values.roles as [Tag, ...Tag[]]);
parentForm.setValue("users", values.users as [Tag, ...Tag[]]);
});
return () => subscription.unsubscribe();
}, [form, parentForm]);
const ssoEnabled = useWatch({ control: form.control, name: "sso" }); const ssoEnabled = useWatch({ control: form.control, name: "sso" });
const selectedIdpId = useWatch({ const selectedIdpId = useWatch({
control: form.control, control: form.control,
@@ -60,165 +90,168 @@ export function CreatePolicyUsersRolesSectionForm({
>(null); >(null);
return ( return (
<SettingsSection> <Form {...form}>
<SettingsSectionHeader> <SettingsSection>
<SettingsSectionTitle> <SettingsSectionHeader>
{t("resourceUsersRoles")} <SettingsSectionTitle>
</SettingsSectionTitle> {t("resourceUsersRoles")}
<SettingsSectionDescription> </SettingsSectionTitle>
{t("resourcePolicyUsersRolesDescription")} <SettingsSectionDescription>
</SettingsSectionDescription> {t("resourcePolicyUsersRolesDescription")}
</SettingsSectionHeader> </SettingsSectionDescription>
<SettingsSectionBody> </SettingsSectionHeader>
<SettingsSectionForm> <SettingsSectionBody>
<SwitchInput <SettingsSectionForm>
id="sso-toggle" <SwitchInput
label={t("ssoUse")} id="sso-toggle"
defaultChecked={ssoEnabled} label={t("ssoUse")}
onCheckedChange={(val) => { defaultChecked={ssoEnabled}
console.log(`form.setValue("sso", ${val})`); onCheckedChange={(val) => {
form.setValue("sso", val); form.setValue("sso", val);
}} }}
/> />
{ssoEnabled && ( {ssoEnabled && (
<> <>
<FormField <FormField
control={form.control} control={form.control}
name="roles" name="roles"
render={({ field }) => ( render={({ field }) => (
<FormItem className="flex flex-col items-start"> <FormItem className="flex flex-col items-start">
<FormLabel>{t("roles")}</FormLabel> <FormLabel>{t("roles")}</FormLabel>
<FormControl> <FormControl>
<TagInput <TagInput
{...field} {...field}
activeTagIndex={ activeTagIndex={
activeRolesTagIndex activeRolesTagIndex
} }
setActiveTagIndex={ setActiveTagIndex={
setActiveRolesTagIndex setActiveRolesTagIndex
} }
placeholder={t( placeholder={t(
"accessRoleSelect2" "accessRoleSelect2"
)} )}
size="sm" size="sm"
tags={form.getValues().roles} tags={form.getValues().roles}
setTags={(newRoles) => { setTags={(newRoles) => {
form.setValue( form.setValue(
"roles", "roles",
newRoles as [ newRoles as [
Tag, Tag,
...Tag[] ...Tag[]
] ]
); );
}} }}
enableAutocomplete={true} enableAutocomplete={true}
autocompleteOptions={allRoles} autocompleteOptions={allRoles}
allowDuplicates={false} allowDuplicates={false}
restrictTagsToAutocompleteOptions={ restrictTagsToAutocompleteOptions={
true true
} }
sortTags={true} sortTags={true}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
<FormDescription> <FormDescription>
{t("resourceRoleDescription")} {t("resourceRoleDescription")}
</FormDescription> </FormDescription>
</FormItem> </FormItem>
)} )}
/> />
<FormField <FormField
control={form.control} control={form.control}
name="users" name="users"
render={({ field }) => ( render={({ field }) => (
<FormItem className="flex flex-col items-start"> <FormItem className="flex flex-col items-start">
<FormLabel>{t("users")}</FormLabel> <FormLabel>{t("users")}</FormLabel>
<FormControl> <FormControl>
<TagInput <TagInput
{...field} {...field}
activeTagIndex={ activeTagIndex={
activeUsersTagIndex activeUsersTagIndex
} }
setActiveTagIndex={ setActiveTagIndex={
setActiveUsersTagIndex setActiveUsersTagIndex
} }
placeholder={t( placeholder={t(
"accessUserSelect" "accessUserSelect"
)} )}
size="sm" size="sm"
tags={form.getValues().users} tags={form.getValues().users}
setTags={(newUsers) => { setTags={(newUsers) => {
form.setValue( form.setValue(
"users", "users",
newUsers as [ newUsers as [
Tag, Tag,
...Tag[] ...Tag[]
] ]
); );
}} }}
enableAutocomplete={true} enableAutocomplete={true}
autocompleteOptions={allUsers} autocompleteOptions={allUsers}
allowDuplicates={false} allowDuplicates={false}
restrictTagsToAutocompleteOptions={ restrictTagsToAutocompleteOptions={
true true
} }
sortTags={true} sortTags={true}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
)} )}
/> />
</> </>
)} )}
{ssoEnabled && allIdps.length > 0 && ( {ssoEnabled && allIdps.length > 0 && (
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium"> <label className="text-sm font-medium">
{t("defaultIdentityProvider")} {t("defaultIdentityProvider")}
</label> </label>
<Select <Select
onValueChange={(value) => { onValueChange={(value) => {
if (value === "none") { if (value === "none") {
form.setValue("skipToIdpId", null); form.setValue("skipToIdpId", null);
} else { } else {
const id = parseInt(value); const id = parseInt(value);
form.setValue("skipToIdpId", id); form.setValue("skipToIdpId", id);
}
}}
value={
selectedIdpId
? selectedIdpId.toString()
: "none"
} }
}} >
value={ <SelectTrigger className="w-full mt-1">
selectedIdpId <SelectValue
? selectedIdpId.toString() placeholder={t(
: "none" "selectIdpPlaceholder"
} )}
> />
<SelectTrigger className="w-full mt-1"> </SelectTrigger>
<SelectValue <SelectContent>
placeholder={t("selectIdpPlaceholder")} <SelectItem value="none">
/> {t("none")}
</SelectTrigger>
<SelectContent>
<SelectItem value="none">
{t("none")}
</SelectItem>
{allIdps.map((idp) => (
<SelectItem
key={idp.id}
value={idp.id.toString()}
>
{idp.text}
</SelectItem> </SelectItem>
))} {allIdps.map((idp) => (
</SelectContent> <SelectItem
</Select> key={idp.id}
<p className="text-sm text-muted-foreground"> value={idp.id.toString()}
{t("defaultIdentityProviderDescription")} >
</p> {idp.text}
</div> </SelectItem>
)} ))}
</SettingsSectionForm> </SelectContent>
</SettingsSectionBody> </Select>
</SettingsSection> <p className="text-sm text-muted-foreground">
{t("defaultIdentityProviderDescription")}
</p>
</div>
)}
</SettingsSectionForm>
</SettingsSectionBody>
</SettingsSection>
</Form>
); );
} }