import React, { useState, useEffect } from 'react'; import { DollarSign, Package, Settings, TrendingUp, Zap, AlertCircle, CheckCircle, RefreshCw, Database, Calculator, Activity, BarChart3, FileText } from 'lucide-react'; // Mock data for demonstration const mockPartNumbers = [ { id: 'PN-001', name: 'Brass Valve 1/2"', family: 'Valves', type: 'Brass Fitting', bom: [ { id: 'RM-001', material: 'Brass Bar', qty: 1.8, unit: 'kg', stdCost: 6.80, lmeLinked: true }, { id: 'RM-002', material: 'Rubber Gasket', qty: 2, unit: 'pcs', stdCost: 0.35, lmeLinked: false }, { id: 'RM-003', material: 'Steel Spring', qty: 0.2, unit: 'kg', stdCost: 3.20, lmeLinked: true }, ], routing: [ { id: 'OP-010', operation: 'Cutting', workCenter: 'WC-CUT-01', cycleTime: 3.0, rate: 45.00, enabled: true }, { id: 'OP-020', operation: 'Machining', workCenter: 'WC-MCH-02', cycleTime: 12.0, rate: 65.00, enabled: true }, { id: 'OP-030', operation: 'Assembly', workCenter: 'WC-ASM-01', cycleTime: 8.5, rate: 38.00, enabled: true }, { id: 'OP-040', operation: 'Painting', workCenter: 'WC-PNT-01', cycleTime: 0, rate: 42.00, enabled: false }, { id: 'OP-050', operation: 'Packaging', workCenter: 'WC-PKG-01', cycleTime: 2.0, rate: 28.00, enabled: true }, ] }, { id: 'PN-002', name: 'Steel Coupling 3/4"', family: 'Couplings', type: 'Steel Component', bom: [ { id: 'RM-001', material: 'Steel Grade 304', qty: 2.5, unit: 'kg', stdCost: 3.20, lmeLinked: true }, { id: 'RM-002', material: 'Zinc Coating Material', qty: 0.1, unit: 'kg', stdCost: 4.50, lmeLinked: false }, ], routing: [ { id: 'OP-010', operation: 'Cutting', workCenter: 'WC-CUT-01', cycleTime: 2.5, rate: 45.00, enabled: true }, { id: 'OP-020', operation: 'Machining', workCenter: 'WC-MCH-02', cycleTime: 15.0, rate: 65.00, enabled: true }, { id: 'OP-030', operation: 'Assembly', workCenter: 'WC-ASM-01', cycleTime: 0, rate: 38.00, enabled: false }, { id: 'OP-040', operation: 'Painting', workCenter: 'WC-PNT-01', cycleTime: 5.0, rate: 42.00, enabled: true }, { id: 'OP-050', operation: 'Packaging', workCenter: 'WC-PKG-01', cycleTime: 1.5, rate: 28.00, enabled: true }, ] }, { id: 'PN-003', name: 'Copper Elbow 1"', family: 'Elbows', type: 'Copper Fitting', bom: [ { id: 'RM-001', material: 'Copper Sheet', qty: 1.2, unit: 'kg', stdCost: 8.50, lmeLinked: true }, { id: 'RM-002', material: 'Solder Wire', qty: 0.05, unit: 'kg', stdCost: 12.00, lmeLinked: false }, ], routing: [ { id: 'OP-010', operation: 'Cutting', workCenter: 'WC-CUT-01', cycleTime: 4.0, rate: 45.00, enabled: true }, { id: 'OP-020', operation: 'Machining', workCenter: 'WC-MCH-02', cycleTime: 10.0, rate: 65.00, enabled: true }, { id: 'OP-030', operation: 'Assembly', workCenter: 'WC-ASM-01', cycleTime: 6.0, rate: 38.00, enabled: true }, { id: 'OP-040', operation: 'Painting', workCenter: 'WC-PNT-01', cycleTime: 0, rate: 42.00, enabled: false }, { id: 'OP-050', operation: 'Packaging', workCenter: 'WC-PKG-01', cycleTime: 1.8, rate: 28.00, enabled: true }, ] }, { id: 'PN-004', name: 'Plastic Adapter 1/2"', family: 'Adapters', type: 'Plastic Component', bom: [ { id: 'RM-001', material: 'Plastic PVC', qty: 0.8, unit: 'kg', stdCost: 2.10, lmeLinked: false }, { id: 'RM-002', material: 'Rubber O-Ring', qty: 1, unit: 'pcs', stdCost: 0.25, lmeLinked: false }, ], routing: [ { id: 'OP-010', operation: 'Cutting', workCenter: 'WC-CUT-01', cycleTime: 1.5, rate: 45.00, enabled: true }, { id: 'OP-020', operation: 'Machining', workCenter: 'WC-MCH-02', cycleTime: 5.0, rate: 65.00, enabled: true }, { id: 'OP-030', operation: 'Assembly', workCenter: 'WC-ASM-01', cycleTime: 3.5, rate: 38.00, enabled: true }, { id: 'OP-040', operation: 'Painting', workCenter: 'WC-PNT-01', cycleTime: 3.0, rate: 42.00, enabled: true }, { id: 'OP-050', operation: 'Packaging', workCenter: 'WC-PKG-01', cycleTime: 1.2, rate: 28.00, enabled: true }, ] }, { id: 'PN-005', name: 'Aluminum Housing Assembly', family: 'Housing', type: 'Aluminum Component', bom: [ { id: 'RM-001', material: 'Aluminum Alloy 6061', qty: 3.2, unit: 'kg', stdCost: 2.45, lmeLinked: true }, { id: 'RM-002', material: 'Steel Fasteners', qty: 8, unit: 'pcs', stdCost: 0.15, lmeLinked: false }, { id: 'RM-003', material: 'Rubber Seal', qty: 1, unit: 'pcs', stdCost: 0.45, lmeLinked: false }, ], routing: [ { id: 'OP-010', operation: 'Cutting', workCenter: 'WC-CUT-01', cycleTime: 5.5, rate: 45.00, enabled: true }, { id: 'OP-020', operation: 'Machining', workCenter: 'WC-MCH-02', cycleTime: 20.0, rate: 65.00, enabled: true }, { id: 'OP-030', operation: 'Assembly', workCenter: 'WC-ASM-01', cycleTime: 12.0, rate: 38.00, enabled: true }, { id: 'OP-040', operation: 'Painting', workCenter: 'WC-PNT-01', cycleTime: 8.0, rate: 42.00, enabled: true }, { id: 'OP-050', operation: 'Packaging', workCenter: 'WC-PKG-01', cycleTime: 3.5, rate: 28.00, enabled: true }, ] }, ]; const WelspringCostSimulator = () => { const [selectedPart, setSelectedPart] = useState(null); const [bom, setBom] = useState([]); const [routing, setRouting] = useState([]); const [lmePrices, setLmePrices] = useState({ copper: 8.45, brass: 6.75, steel: 3.18, aluminum: 2.45, }); const [isRefreshing, setIsRefreshing] = useState(false); const [costBreakdown, setCostBreakdown] = useState(null); const [activeTab, setActiveTab] = useState('selection'); // Simulate LME API refresh const refreshLMEPrices = () => { setIsRefreshing(true); setTimeout(() => { setLmePrices({ copper: (8.45 + (Math.random() - 0.5) * 0.5).toFixed(2), brass: (6.75 + (Math.random() - 0.5) * 0.4).toFixed(2), steel: (3.18 + (Math.random() - 0.5) * 0.2).toFixed(2), aluminum: (2.45 + (Math.random() - 0.5) * 0.3).toFixed(2), }); setIsRefreshing(false); }, 1200); }; // Calculate costs when part, BOM, or routing changes useEffect(() => { if (selectedPart && bom.length > 0 && routing.length > 0) { calculateCosts(); } }, [selectedPart, bom, routing, lmePrices]); const calculateCosts = () => { // Raw Material Cost const rmCost = bom.reduce((sum, item) => { let itemCost = item.stdCost; if (item.lmeLinked) { const materialType = item.material.toLowerCase(); if (materialType.includes('copper')) itemCost = parseFloat(lmePrices.copper); if (materialType.includes('brass')) itemCost = parseFloat(lmePrices.brass); if (materialType.includes('steel')) itemCost = parseFloat(lmePrices.steel); if (materialType.includes('aluminum') || materialType.includes('aluminium')) itemCost = parseFloat(lmePrices.aluminum); } return sum + (item.qty * itemCost); }, 0); // Processing Cost - only count enabled operations const processingCost = routing.reduce((sum, op) => { if (op.enabled) { return sum + ((op.cycleTime / 60) * op.rate); } return sum; }, 0); const grossProductCost = rmCost + processingCost; const laborCost = grossProductCost * 0.10; const consumables = grossProductCost * 0.05; const powerCost = grossProductCost * 0.05; const maintenance = grossProductCost * 0.05; const grossMargin = grossProductCost * 0.15; const costOfProduction = grossProductCost + grossMargin; setCostBreakdown({ rmCost: rmCost.toFixed(2), processingCost: processingCost.toFixed(2), grossProductCost: grossProductCost.toFixed(2), laborCost: laborCost.toFixed(2), consumables: consumables.toFixed(2), powerCost: powerCost.toFixed(2), maintenance: maintenance.toFixed(2), grossMargin: grossMargin.toFixed(2), costOfProduction: costOfProduction.toFixed(2), rmPercentage: ((rmCost / costOfProduction) * 100).toFixed(1), processingPercentage: ((processingCost / costOfProduction) * 100).toFixed(1), }); }; const selectPart = (part) => { setSelectedPart(part); setBom(part.bom); setRouting(part.routing); setActiveTab('bom'); }; const updateBOMItem = (index, field, value) => { const newBom = [...bom]; newBom[index][field] = field === 'qty' || field === 'stdCost' ? parseFloat(value) : value; setBom(newBom); }; const updateRoutingItem = (index, field, value) => { const newRouting = [...routing]; if (field === 'enabled') { newRouting[index][field] = value; } else { newRouting[index][field] = field === 'cycleTime' || field === 'rate' ? parseFloat(value) : value; } setRouting(newRouting); }; return (
{/* Subtle grid pattern */}
{/* Header */}

WELSPRING

Cost Simulator & Strategic Pricing

LME Status
● LIVE
{/* Main Content */}
{/* LME Price Ticker */}

London Metal Exchange - Live Commodity Prices

{Object.entries(lmePrices).map(([metal, price]) => (
{metal}
${price} /kg
● Live Feed
))}
{/* Navigation Tabs */}
{[ { id: 'selection', label: 'Part Selection', icon: Package }, { id: 'bom', label: 'Bill of Materials', icon: Database }, { id: 'routing', label: 'Routing & Operations', icon: Settings }, { id: 'results', label: 'Cost Analysis', icon: BarChart3 } ].map(tab => { const Icon = tab.icon; return ( ); })}
{/* Tab Content */}
{/* Part Selection Tab */} {activeTab === 'selection' && (

Select Part Number

{mockPartNumbers.map(part => (
selectPart(part)} style={{ background: selectedPart?.id === part.id ? 'linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%)' : '#f8fafc', border: selectedPart?.id === part.id ? '3px solid #3b82f6' : '2px solid #e2e8f0', borderRadius: '14px', padding: '1.5rem', cursor: 'pointer', transition: 'all 0.3s ease', position: 'relative' }} onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-4px)'; e.currentTarget.style.boxShadow = '0 12px 28px rgba(59, 130, 246, 0.15)'; }} onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }} > {selectedPart?.id === part.id && (
)}
{part.id}
{part.name}
{part.type} {part.family}
{/* Process Steps Preview */}
Process Steps
{part.routing.filter(r => r.enabled).map(r => ( {r.operation === 'Cutting' && '✂️'} {r.operation === 'Machining' && '⚙️'} {r.operation === 'Assembly' && '🔧'} {r.operation === 'Painting' && '🎨'} {r.operation === 'Packaging' && '📦'} {' '}{r.cycleTime}m ))}
))}
{selectedPart && (
Part Selected: {selectedPart.id}
Click "Bill of Materials" tab to configure BOM and routing
)}
)} {/* BOM Tab */} {activeTab === 'bom' && (

Bill of Materials

{selectedPart && (
Part: {selectedPart.id}
)}
{bom.length > 0 ? (
{bom.map((item, index) => { let currentCost = item.stdCost; if (item.lmeLinked) { const materialType = item.material.toLowerCase(); if (materialType.includes('copper')) currentCost = parseFloat(lmePrices.copper); if (materialType.includes('brass')) currentCost = parseFloat(lmePrices.brass); if (materialType.includes('steel')) currentCost = parseFloat(lmePrices.steel); if (materialType.includes('aluminum') || materialType.includes('aluminium')) currentCost = parseFloat(lmePrices.aluminum); } const totalCost = (item.qty * currentCost).toFixed(2); return ( ); })}
Material ID Description Quantity Unit Cost ($/unit) Total LME
{item.id} {item.material} updateBOMItem(index, 'qty', e.target.value)} style={{ background: '#ffffff', border: '2px solid #cbd5e1', color: '#0f172a', padding: '0.6rem', borderRadius: '8px', width: '90px', textAlign: 'right', fontSize: '0.9rem', fontWeight: 600, transition: 'all 0.2s ease' }} /> {item.unit} updateBOMItem(index, 'stdCost', e.target.value)} disabled={item.lmeLinked} style={{ background: item.lmeLinked ? '#d1fae5' : '#ffffff', border: item.lmeLinked ? '2px solid #6ee7b7' : '2px solid #cbd5e1', color: item.lmeLinked ? '#047857' : '#0f172a', padding: '0.6rem', borderRadius: '8px', width: '110px', textAlign: 'right', fontSize: '0.9rem', fontWeight: 700, cursor: item.lmeLinked ? 'not-allowed' : 'text', transition: 'all 0.2s ease' }} /> ${totalCost} {item.lmeLinked && ( ✓ LIVE )}
) : (
Please select a part number first
)}
)} {/* Routing Tab */} {activeTab === 'routing' && (

Routing & Operations

{selectedPart && (
Part: {selectedPart.id}
)}
{routing.length > 0 ? (
{routing.map((op, index) => { const opCost = op.enabled ? ((op.cycleTime / 60) * op.rate).toFixed(2) : '0.00'; const isDisabled = !op.enabled; return ( ); })}
Enable Operation Process Step Work Center Cycle Time (min) Rate ($/hr) Cost
updateRoutingItem(index, 'enabled', e.target.checked)} style={{ width: '20px', height: '20px', cursor: 'pointer', accentColor: '#3b82f6' }} /> {op.id}
{op.operation === 'Cutting' && ✂️} {op.operation === 'Machining' && ⚙️} {op.operation === 'Assembly' && 🔧} {op.operation === 'Painting' && 🎨} {op.operation === 'Packaging' && 📦} {op.operation}
{op.workCenter} updateRoutingItem(index, 'cycleTime', e.target.value)} disabled={isDisabled} style={{ background: isDisabled ? '#e2e8f0' : '#ffffff', border: '2px solid #cbd5e1', color: '#0f172a', padding: '0.6rem', borderRadius: '8px', width: '90px', textAlign: 'right', fontSize: '0.9rem', fontWeight: 600, transition: 'all 0.2s ease', cursor: isDisabled ? 'not-allowed' : 'text' }} /> updateRoutingItem(index, 'rate', e.target.value)} disabled={isDisabled} style={{ background: isDisabled ? '#e2e8f0' : '#ffffff', border: '2px solid #cbd5e1', color: '#0f172a', padding: '0.6rem', borderRadius: '8px', width: '110px', textAlign: 'right', fontSize: '0.9rem', fontWeight: 600, transition: 'all 0.2s ease', cursor: isDisabled ? 'not-allowed' : 'text' }} /> ${opCost}
{/* Total Processing Time Summary */}
Total Processing Time (Enabled Operations)
{routing.reduce((sum, op) => op.enabled ? sum + op.cycleTime : sum, 0).toFixed(1)} minutes
Total Processing Cost
${routing.reduce((sum, op) => op.enabled ? sum + ((op.cycleTime / 60) * op.rate) : sum, 0).toFixed(2)}
) : (
Please select a part number first
)}
)} {/* Results Tab */} {activeTab === 'results' && (

Cost Analysis & Breakdown

{costBreakdown ? (
{/* Cost Summary Cards */}
{[ { label: 'Raw Material Cost', value: costBreakdown.rmCost, color: '#3b82f6', gradient: 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)', icon: Package }, { label: 'Processing Cost', value: costBreakdown.processingCost, color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)', icon: Settings }, { label: 'Gross Product Cost', value: costBreakdown.grossProductCost, color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)', icon: Calculator }, { label: 'Cost of Production', value: costBreakdown.costOfProduction, color: '#10b981', gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)', icon: DollarSign } ].map((item, index) => { const Icon = item.icon; return (
{item.label}
${item.value}
); })}
{/* Detailed Breakdown */}

Detailed Cost Structure (per Welspring Model)

{[ { label: 'Raw Material Consumption', value: costBreakdown.rmCost, percentage: costBreakdown.rmPercentage, standard: '60%', color: '#3b82f6' }, { label: 'Labour Bills', value: costBreakdown.laborCost, percentage: '10', standard: '10%', color: '#8b5cf6' }, { label: 'Process Consumables', value: costBreakdown.consumables, percentage: '5', standard: '5%', color: '#06b6d4' }, { label: 'Power Bill', value: costBreakdown.powerCost, percentage: '5', standard: '5%', color: '#f59e0b' }, { label: 'Repair & Maintenance', value: costBreakdown.maintenance, percentage: '5', standard: '5%', color: '#ef4444' }, { label: 'Overheads (Gross Margin)', value: costBreakdown.grossMargin, percentage: '15', standard: '15%', color: '#10b981' } ].map((item, index) => (
{ e.currentTarget.style.borderColor = item.color; e.currentTarget.style.boxShadow = `0 4px 16px ${item.color}20`; }} onMouseLeave={(e) => { e.currentTarget.style.borderColor = '#e2e8f0'; e.currentTarget.style.boxShadow = 'none'; }} >
{item.label}
Target: {item.standard}
Actual %
{item.percentage}%
${item.value}
))}
{/* Visual Breakdown */}

Cost Composition

RM {costBreakdown.rmPercentage}%
Process {costBreakdown.processingPercentage}%
Overheads 25%
) : (
Please configure part, BOM, and routing to see cost analysis
)}
)}
); }; export default WelspringCostSimulator;