275 lines
7.3 KiB
TypeScript
275 lines
7.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, 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";
|
|
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
|
|
|
function AddAdminDialog() {
|
|
const queryClient = useQueryClient();
|
|
const alert = useAlertStore((state) => state.setMessage);
|
|
const { confirm } = useConfirm();
|
|
|
|
const [open, setOpen] = useState(false);
|
|
const [userSearchQuery, setUserSearchQuery] = useState<UserSearchParams>({
|
|
keywordType: "userName",
|
|
keyword: "",
|
|
});
|
|
const [selectedGroupId, setSelectedGroupId] = useState("");
|
|
const [pagination, setPagination] = useState<PaginationState>({
|
|
pageIndex: 0,
|
|
pageSize: 10,
|
|
});
|
|
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
|
|
|
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, "findPageUser", pagination],
|
|
queryFn: () =>
|
|
UserApi.findPageUser({
|
|
...userSearchQuery,
|
|
page: pagination.pageIndex,
|
|
size: pagination.pageSize,
|
|
}),
|
|
enabled: open,
|
|
placeholderData: keepPreviousData,
|
|
});
|
|
|
|
const columns: ColumnDef<UserListResponse>[] = [
|
|
{
|
|
id: "select",
|
|
header: ({ table }) => (
|
|
<Checkbox
|
|
checked={
|
|
table.getIsAllPageRowsSelected() ||
|
|
(table.getIsSomePageRowsSelected() && "indeterminate")
|
|
}
|
|
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
|
aria-label="전체 선택"
|
|
/>
|
|
),
|
|
cell: ({ row }) => (
|
|
<Checkbox
|
|
checked={row.getIsSelected()}
|
|
onCheckedChange={(value) => 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 (!(await confirm("관리자를 추가하시겠습니까?"))) {
|
|
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<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
setPagination({ pageIndex: 0, pageSize: 10 });
|
|
query.refetch();
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!open) {
|
|
setRowSelection({});
|
|
setSelectedGroupId("");
|
|
setUserSearchQuery({
|
|
keywordType: "userName",
|
|
keyword: "",
|
|
});
|
|
setPagination({ pageIndex: 0, pageSize: 10 });
|
|
queryClient.removeQueries({
|
|
queryKey: [ENDPOINT.USER_SERVICE.USERS, "findPageUser"],
|
|
});
|
|
}
|
|
}, [open]);
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogTrigger asChild>
|
|
<Button>관리자등록</Button>
|
|
</DialogTrigger>
|
|
<DialogContent className="max-w-4xl">
|
|
<DialogHeader>
|
|
<DialogTitle>관리자 등록</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
<form onSubmit={handleSearch} className="flex items-center gap-2">
|
|
<Select
|
|
value={userSearchQuery.keywordType}
|
|
onValueChange={(value) =>
|
|
setUserSearchQuery({ ...userSearchQuery, keywordType: value })
|
|
}
|
|
>
|
|
<SelectTrigger className="h-[3.2rem] w-[12rem] !text-[1.3rem]">
|
|
<SelectValue placeholder="선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="userName">이름</SelectItem>
|
|
<SelectItem value="userId">아이디</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<Input
|
|
value={userSearchQuery.keyword}
|
|
onChange={(e) =>
|
|
setUserSearchQuery({
|
|
...userSearchQuery,
|
|
keyword: e.target.value,
|
|
})
|
|
}
|
|
className="!text-[1.3rem]"
|
|
placeholder="검색어 입력"
|
|
/>
|
|
<Button type="submit">검색</Button>
|
|
</form>
|
|
<hr className="my-4" />
|
|
<Label className="text-label">1. 사용자 선택</Label>
|
|
{tableComponent}
|
|
<hr className="my-4" />
|
|
<div className="mb-4 flex flex-col gap-4">
|
|
<Label className="mr-2 text-label">2. 그룹 선택</Label>
|
|
<Select onValueChange={(value) => setSelectedGroupId(value)}>
|
|
<SelectTrigger className="h-[3.2rem] w-[24rem] !text-[1.3rem]">
|
|
<SelectValue placeholder="그룹 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{groupOptions?.map((item) => (
|
|
<SelectItem key={item.groupId} value={item.groupId}>
|
|
{item.groupNm}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<DialogFooter>
|
|
<Button color="white" onClick={() => setOpen(false)}>
|
|
취소
|
|
</Button>
|
|
<Button
|
|
onClick={handleAddAdmins}
|
|
disabled={
|
|
Object.keys(rowSelection).length === 0 || !selectedGroupId
|
|
}
|
|
>
|
|
등록
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|
|
|
|
export { AddAdminDialog };
|