From 46a96a04fb201f682dc6cdba1c4c307bc5cf86c0 Mon Sep 17 00:00:00 2001 From: bicochan Date: Thu, 19 Jun 2025 12:02:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/admin/ui/add-admin-dialog.tsx | 253 ++++++++++++++++++ apps/cs/src/pages/admin/ui/admin-page.tsx | 10 +- ...al-user-dialog.tsx => add-user-dialog.tsx} | 4 +- .../pages/groups/ui/group-users-section.tsx | 4 +- ...columns.tsx => add-user-table-columns.tsx} | 0 ...al-user-dialog.tsx => add-user-dialog.tsx} | 11 +- .../ui/user-organization-section.tsx | 4 +- 7 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 apps/cs/src/pages/admin/ui/add-admin-dialog.tsx rename apps/cs/src/pages/groups/ui/{additional-user-dialog.tsx => add-user-dialog.tsx} (97%) rename apps/cs/src/pages/organization/model/{additional-user-table-columns.tsx => add-user-table-columns.tsx} (100%) rename apps/cs/src/pages/organization/ui/{additional-user-dialog.tsx => add-user-dialog.tsx} (93%) diff --git a/apps/cs/src/pages/admin/ui/add-admin-dialog.tsx b/apps/cs/src/pages/admin/ui/add-admin-dialog.tsx new file mode 100644 index 000000000..1723f39f0 --- /dev/null +++ b/apps/cs/src/pages/admin/ui/add-admin-dialog.tsx @@ -0,0 +1,253 @@ +"use client"; + +import { useState } from "react"; +import { + keepPreviousData, + useQuery, + useQueryClient, +} from "@tanstack/react-query"; +import { + getCoreRowModel, + type PaginationState, + type RowSelectionState, + type ColumnDef, +} from "@tanstack/react-table"; +import { + Button, + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, + DialogFooter, + Input, + Checkbox, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + Label, +} from "@common/components"; +import { + UserApi, + type UserListResponse, + type UserSearchParams, +} from "@/entities/user"; +import { GroupApi } from "@/entities/group"; +import { GroupUsersApi } from "@/entities/group-user"; +import { ENDPOINT } from "@/shared/config"; +import { useAlertStore, useDataTable } from "@/shared/lib"; + +function AddAdminDialog() { + const queryClient = useQueryClient(); + const alert = useAlertStore((state) => state.setMessage); + + const [open, setOpen] = useState(false); + const [userSearchQuery, setUserSearchQuery] = useState({ + keywordType: "", + keyword: "", + }); + const [selectedGroupId, setSelectedGroupId] = useState(""); + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: 10, + }); + const [rowSelection, setRowSelection] = useState({}); + + const { data: groupOptions } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.GROUPS], + queryFn: () => + GroupApi.findPageGroup({ + delYn: "N", + mngrYn: "Y", + page: 0, + size: 99, + }), + select: (data) => + data.content.map((item) => ({ + groupId: item.groupId, + groupNm: item.groupNm, + })), + enabled: open, + }); + + const query = useQuery({ + queryKey: [ENDPOINT.USER_SERVICE.USERS, pagination, "normal-user"], + queryFn: () => + UserApi.findPageUser({ + ...userSearchQuery, + page: pagination.pageIndex, + size: pagination.pageSize, + }), + enabled: open, + placeholderData: keepPreviousData, + }); + + const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="전체 선택" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="행 선택" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "userId", + header: "사용자ID", + }, + { + accessorKey: "userName", + header: "이름", + }, + { + accessorKey: "ogdpSeNm", + header: "소속", + }, + { + accessorKey: "mphn", + header: "연락처", + }, + ]; + + const { tableComponent } = useDataTable({ + query, + tableOptions: { + columns: columns, + state: { pagination, rowSelection }, + manualPagination: true, + enableRowSelection: true, + enableMultiRowSelection: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + onRowSelectionChange: setRowSelection, + getRowId: (row) => row.userUnqId, + }, + dataTableOptions: { + viewPagination: true, + }, + }); + + const handleAddAdmins = async () => { + const selectedRows = Object.keys(rowSelection); + if (selectedRows.length === 0 || !selectedGroupId) { + alert("그룹과 사용자를 선택해주세요."); + return; + } + + try { + const usersToAdd = selectedRows.map((userUnqId) => ({ + mode: "C", + groupId: selectedGroupId, + userUnqId, + })); + + await GroupUsersApi.saveGroupUser(usersToAdd); + + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.USER_SERVICE.USERS], + }); + alert("관리자 추가를 완료했습니다.", () => { + setOpen(false); + setRowSelection({}); + setSelectedGroupId(""); + }); + } catch (error) { + console.error(error); + } + }; + + const handleSearch = (e: React.FormEvent) => { + e.preventDefault(); + e.stopPropagation(); + setPagination({ pageIndex: 0, pageSize: 10 }); + query.refetch(); + }; + + return ( + + + + + + + 관리자 추가 + +
+ + + setUserSearchQuery({ + ...userSearchQuery, + keyword: e.target.value, + }) + } + className="!text-[1.3rem]" + placeholder="검색어 입력" + /> + +
+ {tableComponent} +
+
+ + +
+ + + + +
+
+ ); +} + +export { AddAdminDialog }; diff --git a/apps/cs/src/pages/admin/ui/admin-page.tsx b/apps/cs/src/pages/admin/ui/admin-page.tsx index 8cf329c78..6507e98fa 100644 --- a/apps/cs/src/pages/admin/ui/admin-page.tsx +++ b/apps/cs/src/pages/admin/ui/admin-page.tsx @@ -13,11 +13,12 @@ import { SelectTrigger, SelectValue, } from "@common/components"; +import { GroupApi } from "@/entities/group"; import { UserApi, type UserSearchParams } from "@/entities/user"; import { ENDPOINT } from "@/shared/config"; import { useDataTable } from "@/shared/lib"; import { columns } from "../model/table-columns"; -import { GroupApi } from "@/entities/group"; +import { AddAdminDialog } from "./add-admin-dialog"; function AdminPage() { const [adminQuery, setAdminQuery] = useState({ @@ -134,7 +135,12 @@ function AdminPage() {
-

관리자 목록

+

+ 관리자 목록(총 {query.data?.totalElements}명) +

+
+ +
{tableComponent}
diff --git a/apps/cs/src/pages/groups/ui/additional-user-dialog.tsx b/apps/cs/src/pages/groups/ui/add-user-dialog.tsx similarity index 97% rename from apps/cs/src/pages/groups/ui/additional-user-dialog.tsx rename to apps/cs/src/pages/groups/ui/add-user-dialog.tsx index 6a415e19e..aafba70db 100644 --- a/apps/cs/src/pages/groups/ui/additional-user-dialog.tsx +++ b/apps/cs/src/pages/groups/ui/add-user-dialog.tsx @@ -36,7 +36,7 @@ type AdditionalUserDialogProps = { groupId?: string; }; -function AdditionalUserDialog({ groupId }: AdditionalUserDialogProps) { +function AddUserDialog({ groupId }: AdditionalUserDialogProps) { const queryClient = useQueryClient(); const alert = useAlertStore((state) => state.setMessage); @@ -188,4 +188,4 @@ function AdditionalUserDialog({ groupId }: AdditionalUserDialogProps) { ); } -export { AdditionalUserDialog }; +export { AddUserDialog }; diff --git a/apps/cs/src/pages/groups/ui/group-users-section.tsx b/apps/cs/src/pages/groups/ui/group-users-section.tsx index cadbb6135..b74ce4db9 100644 --- a/apps/cs/src/pages/groups/ui/group-users-section.tsx +++ b/apps/cs/src/pages/groups/ui/group-users-section.tsx @@ -16,7 +16,7 @@ import { GroupUsersApi } from "@/entities/group-user"; import { ENDPOINT } from "@/shared/config"; import { useAlertStore, useDataTable } from "@/shared/lib"; import { columns } from "../model/group-users-table-columns"; -import { AdditionalUserDialog } from "./additional-user-dialog"; +import { AddUserDialog } from "./add-user-dialog"; type GroupUsersSectionProps = { groupId?: string; @@ -95,7 +95,7 @@ function GroupUsersSection({ groupId }: GroupUsersSectionProps) {

그룹 사용자 목록

- +