Files
frontend/apps/sn/app/components/ui/verticalTable.tsx
T
swcho 12baddecbf fix:
- 사업유형 SelectArray에 ‘AAAAA‘ 항목 빼고 '전체' 항목 추가
- 하수관로, 맨홀에도 '전체' 항목 추가
- 맨홀에서 용도 조회 조건이 적용 안되는 에러 수정
- 맨홀 조회 결과 컬럼에서 '재질'을 '용도'로 변경
2025-08-13 13:31:07 +09:00

223 lines
8.0 KiB
TypeScript

import UiPageNations from "@common/business_components/ui/table/uiPageNations";
import { Table, TableBody, TableCell, TableRow, Button } from "@common/components";
import { useEffect, useState } from "react";
type UiTableProps = {
headName: React.ReactNode | undefined;
tableName1?: React.ReactNode | undefined;
tableData: { [key: string]: string | number | boolean | object }[];
headlist: UiHeadProps[];
pageSize: number;
total: number;
children?: Record<string, React.ReactNode> | undefined;
cellClick: ((index: number | undefined, headId: string) => void) | undefined;
onPageChange: (page: number) => void;
className?: string;
resetPageNo?: boolean;
isEditable?: boolean;
tableName2?: React.ReactNode | undefined;
tableData2?: { [key: string]: string | number | boolean | object }[];
headlist2?: UiHeadProps[];
pageSize2?: number;
total2?: number;
children2?: Record<string, React.ReactNode> | undefined;
cellClick2?: ((index: number | undefined, headId: string) => void) | undefined;
onPageChange2?: (page: number) => void;
className2?: string;
resetPageNo2?: boolean;
isEditable2?: boolean;
showSecondTable?: boolean;
showSaveButton?: boolean;
onSaveClick?: () => void;
onFormDataChange?: (formData: { [key: string]: string | number | boolean }) => void; // 추가
};
type UiHeadProps = {
id: string;
title: string;
align?: string;
type?: string;
options?: string[];
placeholder?: string;
};
export function VerticalTable({
headName,
tableName1,
tableData,
headlist,
pageSize,
total,
children,
onPageChange,
className = "",
resetPageNo = false,
isEditable = false,
tableName2,
headlist2,
isEditable2 = false,
showSecondTable = false,
showSaveButton = false,
onSaveClick,
onFormDataChange,
}: UiTableProps) {
const [cur, setCur] = useState<number>(1);
const [formData, setFormData] = useState<{ [key: string]: string | number | boolean }>({});
useEffect(() => {
if (resetPageNo) {
setCur(1);
onPageChange(1);
}
}, [onPageChange, resetPageNo]);
useEffect(() => {
if (tableData.length > 0 && tableData[0]) {
// 깊은 복사를 통해 새로운 객체 생성
const newData = JSON.parse(JSON.stringify(tableData[0]));
setFormData(newData);
console.log("Form data initialized:", newData); // 디버깅용
}
}, [tableData]);
const handleInputChange = (id: string, value: string | number | boolean) => {
console.log(`Input change: ${id} = ${value}`); // 디버깅용
const newFormData = {
...formData,
[id]: value,
};
console.log("New form data:", newFormData); // 디버깅용
setFormData(newFormData);
// 폼 데이터가 변경될 때마다 부모에게 알림
if (onFormDataChange) {
onFormDataChange(newFormData);
}
};
const handlePageChange = (page: number) => {
setCur(page);
onPageChange(page);
};
return (
<>
{headName ? (
<div className="card-header flex items-center justify-between">
<h3 className="text-2xl mx-3 font-medium text-label">{headName}</h3>
{showSaveButton && onSaveClick && (
<Button
onClick={onSaveClick}
className="px-4 mr-3 py-2 bg-blue-600 text-white rounded-sm text-sm font-medium hover:bg-blue-700"
>
저장
</Button>
)}
</div>
) : null}
<div className={`card !m-[1.2rem] !p-0r ${className}`}>
{tableName1 && ( // tableName prop이 있으면 표시
<div className="text-xl font-semibold my-2 mx-3">{tableName1}</div>
)}
<Table variant="secondary">
<TableBody className="text-center">
{headlist?.map((head) => (
<TableRow key={head.id}>
{/* 컬럼 제목 */}
<TableCell className={`font-bold bg-blue-100 text-xs w-[120px] whitespace-nowrap`}>
{head.title}
</TableCell>
{/* 데이터 값 또는 입력 필드 */}
<TableCell className="text-xs">
{children && children[head.id] ? children[head.id] : isEditable ? (
head.type === "select" ? (
<select
id={head.id}
value={String(formData[head.id]) ?? "-"}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full border border-gray-300 rounded-sm px-2 py-1 text-xl border-radius-0"
>
{head.options?.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
) : head.type === "input" ? (
<input
id={head.id}
type="text"
value={String(formData[head.id] ?? "")}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
/>
) : (
<span>{formData[head.id] ?? "-"}</span>
)
) : (
<span>{formData[head.id] ?? "-"}</span>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{tableName2 && ( // tableName prop이 있으면 표시
<div className="text-xl font-semibold mt-8 my-2 mx-3">{tableName2}</div>
)}
{showSecondTable && (
<Table variant="secondary">
<TableBody className="text-center">
{headlist2?.map((head) => (
<TableRow key={head.id}>
{/* 컬럼 제목 */}
<TableCell className={`font-bold bg-blue-100 text-xs w-[120px] whitespace-nowrap`}>
{head.title}
</TableCell>
{/* 데이터 값 또는 입력 필드 */}
<TableCell className="text-xs">
{children && children[head.id] ? children[head.id] : isEditable2 ? (
head.type === "select" ? (
<select
id={head.id}
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full border border-gray-300 rounded-sm px-2 py-1 text-xl border-radius-0"
>
{head.options?.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
) : head.type === "input" ? (
<input
id={head.id}
type="text"
value={formData[head.id] !== undefined ? String(formData[head.id]) : ""}
onChange={(e) => handleInputChange(head.id, e.target.value)}
className="w-full text-xl border-radius-0 border border-gray-300 rounded-sm px-2 py-1"
placeholder={head.placeholder}
/>
) : (
<span>{formData[head.id] ?? "-"}</span>
)
) : (
<span>{formData[head.id] ?? "-"}</span>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}
{total > 0 && (
<UiPageNations
total={total}
cur={cur}
pageSize={pageSize}
onPageChange={handlePageChange}
/>
)}
</div>
</>
);
}