'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import { FoxButton } from '@fox/core/components/fox-button'; import { FoxButtonGroup } from '@fox/core/components/fox-button-group'; import { FoxListContainer, type FoxListColumn, } from '@fox/core/components/fox-list-container'; import { FoxSelectText } from '@fox/core/components/fox-select-text'; import { FoxStatusIndicator } from '@fox/core/components/fox-status-indicator'; import { formatActiveLabel, formatDuplicableLabel, formatLimitPoint, formatOptionalValue, formatPoint, type PointStandard, } from '@/lib/domain/point-standard'; import { formatCommonCode, type CommonCode } from '@/lib/domain/common-code'; import { POINT_STANDARDS_PATH, POINT_STANDARD_PAGE_SIZE_OPTIONS, buildPointStandardHref, type PointStandardPageSize, type PointStandardQuery, } from '@/lib/domain/point-standard-query'; import { PointStandardFormModal } from './point-standard-form-modal'; import { PointStandardRowActions } from './point-standard-row-actions'; interface PointStandardListProps { items: PointStandard[]; query: PointStandardQuery; currentPage: number; totalPages: number; totalCount: number; /** 공통코드 `CODE_GROUP.pointEvent` — 등록 팝업의 이벤트 선택지. */ eventCodes: readonly CommonCode[]; } export function PointStandardList({ items, query, currentPage, totalPages, totalCount, eventCodes, }: PointStandardListProps) { const router = useRouter(); const [isCreateOpen, setIsCreateOpen] = useState(false); function go(patch: Partial) { router.replace(buildPointStandardHref(query, { ...patch, page: 1 })); } const columns: FoxListColumn[] = [ { key: 'no', header: '번호', width: 80, render: (_row, index) => (currentPage - 1) * query.pageSize + index + 1, }, { key: 'eventCode', header: '이벤트/구분', width: 140, emphasis: true, // 표에 없는 코드는 지어내지 않고 코드 그대로 보여준다(formatCommonCode 규칙). render: (row) => formatCommonCode(eventCodes, row.eventCode), }, { key: 'point', header: '포인트', width: 100, align: 'end', render: (row) => formatPoint(row.point), }, { key: 'limitPoint', header: '제한포인트', width: 120, align: 'end', render: (row) => formatLimitPoint(row.limitPoint), }, { key: 'isDuplicable', header: '중복여부', width: 120, render: (row) => ( ), }, { key: 'description', header: '설명', width: 320 }, { key: 'isActive', header: '사용여부', width: 120, render: (row) => ( ), }, { key: 'updatedAt', header: '수정일시', width: 160, render: (row) => formatOptionalValue(row.updatedAt), }, { key: 'actions', header: '관리', width: 120, render: (row) => , }, ]; return ( <> title="포인트 기준관리 목록" breadcrumb={[ { label: '홈', href: '/' }, { label: '포인트관리' }, { label: '포인트 기준관리' }, ]} caption="포인트 기준관리 목록" columns={columns} rows={items} rowKey={(row) => row.id} totalCount={totalCount} emptyMessage="검색 결과가 없습니다. 다른 검색어로 다시 시도해 주세요." sorts={ ({ value: String(size), label: `${size}개씩 보기`, }))} value={String(query.pageSize)} onValueChange={(value) => go({ pageSize: Number(value) as PointStandardPageSize }) } /> } searchFields={[]} keyword={query.keyword} searchPlaceholder="검색어를 입력하세요." toolbarActions={ router.replace(POINT_STANDARDS_PATH)} /> } page={currentPage} totalPages={totalPages} buildHref={(patch) => buildPointStandardHref(query, { page: Number(patch.page ?? 1) }) } onQueryChange={(patch) => { if (patch.keyword !== undefined) { go({ keyword: String(patch.keyword ?? '') }); } }} /> {isCreateOpen && ( setIsCreateOpen(false)} /> )} ); }