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 || '-'}
-
+
|
|