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,255 @@
# Improved Data Structure Proposal
## Current Issues
1. Mixed languages (English/Serbian)
2. String fields for numeric/boolean values
3. Inconsistent status representation
4. No proper inventory tracking
5. Missing important metadata
## Proposed Structure
```typescript
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**
```typescript
// Find all sealed PLA under 1kg
filaments.filter(f =>
f.material.base === 'PLA' &&
f.weight.value <= 1000 &&
f.condition.storageCondition === 'vacuum'
)
```
### 2. **Inventory Management**
```typescript
// 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**
```typescript
// 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**
```typescript
// 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)
```javascript
// 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
1. **Barcode/QR Integration**: Generate QR codes for each spool
2. **Usage History**: Track which prints used which filament
3. **Alerts**: Low stock, expiry warnings
4. **Analytics**: Cost per print, filament usage trends
## DynamoDB Optimization
### Current Indexes
- brand-index
- tip-index
- status-index
### Proposed Indexes
```terraform
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
```javascript
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
```javascript
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**
```tsx
<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**
```tsx
<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?