refactor: 코드 페이지 리팩토링
This commit is contained in:
@@ -25,9 +25,12 @@ export class LwpoCodeApiService implements LwpoCodeService {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async LwpoCodeDetail(upCd: string, LwpoCd: string): Promise<LwpoCodeDetail> {
|
||||
public async lwpoCodeDetail(
|
||||
upCd: string,
|
||||
lwpoCd: string,
|
||||
): Promise<LwpoCodeDetail> {
|
||||
const response = await client.get<LwpoCodeDetail>(
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${LwpoCd}/up-cd/${upCd}`,
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
@@ -41,21 +44,24 @@ export class LwpoCodeApiService implements LwpoCodeService {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updateLwpoCode(upCd: string, LwpoCd: string, data: LwpoCodeFormData): Promise<void> {
|
||||
public async updateLwpoCode(
|
||||
upCd: string,
|
||||
lwpoCd: string,
|
||||
data: LwpoCodeFormData,
|
||||
): Promise<void> {
|
||||
const validatedData = LwpoCodeFormSchema.parse(data);
|
||||
const response = await client.put<void>(
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${LwpoCd}/up-cd/${upCd}`,
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deleteLwpoCode(upCd: string, LwpoCd: string): Promise<void> {
|
||||
public async deleteLwpoCode(upCd: string, lwpoCd: string): Promise<void> {
|
||||
await client.delete<void>(
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${LwpoCd}/up-cd/${upCd}`,
|
||||
`${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const lwpoCodeApi = new LwpoCodeApiService();
|
||||
export const LwpoCodeApi = new LwpoCodeApiService();
|
||||
|
||||
@@ -42,7 +42,6 @@ export class UpCodeApiService implements UpCodeService {
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const upCodeApi = new UpCodeApiService();
|
||||
export const UpCodeApi = new UpCodeApiService();
|
||||
|
||||
@@ -2,13 +2,18 @@ export { CodeApi } from "./api/code-service";
|
||||
export type { ICode } from "./model/code-interface";
|
||||
export { CodeSelect } from "./ui/code-select";
|
||||
|
||||
export { UpCodeApi } from "./api/upcode-service";
|
||||
export {
|
||||
upCodeFormSchema,
|
||||
type UpCode,
|
||||
type UpCodeFormData,
|
||||
type UpCodeParams,
|
||||
} from "./model/upcode-interface";
|
||||
|
||||
export { upCodeApi } from "./api/upcode-service";
|
||||
export type { UpCode } from "./model/upcode-interface";
|
||||
export { upCodeFormSchema, type UpCodeFormData } from "./model/upcode-interface";
|
||||
|
||||
export { lwpoCodeApi} from "./api/lwpocode-service";
|
||||
export type { LwpoCode } from "./model/lwpocode-interface";
|
||||
export { LwpoCodeFormSchema, type LwpoCodeFormData } from "./model/lwpocode-interface";
|
||||
|
||||
|
||||
export { LwpoCodeApi } from "./api/lwpocode-service";
|
||||
export {
|
||||
LwpoCodeFormSchema,
|
||||
type LwpoCode,
|
||||
type LwpoCodeFormData,
|
||||
type LwpoCodeParams,
|
||||
} from "./model/lwpocode-interface";
|
||||
|
||||
@@ -2,60 +2,67 @@ import { z } from "zod";
|
||||
import type { PageableParams, PageableList } from "@/shared/model";
|
||||
|
||||
export interface LwpoCodeParams extends PageableParams {
|
||||
upCd?: string;
|
||||
lwpoCd?: string;
|
||||
lwpoCdNm?: string;
|
||||
useYn?: string;
|
||||
upCd?: string;
|
||||
lwpoCd?: string;
|
||||
lwpoCdNm?: string;
|
||||
useYn?: string;
|
||||
}
|
||||
|
||||
|
||||
export interface LwpoCode {
|
||||
lwpoCd: string;
|
||||
upCd: string;
|
||||
lwpoCdNm: string;
|
||||
lwpoCdExpln: string;
|
||||
unit: string;
|
||||
prntLwpoCd: string;
|
||||
useYn: string;
|
||||
sortSeq: number;
|
||||
regDt: string;
|
||||
rgTr: string;
|
||||
rgTrNm: string;
|
||||
mdfcnDt: string;
|
||||
mdFr: string;
|
||||
lwpoCd: string;
|
||||
upCd: string;
|
||||
lwpoCdNm: string;
|
||||
lwpoCdExpln: string;
|
||||
unit: string;
|
||||
prntLwpoCd: string;
|
||||
useYn: string;
|
||||
sortSeq: number;
|
||||
regDt: string;
|
||||
rgTr: string;
|
||||
rgTrNm: string;
|
||||
mdfcnDt: string;
|
||||
mdFr: string;
|
||||
}
|
||||
|
||||
|
||||
export interface LwpoCodeDetail extends LwpoCodeFormData {
|
||||
lwpoCd: string;
|
||||
upCd: string;
|
||||
lwpoCdNm: string;
|
||||
lwpoCdExpln: string;
|
||||
unit: string;
|
||||
prntLwpoCd: string;
|
||||
useYn: string;
|
||||
sortSeq: 0;
|
||||
lwpoCd: string;
|
||||
upCd: string;
|
||||
lwpoCdNm: string;
|
||||
lwpoCdExpln: string;
|
||||
unit: string;
|
||||
prntLwpoCd: string;
|
||||
useYn: string;
|
||||
sortSeq: 0;
|
||||
}
|
||||
|
||||
|
||||
export const LwpoCodeFormSchema = z.object({
|
||||
lwpoCd: z.string().max(10).nonempty(),
|
||||
upCd: z.string().max(10).nonempty(),
|
||||
lwpoCdNm: z.string().max(100).nonempty(),
|
||||
lwpoCdExpln: z.string().max(1000).nullish(),
|
||||
unit: z.string().max(20).nullish(),
|
||||
prntLwpoCd: z.string().max(10).nullish(),
|
||||
useYn: z.string(),
|
||||
sortSeq: z.number(),
|
||||
delYn: z.string(),
|
||||
lwpoCd: z.string().max(10).nonempty(),
|
||||
upCd: z.string().max(10).nonempty(),
|
||||
lwpoCdNm: z.string().max(100).nonempty(),
|
||||
lwpoCdExpln: z.string().max(1000).nullish(),
|
||||
unit: z.string().max(20).nullish(),
|
||||
prntLwpoCd: z.string().max(10).nullish(),
|
||||
useYn: z.string(),
|
||||
sortSeq: z.number(),
|
||||
delYn: z.string(),
|
||||
});
|
||||
|
||||
|
||||
export type LwpoCodeFormData = z.infer<typeof LwpoCodeFormSchema>;
|
||||
export type LwpoCodeList = PageableList<LwpoCode>;
|
||||
|
||||
|
||||
export interface LwpoCodeService {
|
||||
getLwpoCodeList(params: LwpoCodeParams): Promise<LwpoCodeList>;
|
||||
getUpCodeLwpoCodeList(upCd: string): Promise<LwpoCodeList>;
|
||||
LwpoCodeDetail(upCd: string, LwpoCode: string): Promise<LwpoCodeDetail>;
|
||||
updateLwpoCode(upCd: string, LwpoCode: string, data: LwpoCodeFormData): Promise<void>;
|
||||
createLwpoCode(data: LwpoCodeFormData): Promise<void>;
|
||||
deleteLwpoCode(upCd: string, LwpoCode: string, data: LwpoCodeFormData): Promise<void>;
|
||||
getLwpoCodeList(params: LwpoCodeParams): Promise<LwpoCodeList>;
|
||||
getUpCodeLwpoCodeList(upCd: string): Promise<LwpoCodeList>;
|
||||
lwpoCodeDetail(upCd: string, lwpoCd: string): Promise<LwpoCodeDetail>;
|
||||
updateLwpoCode(
|
||||
upCd: string,
|
||||
lwpoCd: string,
|
||||
data: LwpoCodeFormData,
|
||||
): Promise<void>;
|
||||
createLwpoCode(data: LwpoCodeFormData): Promise<void>;
|
||||
deleteLwpoCode(
|
||||
upCd: string,
|
||||
lwpoCd: string,
|
||||
data: LwpoCodeFormData,
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -2,52 +2,51 @@ import { z } from "zod";
|
||||
import type { PageableParams, PageableList } from "@/shared/model";
|
||||
|
||||
export interface UpCodeParams extends PageableParams {
|
||||
keyword?: string;
|
||||
upCd?: string;
|
||||
cdSe?: string;
|
||||
useYn?: string;
|
||||
siteId?: string;
|
||||
keyword?: string;
|
||||
upCd?: string;
|
||||
cdSe?: string;
|
||||
useYn?: string;
|
||||
siteId?: string;
|
||||
}
|
||||
|
||||
|
||||
export interface UpCode {
|
||||
upCd: string;
|
||||
upCdNm: string;
|
||||
upCdExpln: string;
|
||||
cdSe: string;
|
||||
siteId: string;
|
||||
useYn: string;
|
||||
regDt: string;
|
||||
upCd: string;
|
||||
upCdNm: string;
|
||||
upCdExpln: string;
|
||||
cdSe: string;
|
||||
siteId: string;
|
||||
useYn: string;
|
||||
regDt: string;
|
||||
}
|
||||
|
||||
|
||||
export interface UpCodeDetail extends UpCodeFormData {
|
||||
upCd: string;
|
||||
upCdNm: string;
|
||||
upCdExpln: string;
|
||||
cdSe: string;
|
||||
siteId: string;
|
||||
useYn: string;
|
||||
delYn: string;
|
||||
regDt: string;
|
||||
rgTrNm: string;
|
||||
upCd: string;
|
||||
upCdNm: string;
|
||||
upCdExpln: string;
|
||||
cdSe: string;
|
||||
siteId: string;
|
||||
useYn: string;
|
||||
delYn: string;
|
||||
regDt: string;
|
||||
rgTrNm: string;
|
||||
}
|
||||
|
||||
|
||||
export const upCodeFormSchema = z.object({
|
||||
upCd: z.string().max(10).nonempty(),
|
||||
upCdNm: z.string().max(100).nonempty(),
|
||||
upCdExpln: z.string().max(1000).nullish(),
|
||||
cdSe: z.string().max(10).nonempty(),
|
||||
siteId: z.string().max(2).nullish(),
|
||||
useYn: z.string(),
|
||||
delYn: z.string(),
|
||||
upCd: z.string().max(10).nonempty(),
|
||||
upCdNm: z.string().max(100).nonempty(),
|
||||
upCdExpln: z.string().max(1000).nullish(),
|
||||
cdSe: z.string().max(10).nonempty(),
|
||||
siteId: z.string().max(2).nullish(),
|
||||
useYn: z.string(),
|
||||
delYn: z.string(),
|
||||
});
|
||||
|
||||
|
||||
export type UpCodeFormData = z.infer<typeof upCodeFormSchema>;
|
||||
export type UpCodeList = PageableList<UpCode>;
|
||||
|
||||
|
||||
export interface UpCodeService {
|
||||
getUpCodeList(params: UpCodeParams): Promise<UpCodeList>;
|
||||
upCodeDetail(upCodeId: string): Promise<UpCodeDetail>;
|
||||
updateUpCode(upCodeId: string, data: UpCodeFormData): Promise<void>;
|
||||
createUpCode(data: UpCodeFormData): Promise<void>;
|
||||
getUpCodeList(params: UpCodeParams): Promise<UpCodeList>;
|
||||
upCodeDetail(upCodeId: string): Promise<UpCodeDetail>;
|
||||
updateUpCode(upCodeId: string, data: UpCodeFormData): Promise<void>;
|
||||
createUpCode(data: UpCodeFormData): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import dayjs from "dayjs";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@common/components";
|
||||
import type { LwpoCode } from "@/entities/code";
|
||||
import { LwpoCodeManagementDialog } from "../ui/lwpocode-dialog";
|
||||
import { useState } from "react";
|
||||
|
||||
export const columns: ColumnDef<LwpoCode>[] = [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
cell: ({ row, table }) => {
|
||||
const totalRows = table.getRowCount();
|
||||
const { pageIndex, pageSize } = table.getState().pagination;
|
||||
return totalRows - (pageIndex * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "lwpoCd",
|
||||
header: "하위코드",
|
||||
},
|
||||
{
|
||||
accessorKey: "lwpoCdNm",
|
||||
header: "하위코드명",
|
||||
},
|
||||
{
|
||||
accessorKey: "useYn",
|
||||
header: "사용 여부",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "등록일",
|
||||
cell: ({ row }) => {
|
||||
const date = dayjs(row.original.regDt);
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: "관리",
|
||||
cell: ({ row }) => (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<LwpoCodeManageButton
|
||||
lwpoCd={row.original.lwpoCd}
|
||||
upCd={row.original.upCd}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const LwpoCodeManageButton = ({
|
||||
lwpoCd,
|
||||
upCd,
|
||||
}: {
|
||||
lwpoCd: string;
|
||||
upCd: string;
|
||||
}) => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
return (
|
||||
<LwpoCodeManagementDialog
|
||||
lwpoCd={lwpoCd}
|
||||
upCd={upCd}
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
>
|
||||
<Button size="sm">관리</Button>
|
||||
</LwpoCodeManagementDialog>
|
||||
);
|
||||
};
|
||||
@@ -1,119 +0,0 @@
|
||||
import dayjs from "dayjs";
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@common/components";
|
||||
import type { UpCode } from "@/entities/code/model/upcode-interface";
|
||||
import type { LwpoCode } from "@/entities/code/model/lwpocode-interface";
|
||||
|
||||
const UpCodeManageButton = () => {
|
||||
return (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
// 클릭 이벤트를 부모로 전파하여 onRowClick이 호출되도록 함
|
||||
e.currentTarget.parentElement?.parentElement?.click();
|
||||
}}
|
||||
>
|
||||
관리
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
const LwpoCodeManageButton = () => {
|
||||
return (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
// 클릭 이벤트를 부모로 전파하여 onRowClick이 호출되도록 함
|
||||
e.currentTarget.parentElement?.parentElement?.click();
|
||||
}}
|
||||
>
|
||||
관리
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const upCodecolumns: ColumnDef<UpCode>[] = [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
cell: ({ row, table }) => {
|
||||
const isSelected = row.getIsSelected();
|
||||
if (isSelected) {
|
||||
return "▶";
|
||||
}
|
||||
const totalRows = table.getRowCount();
|
||||
const currentPage = table.getState().pagination.pageIndex;
|
||||
const pageSize = table.getState().pagination.pageSize;
|
||||
return totalRows - (currentPage * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "upCd",
|
||||
header: "상위코드",
|
||||
},
|
||||
{
|
||||
accessorKey: "upCdNm",
|
||||
header: "상위코드명",
|
||||
},
|
||||
{
|
||||
accessorKey: "cdSe",
|
||||
header: "코드구분",
|
||||
},
|
||||
{
|
||||
accessorKey: "useYn",
|
||||
header: "사용여부",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "등록일",
|
||||
cell: ({ row }) => {
|
||||
const date = dayjs(row.original.regDt);
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: "관리",
|
||||
cell: () => <UpCodeManageButton />,
|
||||
}
|
||||
];
|
||||
|
||||
export const lowCodecolumns: ColumnDef<LwpoCode>[] = [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
cell: ({ row, table }) => {
|
||||
const totalRows = table.getRowCount();
|
||||
const currentPage = table.getState().pagination.pageIndex;
|
||||
const pageSize = table.getState().pagination.pageSize;
|
||||
return totalRows - (currentPage * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "lwpoCd",
|
||||
header: "하위코드",
|
||||
},
|
||||
{
|
||||
accessorKey: "lwpoCdNm",
|
||||
header: "하위코드명",
|
||||
},
|
||||
{
|
||||
accessorKey: "useYn",
|
||||
header: "사용 여부",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "등록일",
|
||||
cell: ({ row }) => {
|
||||
const date = dayjs(row.original.regDt);
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: "관리",
|
||||
cell: () => <LwpoCodeManageButton />,
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,64 @@
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@common/components";
|
||||
import type { UpCode } from "@/entities/code";
|
||||
import { UpCodeManagementDialog } from "../ui/upcode-dialog";
|
||||
|
||||
export const columns: ColumnDef<UpCode>[] = [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
cell: ({ row, table }) => {
|
||||
const totalRows = table.getRowCount();
|
||||
const { pageIndex, pageSize } = table.getState().pagination;
|
||||
return totalRows - (pageIndex * pageSize + row.index);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "upCd",
|
||||
header: "상위코드",
|
||||
},
|
||||
{
|
||||
accessorKey: "upCdNm",
|
||||
header: "상위코드명",
|
||||
},
|
||||
{
|
||||
accessorKey: "cdSe",
|
||||
header: "코드구분",
|
||||
},
|
||||
{
|
||||
accessorKey: "useYn",
|
||||
header: "사용여부",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "등록일",
|
||||
cell: ({ row }) => {
|
||||
const date = dayjs(row.original.regDt);
|
||||
return date.format("YYYY-MM-DD");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: "관리",
|
||||
cell: ({ row }) => (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<UpCodeManageButton upCd={row.original.upCd} />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const UpCodeManageButton = ({ upCd }: { upCd: string }) => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
return (
|
||||
<UpCodeManagementDialog
|
||||
upCd={upCd}
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
>
|
||||
<Button size="sm">관리</Button>
|
||||
</UpCodeManagementDialog>
|
||||
);
|
||||
};
|
||||
@@ -1,241 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import "@common/assets/styles/grid.css";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
type PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import { upCodeApi } from "@/entities/code/api/upcode-service";
|
||||
import { type UpCode, type UpCodeParams } from "@/entities/code/model/upcode-interface";
|
||||
import { type LwpoCode, type LwpoCodeParams } from "@/entities/code/model/lwpocode-interface";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { upCodecolumns, lowCodecolumns } from "../model/table-columns";
|
||||
import { lwpoCodeApi } from "@/entities/code/api/lwpocode-service";
|
||||
import { ManagementUpCodeDialog } from "./upcode-dialog";
|
||||
import { ManagementLwpoCodeDialog } from "./lowcode-dialog";
|
||||
import { UpCodeSection } from "./upcode-section";
|
||||
import { LwpoCodeSection } from "./lwpocode-section";
|
||||
|
||||
function CodePage() {
|
||||
const [selectedUpCode, setSelectedUpCode] = useState<UpCode | null>(null);
|
||||
const [isManagementDialogOpen, setIsManagementDialogOpen] = useState(false);
|
||||
|
||||
const [isRegistrationMode, setIsRegistrationMode] = useState(false);
|
||||
const [isLwpoCodeRegistrationMode, setIsLwpoCodeRegistrationMode] = useState(false);
|
||||
|
||||
const [selectedLwpoCode, setSelectedLwpoCode] = useState<LwpoCode | null>(null);
|
||||
const [isLwpoCodeManagementDialogOpen, setIsLwpoCodeManagementDialogOpen] = useState(false);
|
||||
|
||||
const [upCodeQuery, setUpCodeQuery] = useState<UpCodeParams>({
|
||||
upCd: "",
|
||||
});
|
||||
const [lwpoCodeQuery, setLwpoCodeQuery] = useState<LwpoCodeParams>({
|
||||
upCd: "",
|
||||
lwpoCd: "",
|
||||
});
|
||||
const [upCodePagination, setUpCodePagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const [lwpoCodePagination, setLwpoCodePagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 1000,
|
||||
});
|
||||
|
||||
const { data: upCodeList, refetch: refetchUpCode } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE],
|
||||
queryFn: () =>
|
||||
upCodeApi.getUpCodeList({
|
||||
...upCodeQuery,
|
||||
page: upCodePagination.pageIndex,
|
||||
size: upCodePagination.pageSize,
|
||||
}),
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
|
||||
const { data: lwpoCodeList, refetch: refetchLwpoCode } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, lwpoCodeQuery],
|
||||
queryFn: () =>
|
||||
lwpoCodeApi.getLwpoCodeList({
|
||||
...lwpoCodeQuery,
|
||||
page: lwpoCodePagination.pageIndex,
|
||||
size: lwpoCodePagination.pageSize,
|
||||
}),
|
||||
enabled: !!lwpoCodeQuery.upCd,
|
||||
});
|
||||
|
||||
const upCodehandleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
refetchUpCode();
|
||||
};
|
||||
|
||||
const upCodehandleRowClick = (row: UpCode) => {
|
||||
if (selectedUpCode?.upCd === row.upCd) {
|
||||
setIsRegistrationMode(false);
|
||||
setIsManagementDialogOpen(true);
|
||||
} else {
|
||||
setSelectedUpCode(row);
|
||||
setLwpoCodeQuery({ ...lwpoCodeQuery, upCd: row.upCd });
|
||||
refetchLwpoCode();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRegistrationClick = () => {
|
||||
setSelectedUpCode(null);
|
||||
setIsRegistrationMode(true);
|
||||
setIsManagementDialogOpen(true);
|
||||
};
|
||||
|
||||
const lwpoCodehandleRowClick = (row: LwpoCode) => {
|
||||
setSelectedLwpoCode(row);
|
||||
setIsLwpoCodeRegistrationMode(false);
|
||||
setIsLwpoCodeManagementDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleLwpoCodeRegistrationClick = () => {
|
||||
if (!selectedUpCode?.upCd) {
|
||||
alert("상위코드를 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
setSelectedLwpoCode(null);
|
||||
setIsLwpoCodeRegistrationMode(true);
|
||||
setIsLwpoCodeManagementDialogOpen(true);
|
||||
};
|
||||
|
||||
const upCodeTable = useReactTable<UpCode>({
|
||||
data: upCodeList?.content ?? [],
|
||||
columns: upCodecolumns,
|
||||
rowCount: upCodeList?.totalElements ?? 0,
|
||||
state: {
|
||||
pagination: upCodePagination,
|
||||
rowSelection: selectedUpCode ? { [selectedUpCode.upCd]: true } : {},
|
||||
},
|
||||
onPaginationChange: setUpCodePagination,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
manualPagination: true,
|
||||
getRowId: (row) => row.upCd,
|
||||
});
|
||||
|
||||
const lwpoCodeTable = useReactTable<LwpoCode>({
|
||||
data: lwpoCodeList?.content ?? [],
|
||||
columns: lowCodecolumns,
|
||||
rowCount: lwpoCodeList?.totalElements ?? 0,
|
||||
state: {
|
||||
pagination: lwpoCodePagination,
|
||||
rowSelection: selectedLwpoCode ? { [selectedLwpoCode.lwpoCd]: true } : {},
|
||||
},
|
||||
onPaginationChange: setLwpoCodePagination,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
manualPagination: true,
|
||||
getRowId: (row) => row.lwpoCd,
|
||||
});
|
||||
|
||||
const lwpoCodehandleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
refetchLwpoCode();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
refetchUpCode();
|
||||
}, [upCodePagination]);
|
||||
|
||||
return (
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-1">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={upCodehandleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label htmlFor="" className="mr-2 text-label">
|
||||
상위코드명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
value={upCodeQuery.keyword}
|
||||
onChange={(e) =>
|
||||
setUpCodeQuery({
|
||||
...upCodeQuery,
|
||||
keyword: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">상위코드 목록</h3>
|
||||
<Button onClick={handleRegistrationClick}>등록</Button>
|
||||
</div>
|
||||
<div className="card !m-4 h-[calc(100vh-30rem)] overflow-auto !p-0">
|
||||
<DataTable
|
||||
table={upCodeTable}
|
||||
onRowClick={upCodehandleRowClick}
|
||||
viewPagination
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={lwpoCodehandleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label htmlFor="" className="mr-2 text-label">
|
||||
하위코드명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
value={lwpoCodeQuery.lwpoCdNm}
|
||||
onChange={(e) => setLwpoCodeQuery({
|
||||
...lwpoCodeQuery,
|
||||
lwpoCdNm: e.target.value
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">하위코드 목록</h3>
|
||||
<Button onClick={handleLwpoCodeRegistrationClick}>등록</Button>
|
||||
</div>
|
||||
<div className="card !m-4 h-[calc(100vh-30rem)] overflow-auto !p-0">
|
||||
<DataTable
|
||||
table={lwpoCodeTable}
|
||||
onRowClick={lwpoCodehandleRowClick}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isManagementDialogOpen && (
|
||||
<ManagementUpCodeDialog
|
||||
open={isManagementDialogOpen}
|
||||
onOpenChange={setIsManagementDialogOpen}
|
||||
upCd={selectedUpCode?.upCd}
|
||||
isRegistration={isRegistrationMode}
|
||||
/>
|
||||
)}
|
||||
{isLwpoCodeManagementDialogOpen && (
|
||||
<ManagementLwpoCodeDialog
|
||||
open={isLwpoCodeManagementDialogOpen}
|
||||
onOpenChange={setIsLwpoCodeManagementDialogOpen}
|
||||
upCd={isLwpoCodeRegistrationMode ? selectedUpCode?.upCd : selectedLwpoCode?.upCd}
|
||||
lwpoCd={selectedLwpoCode?.lwpoCd}
|
||||
isRegistration={isLwpoCodeRegistrationMode}
|
||||
/>
|
||||
)}
|
||||
const [selectedUpCd, setSelectedUpCd] = useState("");
|
||||
return (
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="flex">
|
||||
<UpCodeSection handleSelectedUpCd={setSelectedUpCd} />
|
||||
<LwpoCodeSection upCd={selectedUpCd} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { CodePage };
|
||||
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { CodePage };
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Input,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Label,
|
||||
} from "@common/components";
|
||||
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { lwpoCodeApi } from "@/entities/code/api/lwpocode-service";
|
||||
import { LwpoCodeFormSchema, type LwpoCodeFormData } from "@/entities/code/model/lwpocode-interface";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { upCodeApi } from "@/entities/code/api/upcode-service";
|
||||
|
||||
type ManagementLwpoCodeDialogProps = {
|
||||
upCd?: string;
|
||||
lwpoCd?: string;
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
isRegistration?: boolean;
|
||||
} & Omit<React.ComponentProps<typeof Dialog>, 'open' | 'onOpenChange'>;
|
||||
|
||||
function ManagementLwpoCodeDialog({
|
||||
lwpoCd,
|
||||
upCd,
|
||||
open,
|
||||
onOpenChange,
|
||||
isRegistration = false,
|
||||
...props
|
||||
}: ManagementLwpoCodeDialogProps) {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const { data: detailData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, upCd, lwpoCd],
|
||||
queryFn: () => lwpoCodeApi.LwpoCodeDetail(upCd as string, lwpoCd as string),
|
||||
enabled: !!upCd && !!lwpoCd && !isRegistration,
|
||||
});
|
||||
|
||||
const { data: upCodeData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, upCd],
|
||||
queryFn: () => upCodeApi.upCodeDetail(upCd as string),
|
||||
enabled: !!upCd,
|
||||
});
|
||||
|
||||
const { mutateAsync: saveLwpoCode } = useMutation({
|
||||
mutationFn: (data: LwpoCodeFormData) =>
|
||||
isRegistration ? lwpoCodeApi.createLwpoCode(data) : lwpoCodeApi.updateLwpoCode(upCd as string, lwpoCd as string, data),
|
||||
onSuccess: () => {
|
||||
alert(isRegistration ? "등록되었습니다." : "수정되었습니다.");
|
||||
onOpenChange?.(false);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<LwpoCodeFormData>({
|
||||
resolver: zodResolver(LwpoCodeFormSchema),
|
||||
values: {
|
||||
upCd: upCd ?? "",
|
||||
lwpoCd: detailData?.lwpoCd ?? "",
|
||||
lwpoCdNm: detailData?.lwpoCdNm ?? "",
|
||||
lwpoCdExpln: detailData?.lwpoCdExpln ?? "",
|
||||
useYn: detailData?.useYn ?? "Y",
|
||||
delYn: "N",
|
||||
unit: detailData?.unit ?? "",
|
||||
prntLwpoCd: detailData?.prntLwpoCd ?? "",
|
||||
sortSeq: detailData?.sortSeq ?? 0,
|
||||
},
|
||||
});
|
||||
|
||||
const handleSave = async () => {
|
||||
if (await confirm(isRegistration ? "등록하시겠습니까?" : "수정하시겠습니까?")) {
|
||||
const data = form.getValues();
|
||||
await saveLwpoCode(data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{isRegistration ? "하위코드 등록" : "하위코드 관리"}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleSave();
|
||||
}} className="space-y-4">
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="20%" />
|
||||
<col width="80%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>하위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드를 입력해주세요"
|
||||
disabled={!isRegistration}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>하위코드명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCdNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>하위코드설명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCdExpln"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드 설명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{upCodeData?.cdSe === "CODECLUNIT" && (
|
||||
<TableRow>
|
||||
<TableHead>단위</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="unit"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="단위를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{upCodeData?.cdSe === "CODECLTREE" && (
|
||||
<TableRow>
|
||||
<TableHead>상위하위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="prntLwpoCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위하위코드를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
<TableRow>
|
||||
<TableHead>정렬순서</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="sortSeq"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
value={field.value ?? 0}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="정렬순서를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
<Label htmlFor="useY">사용</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="N" id="useN" />
|
||||
<Label htmlFor="useN">사용안함</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" type="submit" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleSave();
|
||||
}}>
|
||||
{isRegistration ? "등록" : "저장"}
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export { ManagementLwpoCodeDialog };
|
||||
@@ -0,0 +1,321 @@
|
||||
import { memo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Input,
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Label,
|
||||
DialogTrigger,
|
||||
} from "@common/components";
|
||||
import {
|
||||
UpCodeApi,
|
||||
LwpoCodeApi,
|
||||
LwpoCodeFormSchema,
|
||||
type LwpoCodeFormData,
|
||||
} from "@/entities/code";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
|
||||
type ManagementLwpoCodeDialogProps = {
|
||||
lwpoCd?: string;
|
||||
upCd?: string;
|
||||
children?: React.ReactNode;
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
};
|
||||
|
||||
const LwpoCodeManagementDialog = memo(
|
||||
({
|
||||
lwpoCd,
|
||||
upCd,
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: ManagementLwpoCodeDialogProps) => {
|
||||
const isRegistration = !lwpoCd;
|
||||
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const { data: detailData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, upCd, lwpoCd],
|
||||
queryFn: () => LwpoCodeApi.lwpoCodeDetail(upCd!, lwpoCd!),
|
||||
enabled: !!upCd && !isRegistration,
|
||||
});
|
||||
|
||||
const { data: upCodeData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, upCd],
|
||||
queryFn: () => UpCodeApi.upCodeDetail(upCd!),
|
||||
enabled: !!upCd,
|
||||
});
|
||||
|
||||
const { mutateAsync: createLwpoCode } = useMutation({
|
||||
mutationFn: (data: LwpoCodeFormData) => LwpoCodeApi.createLwpoCode(data),
|
||||
onSuccess: () => {
|
||||
alert("등록되었습니다.", () => onOpenChange?.(false));
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: updateLwpoCode } = useMutation({
|
||||
mutationFn: (data: LwpoCodeFormData) =>
|
||||
LwpoCodeApi.updateLwpoCode(upCd!, lwpoCd!, data),
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.", () => onOpenChange?.(false));
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<LwpoCodeFormData>({
|
||||
resolver: zodResolver(LwpoCodeFormSchema),
|
||||
values: {
|
||||
lwpoCd: detailData?.lwpoCd ?? "",
|
||||
upCd: upCd ?? "",
|
||||
lwpoCdNm: detailData?.lwpoCdNm ?? "",
|
||||
lwpoCdExpln: detailData?.lwpoCdExpln ?? "",
|
||||
unit: detailData?.unit ?? "",
|
||||
prntLwpoCd: detailData?.prntLwpoCd ?? "",
|
||||
useYn: detailData?.useYn ?? "Y",
|
||||
sortSeq: detailData?.sortSeq ?? 0,
|
||||
delYn: "N",
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit =
|
||||
(callback: (data: LwpoCodeFormData) => void) =>
|
||||
async (data: LwpoCodeFormData) => {
|
||||
const confirmMessage = isRegistration
|
||||
? "등록하시겠습니까?"
|
||||
: "수정하시겠습니까?";
|
||||
|
||||
if (await confirm(confirmMessage)) callback(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{isRegistration ? "하위코드 등록" : "하위코드 관리"}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(
|
||||
onSubmit(isRegistration ? createLwpoCode : updateLwpoCode),
|
||||
)}
|
||||
className="space-y-4"
|
||||
>
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="20%" />
|
||||
<col width="80%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>하위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드를 입력해주세요"
|
||||
disabled={!isRegistration}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>하위코드명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCdNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>하위코드설명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lwpoCdExpln"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="하위코드 설명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{upCodeData?.cdSe === "CODECLUNIT" && (
|
||||
<TableRow>
|
||||
<TableHead>단위</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="unit"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="단위를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{upCodeData?.cdSe === "CODECLTREE" && (
|
||||
<TableRow>
|
||||
<TableHead>상위하위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="prntLwpoCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위하위코드를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
<TableRow>
|
||||
<TableHead>정렬순서</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="sortSeq"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
value={field.value ?? 0}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="정렬순서를 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
<Label htmlFor="useY">사용</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="N" id="useN" />
|
||||
<Label htmlFor="useN">사용안함</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" type="submit">
|
||||
{isRegistration ? "등록" : "저장"}
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => {
|
||||
return (
|
||||
prevProps.lwpoCd === nextProps.lwpoCd &&
|
||||
prevProps.upCd === nextProps.upCd &&
|
||||
prevProps.open === nextProps.open
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
LwpoCodeManagementDialog.displayName = "LwpoCodeManagementDialog";
|
||||
|
||||
export { LwpoCodeManagementDialog };
|
||||
@@ -0,0 +1,98 @@
|
||||
import { useState } from "react";
|
||||
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
type PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import { LwpoCodeApi, type LwpoCodeParams } from "@/entities/code";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "../model/lwpocode-table-columns";
|
||||
import { LwpoCodeManagementDialog } from "./lwpocode-dialog";
|
||||
|
||||
type LwpoCodeSectionProps = {
|
||||
upCd?: string;
|
||||
};
|
||||
|
||||
function LwpoCodeSection({ upCd }: LwpoCodeSectionProps) {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [lwpoCodeQuery, setLwpoCodeQuery] = useState<LwpoCodeParams>({
|
||||
lwpoCdNm: "",
|
||||
});
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const { data: lwpoCodeList, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, upCd, pagination],
|
||||
queryFn: () =>
|
||||
LwpoCodeApi.getLwpoCodeList({
|
||||
...lwpoCodeQuery,
|
||||
upCd,
|
||||
page: pagination.pageIndex,
|
||||
size: pagination.pageSize,
|
||||
}),
|
||||
enabled: !!upCd,
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: lwpoCodeList?.content ?? [],
|
||||
columns,
|
||||
rowCount: lwpoCodeList?.totalElements ?? 0,
|
||||
state: { pagination },
|
||||
manualPagination: true,
|
||||
enableMultiRowSelection: false,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onPaginationChange: setPagination,
|
||||
getRowId: (row) => row.lwpoCd,
|
||||
});
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
refetch();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label htmlFor="" className="mr-2 text-label">
|
||||
하위코드명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[20rem] rounded-sm !text-[1.3rem]"
|
||||
value={lwpoCodeQuery.lwpoCdNm}
|
||||
onChange={(e) =>
|
||||
setLwpoCodeQuery({
|
||||
...lwpoCodeQuery,
|
||||
lwpoCdNm: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">하위코드 목록</h3>
|
||||
<LwpoCodeManagementDialog
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
>
|
||||
<Button>등록</Button>
|
||||
</LwpoCodeManagementDialog>
|
||||
</div>
|
||||
<div className="card !m-4 h-[calc(100vh-35rem)] overflow-auto !p-0">
|
||||
<DataTable table={table} viewPagination />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { LwpoCodeSection };
|
||||
@@ -1,8 +1,8 @@
|
||||
import { memo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -20,237 +20,262 @@ import {
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
Label,
|
||||
DialogTrigger,
|
||||
} from "@common/components";
|
||||
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { upCodeApi } from "@/entities/code/api/upcode-service";
|
||||
import { upCodeFormSchema, type UpCodeFormData } from "@/entities/code/model/upcode-interface";
|
||||
import { CodeSelect } from "@/entities/code";
|
||||
import {
|
||||
CodeSelect,
|
||||
UpCodeApi,
|
||||
upCodeFormSchema,
|
||||
type UpCodeFormData,
|
||||
} from "@/entities/code";
|
||||
import { SiteSelect } from "@/entities/site";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
|
||||
|
||||
type ManagementUpCodeDialogProps = {
|
||||
type UpCodeManagementDialogProps = {
|
||||
upCd?: string;
|
||||
children?: React.ReactNode;
|
||||
open?: boolean;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
isRegistration?: boolean;
|
||||
} & Omit<React.ComponentProps<typeof Dialog>, 'open' | 'onOpenChange'>;
|
||||
};
|
||||
|
||||
const UpCodeManagementDialog = memo(
|
||||
({
|
||||
upCd,
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
...props
|
||||
}: UpCodeManagementDialogProps) => {
|
||||
const isRegistration = !upCd;
|
||||
|
||||
function ManagementUpCodeDialog({
|
||||
upCd,
|
||||
open,
|
||||
onOpenChange,
|
||||
isRegistration = false,
|
||||
...props
|
||||
}: ManagementUpCodeDialogProps) {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const { data: detailData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, upCd],
|
||||
queryFn: () => upCodeApi.upCodeDetail(upCd as string),
|
||||
enabled: !!upCd && !isRegistration,
|
||||
});
|
||||
const { data: detailData } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, upCd],
|
||||
queryFn: () => UpCodeApi.upCodeDetail(upCd!),
|
||||
enabled: !!upCd,
|
||||
});
|
||||
|
||||
const { mutateAsync: saveUpCode } = useMutation({
|
||||
mutationFn: (data: UpCodeFormData) =>
|
||||
isRegistration ? upCodeApi.createUpCode(data) : upCodeApi.updateUpCode(upCd as string, data),
|
||||
onSuccess: () => {
|
||||
alert(isRegistration ? "등록되었습니다." : "수정되었습니다.");
|
||||
onOpenChange?.(false);
|
||||
},
|
||||
});
|
||||
const { mutateAsync: createUpCode } = useMutation({
|
||||
mutationFn: (data: UpCodeFormData) => UpCodeApi.createUpCode(data),
|
||||
onSuccess: () => {
|
||||
alert("등록되었습니다.", () => onOpenChange?.(false));
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<UpCodeFormData>({
|
||||
resolver: zodResolver(upCodeFormSchema),
|
||||
values: {
|
||||
upCd: detailData?.upCd ?? "",
|
||||
upCdNm: detailData?.upCdNm ?? "",
|
||||
cdSe: detailData?.cdSe ?? "",
|
||||
siteId: detailData?.siteId ?? "",
|
||||
upCdExpln: detailData?.upCdExpln ?? "",
|
||||
useYn: detailData?.useYn ?? "Y",
|
||||
delYn: "N",
|
||||
},
|
||||
});
|
||||
const { mutateAsync: updateUpCode } = useMutation({
|
||||
mutationFn: (data: UpCodeFormData) => UpCodeApi.updateUpCode(upCd!, data),
|
||||
onSuccess: () => {
|
||||
alert("수정되었습니다.", () => onOpenChange?.(false));
|
||||
},
|
||||
});
|
||||
|
||||
const handleSave = async () => {
|
||||
if (await confirm(isRegistration ? "등록하시겠습니까?" : "수정하시겠습니까?")) {
|
||||
const data = form.getValues();
|
||||
await saveUpCode(data);
|
||||
}
|
||||
};
|
||||
const form = useForm<UpCodeFormData>({
|
||||
resolver: zodResolver(upCodeFormSchema),
|
||||
values: {
|
||||
upCd: detailData?.upCd ?? "",
|
||||
upCdNm: detailData?.upCdNm ?? "",
|
||||
cdSe: detailData?.cdSe ?? "",
|
||||
siteId: detailData?.siteId ?? "",
|
||||
upCdExpln: detailData?.upCdExpln ?? "",
|
||||
useYn: detailData?.useYn ?? "Y",
|
||||
delYn: "N",
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{isRegistration ? "상위코드 등록" : "상위코드 관리"}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
handleSave();
|
||||
}} className="space-y-4">
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>상위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드를를 입력해주세요"
|
||||
disabled={!isRegistration}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>상위코드명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCdNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>상위코드설명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCdExpln"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드설명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>코드구분</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cdSe"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
upCd="CODECL"
|
||||
value={field.value || ""}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사이트</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="siteId"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormControl>
|
||||
<SiteSelect
|
||||
siteId={field.value || ""}
|
||||
value={field.value || ""}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
<Label htmlFor="useY">사용</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="N" id="useN" />
|
||||
<Label htmlFor="useN">사용안함</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" type="submit" onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleSave();
|
||||
}}>
|
||||
{isRegistration ? "등록" : "저장"}
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
const onSubmit =
|
||||
(callback: (data: UpCodeFormData) => void) =>
|
||||
async (data: UpCodeFormData) => {
|
||||
const confirmMessage = isRegistration
|
||||
? "등록하시겠습니까?"
|
||||
: "수정하시겠습니까?";
|
||||
|
||||
if (await confirm(confirmMessage)) callback(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{isRegistration ? "상위코드 등록" : "상위코드 관리"}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(
|
||||
onSubmit(isRegistration ? createUpCode : updateUpCode),
|
||||
)}
|
||||
className="space-y-4"
|
||||
>
|
||||
<Table variant="secondary">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="85%" />
|
||||
</colgroup>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableHead>상위코드</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCd"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드를를 입력해주세요"
|
||||
disabled={!isRegistration}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>상위코드명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCdNm"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>상위코드설명</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="upCdExpln"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
className="!text-[1.3rem]"
|
||||
placeholder="상위코드설명을 입력해주세요"
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>코드구분</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cdSe"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormControl>
|
||||
<CodeSelect
|
||||
upCd="CODECL"
|
||||
value={field.value || ""}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사이트</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="siteId"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col">
|
||||
<FormControl>
|
||||
<SiteSelect
|
||||
siteId={field.value || ""}
|
||||
value={field.value || ""}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableHead>사용여부</TableHead>
|
||||
<TableCell className="border">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="useYn"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
{...field}
|
||||
name="useYn"
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="Y" id="useY" />
|
||||
<Label htmlFor="useY">사용</Label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="N" id="useN" />
|
||||
<Label htmlFor="useN">사용안함</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" type="submit">
|
||||
{isRegistration ? "등록" : "저장"}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => {
|
||||
return (
|
||||
prevProps.upCd === nextProps.upCd && prevProps.open === nextProps.open
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export { ManagementUpCodeDialog };
|
||||
UpCodeManagementDialog.displayName = "UpCodeManagementDialog";
|
||||
|
||||
export { UpCodeManagementDialog };
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import { useState } from "react";
|
||||
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
type PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import { UpCodeApi, type UpCode, type UpCodeParams } from "@/entities/code";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "../model/upcode-table-columns";
|
||||
import { UpCodeManagementDialog } from "./upcode-dialog";
|
||||
|
||||
type UpCodeSectionProps = {
|
||||
handleSelectedUpCd: (upCd: string) => void;
|
||||
};
|
||||
|
||||
function UpCodeSection({ handleSelectedUpCd }: UpCodeSectionProps) {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [upCodeQuery, setUpCodeQuery] = useState<UpCodeParams>({
|
||||
keyword: "",
|
||||
});
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const { data: upCodeList, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, pagination],
|
||||
queryFn: () =>
|
||||
UpCodeApi.getUpCodeList({
|
||||
...upCodeQuery,
|
||||
page: pagination.pageIndex,
|
||||
size: pagination.pageSize,
|
||||
}),
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: upCodeList?.content ?? [],
|
||||
columns,
|
||||
rowCount: upCodeList?.totalElements ?? 0,
|
||||
state: { pagination },
|
||||
manualPagination: true,
|
||||
enableMultiRowSelection: false,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onPaginationChange: setPagination,
|
||||
getRowId: (row) => row.upCd,
|
||||
});
|
||||
|
||||
const handleRowClick = (row: UpCode) => {
|
||||
table.setRowSelection({ [row.upCd]: true });
|
||||
handleSelectedUpCd(row.upCd);
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
refetch();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
<Label htmlFor="" className="mr-2 text-label">
|
||||
상위코드명
|
||||
</Label>
|
||||
<Input
|
||||
className="h-[3.2rem] w-[20rem] rounded-sm !text-[1.3rem]"
|
||||
value={upCodeQuery.keyword}
|
||||
onChange={(e) =>
|
||||
setUpCodeQuery({
|
||||
...upCodeQuery,
|
||||
keyword: e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Button className="h-[3.2rem]" type="submit">
|
||||
조회
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">상위코드 목록</h3>
|
||||
<UpCodeManagementDialog
|
||||
open={dialogOpen}
|
||||
onOpenChange={setDialogOpen}
|
||||
>
|
||||
<Button>등록</Button>
|
||||
</UpCodeManagementDialog>
|
||||
</div>
|
||||
<div className="card !m-4 h-[calc(100vh-35rem)] overflow-auto !p-0">
|
||||
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { UpCodeSection };
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, memo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
@@ -41,110 +41,117 @@ type ManagementAuthorityDialogProps = {
|
||||
rowData?: Authorizations;
|
||||
} & React.ComponentProps<typeof Dialog>;
|
||||
|
||||
function ManagementAuthorityDialog({
|
||||
authorizationNo,
|
||||
rowData,
|
||||
...props
|
||||
}: ManagementAuthorityDialogProps) {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
const ManagementAuthorityDialog = memo(
|
||||
({ authorizationNo, rowData, ...props }: ManagementAuthorityDialogProps) => {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const [isOpened, setIsOpened] = useState(false);
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
const [isOpened, setIsOpened] = useState(false);
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
|
||||
const { data: roleAuthorizationList } = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS, authorizationNo],
|
||||
queryFn: () =>
|
||||
RoleAuthorizationsApi.getRoleAuthorizationsList({ authorizationNo }),
|
||||
enabled: !!authorizationNo && isOpened,
|
||||
});
|
||||
const { data: roleAuthorizationList } = useQuery({
|
||||
queryKey: [ENDPOINT.USER_SERVICE.ROLE_AUTHORIZATIONS, authorizationNo],
|
||||
queryFn: () =>
|
||||
RoleAuthorizationsApi.getRoleAuthorizationsList({ authorizationNo }),
|
||||
enabled: !!authorizationNo && isOpened,
|
||||
});
|
||||
|
||||
const { mutateAsync: saveRoleAuthorization } = useMutation({
|
||||
mutationFn: (data: RoleAuthorizationsData) =>
|
||||
RoleAuthorizationsApi.createRoleAuthorizations(data),
|
||||
onSuccess: () => {
|
||||
alert("저장되었습니다.");
|
||||
},
|
||||
});
|
||||
const { mutateAsync: saveRoleAuthorization } = useMutation({
|
||||
mutationFn: (data: RoleAuthorizationsData) =>
|
||||
RoleAuthorizationsApi.createRoleAuthorizations(data),
|
||||
onSuccess: () => {
|
||||
alert("저장되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<RoleAuthorizationsFormData>({
|
||||
resolver: zodResolver(roleAuthorizationsFormSchema),
|
||||
values: {
|
||||
roleAuthorizations:
|
||||
roleAuthorizationList?.content.map(
|
||||
({ roleId, authorizationNo, useYn }) => ({
|
||||
roleId,
|
||||
authorizationNo,
|
||||
authYn: useYn,
|
||||
}),
|
||||
) ?? [],
|
||||
},
|
||||
});
|
||||
const form = useForm<RoleAuthorizationsFormData>({
|
||||
resolver: zodResolver(roleAuthorizationsFormSchema),
|
||||
values: {
|
||||
roleAuthorizations:
|
||||
roleAuthorizationList?.content.map(
|
||||
({ roleId, authorizationNo, useYn }) => ({
|
||||
roleId,
|
||||
authorizationNo,
|
||||
authYn: useYn,
|
||||
}),
|
||||
) ?? [],
|
||||
},
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: roleAuthorizationList?.content ?? [],
|
||||
columns: createColumns(form),
|
||||
state: {
|
||||
rowSelection,
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onRowSelectionChange: setRowSelection,
|
||||
});
|
||||
const table = useReactTable({
|
||||
data: roleAuthorizationList?.content ?? [],
|
||||
columns: createColumns(form),
|
||||
state: {
|
||||
rowSelection,
|
||||
},
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onRowSelectionChange: setRowSelection,
|
||||
});
|
||||
|
||||
const handleSave = async () => {
|
||||
if (await confirm("저장하시겠습니까?")) {
|
||||
const data = form.getValues("roleAuthorizations");
|
||||
await saveRoleAuthorization(data);
|
||||
}
|
||||
};
|
||||
const handleSave = async () => {
|
||||
if (await confirm("저장하시겠습니까?")) {
|
||||
const data = form.getValues("roleAuthorizations");
|
||||
await saveRoleAuthorization(data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" onClick={() => setIsOpened(true)}>
|
||||
관리
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>모듈API 권한관리</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-8">
|
||||
<Table variant="line">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>API명</TableHead>
|
||||
<TableHead>요청 메소드</TableHead>
|
||||
<TableHead>API URL</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell align="center">
|
||||
{rowData?.authorizationName}
|
||||
</TableCell>
|
||||
<TableCell align="center">{rowData?.httpMethodCode}</TableCell>
|
||||
<TableCell align="center">{rowData?.urlPatternValue}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="max-h-[40rem] overflow-auto">
|
||||
<DataTable table={table} />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" onClick={handleSave}>
|
||||
저장
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" onClick={() => setIsOpened(true)}>
|
||||
관리
|
||||
</Button>
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[60rem]" aria-describedby={undefined}>
|
||||
<DialogHeader>
|
||||
<DialogTitle>모듈API 권한관리</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col gap-8">
|
||||
<Table variant="line">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>API명</TableHead>
|
||||
<TableHead>요청 메소드</TableHead>
|
||||
<TableHead>API URL</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell align="center">
|
||||
{rowData?.authorizationName}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{rowData?.httpMethodCode}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{rowData?.urlPatternValue}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="max-h-[40rem] overflow-auto">
|
||||
<DataTable table={table} />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter className="!justify-center">
|
||||
<Button size="lg" onClick={handleSave}>
|
||||
저장
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
<DialogClose asChild>
|
||||
<Button size="lg" color="white">
|
||||
취소
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
},
|
||||
(prevProps, nextProps) => {
|
||||
return prevProps.authorizationNo === nextProps.authorizationNo;
|
||||
},
|
||||
);
|
||||
|
||||
ManagementAuthorityDialog.displayName = "ManagementAuthorityDialog";
|
||||
|
||||
export { ManagementAuthorityDialog };
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
--popover-foreground: #0a0a0a;
|
||||
--primary: #2094fa;
|
||||
--primary-foreground: #fafafa;
|
||||
--primary-transparent: rgba(32, 148, 250, 0.1);
|
||||
--secondary: #f5f5f5;
|
||||
--secondary-foreground: #0f1e33;
|
||||
--muted: #f5f5f5;
|
||||
@@ -54,6 +55,7 @@
|
||||
--popover-foreground: #fafafa;
|
||||
--primary: #2094fa;
|
||||
--primary-foreground: #171717;
|
||||
--primary-transparent: rgba(32, 148, 250, 0.1);
|
||||
--secondary: #262626;
|
||||
--secondary-foreground: #fafafa;
|
||||
--muted: #262626;
|
||||
|
||||
@@ -42,22 +42,31 @@ function DataTable<T>({
|
||||
<Table className={cn("w-full", className)} variant={variant}>
|
||||
<THead table={table} />
|
||||
<tbody>
|
||||
{table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
onClick={() => onRowClick?.(row.original)}
|
||||
className={cn(onRowClick && "cursor-pointer hover:bg-accent")}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
const { meta } = cell.column.columnDef;
|
||||
return (
|
||||
<TableCell key={cell.id} align="center" {...meta}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
{table.getRowModel().rows.map((row) => {
|
||||
const isSelectedRow = row.getIsSelected();
|
||||
return (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
onClick={() => onRowClick?.(row.original)}
|
||||
className={cn(
|
||||
onRowClick && "cursor-pointer hover:bg-accent",
|
||||
isSelectedRow && "!bg-primary-transparent",
|
||||
)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
const { meta } = cell.column.columnDef;
|
||||
return (
|
||||
<TableCell key={cell.id} align="center" {...meta}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext(),
|
||||
)}
|
||||
</TableCell>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
{viewPagination && <Pagination table={table} />}
|
||||
|
||||
@@ -21,6 +21,7 @@ export default {
|
||||
primary: {
|
||||
DEFAULT: "var(--primary)",
|
||||
foreground: "var(--primary-foreground)",
|
||||
transparent: "var(--primary-transparent)",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "var(--secondary)",
|
||||
|
||||
Reference in New Issue
Block a user