- 협상카드 성공률(사용 세션 대비 타결) 집계 추가, 견적 생성 카드선택 순위 정렬·통계 TOP5 - 상품 엑셀: 품목코드·모델명 라벨화, 리드타임 suffix 제거, 공급사 컬럼 신설(등록 후 supplier_items 매핑) - 설정 화면 JSON 불러오기/내보내기(빈 값은 미갱신), IMK 설정 JSON 보관 - 설정·회원 페이지 새로고침 forbidden 수정(자식 loader 가 initAuth 대기) - 협력사·견적 목록도 포털형 카드(툴바+테이블 결합)로 통일
107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
import { DataTable } from '@/components/ui/data-table';
|
|
import { TablePagination } from '@/components/ui/table-pagination';
|
|
import { formatPhoneKR } from '@/lib/phone';
|
|
import type { Partner } from '../types';
|
|
|
|
type PartnerTableProps = {
|
|
data: Partner[];
|
|
selectedIds: string[];
|
|
onSelectionChange: (ids: string[]) => void;
|
|
onRowClick: (part: Partner) => void;
|
|
page: number;
|
|
totalPages: number;
|
|
totalCount: number;
|
|
pageSize: number;
|
|
onPageChange: (page: number) => void;
|
|
/** 툴바와 한 카드로 붙일 때 테이블 자체 테두리/라운드를 죽이는 용도 */
|
|
className?: string;
|
|
};
|
|
|
|
export function PartnerTable({
|
|
data,
|
|
selectedIds,
|
|
onSelectionChange,
|
|
onRowClick,
|
|
page,
|
|
totalPages,
|
|
totalCount,
|
|
pageSize,
|
|
onPageChange,
|
|
className,
|
|
}: PartnerTableProps) {
|
|
return (
|
|
<DataTable
|
|
className={className}
|
|
data={data}
|
|
rowKey={(part) => part.supplier_id}
|
|
onRowClick={onRowClick}
|
|
selection={{ selectedKeys: selectedIds, onSelectionChange }}
|
|
empty="협약된 가용 B2B 파트너사가 존재하지 않습니다."
|
|
footer={
|
|
<TablePagination
|
|
page={page}
|
|
totalPages={totalPages}
|
|
totalCount={totalCount}
|
|
pageSize={pageSize}
|
|
onPageChange={onPageChange}
|
|
label="연동 파트너사"
|
|
unit="개사"
|
|
/>
|
|
}
|
|
columns={[
|
|
{
|
|
header: '협력사명',
|
|
align: 'left',
|
|
headClassName: 'w-2/5',
|
|
cell: (part) => <span className="font-bold text-sm text-foreground">{part.name}</span>,
|
|
},
|
|
{
|
|
header: '협력사코드',
|
|
align: 'left',
|
|
cellClassName: 'font-mono font-medium text-muted-foreground',
|
|
cell: (part) => part.code,
|
|
},
|
|
{
|
|
header: '담당자명 / 담당자 이메일 / 연락처',
|
|
align: 'left',
|
|
mobileBlock: true, // 여러 줄 블록 → 모바일 카드뷰에서 라벨 아래 풀폭
|
|
cell: (part) => (
|
|
<div className="space-y-0.5 font-mono text-xs">
|
|
<div className="text-foreground font-semibold">{part.manager_name}</div>
|
|
<div className="text-[10px] text-muted-foreground">
|
|
{part.manager_email} / {part.manager_contact_number ? formatPhoneKR(part.manager_contact_number) : '-'}
|
|
</div>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
header: '총매출액',
|
|
align: 'right',
|
|
cellClassName: 'font-mono text-muted-foreground',
|
|
cell: (part) => (part.total_revenue != null ? `₩${Number(part.total_revenue).toLocaleString()}` : '-'),
|
|
},
|
|
{
|
|
header: '채팅 계정',
|
|
align: 'center',
|
|
cellClassName: 'font-mono whitespace-nowrap',
|
|
cell: (part) =>
|
|
part.account_login_id ? (
|
|
<span className="text-xs text-foreground">
|
|
{part.account_login_id}
|
|
{part.account_status === 2 && <span className="ml-1 text-[10px] text-rose-500">비활성</span>}
|
|
</span>
|
|
) : (
|
|
<span className="text-[10px] text-muted-foreground">미발급</span>
|
|
),
|
|
},
|
|
{
|
|
header: '작성자',
|
|
align: 'center',
|
|
cellClassName: 'text-muted-foreground whitespace-nowrap',
|
|
cell: (part) => part.creator_name ?? '-',
|
|
},
|
|
]}
|
|
/>
|
|
);
|
|
}
|