118 lines
4.1 KiB
TypeScript
118 lines
4.1 KiB
TypeScript
import { useState } from "react";
|
|
import {
|
|
Button,
|
|
Dialog,
|
|
DialogContent,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@common/components";
|
|
import type { UpperCodeCandidateItem } from "@/entities/statistics/model/ppltn/statistics-domestic-population-interface";
|
|
|
|
interface UpperCodeSelectDialogProps {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
candidates: UpperCodeCandidateItem[];
|
|
onSelect: (item: UpperCodeCandidateItem) => void;
|
|
}
|
|
|
|
export const UpperCodeSelectDialog = ({
|
|
open,
|
|
onOpenChange,
|
|
candidates,
|
|
onSelect,
|
|
}: UpperCodeSelectDialogProps) => {
|
|
const [selectedCode, setSelectedCode] = useState<string | null>(null);
|
|
|
|
const handleSelect = () => {
|
|
const item = candidates.find((c) => c.adstCd === selectedCode);
|
|
if (!item) return;
|
|
onSelect(item);
|
|
onOpenChange(false);
|
|
setSelectedCode(null);
|
|
};
|
|
|
|
const handleClose = () => {
|
|
onOpenChange(false);
|
|
setSelectedCode(null);
|
|
};
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={handleClose}>
|
|
<DialogContent className="max-w-[50rem]" aria-describedby={undefined}>
|
|
<DialogHeader>
|
|
<DialogTitle>상위 코드 리스트</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
{/* 테이블 */}
|
|
<div className="border border-gray-300 rounded overflow-hidden">
|
|
<table className="w-full text-[1.3rem]">
|
|
<thead className="sticky top-0 z-10">
|
|
<tr className="bg-blue-600 text-white">
|
|
<th className="py-[0.8rem] px-[1rem] text-center font-semibold border-r border-blue-500 w-[40%]">
|
|
코드
|
|
</th>
|
|
<th className="py-[0.8rem] px-[1rem] text-center font-semibold">
|
|
동명
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
{/* 스크롤 영역 분리 */}
|
|
<div className="max-h-[40rem] overflow-y-auto">
|
|
<table className="w-full text-[1.3rem]">
|
|
<tbody>
|
|
{candidates.length === 0 ? (
|
|
<tr>
|
|
<td colSpan={2} className="py-[1rem] text-center text-gray-400">
|
|
후보 코드가 없습니다.
|
|
</td>
|
|
</tr>
|
|
) : (
|
|
candidates.map((item) => (
|
|
<tr
|
|
key={item.adstCd}
|
|
onClick={() => setSelectedCode(item.adstCd)}
|
|
className={`cursor-pointer border-b border-gray-200 transition-colors
|
|
${selectedCode === item.adstCd
|
|
? "bg-blue-100"
|
|
: "hover:bg-gray-50"
|
|
}`}
|
|
>
|
|
<td className="py-[0.7rem] px-[1rem] text-center border-r border-gray-200 w-[40%]">
|
|
{item.adstCd}
|
|
</td>
|
|
<td className="py-[0.7rem] px-[1rem] text-center">
|
|
{item.adstDstrNm}
|
|
</td>
|
|
</tr>
|
|
))
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter className="flex flex-col gap-2">
|
|
<Button
|
|
type="button"
|
|
color="primary"
|
|
disabled={!selectedCode}
|
|
onClick={handleSelect}
|
|
className="w-full py-[1rem] text-[1.4rem]"
|
|
>
|
|
선택
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
color="gray"
|
|
onClick={handleClose}
|
|
className="w-full py-[1rem] text-[1.4rem]"
|
|
>
|
|
닫기
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}; |