'use client'; import { useState, useEffect } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Loader2 } from 'lucide-react'; /** * 필드 정의 */ export interface CRUDFieldDefinition { key: string; label: string; type: 'text' | 'select'; placeholder?: string; options?: { value: string; label: string }[]; defaultValue?: string; } export interface GenericCRUDDialogProps { isOpen: boolean; onOpenChange: (open: boolean) => void; mode: 'add' | 'edit'; entityName: string; fields: CRUDFieldDefinition[]; initialData?: Record; onSubmit: (data: Record) => void; isLoading?: boolean; addLabel?: string; editLabel?: string; } /** * 단순 CRUD 다이얼로그 공통 컴포넌트 * * 텍스트 입력 + Select 조합의 단순 폼 다이얼로그를 생성합니다. * RankDialog, TitleDialog 등 동일 패턴의 다이얼로그를 대체합니다. */ export function GenericCRUDDialog({ isOpen, onOpenChange, mode, entityName, fields, initialData, onSubmit, isLoading = false, addLabel = '등록', editLabel = '수정', }: GenericCRUDDialogProps) { const [formData, setFormData] = useState>({}); useEffect(() => { if (isOpen) { if (mode === 'edit' && initialData) { setFormData({ ...initialData }); } else { const defaults: Record = {}; fields.forEach((f) => { defaults[f.key] = f.defaultValue ?? ''; }); setFormData(defaults); } } }, [isOpen, mode, initialData, fields]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const firstTextField = fields.find((f) => f.type === 'text'); if (firstTextField && !formData[firstTextField.key]?.trim()) return; const trimmed: Record = {}; Object.entries(formData).forEach(([k, v]) => { trimmed[k] = v.trim(); }); onSubmit(trimmed); const defaults: Record = {}; fields.forEach((f) => { defaults[f.key] = f.defaultValue ?? ''; }); setFormData(defaults); }; const title = mode === 'add' ? `${entityName} 추가` : `${entityName} 수정`; const submitText = mode === 'add' ? addLabel : editLabel; const firstTextField = fields.find((f) => f.type === 'text'); const isSubmitDisabled = isLoading || (firstTextField ? !formData[firstTextField.key]?.trim() : false); return ( {title}
{fields.map((field, idx) => (
{field.type === 'text' ? ( setFormData((prev) => ({ ...prev, [field.key]: e.target.value })) } placeholder={field.placeholder} autoFocus={idx === 0} disabled={isLoading} /> ) : ( )}
))}
); }