ElementsPanel.tsx 4.21 KB
import React from 'react';
import { ScrollArea } from '../../ui/scroll-area';
import type { ElementLibraryCategory, ElementType } from '../../../types/labelTemplate';

/** 左侧标签库:四类分组(与产品图一致);打印时输入项可带 config 以正确显示为 input */
const ELEMENT_CATEGORIES: {
  title: ElementLibraryCategory;
  subtitle?: string;
  items: { label: string; type: ElementType; config?: Record<string, unknown> }[];
}[] = [
  {
    title: '模版信息',
    items: [
      { label: 'Text', type: 'TEXT_STATIC' },
      { label: 'QR Code', type: 'QRCODE' },
      { label: 'Barcode', type: 'BARCODE' },
      { label: 'Blank Space', type: 'BLANK' },
      { label: 'Price', type: 'TEXT_PRICE' },
      { label: 'Image', type: 'IMAGE' },
      { label: 'Logo', type: 'IMAGE' },
    ],
  },
  {
    title: '标签信息',
    items: [
      { label: 'Label Name', type: 'TEXT_PRODUCT' },
      { label: 'Text', type: 'TEXT_STATIC' },
      { label: 'QR Code', type: 'QRCODE' },
      { label: 'Barcode', type: 'BARCODE' },
      { label: 'Nutrition Facts', type: 'NUTRITION' },
      { label: 'Price', type: 'TEXT_PRICE' },
      { label: 'Duration Date', type: 'DATE' },
      { label: 'Duration Time', type: 'TIME' },
      { label: 'Duration', type: 'DURATION' },
      { label: 'Image', type: 'IMAGE' },
      { label: 'Label Type', type: 'TEXT_STATIC' },
      { label: 'How-to', type: 'TEXT_STATIC' },
      { label: 'Expiration Alert', type: 'TEXT_STATIC' },
    ],
  },
  {
    title: '自动生成',
    items: [
      { label: 'Company', type: 'TEXT_STATIC' },
      { label: 'Employee', type: 'TEXT_STATIC' },
      { label: 'Current Date', type: 'DATE' },
      { label: 'Current Time', type: 'TIME' },
      { label: 'Label ID', type: 'TEXT_STATIC' },
    ],
  },
  {
    title: '打印时输入',
    subtitle: '点击添加到画布',
    items: [
      { label: 'Text', type: 'TEXT_STATIC', config: { inputType: 'text' } },
      { label: 'Weight', type: 'WEIGHT' },
      { label: 'Number', type: 'TEXT_STATIC', config: { inputType: 'number', text: '0' } },
      { label: 'Date & Time', type: 'DATE', config: { inputType: 'datetime' } },
      {
        label: 'Multiple Options',
        type: 'TEXT_STATIC',
        config: {
          inputType: 'options',
          multipleOptionId: '',
          selectedOptionValues: [],
          text: '文本',
          fontFamily: 'Arial',
          fontSize: 14,
          fontWeight: 'normal',
          textAlign: 'left',
          prefix: '¥',
        },
      },
    ],
  },
];

interface ElementsPanelProps {
  onAddElement: (
    type: ElementType,
    configOverride: Partial<Record<string, unknown>> | undefined,
    libraryCategory: ElementLibraryCategory,
    paletteItemLabel: string,
  ) => void;
}

export function ElementsPanel({ onAddElement }: ElementsPanelProps) {
  return (
    <div className="w-44 shrink-0 border-r border-gray-200 bg-white flex flex-col h-full">
      <div className="px-2 py-2 border-b border-gray-200 font-semibold text-gray-800 text-sm">
        Elements
      </div>
      <ScrollArea className="flex-1">
        <div className="p-1.5 space-y-3">
          {ELEMENT_CATEGORIES.map((cat) => (
            <div key={cat.title}>
              <div className="px-2 py-1 text-xs font-medium text-gray-500 uppercase tracking-wide">
                {cat.title}
              </div>
              {cat.subtitle && (
                <div className="px-2 py-0.5 text-[10px] text-gray-400">
                  {cat.subtitle}
                </div>
              )}
              <div className="grid grid-cols-2 gap-1 mt-0.5">
                {cat.items.map((item, i) => (
                  <button
                    key={`${cat.title}-${item.label}-${i}`}
                    type="button"
                    onClick={() =>
                      onAddElement(item.type, item.config, cat.title, item.label)
                    }
                    className="text-left px-2 py-1 text-xs rounded hover:bg-gray-100 border border-transparent hover:border-gray-200 truncate"
                  >
                    {item.label}
                  </button>
                ))}
              </div>
            </div>
          ))}
        </div>
      </ScrollArea>
    </div>
  );
}