Files
frontend/apps/cs/src/pages/code/ui/lwpocode-dialog.tsx
T

372 lines
13 KiB
TypeScript

import { memo, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQuery, useQueryClient } 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, useMutationWrapper } from "@/shared/lib";
import { Form, FormField, FormItem, FormControl } from "@/shared/ui/form";
type ManagementLwpoCodeDialogProps = {
lwpoCd?: string;
upCd?: string;
children?: React.ReactNode;
open?: boolean;
onOpenChange?: (open: boolean) => void;
onAfterSave?: () => void; // 콜백 추가
};
const LwpoCodeManagementDialog = memo(
({
lwpoCd,
upCd,
children,
open,
onOpenChange,
onAfterSave, // 콜백 사용
...props
}: ManagementLwpoCodeDialogProps) => {
const isRegistration = !lwpoCd;
const { confirm } = useConfirm();
const queryClient = useQueryClient();
const alert = useAlertStore((state) => state.setMessage);
const { data: detailData } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, upCd, lwpoCd],
queryFn: () => LwpoCodeApi.lwpoCodeDetail(upCd!, lwpoCd!),
enabled: !!upCd && !isRegistration && open,
});
const { data: upCodeData } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.UP_CODE, upCd],
queryFn: () => UpCodeApi.upCodeDetail(upCd!),
enabled: !!upCd,
});
const { mutateAsync: createLwpoCode } = useMutationWrapper({
mutationFn: (data: LwpoCodeFormData) => LwpoCodeApi.createLwpoCode(data),
onSuccess: () => {
alert("등록되었습니다.", () => {
onOpenChange?.(false);
onAfterSave?.();
});
queryClient.invalidateQueries({
queryKey: [ENDPOINT.CMS_SERVICE.LWPO_CODE, upCd],
});
},
});
const { mutateAsync: updateLwpoCode } = useMutationWrapper({
mutationFn: (data: LwpoCodeFormData) =>
LwpoCodeApi.updateLwpoCode(upCd!, lwpoCd!, data),
onSuccess: () => {
alert("수정되었습니다.", () => {
onOpenChange?.(false);
onAfterSave?.();
});
},
});
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 handleRegister = async () => {
if (!upCd) {
alert("상위코드가 없습니다.");
return;
}
const confirmMessage = "등록하시겠습니까?";
if (await confirm(confirmMessage)) {
const rawValues = form.getValues();
const values = {
...rawValues,
upCd: upCd,
sortSeq: Number(rawValues.sortSeq) || 0,
};
await createLwpoCode(values);
}
};
const handleSave = async () => {
if (!upCd) {
alert("상위코드가 없습니다.");
return;
}
const confirmMessage = "수정하시겠습니까?";
if (await confirm(confirmMessage)) {
const rawValues = form.getValues();
const values = {
...rawValues,
upCd: upCd,
sortSeq: Number(rawValues.sortSeq) || 0,
};
await updateLwpoCode(values);
}
};
useEffect(() => {
if (!open) form.reset();
}, [open]);
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={(e) => {
e.preventDefault();
if (isRegistration) {
handleRegister();
} else {
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}
onChange={(e) => {
field.onChange(parseInt(e.target.value));
}}
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={isRegistration ? handleRegister : handleSave}
>
{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 };