File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
'use client';
import { useRouter } from 'next/navigation';
import { FoxBadge } from '@fox/core/components/fox-badge';
import { FoxButton } from '@fox/core/components/fox-button';
import { FoxStatusIndicator } from '@fox/core/components/fox-status-indicator';
import { FoxTable } from '@fox/core/components/fox-table';
import { FoxTableCell } from '@fox/core/components/fox-table-cell';
import { FoxTableRow } from '@fox/core/components/fox-table-row';
import { EMPTY_FIELD_PLACEHOLDER } from '@/lib/domain/merchant-detail';
import { merchantProductNewPath } from '@/lib/domain/merchant-detail-query';
import {
formatProductBadgeLabel,
formatProductPrice,
formatProductVisibilityLabel,
type MerchantProduct,
} from '@/lib/domain/merchant-product';
import { MerchantProductRowActions } from './merchant-product-row-actions';
import styles from './merchant-product-table.module.scss';
interface MerchantProductTableProps {
frcsNo: string;
products: MerchantProduct[];
/** 상세가 아직 저장되지 않은 가맹점 — 백엔드가 메뉴 등록을 거부하므로 추가를 막는다. */
canAdd: boolean;
}
/**
* 기획 BO-MAL-002 ⑥ — 메뉴는 목록으로만 보이고 등록·수정은 별도 화면에서 한다.
* 목록 화면 뼈대(FoxListContainer)는 머리말·검색까지 딸려 와 카드 안에는 표 조각만 놓는다.
*/
export function MerchantProductTable({ frcsNo, products, canAdd }: MerchantProductTableProps) {
const router = useRouter();
return (
<div className={styles.root}>
<div className={styles.toolbar}>
<span className={styles.count}>등록 메뉴 {products.length}건</span>
<FoxButton
type="primary"
size="md"
leadingIcon={<i className="fox-ico fox-ico-Plus" aria-hidden="true" />}
label="메뉴 추가"
disabled={!canAdd}
onAction={() => router.push(merchantProductNewPath(frcsNo))}
/>
</div>
{!canAdd && (
<p className={styles.hint}>상세를 먼저 저장하면 메뉴를 추가할 수 있습니다.</p>
)}
<div className={styles.table}>
<FoxTable type="list" caption="메뉴 목록">
<FoxTableRow head>
<FoxTableCell head width={64} align="center">순서</FoxTableCell>
<FoxTableCell head width={96} align="center">이미지</FoxTableCell>
<FoxTableCell head width={240}>메뉴명</FoxTableCell>
<FoxTableCell head>설명</FoxTableCell>
<FoxTableCell head width={140} align="center">가격</FoxTableCell>
<FoxTableCell head width={180} align="center">배지</FoxTableCell>
<FoxTableCell head width={96} align="center">노출</FoxTableCell>
<FoxTableCell head width={220} align="center">관리</FoxTableCell>
</FoxTableRow>
{products.length === 0 ? (
<FoxTableRow>
<FoxTableCell colSpan={8} align="center">
등록된 메뉴가 없습니다.
</FoxTableCell>
</FoxTableRow>
) : (
products.map((product, index) => (
<FoxTableRow key={product.id}>
<FoxTableCell align="center" label="순서">
{product.sortOrder ?? index + 1}
</FoxTableCell>
<FoxTableCell align="center" label="이미지">
{product.imageUrl ? (
// 백엔드의 공개 이미지 GET — 목록 대표이미지와 같은 이유로 <img>를 쓴다.
// eslint-disable-next-line @next/next/no-img-element
<img className={styles.thumbnail} src={product.imageUrl} alt={`${product.name} 이미지`} />
) : (
EMPTY_FIELD_PLACEHOLDER
)}
</FoxTableCell>
<FoxTableCell emphasis label="메뉴명">{product.name}</FoxTableCell>
<FoxTableCell label="설명">
<span className={styles.description}>
{product.description ?? EMPTY_FIELD_PLACEHOLDER}
</span>
</FoxTableCell>
<FoxTableCell align="center" label="가격">
{formatProductPrice(product.price)}
</FoxTableCell>
<FoxTableCell align="center" label="배지">
{product.badges.length === 0 ? (
EMPTY_FIELD_PLACEHOLDER
) : (
<span className={styles.badges}>
{product.badges.map((badge) => (
<FoxBadge key={badge} type="pastel" color="neutral" size="sm">
{formatProductBadgeLabel(badge)}
</FoxBadge>
))}
</span>
)}
</FoxTableCell>
<FoxTableCell align="center" label="노출">
<FoxStatusIndicator
type={product.isVisible ? 'success' : 'default'}
label={formatProductVisibilityLabel(product.isVisible)}
/>
</FoxTableCell>
<FoxTableCell align="center" label="관리">
<MerchantProductRowActions product={product} />
</FoxTableCell>
</FoxTableRow>
))
)}
</FoxTable>
</div>
</div>
);
}