forked from baron/baron-sso
feat: update worksmobile sync and restore planning
This commit is contained in:
@@ -95,6 +95,7 @@ import { resolvePersonalTenant } from "./utils/personalTenant";
|
||||
type UserFormValues = Omit<UserUpdateRequest, "metadata"> & {
|
||||
email: string;
|
||||
metadata: Record<string, unknown> & {
|
||||
employee_id?: string;
|
||||
sub_email?: string | string[];
|
||||
};
|
||||
};
|
||||
@@ -130,6 +131,29 @@ function cleanMetadataValue(value: unknown): unknown {
|
||||
return value;
|
||||
}
|
||||
|
||||
function normalizeEmployeeIDMetadataValue(value: unknown) {
|
||||
if (typeof value === "string" || typeof value === "number") {
|
||||
return String(value).trim();
|
||||
}
|
||||
if (!isMetadataRecord(value)) {
|
||||
return "";
|
||||
}
|
||||
const entries = Object.entries(value)
|
||||
.map(([key, fieldValue]) => ({
|
||||
index: Number(key),
|
||||
value: typeof fieldValue === "string" ? fieldValue : "",
|
||||
}))
|
||||
.filter((entry) => Number.isInteger(entry.index) && entry.value.length > 0)
|
||||
.sort((a, b) => a.index - b.index);
|
||||
if (entries.length === 0) {
|
||||
return "";
|
||||
}
|
||||
return entries
|
||||
.map((entry) => entry.value)
|
||||
.join("")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function normalizeSubEmails(value: unknown): string[] {
|
||||
if (Array.isArray(value)) {
|
||||
return value
|
||||
@@ -699,6 +723,9 @@ function UserDetailPage() {
|
||||
string,
|
||||
Record<string, string | number | boolean>
|
||||
>) || {}),
|
||||
employee_id: normalizeEmployeeIDMetadataValue(
|
||||
user.metadata?.employee_id,
|
||||
),
|
||||
sub_email: Array.isArray(user.metadata?.sub_email)
|
||||
? user.metadata.sub_email
|
||||
: typeof user.metadata?.sub_email === "string"
|
||||
@@ -837,15 +864,22 @@ function UserDetailPage() {
|
||||
...safeMetadata,
|
||||
...(subEmail.length > 0 ? { sub_email: subEmail } : { sub_email: [] }),
|
||||
};
|
||||
const employeeID = String(data.metadata?.employee_id ?? "").trim();
|
||||
if (employeeID) {
|
||||
metadata.employee_id = employeeID;
|
||||
} else {
|
||||
delete metadata.employee_id;
|
||||
}
|
||||
|
||||
const payload: UserUpdateRequest = {
|
||||
...data,
|
||||
metadata,
|
||||
};
|
||||
// email cannot be updated directly via this API in current backend implementation,
|
||||
// so we delete it from payload if it spread
|
||||
// @ts-expect-error
|
||||
delete payload.email;
|
||||
if (profileRole !== "super_admin") {
|
||||
delete payload.email;
|
||||
} else {
|
||||
payload.email = data.email.trim();
|
||||
}
|
||||
payload.role = undefined;
|
||||
|
||||
if (userCategory === "personal") {
|
||||
@@ -1107,9 +1141,19 @@ function UserDetailPage() {
|
||||
</Label>
|
||||
<Input
|
||||
id="email"
|
||||
value={user.email}
|
||||
disabled
|
||||
className="bg-muted/50 border-none font-medium h-11"
|
||||
type="email"
|
||||
disabled={profileRole !== "super_admin"}
|
||||
{...register("email", {
|
||||
required: t(
|
||||
"msg.admin.users.detail.email_required",
|
||||
"이메일을 입력하세요.",
|
||||
),
|
||||
})}
|
||||
className={
|
||||
profileRole === "super_admin"
|
||||
? "h-11 shadow-sm"
|
||||
: "bg-muted/50 border-none font-medium h-11"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -1146,6 +1190,37 @@ function UserDetailPage() {
|
||||
className="h-11 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label
|
||||
htmlFor="metadata_employee_id"
|
||||
className="text-xs font-bold uppercase text-muted-foreground"
|
||||
>
|
||||
사번
|
||||
</Label>
|
||||
<Input
|
||||
id="metadata_employee_id"
|
||||
maxLength={20}
|
||||
{...register("metadata.employee_id", {
|
||||
setValueAs: (value) =>
|
||||
typeof value === "string" ? value.trim() : value,
|
||||
maxLength: {
|
||||
value: 20,
|
||||
message:
|
||||
"Worksmobile 사번은 20자 이하로 입력해야 합니다.",
|
||||
},
|
||||
})}
|
||||
className="h-11 shadow-sm"
|
||||
/>
|
||||
{errors.metadata?.employee_id && (
|
||||
<p className="text-xs text-destructive">
|
||||
{String(errors.metadata.employee_id.message)}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-[10px] text-muted-foreground mt-1">
|
||||
Worksmobile employeeNumber로 전송됩니다. 1~20자만
|
||||
허용됩니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-8 md:grid-cols-2 pt-6 border-t border-dashed">
|
||||
|
||||
Reference in New Issue
Block a user