import React, { useState, useCallback } from 'react'; import { QRCodeSVG } from 'qrcode.react'; import { Download, Plus } from 'lucide-react'; import { Button } from '../ui/button'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '../ui/table'; import { cn } from '../ui/utils'; // Notes: // 1. Enter quantity to generate the corresponding number of QR codes // 2. QR code size can be selected // 3. Each generated QR has a numeric ID for manual entry when scanning is not available (e.g. recharge) // 4. Generated QR codes can be bulk exported for batch printing // 5. QR report shows generation status and usage status export type QRSize = 'small' | 'medium' | 'large'; const SIZE_OPTIONS: { value: QRSize; label: string; pixels: number }[] = [ { value: 'small', label: 'Small (80px)', pixels: 80 }, { value: 'medium', label: 'Medium (120px)', pixels: 120 }, { value: 'large', label: 'Large (160px)', pixels: 160 }, ]; export type QRUsageStatus = 'Unused' | 'Used'; export interface QRCodeItem { id: string; numericId: string; // For manual entry when scan doesn't work (e.g. recharge) value: string; // Encoded in QR (same as numericId or extended code) usageStatus: QRUsageStatus; createdAt: string; } const PREFIX = 'QR'; let nextNumericId = 100001; function generateNumericId(): string { return String(nextNumericId++); } export function QRCodesView() { const [quantity, setQuantity] = useState(10); const [sizeOption, setSizeOption] = useState('medium'); const [items, setItems] = useState([]); const [activeTab, setActiveTab] = useState<'generate' | 'report'>('generate'); const pixels = SIZE_OPTIONS.find((s) => s.value === sizeOption)?.pixels ?? 120; const handleGenerate = useCallback(() => { const count = Math.min(Math.max(1, Math.floor(quantity) || 0), 500); const newItems: QRCodeItem[] = []; for (let i = 0; i < count; i++) { const numericId = generateNumericId(); newItems.push({ id: `${PREFIX}-${numericId}`, numericId, value: numericId, usageStatus: 'Unused', createdAt: new Date().toISOString().slice(0, 10), }); } setItems((prev) => [...prev, ...newItems]); }, [quantity]); const [showPrintView, setShowPrintView] = useState(false); const handleBulkExportPrint = useCallback(() => { if (items.length === 0) return; setShowPrintView(true); }, [items.length]); const handlePrint = useCallback(() => { window.print(); }, []); const handleClosePrintView = useCallback(() => { setShowPrintView(false); }, []); const setUsageStatus = useCallback((id: string, status: QRUsageStatus) => { setItems((prev) => prev.map((item) => (item.id === id ? { ...item, usageStatus: status } : item))); }, []); return (
{/* Print-only view: full grid of QRs for batch printing */} {showPrintView && (

QR Codes – Batch Print

{items.map((item) => (
ID: {item.numericId}
))}
)} {/* Tabs:与 Labels/Reports 一致 */}
{(['generate', 'report'] as const).map((tab) => ( ))}
{/* Content Area:上下左右间距与 Products/Locations 一致(由 Layout main p-8 控制) */}
{activeTab === 'generate' && (
{/* 1. Quantity input and size selection — 圆角、细边框 */}
setQuantity(Number(e.target.value) || 0)} className="w-32 rounded-lg border border-black h-9" />
{/* 2 & 3. Generated QRs; 4. Bulk export */}
{items.length} QR code(s) generated. Each has a numeric ID for manual entry when scanning is not available. {items.length > 0 && ( )}
{items.length > 0 && (
{items.map((item) => (
ID: {item.numericId}
{item.usageStatus}
))}
)}
)} {activeTab === 'report' && (

QR code generation and usage status. Use this report to see which codes have been used (e.g. after recharge or scan).

QR ID Generation Status Usage Status Date Generated {items.length === 0 ? ( No QR codes generated yet. Go to Generate & Export and enter a quantity, then click Generate. ) : ( items.map((row) => ( {row.numericId} Generated {row.usageStatus} {row.createdAt} )) )}
)}
); }