'use client'; import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/navigation'; import Image from 'next/image'; import { PageLayout } from '@/components/organisms/PageLayout'; import { PageHeader } from '@/components/organisms/PageHeader'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { Users, Plus, Trash2, ArrowLeft, Save, Camera, User } from 'lucide-react'; import type { Employee, EmployeeFormData, DepartmentPosition, FieldSettings, } from './types'; import { EMPLOYMENT_TYPE_LABELS, GENDER_LABELS, USER_ROLE_LABELS, USER_ACCOUNT_STATUS_LABELS, EMPLOYEE_STATUS_LABELS, DEFAULT_FIELD_SETTINGS, } from './types'; interface EmployeeFormProps { mode: 'create' | 'edit'; employee?: Employee; onSave: (data: EmployeeFormData) => void; fieldSettings?: FieldSettings; } const initialFormData: EmployeeFormData = { name: '', residentNumber: '', phone: '', email: '', salary: '', bankAccount: { bankName: '', accountNumber: '', accountHolder: '' }, profileImage: '', employeeCode: '', gender: '', address: { zipCode: '', address1: '', address2: '' }, hireDate: '', employmentType: '', rank: '', status: 'active', departmentPositions: [], hasUserAccount: false, userId: '', password: '', confirmPassword: '', role: 'user', accountStatus: 'active', }; export function EmployeeForm({ mode, employee, onSave, fieldSettings = DEFAULT_FIELD_SETTINGS, }: EmployeeFormProps) { const router = useRouter(); const [formData, setFormData] = useState(initialFormData); const [previewImage, setPreviewImage] = useState(null); const fileInputRef = useRef(null); const title = mode === 'create' ? '사원 등록' : '사원 수정'; // 데이터 초기화 useEffect(() => { if (employee && mode === 'edit') { setFormData({ name: employee.name, residentNumber: employee.residentNumber || '', phone: employee.phone || '', email: employee.email || '', salary: employee.salary?.toString() || '', bankAccount: employee.bankAccount || { bankName: '', accountNumber: '', accountHolder: '' }, profileImage: employee.profileImage || '', employeeCode: employee.employeeCode || '', gender: employee.gender || '', address: employee.address || { zipCode: '', address1: '', address2: '' }, hireDate: employee.hireDate || '', employmentType: employee.employmentType || '', rank: employee.rank || '', status: employee.status, departmentPositions: employee.departmentPositions || [], hasUserAccount: !!employee.userInfo, userId: employee.userInfo?.userId || '', password: '', confirmPassword: '', role: employee.userInfo?.role || 'user', accountStatus: employee.userInfo?.accountStatus || 'active', }); } }, [employee, mode]); // 입력 변경 핸들러 const handleChange = (field: keyof EmployeeFormData, value: unknown) => { setFormData(prev => ({ ...prev, [field]: value })); }; // 부서/직책 추가 const handleAddDepartmentPosition = () => { const newDP: DepartmentPosition = { id: String(Date.now()), departmentId: '', departmentName: '', positionId: '', positionName: '', }; setFormData(prev => ({ ...prev, departmentPositions: [...prev.departmentPositions, newDP], })); }; // 부서/직책 삭제 const handleRemoveDepartmentPosition = (id: string) => { setFormData(prev => ({ ...prev, departmentPositions: prev.departmentPositions.filter(dp => dp.id !== id), })); }; // 부서/직책 변경 const handleDepartmentPositionChange = (id: string, field: keyof DepartmentPosition, value: string) => { setFormData(prev => ({ ...prev, departmentPositions: prev.departmentPositions.map(dp => dp.id === id ? { ...dp, [field]: value } : dp ), })); }; // 저장 const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); onSave(formData); }; // 취소 const handleCancel = () => { router.back(); }; // 프로필 이미지 업로드 핸들러 const handleImageUpload = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onloadend = () => { setPreviewImage(reader.result as string); handleChange('profileImage', reader.result as string); }; reader.readAsDataURL(file); } }; // 프로필 이미지 삭제 핸들러 const handleRemoveImage = () => { setPreviewImage(null); handleChange('profileImage', ''); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; return (
{/* 사원 정보 - 프로필 사진 + 기본 정보 */} 사원 정보
{/* 프로필 사진 영역 */} {fieldSettings.showProfileImage && (
{previewImage || formData.profileImage ? ( 프로필 사진 ) : ( )}
{(previewImage || formData.profileImage) && ( )}
)} {/* 기본 정보 필드들 */}
handleChange('name', e.target.value)} placeholder="이름을 입력하세요" required />
handleChange('residentNumber', e.target.value)} placeholder="000000-0000000" />
handleChange('phone', e.target.value)} placeholder="010-0000-0000" />
handleChange('email', e.target.value)} placeholder="email@company.com" />
handleChange('salary', e.target.value)} placeholder="연봉 (원)" />
{/* 급여 계좌 */}
handleChange('bankAccount', { ...formData.bankAccount, bankName: e.target.value })} placeholder="은행명" /> handleChange('bankAccount', { ...formData.bankAccount, accountNumber: e.target.value })} placeholder="계좌번호" /> handleChange('bankAccount', { ...formData.bankAccount, accountHolder: e.target.value })} placeholder="예금주" />
{/* 선택 정보 (사원 상세) */} {(fieldSettings.showEmployeeCode || fieldSettings.showGender || fieldSettings.showAddress) && ( 선택 정보
{fieldSettings.showEmployeeCode && (
handleChange('employeeCode', e.target.value)} placeholder="자동생성 또는 직접입력" />
)} {fieldSettings.showGender && (
)}
{fieldSettings.showAddress && (
handleChange('address', { ...formData.address, zipCode: e.target.value })} placeholder="우편번호" className="w-32" />
handleChange('address', { ...formData.address, address1: e.target.value })} placeholder="기본주소" /> handleChange('address', { ...formData.address, address2: e.target.value })} placeholder="상세주소" />
)}
)} {/* 인사 정보 */} 인사 정보
{fieldSettings.showHireDate && (
handleChange('hireDate', e.target.value)} />
)} {fieldSettings.showEmploymentType && (
)} {fieldSettings.showRank && (
handleChange('rank', e.target.value)} placeholder="직급 입력" />
)} {fieldSettings.showStatus && (
)}
{/* 부서/직책 */} {(fieldSettings.showDepartment || fieldSettings.showPosition) && (
{formData.departmentPositions.length === 0 ? (

부서/직책을 추가해주세요

) : (
{formData.departmentPositions.map((dp) => (
handleDepartmentPositionChange(dp.id, 'departmentName', e.target.value)} placeholder="부서명" className="flex-1" /> handleDepartmentPositionChange(dp.id, 'positionName', e.target.value)} placeholder="직책" className="flex-1" />
))}
)}
)}
{/* 사용자 정보 */}
사용자 정보
handleChange('hasUserAccount', checked)} className="data-[state=checked]:bg-white data-[state=checked]:text-black" />
{formData.hasUserAccount && (
handleChange('userId', e.target.value)} placeholder="사용자 아이디" required={formData.hasUserAccount} />
{mode === 'create' && ( <>
handleChange('password', e.target.value)} placeholder="비밀번호" required={formData.hasUserAccount} />
handleChange('confirmPassword', e.target.value)} placeholder="비밀번호 확인" />
)}
)}
{/* 버튼 영역 */}
); }