1
0
forked from baron/baron-sso

feat: implement enhanced user schema management with validation and admin_only fields

This commit is contained in:
2026-03-04 10:09:52 +09:00
parent 69470e8e4a
commit db88c7ab1c
4 changed files with 346 additions and 96 deletions

View File

@@ -26,8 +26,10 @@ import { t } from "../../lib/i18n";
type UserSchemaField = {
key: string;
label?: string;
type?: "text" | "number" | "boolean";
type?: "text" | "number" | "boolean" | "date";
required?: boolean;
adminOnly?: boolean;
validation?: string;
};
type UserFormValues = UserCreateRequest & { metadata: Record<string, unknown> };
@@ -85,8 +87,24 @@ function UserCreatePage() {
? (tenantDetail?.config?.userSchema as UserSchemaField[])
: [];
const registerMetadata = (key: string) =>
register(`metadata.${key}` as `metadata.${string}`);
const registerMetadata = (field: UserSchemaField) =>
register(`metadata.${field.key}` as `metadata.${string}`, {
required: field.required
? t("msg.admin.users.create.form.field_required", "{{label}}은(는) 필수입니다.", {
label: field.label || field.key,
})
: false,
pattern: field.validation
? {
value: new RegExp(field.validation),
message: t(
"msg.admin.users.create.form.field_invalid",
"{{label}} 형식이 올바르지 않습니다.",
{ label: field.label || field.key },
),
}
: undefined,
});
const mutation = useMutation({
mutationFn: createUser,
@@ -107,17 +125,16 @@ function UserCreatePage() {
},
});
const onSubmit = (data: UserCreateRequest) => {
const onSubmit = (data: UserFormValues) => {
setError(null);
setGeneratedPassword(null);
setCreatedEmail(null);
if (autoPassword) {
mutation.mutate({ ...data, password: "" });
return;
}
const payload = { ...data };
if (!data.password) {
if (autoPassword) {
payload.password = "";
} else if (!data.password) {
setError(
t(
"msg.admin.users.create.password_required",
@@ -127,7 +144,7 @@ function UserCreatePage() {
return;
}
mutation.mutate(data);
mutation.mutate(payload);
};
const onCopyPassword = async () => {
@@ -414,13 +431,37 @@ function UserCreatePage() {
<div key={field.key} className="space-y-2">
<Label htmlFor={`metadata.${field.key}`}>
{field.label}
{field.required && (
<span className="ml-1 text-destructive">*</span>
)}
{field.adminOnly && (
<span className="ml-2 text-[10px] bg-blue-500/10 text-blue-500 px-1.5 py-0.5 rounded uppercase font-bold tracking-tighter">
Admin Only
</span>
)}
</Label>
<Input
id={`metadata.${field.key}`}
type={field.type === "number" ? "number" : "text"}
{...registerMetadata(field.key)}
type={
field.type === "number"
? "number"
: field.type === "date"
? "date"
: field.type === "boolean"
? "checkbox"
: "text"
}
className={
field.type === "boolean" ? "w-auto h-auto" : ""
}
{...registerMetadata(field)}
/>
{errors.metadata?.[field.key] && (
<p className="text-xs text-destructive">
{(errors.metadata[field.key] as any).message}
</p>
)}
</div>
))}
</div>
@@ -482,4 +523,5 @@ function UserCreatePage() {
);
}
export default UserCreatePage;