Files
frontend/apps/cs/src/pages/linkTable/ui/link-table-dialog.tsx
T
2025-07-25 22:49:06 +09:00

503 lines
29 KiB
TypeScript

'use client';
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogFooter,
DialogClose,
Button,
Input,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Select,
SelectTrigger,
SelectContent,
SelectItem,
SelectValue,
Checkbox
} from "@common/components";
import { FormItem, FormControl, FormField, Form } from "@/shared/ui/form";
import { type LinkTableColData, type LinkTable } from "@/entities/link";
import dayjs from "dayjs";
import type { UseFormReturn } from "react-hook-form";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { useState, useEffect } from "react";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
interface LinkTableDialogProps {
dialogOpen: boolean;
onOpenChange: (val: boolean) => void;
form: UseFormReturn<LinkTableColData>;
tableInfo: LinkTable;
insertLinkTableCol: (data: LinkTableColData) => void;
updateLinkTableCol: (data: LinkTableColData) => void;
}
function LinkTableDialog({ dialogOpen, onOpenChange, form, tableInfo, insertLinkTableCol, updateLinkTableCol }: LinkTableDialogProps) {
const isModifyMode = !!form.getValues('col_sn');
const { confirm } = useConfirm();
const [onConfirm, setOnConfirm] = useState<boolean>(false);
const [useColSeq, setUseColSeq] = useState<boolean>(false);
const handleConfirm = async (callback: () => Promise<void>) => {
setOnConfirm(true);
await callback();
setOnConfirm(false);
};
const handleSubmit = async (data: LinkTableColData) => {
const confirmMsg = isModifyMode ? '수정 하시겠습니까?' : '저장 하시겠습니까?';
await handleConfirm(async () => {
if (await confirm(confirmMsg)) {
if (!isModifyMode) {
insertLinkTableCol({
...data,
link_sn: tableInfo.link_sn,
tbl_sn: tableInfo.tbl_sn,
});
} else {
updateLinkTableCol({
...data,
link_sn: tableInfo.link_sn,
tbl_sn: tableInfo.tbl_sn,
});
}
}
});
};
const handleCheckColSeqValue = (check: boolean | string) => {
if (check) {
setUseColSeq(false);
form.setValue('col_seq', null);
} else {
setUseColSeq(true);
}
};
useEffect(() => {
if (!dialogOpen) {
setUseColSeq(false);
form.reset({
tbl_sn: '',
col_sn: '',
sou_col_nm: '',
sou_col_korn_nm: '',
sou_col_data_frm: '',
sou_col_sz: null,
trsf_col_nm: '',
trsf_col_korn_nm: '',
trsf_col_data_frm: '',
trsf_col_sz: null,
col_seq: null,
pk_yn: 'N',
mdfcn_dt: '',
mdfr: '',
});
}
if (isModifyMode && form.getValues('col_seq')) {
setUseColSeq(true);
}
}, [dialogOpen]);
return (
<Dialog
open={dialogOpen}
onOpenChange={(open) => {
onOpenChange(open);
}}
>
<DialogTrigger asChild>
<Button color="green" className="h-[3.2rem]" onClick={() => onOpenChange(true)}>행 추가</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[55rem]">
<DialogHeader>
<DialogTitle>
{tableInfo.trsf_tbl_korn_nm} ({tableInfo.tbl_sn})
</DialogTitle>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)}>
<div className="card">
<Table variant="secondary">
<colgroup>
<col width="30%" />
<col width="70%" />
</colgroup>
<TableBody>
{isModifyMode &&
<TableRow>
<TableHead>컬럼 일련번호</TableHead>
<TableCell>
<FormField
control={form.control}
name="col_sn"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
disabled
/>
</FormControl>
</FormItem>
)}
/>
</TableCell>
</TableRow>
}
<TableRow>
<TableHead>* 원천컬럼명</TableHead>
<TableCell>
<FormField
control={form.control}
name="sou_col_nm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.sou_col_nm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.sou_col_nm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>* 원천컬럼 한글명</TableHead>
<TableCell>
<FormField
control={form.control}
name="sou_col_korn_nm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.sou_col_korn_nm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.sou_col_korn_nm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>* 원천컬럼 데이터 형식</TableHead>
<TableCell>
<FormField
control={form.control}
name="sou_col_data_frm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.sou_col_data_frm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.sou_col_data_frm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>원천컬럼 크기</TableHead>
<TableCell>
<FormField
control={form.control}
name="sou_col_sz"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
type="number"
min={0}
max={99999999999999}
onChange={(e) => {
const onlyDigits = e.target.value.replace(/\D/g, "").slice(0, 14);
field.onChange(onlyDigits); // react-hook-form에 반영
}}
/>
</FormControl>
<p className="text-gray-500 text-base pt-2">
※ 14자리까지 입력 가능합니다.
</p>
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>PK 여부</TableHead>
<TableCell>
<FormField
control={form.control}
name="pk_yn"
render={({ field }) => (
<FormItem>
<FormControl>
<Select value={field.value ?? "N"} onValueChange={field.onChange}>
<SelectTrigger id="liResultCode" className="w-[10rem] mr-4">
<SelectValue placeholder="아니오"></SelectValue>
</SelectTrigger>
<SelectContent>
<SelectItem value="Y">예</SelectItem>
<SelectItem value="N">아니오</SelectItem>
</SelectContent>
</Select>
</FormControl>
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>* 변환컬럼명</TableHead>
<TableCell>
<FormField
control={form.control}
name="trsf_col_nm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.trsf_col_nm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.trsf_col_nm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>* 변환컬럼 한글명</TableHead>
<TableCell>
<FormField
control={form.control}
name="trsf_col_korn_nm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.trsf_col_korn_nm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.trsf_col_korn_nm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>* 변환컬럼 데이터 형식</TableHead>
<TableCell>
<FormField
control={form.control}
name="trsf_col_data_frm"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
/>
</FormControl>
{form.formState.errors.trsf_col_data_frm && (
<p className="text-red-500 text-base pt-2">
{form.formState.errors.trsf_col_data_frm.message}
</p>
)}
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>변환컬럼 크기</TableHead>
<TableCell>
<FormField
control={form.control}
name="trsf_col_sz"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
type="number"
min={0}
max={99999999999999}
onChange={(e) => {
const onlyDigits = e.target.value.replace(/\D/g, "").slice(0, 14);
field.onChange(onlyDigits); // react-hook-form에 반영
}}
/>
</FormControl>
<p className="text-gray-500 text-base pt-2">
※ 14자리까지 입력 가능합니다.
</p>
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>컬럼 매칭 순서</TableHead>
<TableCell>
<FormField
control={form.control}
name="col_seq"
render={({ field }) => (
<FormItem>
<div className="flex items-center gap-x-2 mb-4">
<Checkbox id="useColSeq" className="!border-gray-600" checked={!useColSeq} onCheckedChange={(check) => handleCheckColSeqValue(check)} />
<label htmlFor="useColSeq" className="text-gray-600">사용안함</label>
</div>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
autoComplete="off"
type="number"
min={0}
disabled={!useColSeq}
max={999}
onChange={(e) => {
const onlyDigits = e.target.value.replace(/\D/g, "").slice(0, 3);
field.onChange(onlyDigits); // react-hook-form에 반영
}}
/>
</FormControl>
<p className="text-gray-500 text-base pt-2">
※ 3자리까지 입력 가능합니다.
</p>
</FormItem>
)}
/>
</TableCell>
</TableRow>
{isModifyMode &&
<>
<TableRow>
<TableHead>수정자</TableHead>
<TableCell>
<FormField
control={form.control}
name="mdfr"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ?? ""}
className="!text-[1.3rem]"
disabled
/>
</FormControl>
</FormItem>
)}
/>
</TableCell>
</TableRow>
<TableRow>
<TableHead>수정일시</TableHead>
<TableCell>
<FormField
control={form.control}
name="mdfcn_dt"
render={({ field }) => (
<FormItem>
<FormControl>
<Input
{...field}
value={field.value ? dayjs(field.value).format('YYYY-MM-DD') : ""}
className="!text-[1.3rem]"
disabled
/>
</FormControl>
</FormItem>
)}
/>
</TableCell>
</TableRow>
</>
}
</TableBody>
</Table>
</div>
<DialogFooter>
<Button type="submit">저장</Button>
<DialogClose asChild>
<Button color="white">취소</Button>
</DialogClose>
</DialogFooter>
</form>
</Form>
<ConfirmDialog isOpen={onConfirm} />
</DialogContent>
</Dialog>
)
}
export { LinkTableDialog };