import { useEffect, useState } from 'react' import { provisionChannels, updateContact, type Contact, type Org, type ProvisionResult, } from '../api/client' import ConfirmDialog from './ConfirmDialog' import StatusBadge from './StatusBadge' // 엑셀처럼 한 사람이 한 행이다. 셀이 null이면 그 역할에 해당 항목이 없다는 뜻(- 표시). // aria-label은 "행 제목 + 항목"으로 유일하게 만들어 라벨 중복 없이 접근 가능하게 한다. const CONTACT_COLUMNS = ['부서명', '담당자명', '직급/직함', '연락처', '이메일', '배정일'] interface ContactCell { key: keyof Contact label: string type?: string } const CONTACT_ROWS: { title: string; cells: (ContactCell | null)[] }[] = [ { title: '신청기관 담당자', cells: [ { key: 'deptName', label: '신청기관 담당자 부서명' }, { key: 'managerName', label: '신청기관 담당자 담당자명' }, { key: 'managerTitle', label: '신청기관 담당자 직급/직함' }, { key: 'managerPhone', label: '신청기관 담당자 연락처' }, { key: 'managerEmail', label: '신청기관 담당자 이메일' }, null, ], }, { title: '문정원 담당자', cells: [ { key: 'mjDeptName', label: '문정원 담당자 부서명' }, { key: 'mjManagerName', label: '문정원 담당자 담당자명' }, null, { key: 'mjManagerPhone', label: '문정원 담당자 연락처' }, { key: 'mjManagerEmail', label: '문정원 담당자 이메일' }, null, ], }, { title: '담당 변호사', cells: [ null, { key: 'lawyerName', label: '담당 변호사 성명' }, null, { key: 'lawyerPhone', label: '담당 변호사 연락처' }, { key: 'lawyerEmail', label: '담당 변호사 이메일' }, { key: 'lawyerAssignedDate', label: '담당 변호사 배정일', type: 'date' }, ], }, ] function emptyContact(org: Org): Contact { return { deptName: org.deptName ?? '', managerName: org.managerName ?? '', managerTitle: org.managerTitle ?? '', managerPhone: org.managerPhone ?? '', managerEmail: org.managerEmail ?? '', mjDeptName: org.mjDeptName ?? '', mjManagerName: org.mjManagerName ?? '', mjManagerPhone: org.mjManagerPhone ?? '', mjManagerEmail: org.mjManagerEmail ?? '', lawyerName: org.lawyerName ?? '', lawyerPhone: org.lawyerPhone ?? '', lawyerEmail: org.lawyerEmail ?? '', lawyerAssignedDate: org.lawyerAssignedDate ?? '', } } const REQUIRED_FIELDS: (keyof Contact)[] = [ 'deptName', 'managerName', 'managerPhone', 'managerEmail', ] function ContactEditTable({ contact, onChange, }: { contact: Contact onChange: (key: keyof Contact, value: string) => void }) { return (
| 구분 | {CONTACT_COLUMNS.map((col) => ({col} | ))}
|---|---|
| {row.title} | {row.cells.map((cell, i) => ({cell ? ( onChange(cell.key, e.target.value)} /> ) : ( - )} | ))}
신청기관 담당자의 부서명·담당자명·연락처·이메일은 채널 생성을 위해 필수입니다.
{error}
} {result && (문정원 채널: {outcomeLabel(result.mj)}
법률검토 채널: {outcomeLabel(result.law)}
{result.mj === 'FAILED' && result.law === 'FAILED' ? (문정원 채널과 법률검토 채널 모두 생성에 실패했습니다. 아직 만들어진 채널이 없으니 [채널 생성]을 다시 눌러도 안전합니다.
) : ( <> {result.law === 'FAILED' && (법률검토 채널 생성에 실패했습니다. 문정원 채널은 그대로 남아 있으니 [채널 생성]을 다시 눌러도 안전합니다. 없는 채널만 다시 만듭니다.
)} {result.mj === 'FAILED' && (문정원 채널 생성에 실패했습니다. 법률검토 채널은 그대로 남아 있으니 [채널 생성]을 다시 눌러도 안전합니다. 없는 채널만 다시 만듭니다.
)} > )} {result.message && ({result.message}
)}