Takazudo Modular Styleguide

MDX/Addac120sBundleTable

Default
English

Component Source

addac120s-bundle-table.tsx

import {
  ADDAC120S_SERIES_SLUGS,
  bundleEconomics,
  NameCell,
  yen,
  PRICE_CLASS,
  SET_PRICE_CLASS,
  SMALLER_CLASS,
} from '@/lib/data/addac120s-series';
import { productsMapping } from '@/lib/data/products-mapping';
import { Table } from '@components/article/table';
import type { Locale } from '@/lib/i18n/types';

interface Addac120sBundleTableProps {
  locale?: Locale;
}

const BUNDLE_COL = {
  ja: {
    product: '商品名',
    setPrice: 'セット価格(税込)',
    sum: '単価合計(税込)',
    discount: 'バンドルディスカウント',
  },
  en: {
    product: 'Product',
    setPrice: 'Set price (incl. tax)',
    sum: 'Total of unit prices (incl. tax)',
    discount: 'Bundle discount',
  },
} as const;

/**
 * ADDAC120s Four Strings — bundle-discount comparison table only.
 *
 * Columns: 商品名 / セット価格(税込)/ 単価合計(税込)/ バンドルディスカウント,
 * with locale-aware headers. Renders only bundle rows; no H2/H3/caption.
 * Embeddable as a standalone MDX block so headings can be authored in MDX itself.
 *
 * Prices render in the Futura style; non-price text renders one type-scale step
 * smaller (text-sm relative to the price cells).
 *
 * Plain SSR component (no island wrapper) — safe to import productsMapping directly.
 */
export function Addac120sBundleTable({ locale = 'ja' }: Addac120sBundleTableProps) {
  const bundleCol = BUNDLE_COL[locale];
  const { bundleSlugs } = ADDAC120S_SERIES_SLUGS;

  return (
    <Table>
      <thead>
        <tr>
          <th className={`text-left ${SMALLER_CLASS}`}>{bundleCol.product}</th>
          <th className={`text-left text-zd-strong ${SMALLER_CLASS}`}>{bundleCol.setPrice}</th>
          <th className={`text-left ${SMALLER_CLASS}`}>{bundleCol.sum}</th>
          <th className={`text-left ${SMALLER_CLASS}`}>{bundleCol.discount}</th>
        </tr>
      </thead>
      <tbody>
        {bundleSlugs.map((slug) => {
          const product = productsMapping[slug];
          // Defensive guard — getAddac120sSeriesSlugs() pre-filters unknown slugs,
          // but guards against future catalog changes before a data rebuild.
          if (!product) return null;
          const price = typeof product.price === 'number' ? product.price : null;
          const econ =
            price != null && product.bundle != null
              ? bundleEconomics(product.bundle.componentSlugs, price)
              : null;
          return (
            <tr key={slug}>
              <td className={SMALLER_CLASS}>
                <NameCell slug={slug} locale={locale} />
              </td>
              <td className={SET_PRICE_CLASS}>{price != null ? yen(price) : '—'}</td>
              <td className={PRICE_CLASS}>{econ ? yen(econ.referencePrice) : '—'}</td>
              <td className={PRICE_CLASS}>{econ ? `-${yen(econ.savings)}` : '—'}</td>
            </tr>
          );
        })}
      </tbody>
    </Table>
  );
}

Story Source

addac120s-bundle-table.stories.tsx

import { Addac120sBundleTable } from './addac120s-bundle-table';

/**
 * Addac120sBundleTable
 *
 * Bundle-discount comparison table for the ADDAC120s "Four Strings" series.
 * Columns: 商品名 / セット価格(税込)/ 単価合計(税込)/ バンドルディスカウント.
 * Set price is accented in orange (text-zd-strong); discount shows a -¥ prefix.
 * No H2/H3/caption — embeddable as a standalone MDX block.
 */
export const meta = {
  title: 'MDX/Addac120sBundleTable',
};

/** Japanese (default) */
export const Default = () => <Addac120sBundleTable locale="ja" />;

/** English */
export const English = () => <Addac120sBundleTable locale="en" />;