- 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>
5.9 KiB
5.9 KiB
Improved Data Structure Proposal
Current Issues
- Mixed languages (English/Serbian)
- String fields for numeric/boolean values
- Inconsistent status representation
- No proper inventory tracking
- Missing important metadata
Proposed Structure
interface Filament {
// Identifiers
id: string;
sku?: string; // For internal tracking
// Product Info
brand: string;
type: 'PLA' | 'PETG' | 'ABS' | 'TPU' | 'SILK' | 'CF' | 'WOOD';
material: {
base: 'PLA' | 'PETG' | 'ABS' | 'TPU';
modifier?: 'Silk' | 'Matte' | 'Glow' | 'Wood' | 'CF';
};
color: {
name: string;
hex?: string; // Color code for UI display
pantone?: string; // For color matching
};
// Physical Properties
weight: {
value: number; // 1000 for 1kg, 500 for 0.5kg
unit: 'g' | 'kg';
};
diameter: number; // 1.75 or 2.85
// Inventory Status
inventory: {
total: number; // Total spools
available: number; // Available for use
inUse: number; // Currently being used
locations: {
vacuum: number; // In vacuum storage
opened: number; // Opened but usable
printer: number; // Loaded in printer
};
};
// Purchase Info
pricing: {
purchasePrice?: number;
currency: 'RSD' | 'EUR' | 'USD';
supplier?: string;
purchaseDate?: string;
};
// Condition
condition: {
isRefill: boolean;
openedDate?: string;
expiryDate?: string;
storageCondition: 'vacuum' | 'sealed' | 'opened' | 'desiccant';
humidity?: number; // Last measured
};
// Metadata
tags: string[]; // ['premium', 'engineering', 'easy-print']
notes?: string; // Special handling instructions
images?: string[]; // S3 URLs for photos
// Timestamps
createdAt: string;
updatedAt: string;
lastUsed?: string;
}
Benefits
1. Better Filtering
// Find all sealed PLA under 1kg
filaments.filter(f =>
f.material.base === 'PLA' &&
f.weight.value <= 1000 &&
f.condition.storageCondition === 'vacuum'
)
2. Inventory Management
// Get total available filament weight
const totalWeight = filaments.reduce((sum, f) =>
sum + (f.inventory.available * f.weight.value), 0
);
// Find low stock items
const lowStock = filaments.filter(f =>
f.inventory.available <= 1 && f.inventory.total > 0
);
3. Color Management
// Group by color for visualization
const colorGroups = filaments.reduce((groups, f) => {
const color = f.color.name;
groups[color] = groups[color] || [];
groups[color].push(f);
return groups;
}, {});
4. Usage Tracking
// Find most used filaments
const mostUsed = filaments
.filter(f => f.lastUsed)
.sort((a, b) => new Date(b.lastUsed) - new Date(a.lastUsed))
.slice(0, 10);
Migration Strategy
Phase 1: Add New Fields (Non-breaking)
// Update Lambda to handle both old and new structure
const migrateFilament = (old) => ({
...old,
material: {
base: old.tip || 'PLA',
modifier: old.finish !== 'Basic' ? old.finish : undefined
},
color: {
name: old.boja
},
weight: {
value: 1000, // Default 1kg
unit: 'g'
},
inventory: {
total: parseInt(old.kolicina) || 1,
available: old.otvoreno ? 0 : 1,
inUse: 0,
locations: {
vacuum: old.vakum ? 1 : 0,
opened: old.otvoreno ? 1 : 0,
printer: 0
}
},
condition: {
isRefill: old.refill === 'Da',
storageCondition: old.vakum ? 'vacuum' : (old.otvoreno ? 'opened' : 'sealed')
}
});
Phase 2: Update UI Components
- Create new filter components for material type
- Add inventory status indicators
- Color preview badges
- Storage condition icons
Phase 3: Enhanced Features
- Barcode/QR Integration: Generate QR codes for each spool
- Usage History: Track which prints used which filament
- Alerts: Low stock, expiry warnings
- Analytics: Cost per print, filament usage trends
DynamoDB Optimization
Current Indexes
- brand-index
- tip-index
- status-index
Proposed Indexes
global_secondary_index {
name = "material-color-index"
hash_key = "material.base"
range_key = "color.name"
}
global_secondary_index {
name = "inventory-status-index"
hash_key = "condition.storageCondition"
range_key = "inventory.available"
}
global_secondary_index {
name = "brand-type-index"
hash_key = "brand"
range_key = "material.base"
}
Example Queries
Find all available green filaments
const greenFilaments = await dynamodb.query({
IndexName: 'material-color-index',
FilterExpression: 'contains(color.name, :green) AND inventory.available > :zero',
ExpressionAttributeValues: {
':green': 'Green',
':zero': 0
}
}).promise();
Get inventory summary
const summary = await dynamodb.scan({
TableName: TABLE_NAME,
ProjectionExpression: 'brand, material.base, inventory'
}).promise();
const report = summary.Items.reduce((acc, item) => {
const key = `${item.brand}-${item.material.base}`;
acc[key] = (acc[key] || 0) + item.inventory.total;
return acc;
}, {});
UI Improvements
1. Visual Inventory Status
<div className="flex gap-2">
{filament.inventory.locations.vacuum > 0 && (
<Badge icon="vacuum" count={filament.inventory.locations.vacuum} />
)}
{filament.inventory.locations.opened > 0 && (
<Badge icon="box-open" count={filament.inventory.locations.opened} />
)}
</div>
2. Color Swatches
<div
className="w-8 h-8 rounded-full border-2"
style={{ backgroundColor: filament.color.hex || getColorFromName(filament.color.name) }}
title={filament.color.name}
/>
3. Smart Filters
- Quick filters: "Ready to use", "Low stock", "Refills only"
- Material groups: "Standard PLA", "Engineering", "Specialty"
- Storage status: "Vacuum sealed", "Open spools", "In printer"
Would you like me to implement this improved structure?