feat: 그룹 관리 > 그룹 수정 작업

This commit is contained in:
2025-06-18 14:42:56 +09:00
parent de67befb6c
commit 1309767de9
7 changed files with 66 additions and 40 deletions
+1 -5
View File
@@ -17,7 +17,6 @@ type SiteSelectProps = {
} & React.ComponentPropsWithoutRef<typeof Select>;
function SiteSelect({
defaultValue,
placeholder = "선택",
enabledAllSite,
className,
@@ -34,13 +33,10 @@ function SiteSelect({
},
});
const defaultValueText =
sites?.find((item) => item.siteId === defaultValue)?.siteNm ?? placeholder;
return (
<Select {...props}>
<SelectTrigger className={cn("w-[12rem]", className)}>
<SelectValue placeholder={defaultValueText} />
<SelectValue placeholder={placeholder} />
</SelectTrigger>
<SelectContent>
{sites?.map((item) => (
@@ -4,7 +4,7 @@ import type {
GroupService,
GroupSearchParams,
GroupList,
GroupDetailResponse,
GroupResponseDto,
GroupFormData,
} from "../model/groups-interface";
@@ -19,16 +19,16 @@ export class GroupsApiService implements GroupService {
}
// 그룹 단건 조회
public async findById(groupId: string): Promise<GroupDetailResponse> {
const response = await client.get<GroupDetailResponse>(
public async findGroupById(groupId: string): Promise<GroupResponseDto> {
const response = await client.get<GroupResponseDto>(
`${ENDPOINT.CMS_SERVICE.GROUPS}/${groupId}`,
);
return response.data;
}
// 그룹 저장
public async saveGroup(data: GroupFormData): Promise<GroupDetailResponse> {
const response = await client.post<GroupDetailResponse>(
public async saveGroup(data: GroupFormData): Promise<GroupResponseDto> {
const response = await client.post<GroupResponseDto>(
`${ENDPOINT.CMS_SERVICE.GROUPS}`,
data,
);
@@ -39,8 +39,8 @@ export class GroupsApiService implements GroupService {
public async updateGroup(
groupId: string,
data: GroupFormData,
): Promise<GroupDetailResponse> {
const response = await client.put<GroupDetailResponse>(
): Promise<GroupResponseDto> {
const response = await client.put<GroupResponseDto>(
`${ENDPOINT.CMS_SERVICE.GROUPS}/${groupId}`,
data,
);
@@ -34,17 +34,20 @@ export interface GroupListResponseDto {
}
// 그룹 상세 응답 인터페이스
export interface GroupDetailResponse {
grpSn: number;
grpNm: string;
grpExpln: string;
useYn: string;
export interface GroupResponseDto {
groupId: string;
groupNm: string;
groupSeCd: string;
groupSeNm: string;
groupExpln: string;
delYn: string;
regDt: string;
rgtr: string;
mdfcnDt: string;
mdfr: string;
rgtrNm: string;
mdfrNm: string;
authrtId: string;
siteId: string;
mngrYn: string;
}
// 그룹 저장 데이터 스키마
@@ -68,16 +71,16 @@ export interface GroupService {
findPageGroup: (params: GroupSearchParams) => Promise<GroupList>;
// 그룹 단건 조회
findById: (groupId: string) => Promise<GroupDetailResponse>;
findGroupById: (groupId: string) => Promise<GroupResponseDto>;
// 그룹 저장
saveGroup: (data: GroupFormData) => Promise<GroupDetailResponse>;
saveGroup: (data: GroupFormData) => Promise<GroupResponseDto>;
// 그룹 수정
updateGroup: (
groupId: string,
data: GroupFormData,
) => Promise<GroupDetailResponse>;
) => Promise<GroupResponseDto>;
// 그룹 삭제
deleteGroup: (groupId: string) => Promise<boolean>;
@@ -1,6 +1,8 @@
import { type ColumnDef } from "@tanstack/react-table";
import { Button } from "@common/components";
import { type GroupListResponseDto } from "./groups-interface";
import { MenuAuthorityDialog } from "../ui/menu-authority-dialog";
import { GroupsDialog } from "../ui/groups-dialog";
export const columns: ColumnDef<GroupListResponseDto>[] = [
{
@@ -19,8 +21,16 @@ export const columns: ColumnDef<GroupListResponseDto>[] = [
id: "actions",
header: "관리",
cell: ({ row }) => (
<div className="flex justify-center gap-2">
<div
onClick={(e) => e.stopPropagation()}
className="flex justify-center gap-2"
>
<MenuAuthorityDialog groupId={row.original.groupId} />
<GroupsDialog groupId={row.original.groupId}>
<Button size="sm" color="white">
수정
</Button>
</GroupsDialog>
</div>
),
},
+25 -9
View File
@@ -4,6 +4,7 @@ import { memo, useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { useQuery } from "@tanstack/react-query";
import {
Button,
Dialog,
@@ -15,6 +16,7 @@ import {
DialogClose,
} from "@common/components";
import { Form } from "@/shared/ui/form";
import { ENDPOINT } from "@/shared/config";
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
import { GroupForm } from "./group-form";
import { GroupsApi } from "../api/groups-service";
@@ -22,21 +24,23 @@ import { groupFormSchema, type GroupFormData } from "../model/groups-interface";
type GroupsDialogProps = {
groupId?: string;
children: React.ReactNode;
onSuccess?: () => void;
};
const GroupsDialog = memo(
({ groupId, onSuccess, ...props }: GroupsDialogProps) => {
({ groupId, children, onSuccess, ...props }: GroupsDialogProps) => {
const isRegistration = !groupId;
const { confirm } = useConfirm();
const alert = useAlertStore((state) => state.setMessage);
const [open, setOpen] = useState(false);
const form = useForm<GroupFormData>({
resolver: zodResolver(groupFormSchema),
defaultValues: {
mngrYn: "N",
},
const { data: group } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.GROUPS, groupId],
queryFn: () => GroupsApi.findGroupById(groupId!),
enabled: !!groupId,
});
const { mutateAsync: createGroup } = useMutationWrapper({
@@ -60,6 +64,20 @@ const GroupsDialog = memo(
},
});
const form = useForm<GroupFormData>({
resolver: zodResolver(groupFormSchema),
values: {
groupId: group?.groupId ?? "",
groupNm: group?.groupNm ?? "",
groupSeCd: group?.groupSeCd ?? "",
groupExpln: group?.groupExpln ?? "",
delYn: group?.delYn ?? "",
authrtId: group?.authrtId ?? "",
siteId: group?.siteId ?? "",
mngrYn: group?.mngrYn ?? "",
},
});
const onSubmit =
(callback: (data: GroupFormData) => void) =>
async (data: GroupFormData) => {
@@ -72,9 +90,7 @@ const GroupsDialog = memo(
return (
<Dialog open={open} onOpenChange={setOpen} {...props}>
<DialogTrigger asChild>
<Button>등록</Button>
</DialogTrigger>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
<DialogHeader>
<DialogTitle>
@@ -7,7 +7,7 @@ import {
useReactTable,
type PaginationState,
} from "@tanstack/react-table";
import { DataTable } from "@common/components";
import { Button, DataTable } from "@common/components";
import { ENDPOINT } from "@/shared/config";
import { columns } from "../model/groups-table-columns";
import { GroupsApi } from "../api/groups-service";
@@ -55,7 +55,9 @@ function GroupsSection({ handleSelectedGroup }: GroupsSectionProps) {
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">그룹 목록</h3>
<GroupsDialog onSuccess={refetch} />
<GroupsDialog onSuccess={refetch}>
<Button>등록</Button>
</GroupsDialog>
</div>
<div className="card !m-4 h-[calc(100vh-25.5rem)] overflow-auto !p-0">
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
+5 -6
View File
@@ -17,20 +17,19 @@ function RoleSelect({ mngrYn = "N", ...props }: RoleSelectProps) {
const { data: roles } = useQuery({
queryKey: [ENDPOINT.USER_SERVICE.ROLES],
queryFn: () => RoleApi.getRoles(),
select: (data) => {
return data.content.filter((role) => role.mngrYn === mngrYn);
},
});
const options = roles?.content.filter((role) => role.mngrYn === mngrYn);
return (
<Select {...props}>
<SelectTrigger className="w-[24rem]">
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{roles?.map((role) => (
<SelectItem key={role.roleId} value={role.roleId}>
{role.roleName}
{options?.map((item) => (
<SelectItem key={item.roleId} value={item.roleId}>
{item.roleName}
</SelectItem>
))}
</SelectContent>