forked from baron/baron-sso
조직현황 구조변경. 총괄센터삼안 실 조직 삽입확인
This commit is contained in:
@@ -98,6 +98,7 @@ function createEmptyAppointment(): AppointmentDraft {
|
||||
tenantName: "",
|
||||
tenantSlug: "",
|
||||
isOwner: false,
|
||||
grade: "",
|
||||
jobTitle: "",
|
||||
position: "",
|
||||
};
|
||||
@@ -148,6 +149,7 @@ function UserCreatePage() {
|
||||
phone: "",
|
||||
tenantSlug: searchParams.get("tenantSlug") || "",
|
||||
department: "",
|
||||
grade: "",
|
||||
position: "",
|
||||
jobTitle: "",
|
||||
metadata: {},
|
||||
@@ -379,6 +381,7 @@ function UserCreatePage() {
|
||||
}
|
||||
payload.tenantSlug = data.tenantSlug;
|
||||
payload.department = data.department;
|
||||
payload.grade = data.grade;
|
||||
payload.position = data.position;
|
||||
payload.jobTitle = data.jobTitle;
|
||||
}
|
||||
@@ -411,6 +414,7 @@ function UserCreatePage() {
|
||||
tenantName: appointment.tenantName,
|
||||
isPrimary: appointment.isOwner,
|
||||
isOwner: appointment.isOwner,
|
||||
grade: appointment.grade,
|
||||
jobTitle: appointment.jobTitle,
|
||||
position: appointment.position,
|
||||
}));
|
||||
@@ -685,12 +689,20 @@ function UserCreatePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="position">직급</Label>
|
||||
<Label htmlFor="grade">직급</Label>
|
||||
<Input
|
||||
id="grade"
|
||||
placeholder="수석/책임/선임"
|
||||
{...register("grade")}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="position">직책</Label>
|
||||
<Input
|
||||
id="position"
|
||||
placeholder="수석/책임/선임"
|
||||
placeholder="팀장/센터장"
|
||||
{...register("position")}
|
||||
/>
|
||||
</div>
|
||||
@@ -709,9 +721,11 @@ function UserCreatePage() {
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<p className="text-sm font-medium">소속별 직급/직무</p>
|
||||
<p className="text-sm font-medium">
|
||||
소속별 직급/직책/직무
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
테넌트별 조직장 여부, 직무, 직급을 입력합니다.
|
||||
테넌트별 조직장 여부, 직급, 직책, 직무를 입력합니다.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
@@ -778,9 +792,23 @@ function UserCreatePage() {
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="grid gap-3 sm:grid-cols-2"
|
||||
className="grid gap-3 sm:grid-cols-3"
|
||||
data-testid={`appointment-position-line-${index}`}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`appointment-grade-${index}`}>
|
||||
직급
|
||||
</Label>
|
||||
<Input
|
||||
id={`appointment-grade-${index}`}
|
||||
value={appointment.grade ?? ""}
|
||||
onChange={(event) =>
|
||||
updateAppointment(index, {
|
||||
grade: event.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`appointment-job-title-${index}`}>
|
||||
직무
|
||||
@@ -797,7 +825,7 @@ function UserCreatePage() {
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor={`appointment-position-${index}`}>
|
||||
직급
|
||||
직책
|
||||
</Label>
|
||||
<Input
|
||||
id={`appointment-position-${index}`}
|
||||
|
||||
@@ -125,6 +125,7 @@ function createEmptyAppointment(): AppointmentDraft {
|
||||
tenantSlug: "",
|
||||
isPrimary: false,
|
||||
isOwner: false,
|
||||
grade: "",
|
||||
jobTitle: "",
|
||||
position: "",
|
||||
};
|
||||
@@ -379,6 +380,7 @@ function UserDetailPage() {
|
||||
status: "active",
|
||||
tenantSlug: "",
|
||||
department: "",
|
||||
grade: "",
|
||||
position: "",
|
||||
jobTitle: "",
|
||||
metadata: {},
|
||||
@@ -622,6 +624,7 @@ function UserDetailPage() {
|
||||
)?.slug ||
|
||||
"",
|
||||
department: user.department || "",
|
||||
grade: user.grade || "",
|
||||
position: user.position || "",
|
||||
jobTitle: user.jobTitle || "",
|
||||
metadata:
|
||||
@@ -671,6 +674,7 @@ function UserDetailPage() {
|
||||
isOwner:
|
||||
metadata.primaryTenantIsOwner === true &&
|
||||
tenant.id === fallbackAppointment?.id,
|
||||
grade: user.grade,
|
||||
jobTitle: user.jobTitle,
|
||||
position: user.position,
|
||||
}))
|
||||
@@ -683,6 +687,7 @@ function UserDetailPage() {
|
||||
tenantSlug: fallbackAppointment.slug,
|
||||
isPrimary: true,
|
||||
isOwner: metadata.primaryTenantIsOwner === true,
|
||||
grade: user.grade,
|
||||
jobTitle: user.jobTitle,
|
||||
position: user.position,
|
||||
},
|
||||
@@ -750,6 +755,7 @@ function UserDetailPage() {
|
||||
const tenant = await ensurePersonalTenant();
|
||||
payload.tenantSlug = tenant.slug;
|
||||
payload.department = undefined;
|
||||
payload.grade = undefined;
|
||||
payload.position = undefined;
|
||||
payload.jobTitle = undefined;
|
||||
payload.metadata = {
|
||||
@@ -771,6 +777,7 @@ function UserDetailPage() {
|
||||
tenantName: appointment.tenantName,
|
||||
isPrimary: appointment.isOwner,
|
||||
isOwner: appointment.isOwner,
|
||||
grade: appointment.grade,
|
||||
jobTitle: appointment.jobTitle,
|
||||
position: appointment.position,
|
||||
}));
|
||||
@@ -790,6 +797,7 @@ function UserDetailPage() {
|
||||
}
|
||||
|
||||
payload.department = undefined;
|
||||
payload.grade = undefined;
|
||||
payload.position = undefined;
|
||||
payload.jobTitle = undefined;
|
||||
payload.additionalAppointments = appointments;
|
||||
@@ -1142,13 +1150,13 @@ function UserDetailPage() {
|
||||
<p className="text-sm font-medium">
|
||||
{t(
|
||||
"ui.admin.users.detail.form.additional_appointments",
|
||||
"소속별 직급/직무",
|
||||
"소속별 직급/직책/직무",
|
||||
)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t(
|
||||
"msg.admin.users.detail.form.additional_appointments_help",
|
||||
"테넌트별 조직장 여부, 직무, 직급을 입력합니다.",
|
||||
"테넌트별 조직장 여부, 직급, 직책, 직무를 입력합니다.",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -1226,9 +1234,28 @@ function UserDetailPage() {
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="grid gap-3 sm:grid-cols-2"
|
||||
className="grid gap-3 sm:grid-cols-3"
|
||||
data-testid={`detail-appointment-position-line-${index}`}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<Label
|
||||
htmlFor={`detail-appointment-grade-${index}`}
|
||||
>
|
||||
{t(
|
||||
"ui.admin.users.detail.form.grade",
|
||||
"직급",
|
||||
)}
|
||||
</Label>
|
||||
<Input
|
||||
id={`detail-appointment-grade-${index}`}
|
||||
value={appointment.grade ?? ""}
|
||||
onChange={(event) =>
|
||||
updateAppointment(index, {
|
||||
grade: event.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label
|
||||
htmlFor={`detail-appointment-job-title-${index}`}
|
||||
@@ -1255,7 +1282,7 @@ function UserDetailPage() {
|
||||
>
|
||||
{t(
|
||||
"ui.admin.users.detail.form.position",
|
||||
"직급",
|
||||
"직책",
|
||||
)}
|
||||
</Label>
|
||||
<Input
|
||||
@@ -1313,12 +1340,25 @@ function UserDetailPage() {
|
||||
className="h-11 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label
|
||||
htmlFor="grade"
|
||||
className="text-xs font-bold uppercase text-muted-foreground"
|
||||
>
|
||||
{t("ui.admin.users.detail.form.grade", "직급")}
|
||||
</Label>
|
||||
<Input
|
||||
id="grade"
|
||||
{...register("grade")}
|
||||
className="h-11 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label
|
||||
htmlFor="position"
|
||||
className="text-xs font-bold uppercase text-muted-foreground"
|
||||
>
|
||||
{t("ui.admin.users.detail.form.position", "직급")}
|
||||
{t("ui.admin.users.detail.form.position", "직책")}
|
||||
</Label>
|
||||
<Input
|
||||
id="position"
|
||||
|
||||
@@ -249,9 +249,9 @@ export function UserBulkUploadModal({ onSuccess }: UserBulkUploadModalProps) {
|
||||
|
||||
const downloadTemplate = () => {
|
||||
const headers =
|
||||
"email,name,phone,role,tenant_slug,department,position,jobTitle,employee_id";
|
||||
"email,name,phone,role,tenant_slug,department,grade,position,jobTitle,employee_id";
|
||||
const example =
|
||||
"user1@example.com,홍길동,010-1234-5678,user,tenant-slug,개발팀,수석,프론트엔드,EMP001";
|
||||
"user1@example.com,홍길동,010-1234-5678,user,tenant-slug,개발팀,수석,팀장,프론트엔드,EMP001";
|
||||
const blob = new Blob([`${headers}\n${example}`], {
|
||||
type: "text/csv;charset=utf-8;",
|
||||
});
|
||||
|
||||
@@ -57,6 +57,7 @@ test@test.com,Test,baron`;
|
||||
name: "John Doe",
|
||||
phone: "+19144812222",
|
||||
department: "myteam",
|
||||
grade: "Manager",
|
||||
position: "Manager",
|
||||
jobTitle: "Sales management",
|
||||
tenantImport: {
|
||||
|
||||
@@ -79,6 +79,8 @@ export function parseUserCSV(text: string): BulkUserItem[] {
|
||||
};
|
||||
} else if (header === "department") {
|
||||
item.department = value;
|
||||
} else if (header === "grade") {
|
||||
item.grade = value;
|
||||
} else if (header === "position") {
|
||||
item.position = value;
|
||||
} else if (header === "jobtitle") {
|
||||
@@ -100,6 +102,7 @@ export function parseUserCSV(text: string): BulkUserItem[] {
|
||||
} else if (header === "usertype") {
|
||||
item.metadata.naverworks_user_type = value;
|
||||
} else if (header === "level") {
|
||||
item.grade = value;
|
||||
item.metadata.naverworks_level = value;
|
||||
} else if (header === "organization") {
|
||||
item.metadata.naverworks_organization_path = value;
|
||||
@@ -247,7 +250,7 @@ function applyNaverWorksFallbacks(
|
||||
item.phone = `${countryCode}${number}`.replace(/\s/g, "");
|
||||
}
|
||||
|
||||
if (!item.position && item.metadata.naverworks_level) {
|
||||
item.position = item.metadata.naverworks_level;
|
||||
if (!item.grade && item.metadata.naverworks_level) {
|
||||
item.grade = item.metadata.naverworks_level;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user