/** * FormField - 통합 폼 필드 컴포넌트 */ import { ReactNode } from "react"; import { Label } from "../ui/label"; import { Input } from "../ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"; import { Textarea } from "../ui/textarea"; import { AlertCircle } from "lucide-react"; export type FormFieldType = 'text' | 'number' | 'date' | 'select' | 'textarea' | 'custom' | 'password'; export interface SelectOption { value: string; label: string; disabled?: boolean; } export interface FormFieldProps { label: string; required?: boolean; type?: FormFieldType; value?: string | number; onChange?: (value: string) => void; placeholder?: string; disabled?: boolean; error?: string; helpText?: string; options?: SelectOption[]; selectPlaceholder?: string; children?: ReactNode; className?: string; inputClassName?: string; rows?: number; min?: number; max?: number; step?: number; htmlFor?: string; } export function FormField({ label, required = false, type = 'text', value, onChange, placeholder, disabled = false, error, helpText, options = [], selectPlaceholder = "선택하세요", children, className = "", inputClassName = "", rows = 3, min, max, step, htmlFor, }: FormFieldProps) { const renderInput = () => { switch (type) { case 'select': return ( {options.map((option) => ( {option.label} ))} ); case 'textarea': return ( onChange?.(e.target.value)} placeholder={placeholder} disabled={disabled} rows={rows} className={`${error ? 'border-red-500' : ''} ${inputClassName}`} /> ); case 'custom': return children; case 'number': return ( onChange?.(e.target.value)} placeholder={placeholder} disabled={disabled} min={min} max={max} step={step} className={`${error ? 'border-red-500' : ''} ${inputClassName}`} /> ); case 'date': return ( onChange?.(e.target.value)} disabled={disabled} className={`${error ? 'border-red-500' : ''} ${inputClassName}`} /> ); case 'password': return ( onChange?.(e.target.value)} placeholder={placeholder} disabled={disabled} className={`${error ? 'border-red-500' : ''} ${inputClassName}`} /> ); case 'text': default: return ( onChange?.(e.target.value)} placeholder={placeholder} disabled={disabled} className={`${error ? 'border-red-500' : ''} ${inputClassName}`} /> ); } }; return ( {label} {required && *} {renderInput()} {error && ( {error} )} {helpText && !error && ( {helpText} )} ); }
{helpText}