diff --git a/src/components/ProductColorBadge.tsx b/src/components/ProductColorBadge.tsx new file mode 100644 index 0000000..ef02606 --- /dev/null +++ b/src/components/ProductColorBadge.tsx @@ -0,0 +1,63 @@ +const COLOR_SWATCHES: Array<{ pattern: string; color: string }> = [ + { pattern: 'preto', color: '#171717' }, + { pattern: 'branco', color: '#f8fafc' }, + { pattern: 'bege', color: '#d7bf9a' }, + { pattern: 'cafe', color: '#79553d' }, + { pattern: 'perola', color: '#e7dfcf' }, + { pattern: 'marinho', color: '#172554' }, + { pattern: 'bordo', color: '#6b1226' }, + { pattern: 'verde', color: '#166534' }, + { pattern: 'rosa', color: '#f0a6bf' }, + { pattern: 'cinza', color: '#8f8f8f' }, + { pattern: 'vermelho', color: '#b91c1c' }, + { pattern: 'grafite', color: '#3f3f46' }, + { pattern: 'azul', color: '#2563eb' }, + { pattern: 'marron', color: '#6b4f3b' }, + { pattern: 'marrom', color: '#6b4f3b' } +]; + +const normalizeColorLabel = (label: string) => ( + label.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase() +); + +export const getProductColor = (label: string) => { + const normalizedLabel = normalizeColorLabel(label); + return COLOR_SWATCHES.find(item => normalizedLabel.includes(item.pattern))?.color || '#64748b'; +}; + +export const ProductColorSwatch = ({ + label, + className = 'h-2.5 w-2.5' +}: { + label: string; + className?: string; +}) => ( + +); + +const ProductColorBadge = ({ + label, + emptyLabel = 'Sem cor', + className = '' +}: { + label?: string; + emptyLabel?: string; + className?: string; +}) => { + const displayLabel = label?.trim() || emptyLabel; + + return ( + + + {displayLabel} + + ); +}; + +export default ProductColorBadge; diff --git a/src/pages/Cutting.tsx b/src/pages/Cutting.tsx index 1217cb3..75afbce 100644 --- a/src/pages/Cutting.tsx +++ b/src/pages/Cutting.tsx @@ -3,6 +3,7 @@ import { Link, useOutletContext } from 'react-router-dom'; import { AlertTriangle, ClipboardList, Download, Layers3, Package, Palette, RotateCcw, Ruler, Save as SaveIcon, Scissors, Search, Settings2, X } from 'lucide-react'; import DateRangePicker from '../components/DateRangePicker'; import PaginationControls from '../components/PaginationControls'; +import ProductColorBadge from '../components/ProductColorBadge'; import RefreshStatus from '../components/RefreshStatus'; import { CUT_FAMILY_RULES, buildCutPlan, buildOpenProductionByProductId, type CutFamilyKey, type CutIssue, type CutPlanSkuRow, type CutProductOverride } from '../analytics/cutting'; import { exportToCSV, fetchCuttingSettings, fetchProductAnalytics, fetchProductionOrders, saveCuttingSettings } from '../dataService'; @@ -895,10 +896,7 @@ const Cutting = () => {
- - - {row.color || '-'} - + {row.size || '-'} diff --git a/src/pages/ProductGroupDetails.tsx b/src/pages/ProductGroupDetails.tsx index 4a74d73..4371013 100644 --- a/src/pages/ProductGroupDetails.tsx +++ b/src/pages/ProductGroupDetails.tsx @@ -4,6 +4,7 @@ import { DollarSign, Package, Palette, Ruler, TrendingDown, TrendingUp, Warehous import BackButton from '../components/BackButton'; import DateRangePicker from '../components/DateRangePicker'; import PaginationControls from '../components/PaginationControls'; +import ProductColorBadge, { ProductColorSwatch, getProductColor } from '../components/ProductColorBadge'; import RefreshStatus from '../components/RefreshStatus'; import { fetchProductAnalytics } from '../dataService'; import { decodeProductGroupKey, normalizeProductText, parseProductName } from '../productParsing'; @@ -26,25 +27,6 @@ type BreakdownRow = { const BREAKDOWN_LIMIT = 12; -const COLOR_SWATCHES: Array<{ pattern: string; color: string }> = [ - { pattern: 'preto', color: '#171717' }, - { pattern: 'branco', color: '#f8fafc' }, - { pattern: 'bege', color: '#d7bf9a' }, - { pattern: 'café', color: '#79553d' }, - { pattern: 'cafe', color: '#79553d' }, - { pattern: 'perola', color: '#e7dfcf' }, - { pattern: 'pérola', color: '#e7dfcf' }, - { pattern: 'marinho', color: '#172554' }, - { pattern: 'bordo', color: '#6b1226' }, - { pattern: 'bordô', color: '#6b1226' }, - { pattern: 'verde', color: '#166534' }, - { pattern: 'rosa', color: '#f0a6bf' }, - { pattern: 'cinza', color: '#8f8f8f' }, - { pattern: 'vermelho', color: '#b91c1c' }, - { pattern: 'grafite', color: '#3f3f46' }, - { pattern: 'azul', color: '#2563eb' } -]; - const getRangeDays = (range: DateRange) => { const start = new Date(range.start); const end = new Date(range.end); @@ -67,26 +49,11 @@ const formatDays = (value: number | null) => { return `${formatNumber(value, value < 10 ? 1 : 0)} dias`; }; -const getSwatchColor = (label: string) => { - const normalizedLabel = label.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase(); - return COLOR_SWATCHES.find(item => normalizedLabel.includes(item.pattern.normalize('NFD').replace(/\p{Diacritic}/gu, '')))?.color || '#64748b'; -}; - const getBarColor = (label: string) => { - const color = getSwatchColor(label); + const color = getProductColor(label); return `color-mix(in srgb, ${color} 74%, var(--color-dark-text) 26%)`; }; -const ColorSwatch = ({ label, className = 'h-2.5 w-2.5' }: { label: string; className?: string }) => ( - -); - const buildBreakdown = (rows: VariantRow[], field: 'color' | 'size') => { const totals = new Map(); @@ -147,7 +114,7 @@ const BreakdownPanel = ({ return (
- {type === 'color' ? : } + {type === 'color' ? : } {type === 'size' && row.label !== 'Sem tamanho' ? `Tam. ${row.label}` : row.label} @@ -439,10 +406,7 @@ const ProductGroupDetails = () => {
Preço Atual: {formatCurrency(row.lastPrice)}
- - - {row.color || '-'} - +