import { useState } from 'react'; import { createPortal } from 'react-dom'; import { apiClient, getApiErrorMessage } from '../../lib/apiClient'; import type { TeamMemberForm } from '../../hooks/useTeamMembersAdmin'; import { EMPTY_MEMBER_FORM } from '../../hooks/useTeamMembersAdmin'; import { TeamMemberAvatar } from '../dashboard/TeamMemberAvatar'; import { getCellLabel } from '../../lib/teamStatus'; import type { TeamMemberBrief } from '../../types'; const CELL_OPTIONS = [ { value: '리더', label: '리더 (팀장)' }, { value: 'HR', label: '인사' }, { value: '총무', label: '총무' }, ]; const RANK_OPTIONS = ['수석연구원', '책임연구원', '선임연구원', '연구원', '주임', '사원']; const ROLE_OPTIONS = ['팀장', '셀장', '팀원']; interface TeamMemberFormModalProps { mode: 'add' | 'edit'; initial?: TeamMemberForm; onSave: (form: TeamMemberForm) => void | Promise; onClose: () => void; saving?: boolean; } export function TeamMemberFormModal({ mode, initial = EMPTY_MEMBER_FORM, onSave, onClose, saving = false, }: TeamMemberFormModalProps) { const [form, setForm] = useState(initial); const [uploadingPhoto, setUploadingPhoto] = useState(false); const set = (key: K, value: TeamMemberForm[K]) => setForm((prev) => ({ ...prev, [key]: value })); const handlePhotoFile = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setUploadingPhoto(true); try { const fd = new FormData(); fd.append('photo', file); const { data } = await apiClient.post<{ url: string }>('/team-members/photo', fd); set('photoUrl', data.url); } catch (err) { alert(getApiErrorMessage(err, '사진 업로드에 실패했습니다.')); } finally { setUploadingPhoto(false); e.target.value = ''; } }; const preview: TeamMemberBrief = { id: 'preview', name: form.name || '이름', rank: form.rank || null, role: form.role || null, cell: form.cell || null, contact: form.contact || null, photoUrl: form.photoUrl || null, }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!form.name.trim()) return; await onSave(form); }; return createPortal(
e.stopPropagation()}>

{mode === 'add' ? '팀원 추가' : '팀원 수정'}

{form.name || '이름'}
{[form.rank, form.role].filter(Boolean).join(' · ') || '직급 · 직책'}
{getCellLabel(form.cell) || '셀'}
프로필 사진
로컬 서버 uploads/team/ 에 저장됩니다
set('photoUrl', e.target.value)} placeholder="또는 URL 직접 입력 (/uploads/team/...)" />
{RANK_OPTIONS.map((r) => {ROLE_OPTIONS.map((r) =>
, document.body, ); }