feat: 조직도 소속원 폼 작업

This commit is contained in:
2025-04-22 20:13:12 +09:00
parent 086a81aa4b
commit 14bb8e9e60
7 changed files with 42 additions and 31 deletions
@@ -2,7 +2,9 @@ export { UserOrganizationApi } from "./api/user-organization-service";
export {
userOrganizationFormSchema,
type TreeUserOrganization,
type TreeUser,
type UserOrganizationFormData,
type UserOrganizationPayloadData,
type User,
type SearchUser,
} from "./model/user-organization-interface";
@@ -53,21 +53,24 @@ export interface TreeUserOrganization {
children: TreeUserOrganization[];
}
export const userOrganizationPayloadSchema = z.object({
mode: z.string(),
ognzSn: z.number(),
userUnqId: z.string(),
jbpsSeCd: z.string(),
jbgdSeCd: z.string(),
sortSeq: z.number(),
});
export const userOrganizationFormSchema = z.object({
userOrganization: z.array(
z.object({
mode: z.string(),
ognzSn: z.number(),
userUnqId: z.string(),
jbpsSeCd: z.string(),
jbgdSeCd: z.string(),
sortSeq: z.number(),
}),
),
userOrganization: z.array(userOrganizationPayloadSchema),
});
export type UserOrganizationList = PageableList<User>;
export type SearchUserList = PageableList<SearchUser>;
export type UserOrganizationPayloadData = z.infer<
typeof userOrganizationPayloadSchema
>;
export type UserOrganizationFormData = z.infer<
typeof userOrganizationFormSchema
>;
+11 -8
View File
@@ -1,5 +1,8 @@
import type { DropOptions, NodeModel } from "@minoru/react-dnd-treeview";
import type { UserOrganization, User } from "@/entities/user-organization";
import type {
TreeUserOrganization,
TreeUser,
} from "@/entities/user-organization";
import type { TreeMenu, TreeNode } from "../model/menu-interface";
export const generateMenuTreeData = (
@@ -108,11 +111,11 @@ export const handleNodeTextChange =
};
export const generateUserOrganizationTreeData = (
organizations: UserOrganization[],
): NodeModel<UserOrganization | User>[] => {
return organizations.reduce<NodeModel<UserOrganization | User>[]>(
organizations: TreeUserOrganization[],
): NodeModel<TreeUserOrganization | TreeUser>[] => {
return organizations.reduce<NodeModel<TreeUserOrganization | TreeUser>[]>(
(acc, org) => {
const orgNode: NodeModel<UserOrganization> = {
const orgNode: NodeModel<TreeUserOrganization> = {
id: org.ognzSn,
parent: org.upOgnzSn ?? 0,
text: org.ognzNm,
@@ -145,9 +148,9 @@ export const generateUserOrganizationTreeData = (
};
export const filterUserOrganizationTreeDataByKeyword = (
treeData: NodeModel<UserOrganization | User>[],
treeData: NodeModel<TreeUserOrganization | TreeUser>[],
keyword: string,
): NodeModel<UserOrganization | User>[] => {
): NodeModel<TreeUserOrganization | TreeUser>[] => {
return Array.from(
treeData.reduce((matchedNodes, node) => {
if (!node.text.includes(keyword)) return matchedNodes;
@@ -163,6 +166,6 @@ export const filterUserOrganizationTreeDataByKeyword = (
}
return matchedNodes;
}, new Set<NodeModel<UserOrganization | User>>()),
}, new Set<NodeModel<TreeUserOrganization | TreeUser>>()),
);
};
@@ -21,8 +21,8 @@ import {
import { cn } from "@common/components/lib";
import {
UserOrganizationApi,
type User,
type TreeUserOrganization,
type TreeUser,
} from "@/entities/user-organization";
import { ENDPOINT } from "@/shared/config";
import {
@@ -30,10 +30,10 @@ import {
generateUserOrganizationTreeData,
} from "../lib/utils";
type TreeModel = TreeUserOrganization | User;
type TreeModel = TreeUserOrganization | TreeUser;
interface OrganizationSearchDialogProps {
handleUserSelect: (user: User) => void;
handleUserSelect: (user: TreeUser) => void;
}
function OrganizationSearchDialog({
@@ -53,7 +53,7 @@ function OrganizationSearchDialog({
const handleSelectNode = (node: NodeModel<TreeModel>) => {
setSelectedNode(node);
handleUserSelect(node.data as User);
handleUserSelect(node.data as TreeUser);
};
useEffect(() => {
+2 -2
View File
@@ -15,7 +15,7 @@ import {
} from "@common/components";
import type { BoardPopup } from "@/entities/board";
import type { Contents } from "@/entities/content";
import type { User } from "@/entities/user-organization";
import type { TreeUser } from "@/entities/user-organization";
import { FormItem, FormControl, FormField } from "@/shared/ui/form";
import type { MenuFormData, MenuType } from "../model/menu-interface";
import { OrganizationSearchDialog } from "./organization-search-dialog";
@@ -37,7 +37,7 @@ function TypeMenuForm({ form, menuType }: TypeMenuFormProps) {
form.setValue("menuLnkgSnNm", content.contsTtl);
};
const handleUserSelect = (user: User) => {
const handleUserSelect = (user: TreeUser) => {
form.setValue("menuPicUserUnqId", user.userUnqId);
form.setValue("menuPicUserUnqIdNm", user.userNm);
};
@@ -227,7 +227,9 @@ function OrganizationPage() {
handleUpdate={updateOrganization}
handleDelete={deleteOrganization}
/>
<UserOrganizationSection ognzSn={selectedOrganization?.ognzSn} />
{selectedOrganization?.ognzSn && (
<UserOrganizationSection ognzSn={selectedOrganization.ognzSn} />
)}
</div>
</div>
);
@@ -31,7 +31,7 @@ type UserOrganizationSectionProps = {
function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
const [userList, setUserList] = useState<User[]>([]);
const { data } = useQuery({
const { data: userOrganizationList } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.USER_ORGANIZATION, ognzSn],
queryFn: () =>
UserOrganizationApi.getUserOrganizationList({ ognzSn: ognzSn! }),
@@ -53,7 +53,7 @@ function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
resolver: zodResolver(userOrganizationFormSchema),
values: {
userOrganization: [
...(data?.content ?? []).map((user) => ({
...userList.map((user) => ({
mode: user.mode,
ognzSn: user.ognzSn,
userUnqId: user.userUnqId,
@@ -64,14 +64,13 @@ function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
],
},
});
const { append } = useFieldArray({
control: form.control,
name: "userOrganization",
});
const table = useReactTable({
data: data?.content ?? [],
data: userList,
columns: createColumns(
form,
(props) => <CodeSelect codeData={jobPositionCodes} {...props} />,
@@ -109,8 +108,9 @@ function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
};
useEffect(() => {
if (data?.content) setUserList(data.content);
}, [data]);
if (userOrganizationList?.content)
setUserList(userOrganizationList.content);
}, [userOrganizationList]);
return (
<div className={cn("card card-border", !ognzSn && "hidden")}>
@@ -134,6 +134,7 @@ function UserOrganizationSection({ ognzSn }: UserOrganizationSectionProps) {
type CodeSelectProps = React.ComponentPropsWithoutRef<typeof Select> & {
codeData?: ICode[];
};
const CodeSelect = ({ codeData, ...props }: CodeSelectProps) => {
if (!codeData) return null;