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:
@@ -1,4 +1,5 @@
|
||||
export interface Filament {
|
||||
id?: string;
|
||||
brand: string;
|
||||
tip: string;
|
||||
finish: string;
|
||||
@@ -8,4 +9,7 @@ export interface Filament {
|
||||
otvoreno: string;
|
||||
kolicina: string;
|
||||
cena: string;
|
||||
status?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
142
src/types/filament.v2.ts
Normal file
142
src/types/filament.v2.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
// Version 2 - Improved filament data structure
|
||||
|
||||
export type MaterialBase = 'PLA' | 'PETG' | 'ABS' | 'TPU' | 'SILK' | 'CF' | 'WOOD';
|
||||
export type MaterialModifier = 'Silk' | 'Matte' | 'Glow' | 'Wood' | 'CF';
|
||||
export type StorageCondition = 'vacuum' | 'sealed' | 'opened' | 'desiccant';
|
||||
export type Currency = 'RSD' | 'EUR' | 'USD';
|
||||
|
||||
export interface Material {
|
||||
base: MaterialBase;
|
||||
modifier?: MaterialModifier;
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
name: string;
|
||||
hex?: string;
|
||||
pantone?: string;
|
||||
}
|
||||
|
||||
export interface Weight {
|
||||
value: number;
|
||||
unit: 'g' | 'kg';
|
||||
}
|
||||
|
||||
export interface InventoryLocation {
|
||||
vacuum: number;
|
||||
opened: number;
|
||||
printer: number;
|
||||
}
|
||||
|
||||
export interface Inventory {
|
||||
total: number;
|
||||
available: number;
|
||||
inUse: number;
|
||||
locations: InventoryLocation;
|
||||
}
|
||||
|
||||
export interface Pricing {
|
||||
purchasePrice?: number;
|
||||
currency: Currency;
|
||||
supplier?: string;
|
||||
purchaseDate?: string;
|
||||
}
|
||||
|
||||
export interface Condition {
|
||||
isRefill: boolean;
|
||||
openedDate?: string;
|
||||
expiryDate?: string;
|
||||
storageCondition: StorageCondition;
|
||||
humidity?: number;
|
||||
}
|
||||
|
||||
// Legacy fields for backwards compatibility
|
||||
export interface LegacyFields {
|
||||
tip: string;
|
||||
finish: string;
|
||||
boja: string;
|
||||
refill: string;
|
||||
vakum: string;
|
||||
otvoreno: string;
|
||||
kolicina: string;
|
||||
cena: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface FilamentV2 {
|
||||
// Identifiers
|
||||
id: string;
|
||||
sku?: string;
|
||||
|
||||
// Product Info
|
||||
brand: string;
|
||||
type: MaterialBase;
|
||||
material: Material;
|
||||
color: Color;
|
||||
|
||||
// Physical Properties
|
||||
weight: Weight;
|
||||
diameter: number;
|
||||
|
||||
// Inventory Status
|
||||
inventory: Inventory;
|
||||
|
||||
// Purchase Info
|
||||
pricing: Pricing;
|
||||
|
||||
// Condition
|
||||
condition: Condition;
|
||||
|
||||
// Metadata
|
||||
tags: string[];
|
||||
notes?: string;
|
||||
images?: string[];
|
||||
|
||||
// Timestamps
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
lastUsed?: string;
|
||||
|
||||
// Backwards compatibility
|
||||
_legacy?: LegacyFields;
|
||||
}
|
||||
|
||||
// Helper type guards
|
||||
export const isFilamentV2 = (filament: any): filament is FilamentV2 => {
|
||||
return filament &&
|
||||
typeof filament === 'object' &&
|
||||
'material' in filament &&
|
||||
'inventory' in filament &&
|
||||
'condition' in filament;
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
export const getTotalWeight = (filament: FilamentV2): number => {
|
||||
const multiplier = filament.weight.unit === 'kg' ? 1000 : 1;
|
||||
return filament.inventory.total * filament.weight.value * multiplier;
|
||||
};
|
||||
|
||||
export const getAvailableWeight = (filament: FilamentV2): number => {
|
||||
const multiplier = filament.weight.unit === 'kg' ? 1000 : 1;
|
||||
return filament.inventory.available * filament.weight.value * multiplier;
|
||||
};
|
||||
|
||||
export const isLowStock = (filament: FilamentV2, threshold = 1): boolean => {
|
||||
return filament.inventory.available <= threshold && filament.inventory.total > 0;
|
||||
};
|
||||
|
||||
export const needsRefill = (filament: FilamentV2): boolean => {
|
||||
return filament.inventory.available === 0 && filament.inventory.total > 0;
|
||||
};
|
||||
|
||||
export const isExpired = (filament: FilamentV2): boolean => {
|
||||
if (!filament.condition.expiryDate) return false;
|
||||
return new Date(filament.condition.expiryDate) < new Date();
|
||||
};
|
||||
|
||||
export const daysOpen = (filament: FilamentV2): number | null => {
|
||||
if (!filament.condition.openedDate) return null;
|
||||
const opened = new Date(filament.condition.openedDate);
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - opened.getTime();
|
||||
return Math.floor(diff / (1000 * 60 * 60 * 24));
|
||||
};
|
||||
Reference in New Issue
Block a user