import { useRef, useState } from 'react'; import { message } from 'antd'; import { ModalForm, ProForm, ProFormDatePicker, ProFormDigit, ProFormSelect, ProFormText, ProTable, type ActionType, type ProColumns, } from '@ant-design/pro-components'; import { useQuery } from '@tanstack/react-query'; import dayjs from 'dayjs'; import PageContainer from '@/components/common/PageContainer'; import CodeBadge from '@/components/common/CodeBadge'; import MoneyText from '@/components/common/MoneyText'; import PermissionButton from '@/components/common/PermissionButton'; import { useCommonCodes } from '@/hooks/useCommonCodes'; import { contractApi, ContractResp, ContractSaveReq, ContractSearchParam } from '@/api/contract'; import { productApi } from '@/api/product'; import { agentApi } from '@/api/agent'; /** * 계약 관리 화면. * API: contractApi.list/create, 등록 모달용 productApi.list / agentApi.list * 보험종류/계약상태/납입주기/판매채널은 공통코드로 불러와 CodeBadge·CodeSelect 에 사용한다. */ export default function ContractList() { const actionRef = useRef(); const [open, setOpen] = useState(false); // 계약 등록 모달 열림 여부 const { data: insuranceCodes = [] } = useCommonCodes('INSURANCE_TYPE'); const { data: statusCodes = [] } = useCommonCodes('CONTRACT_STATUS'); const { data: payCycleCodes = [] } = useCommonCodes('PAY_CYCLE'); const { data: salesChannelCodes = [] } = useCommonCodes('SALES_CHANNEL'); // 등록 모달용 - 상품/설계사 옵션 const { data: products } = useQuery({ queryKey: ['products', 'all'], queryFn: () => productApi.list({ pageSize: 999 }), enabled: open, }); const { data: agents } = useQuery({ queryKey: ['agents', 'all'], queryFn: () => agentApi.list({ pageSize: 999 }), enabled: open, }); // 계약 등록 제출 — 날짜를 문자열로 변환 후 생성 API 호출, 성공 시 목록 새로고침 const onSubmit = async (v: any) => { const req: ContractSaveReq = { ...v, contractDate: v.contractDate ? dayjs(v.contractDate).format('YYYY-MM-DD') : undefined, effectiveDate: v.effectiveDate ? dayjs(v.effectiveDate).format('YYYY-MM-DD') : undefined, }; await contractApi.create(req); message.success('등록 완료'); setOpen(false); actionRef.current?.reload(); return true; }; const columns: ProColumns[] = [ { title: '검색어', dataIndex: 'searchKeyword', hideInTable: true, fieldProps: { placeholder: '계약자/증권번호' } }, { title: '보험종류', dataIndex: 'insuranceType', width: 100, valueType: 'select', valueEnum: Object.fromEntries(insuranceCodes.map((c) => [c.code, { text: c.codeName }])), render: (_, r) => , }, { title: '상태', dataIndex: 'status', width: 90, valueType: 'select', valueEnum: Object.fromEntries(statusCodes.map((c) => [c.code, { text: c.codeName }])), render: (_, r) => , }, { title: '증권번호', dataIndex: 'policyNo', width: 140, search: false }, { title: '계약자', dataIndex: 'contractorName', width: 100, search: false }, { title: '설계사', dataIndex: 'agentName', width: 100, search: false }, { title: '보험사', dataIndex: 'companyName', width: 120, search: false }, { title: '상품', dataIndex: 'productName', width: 220, search: false }, { title: '보험료', dataIndex: 'premium', width: 120, align: 'right', search: false, render: (_, r) => , }, { title: '납입주기', dataIndex: 'payCycle', width: 90, search: false, render: (_, r) => , }, { title: '계약일', dataIndex: 'contractDate', width: 110, search: false }, { title: '판매채널', dataIndex: 'salesChannel', width: 110, search: false, render: (_, r) => r.salesChannelName ?? r.salesChannel ?? '-', }, ]; return ( actionRef={actionRef} rowKey="contractId" columns={columns} scroll={{ x: 1300 }} request={async (params) => { const { current, pageSize, ...rest } = params as any; const res = await contractApi.list({ ...rest, pageNum: current, pageSize }); return { data: res.list, total: res.total, success: true }; }} pagination={{ pageSize: 20, showSizeChanger: true, pageSizeOptions: ['20', '50', '100'], showTotal: (total) => `총 ${total.toLocaleString()}건`, }} search={{ labelWidth: 'auto', searchText: '검색', resetText: '초기화', collapsed: false, collapseRender: false }} options={{ density: false, fullScreen: true, reload: true, setting: true }} toolBarRender={() => [ setOpen(true)}>+ 계약 등록, ]} dateFormatter="string" /> ({ value: a.agentId, label: `${a.agentName} (${a.licenseNo ?? '-'})` })) ?? []} /> ({ value: p.productId, label: `${p.productName} — ${p.companyName}` })) ?? []} /> `${v}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',') }} /> ({ value: c.code, label: c.codeName }))} /> ({ value: c.code, label: c.codeName }))} placeholder="선택 안 함(직판 기본)" /> ); }