Major restructure: Remove Confluence, add V2 data structure, organize for dev/prod

- Import real data from PDF (35 Bambu Lab filaments)
- Remove all Confluence integration and dependencies
- Implement new V2 data structure with proper inventory tracking
- Add backwards compatibility for existing data
- Create enhanced UI components (ColorSwatch, InventoryBadge, MaterialBadge)
- Add advanced filtering with quick filters and multi-criteria search
- Organize codebase for dev/prod environments
- Update Lambda functions to support both V1/V2 formats
- Add inventory summary dashboard
- Clean up project structure and documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DaX
2025-06-20 01:12:50 +02:00
parent a2252fa923
commit 18110ab159
40 changed files with 2171 additions and 1094 deletions

View File

@@ -0,0 +1,79 @@
import React from 'react';
interface ColorSwatchProps {
name: string;
hex?: string;
size?: 'sm' | 'md' | 'lg';
showLabel?: boolean;
className?: string;
}
export const ColorSwatch: React.FC<ColorSwatchProps> = ({
name,
hex,
size = 'md',
showLabel = true,
className = ''
}) => {
const sizeClasses = {
sm: 'w-6 h-6',
md: 'w-8 h-8',
lg: 'w-10 h-10'
};
// Default color mappings if hex is not provided
const defaultColors: Record<string, string> = {
'Black': '#000000',
'White': '#FFFFFF',
'Gray': '#808080',
'Red': '#FF0000',
'Blue': '#0000FF',
'Green': '#00FF00',
'Yellow': '#FFFF00',
'Transparent': 'rgba(255, 255, 255, 0.1)'
};
const getColorFromName = (colorName: string): string => {
// Check exact match first
if (defaultColors[colorName]) return defaultColors[colorName];
// Check if color name contains a known color
const lowerName = colorName.toLowerCase();
for (const [key, value] of Object.entries(defaultColors)) {
if (lowerName.includes(key.toLowerCase())) {
return value;
}
}
// Generate a color from the name hash
let hash = 0;
for (let i = 0; i < colorName.length; i++) {
hash = colorName.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = hash % 360;
return `hsl(${hue}, 70%, 50%)`;
};
const backgroundColor = hex || getColorFromName(name);
const isLight = backgroundColor.startsWith('#') &&
parseInt(backgroundColor.slice(1, 3), 16) > 200 &&
parseInt(backgroundColor.slice(3, 5), 16) > 200 &&
parseInt(backgroundColor.slice(5, 7), 16) > 200;
return (
<div className={`flex items-center gap-2 ${className}`}>
<div
className={`${sizeClasses[size]} rounded-full border-2 ${isLight ? 'border-gray-300' : 'border-gray-700'} shadow-sm`}
style={{ backgroundColor }}
title={name}
>
{name.toLowerCase().includes('transparent') && (
<div className="w-full h-full rounded-full bg-gradient-to-br from-gray-200 to-gray-300 opacity-50" />
)}
</div>
{showLabel && (
<span className="text-sm text-gray-700 dark:text-gray-300">{name}</span>
)}
</div>
);
};