- DynamicItemForm 컴포넌트 구조 생성 - DynamicField: 필드 타입별 렌더링 - DynamicSection: 섹션 단위 렌더링 - DynamicFormRenderer: 페이지 전체 렌더링 - 필드 타입별 컴포넌트 (TextField, NumberField, DropdownField, CheckboxField, DateField, FileField, CustomField) - 커스텀 훅 (useDynamicFormState, useFormStructure, useConditionalFields) - DataTable 공통 컴포넌트 (테이블, 페이지네이션, 검색, 탭필터, 통계카드) - ItemFormWrapper: Feature Flag 기반 폼 선택 - 타입 정의 및 문서화 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
92 lines
2.4 KiB
TypeScript
92 lines
2.4 KiB
TypeScript
/**
|
|
* CheckboxField Component
|
|
*
|
|
* 체크박스/스위치 필드 (checkbox, switch)
|
|
*/
|
|
|
|
'use client';
|
|
|
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
import { Switch } from '@/components/ui/switch';
|
|
import { Label } from '@/components/ui/label';
|
|
import type { DynamicFieldProps } from '../types';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
export function CheckboxField({
|
|
field,
|
|
value,
|
|
error,
|
|
onChange,
|
|
onBlur,
|
|
disabled,
|
|
}: DynamicFieldProps) {
|
|
const isSwitch = field.field_type === 'switch';
|
|
const checked = value === true || value === 'true' || value === 1;
|
|
|
|
const handleChange = (newChecked: boolean) => {
|
|
onChange(newChecked);
|
|
onBlur();
|
|
};
|
|
|
|
if (isSwitch) {
|
|
return (
|
|
<div className="space-y-2">
|
|
<div className="flex items-center justify-between">
|
|
<Label
|
|
htmlFor={field.field_key}
|
|
className={cn(
|
|
'text-sm font-medium',
|
|
field.is_required && "after:content-['*'] after:ml-0.5 after:text-red-500"
|
|
)}
|
|
>
|
|
{field.field_name}
|
|
</Label>
|
|
<Switch
|
|
id={field.field_key}
|
|
checked={checked}
|
|
onCheckedChange={handleChange}
|
|
disabled={disabled || field.is_readonly}
|
|
/>
|
|
</div>
|
|
|
|
{field.help_text && !error && (
|
|
<p className="text-xs text-muted-foreground">{field.help_text}</p>
|
|
)}
|
|
|
|
{error && <p className="text-xs text-red-500">{error}</p>}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id={field.field_key}
|
|
checked={checked}
|
|
onCheckedChange={handleChange}
|
|
disabled={disabled || field.is_readonly}
|
|
/>
|
|
<Label
|
|
htmlFor={field.field_key}
|
|
className={cn(
|
|
'text-sm font-medium cursor-pointer',
|
|
field.is_required && "after:content-['*'] after:ml-0.5 after:text-red-500",
|
|
(disabled || field.is_readonly) && 'cursor-not-allowed opacity-50'
|
|
)}
|
|
>
|
|
{field.field_name}
|
|
</Label>
|
|
</div>
|
|
|
|
{field.help_text && !error && (
|
|
<p className="text-xs text-muted-foreground ml-6">{field.help_text}</p>
|
|
)}
|
|
|
|
{error && <p className="text-xs text-red-500 ml-6">{error}</p>}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default CheckboxField;
|