2 Commits

Author SHA1 Message Date
DaX
d55d0e5e02 Clean up fake colors and add missing Bambu Lab colors
All checks were successful
Deploy / detect (push) Successful in 4s
Deploy / deploy-api (push) Successful in 34s
Deploy / deploy-frontend (push) Successful in 2m4s
Deploy / tag-deploy (push) Successful in 4s
- Add migration 023: delete 67 fake colors, rename IronGray typo, add 16 missing real colors from spreadsheet
- Fix frontend color mappings: remove typo duplicates, rename Silk prefixed colors to match catalog
- Add Translucent Teal, Phantom Blue, Mystic Magenta mappings
- Remove non-existent ABS GF, TPU 95A HF entries
- Update tests for corrected color names
2026-03-05 03:04:19 +01:00
DaX
cff73c1381 Add manual customer creation and fix color edit modal
All checks were successful
Deploy / detect (push) Successful in 4s
Deploy / deploy-frontend (push) Successful in 2m24s
Deploy / tag-deploy (push) Successful in 5s
Deploy / deploy-api (push) Has been skipped
- Add "Dodaj kupca" button and modal form to customers page
- Fix color edit modal dark mode styling and add backdrop blur
2026-03-05 02:35:13 +01:00
9 changed files with 286 additions and 39 deletions

View File

@@ -48,14 +48,14 @@ scripts/deploy-frontend.sh # Manual frontend deploy to S3/CloudFront
### Frontend (Next.js App Router) ### Frontend (Next.js App Router)
- `/app/page.tsx` — Public filament inventory table (home page) - `/app/page.tsx` — Public filament inventory table (home page)
- `/app/upadaj/` — Admin panel: login, `/dashboard` (filament CRUD), `/colors` (color management), `/requests` (customer color requests) - `/app/upadaj/` — Admin panel: login, `/dashboard` (filament CRUD), `/colors` (color management), `/customers` (customer management), `/sales` (sales recording), `/requests` (customer color requests), `/analytics` (revenue/inventory dashboards)
- `/src/services/api.ts` — Axios instance with auth interceptors (auto token injection, 401/403 redirect) - `/src/services/api.ts` — Axios instance with auth interceptors (auto token injection, 401/403 redirect)
- `/src/data/bambuLabColors.ts` — Primary color-to-hex mapping with gradient support (used by `ColorCell` component) - `/src/data/bambuLabColors.ts` — Primary color-to-hex mapping with gradient support (used by `ColorCell` component)
- `/src/data/bambuLabColorsComplete.ts` — Extended color database grouped by finish type (used by filters) - `/src/data/bambuLabColorsComplete.ts` — Extended color database grouped by finish type (used by filters)
### API (`/api/server.js`) ### API (`/api/server.js`)
Single-file Express server running on EC2 (port 80). All routes inline. Single-file Express server running on EC2 (port 80). All routes inline.
- Endpoints: `/api/login`, `/api/filaments`, `/api/colors`, `/api/sale/bulk`, `/api/color-requests` - Endpoints: `/api/login`, `/api/filaments`, `/api/colors`, `/api/customers`, `/api/sales`, `/api/color-requests`, `/api/analytics/*`
- Auth: JWT tokens with 24h expiry, single admin user (password from `ADMIN_PASSWORD` env var) - Auth: JWT tokens with 24h expiry, single admin user (password from `ADMIN_PASSWORD` env var)
### Database (PostgreSQL on RDS) ### Database (PostgreSQL on RDS)
@@ -64,13 +64,15 @@ Key schemas and constraints:
``` ```
filaments: id, tip (material), finish, boja (color), refill, spulna, kolicina, cena, sale_* filaments: id, tip (material), finish, boja (color), refill, spulna, kolicina, cena, sale_*
colors: id, name, hex, cena_refill (default 3499), cena_spulna (default 3999) colors: id, name, hex, cena_refill (default 3499), cena_spulna (default 3999)
customers: id, name, phone (unique), city, notes, created_at
sales: id, customer_id (FK→customers), total_amount, notes, created_at + sale_items join table
color_requests: id, color_name, message, contact_name, contact_phone, status color_requests: id, color_name, message, contact_name, contact_phone, status
``` ```
**Critical constraints:** **Critical constraints:**
- `filaments.boja` → FK to `colors.name` (ON UPDATE CASCADE) — colors must exist before filaments reference them - `filaments.boja` → FK to `colors.name` (ON UPDATE CASCADE) — colors must exist before filaments reference them
- `kolicina = refill + spulna` — enforced by check constraint - `kolicina = refill + spulna` — enforced by check constraint
- Migrations in `/database/migrations/` with sequential numbering (currently up to `020_`) - Migrations in `/database/migrations/` with sequential numbering (currently up to `023_`)
## Key Patterns ## Key Patterns
@@ -86,7 +88,7 @@ color_requests: id, color_name, message, contact_name, contact_phone, status
3. Optionally add to `src/data/bambuLabColorsComplete.ts` finish groups 3. Optionally add to `src/data/bambuLabColorsComplete.ts` finish groups
### API Communication ### API Communication
- Service modules in `src/services/api.ts`: `authService`, `colorService`, `filamentService`, `colorRequestService` - Service modules in `src/services/api.ts`: `authService`, `colorService`, `filamentService`, `colorRequestService`, `customerService`, `saleService`, `analyticsService`
- Auth token stored in localStorage with 24h expiry - Auth token stored in localStorage with 24h expiry
- Cache busting on filament fetches via timestamp query param - Cache busting on filament fetches via timestamp query param

View File

@@ -33,9 +33,9 @@ describe('Bambu Lab Colors Data', () => {
}); });
}); });
it('should have Unknown fallback color', () => { it('should return fallback for unknown colors', () => {
expect(bambuLabColors).toHaveProperty('Unknown'); const result = getFilamentColor('NonExistentColor');
expect(bambuLabColors.Unknown.hex).toBe('#CCCCCC'); expect(result.hex).toBe('#CCCCCC');
}); });
}); });

View File

@@ -21,9 +21,9 @@ describe('Bambu Lab Colors Complete Data', () => {
}); });
it('should have silk colors', () => { it('should have silk colors', () => {
expect(bambuLabColors).toHaveProperty('Silk Aurora Purple'); expect(bambuLabColors).toHaveProperty('Aurora Purple');
expect(bambuLabColors).toHaveProperty('Silk Phantom Blue'); expect(bambuLabColors).toHaveProperty('Phantom Blue');
expect(bambuLabColors).toHaveProperty('Silk Mystic Magenta'); expect(bambuLabColors).toHaveProperty('Mystic Magenta');
}); });
it('should have valid hex colors', () => { it('should have valid hex colors', () => {

View File

@@ -370,10 +370,24 @@ export default function ColorsManagement() {
{/* Edit Modal */} {/* Edit Modal */}
{editingColor && ( {editingColor && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"> <div
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-auto"> className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4"
onClick={() => setEditingColor(null)}
>
<div
className="bg-white dark:bg-gray-800 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-700 max-w-md w-full max-h-[90vh] overflow-auto"
onClick={(e) => e.stopPropagation()}
>
<div className="flex justify-between items-center p-6 pb-0">
<h3 className="text-xl font-bold text-gray-900 dark:text-white">Izmeni boju</h3>
<button
onClick={() => setEditingColor(null)}
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-2xl leading-none"
>
&times;
</button>
</div>
<div className="p-6"> <div className="p-6">
<h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">Izmeni boju</h3>
<ColorForm <ColorForm
color={editingColor} color={editingColor}
onSave={(color) => { onSave={(color) => {
@@ -477,7 +491,7 @@ function ColorForm({
readOnly={isBambuLabColor} readOnly={isBambuLabColor}
pattern="^#[0-9A-Fa-f]{6}$" pattern="^#[0-9A-Fa-f]{6}$"
placeholder="#000000" placeholder="#000000"
className={`flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isBambuLabColor ? 'bg-gray-100 dark:bg-gray-900 cursor-not-allowed' : ''}`} className={`flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 ${isBambuLabColor ? 'bg-gray-100 dark:bg-gray-900 cursor-not-allowed' : 'bg-white dark:bg-gray-700'}`}
/> />
</div> </div>
{isBambuLabColor && ( {isBambuLabColor && (

View File

@@ -25,6 +25,10 @@ export default function CustomersManagement() {
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [darkMode, setDarkMode] = useState(false); const [darkMode, setDarkMode] = useState(false);
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [showAddModal, setShowAddModal] = useState(false);
const [addForm, setAddForm] = useState({ name: '', phone: '', city: '', notes: '' });
const [addError, setAddError] = useState('');
const [addSaving, setAddSaving] = useState(false);
// Initialize dark mode // Initialize dark mode
useEffect(() => { useEffect(() => {
@@ -139,6 +143,35 @@ export default function CustomersManagement() {
} }
}; };
const handleAddCustomer = async () => {
if (!addForm.name.trim()) {
setAddError('Ime je obavezno');
return;
}
setAddSaving(true);
setAddError('');
try {
await customerService.create({
name: addForm.name.trim(),
phone: addForm.phone.trim() || undefined,
city: addForm.city.trim() || undefined,
notes: addForm.notes.trim() || undefined,
});
setShowAddModal(false);
setAddForm({ name: '', phone: '', city: '', notes: '' });
await fetchCustomers();
} catch (err: unknown) {
const error = err as { response?: { data?: { code?: string } } };
if (error.response?.data?.code === '23505') {
setAddError('Kupac sa ovim brojem telefona vec postoji');
} else {
setAddError('Greska pri dodavanju kupca');
}
} finally {
setAddSaving(false);
}
};
const handleLogout = () => { const handleLogout = () => {
localStorage.removeItem('authToken'); localStorage.removeItem('authToken');
localStorage.removeItem('tokenExpiry'); localStorage.removeItem('tokenExpiry');
@@ -230,8 +263,8 @@ export default function CustomersManagement() {
</div> </div>
)} )}
{/* Search bar */} {/* Search bar + Add button */}
<div className="mb-6"> <div className="mb-6 flex items-center gap-4">
<input <input
type="text" type="text"
placeholder="Pretrazi kupce..." placeholder="Pretrazi kupce..."
@@ -239,6 +272,12 @@ export default function CustomersManagement() {
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="w-full max-w-md px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="w-full max-w-md px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/> />
<button
onClick={() => setShowAddModal(true)}
className="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 whitespace-nowrap font-medium"
>
+ Dodaj kupca
</button>
</div> </div>
{/* Customer count */} {/* Customer count */}
@@ -488,6 +527,108 @@ export default function CustomersManagement() {
</main> </main>
</div> </div>
</div> </div>
{/* Add Customer Modal */}
{showAddModal && (
<div
className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"
onClick={() => setShowAddModal(false)}
>
<div
className="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md mx-4 p-6"
onClick={(e) => e.stopPropagation()}
>
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-bold text-gray-900 dark:text-white">
Dodaj kupca
</h2>
<button
onClick={() => setShowAddModal(false)}
className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-2xl leading-none"
>
&times;
</button>
</div>
{addError && (
<div className="mb-4 p-3 bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-400 rounded text-sm">
{addError}
</div>
)}
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Ime *
</label>
<input
type="text"
value={addForm.name}
onChange={(e) => setAddForm({ ...addForm, name: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Ime i prezime"
autoFocus
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Telefon
</label>
<input
type="text"
value={addForm.phone}
onChange={(e) => setAddForm({ ...addForm, phone: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Broj telefona"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Grad
</label>
<input
type="text"
value={addForm.city}
onChange={(e) => setAddForm({ ...addForm, city: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Grad"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Napomena
</label>
<textarea
value={addForm.notes}
onChange={(e) => setAddForm({ ...addForm, notes: e.target.value })}
rows={3}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="npr. stampa figurice, obicno crna..."
/>
</div>
</div>
<div className="flex justify-end gap-3 mt-6">
<button
onClick={() => setShowAddModal(false)}
className="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600"
>
Otkazi
</button>
<button
onClick={handleAddCustomer}
disabled={addSaving}
className="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 font-medium"
>
{addSaving ? 'Cuvanje...' : 'Dodaj'}
</button>
</div>
</div>
</div>
)}
</div> </div>
); );
} }

View File

@@ -0,0 +1,100 @@
-- Migration 023: Clean up fake colors and add missing real Bambu Lab colors
-- Source of truth: bambu_lab_filaments.numbers spreadsheet
BEGIN;
-- 1. Rename typo: IronGray Metallic → Iron Gray Metallic (FK cascades to filaments)
UPDATE colors SET name = 'Iron Gray Metallic' WHERE name = 'IronGray Metallic';
-- 2. Delete 67 fake colors not used by any filament
DELETE FROM colors WHERE name IN (
'Coton Candy Cloud',
'Glow in the Dark Blue',
'Glow in the Dark Green',
'Grey',
'Indingo Purple',
'Ivory',
'Ivory White',
'Light Blue',
'Light Green',
'Matte Black',
'Matte Blue',
'Matte Brown',
'Matte Coral',
'Matte Green',
'Matte Grey',
'Matte Lime',
'Matte Mint',
'Matte Navy',
'Matte Orange',
'Matte Pink',
'Matte Purple',
'Matte White',
'Matte Yellow',
'Metal Bronze',
'Metal Copper',
'Metal Gold',
'Metal Grey',
'Metal Silver',
'Mint Green',
'Natural',
'Navy Blue',
'Nebulane',
'Silk Black',
'Silk Blue',
'Silk Bronze',
'Silk Copper',
'Silk Emerald',
'Silk Gold',
'Silk Green',
'Silk Jade',
'Silk Orange',
'Silk Pearl',
'Silk Pink',
'Silk Purple',
'Silk Red',
'Silk Rose Gold',
'Silk Ruby',
'Silk Sapphire',
'Silk Silver',
'Silk White',
'Sky Blue',
'Sparkle Blue',
'Sparkle Gold',
'Sparkle Green',
'Sparkle Purple',
'Sparkle Red',
'Sparkle Silver',
'Support G',
'Support White',
'Translucent Tea',
'Transparent Blue',
'Transparent Green',
'Transparent Orange',
'Transparent Purple',
'Transparent Red',
'Transparent Yellow',
'Violet'
);
-- 3. Add 17 missing real Bambu Lab colors from spreadsheet
INSERT INTO colors (name, hex) VALUES
('Aurora Purple', '#285BB7'),
('Candy Green', '#408619'),
('Candy Red', '#BB3A2E'),
('Crystal Blue', '#5BC0EB'),
('Flesh', '#E8C4A2'),
('Forest Green', '#415520'),
('Grape Jelly', '#6B2D75'),
('Lake Blue', '#4672E4'),
('Lime', '#C5ED48'),
('Mystic Magenta', '#720062'),
('Nebulae', '#424379'),
('Neon Green', '#ABFF1E'),
('Phantom Blue', '#00629B'),
('Quicksilver', '#A6A9AA'),
('Rose Gold', '#B29593'),
('Translucent Teal', '#008080')
ON CONFLICT (name) DO NOTHING;
COMMIT;

View File

@@ -115,9 +115,9 @@ export const BAMBU_LAB_CATALOG: BambuLabCatalog = {
}, },
'Silk Multi-Color': { 'Silk Multi-Color': {
colors: [ colors: [
{ name: 'Silk Aurora Purple', refill: false, spool: true }, { name: 'Aurora Purple', refill: false, spool: true },
{ name: 'Silk Phantom Blue', refill: false, spool: true }, { name: 'Phantom Blue', refill: false, spool: true },
{ name: 'Silk Mystic Magenta', refill: false, spool: true }, { name: 'Mystic Magenta', refill: false, spool: true },
], ],
}, },
Metal: { Metal: {

View File

@@ -8,7 +8,7 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Apple Green': { hex: '#C6E188' }, 'Apple Green': { hex: '#C6E188' },
'Arctic Whisper': { hex: '#ECF7F8' }, 'Arctic Whisper': { hex: '#ECF7F8' },
'Ash Grey': { hex: '#9B9EA0' }, 'Ash Grey': { hex: '#9B9EA0' },
'Aurora Purple': { hex: '#285BB7' }, 'Aurora Purple': { hex: ['#7F3696', '#006EC9'], isGradient: true },
'Azure': { hex: '#489FDF' }, 'Azure': { hex: '#489FDF' },
'Baby Blue': { hex: '#AEC3ED' }, 'Baby Blue': { hex: '#AEC3ED' },
'Bambu Green': { hex: '#00AE42' }, 'Bambu Green': { hex: '#00AE42' },
@@ -73,8 +73,6 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Iridium Gold Metallic': { hex: '#B39B84' }, 'Iridium Gold Metallic': { hex: '#B39B84' },
'Iris Purple': { hex: '#69398E' }, 'Iris Purple': { hex: '#69398E' },
'Iron Gray Metallic': { hex: '#6B6C6F' }, 'Iron Gray Metallic': { hex: '#6B6C6F' },
'IronGray Metallic': { hex: '#6B6C6F' },
'Ivory White': { hex: '#FFFFFF' },
'Jade White': { hex: '#FFFFFF' }, 'Jade White': { hex: '#FFFFFF' },
'Jeans Blue': { hex: '#6E88BC' }, 'Jeans Blue': { hex: '#6E88BC' },
'Lake Blue': { hex: '#4672E4' }, 'Lake Blue': { hex: '#4672E4' },
@@ -103,7 +101,6 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Nardo Gray': { hex: '#747474' }, 'Nardo Gray': { hex: '#747474' },
'Navy Blue': { hex: '#0C2340' }, 'Navy Blue': { hex: '#0C2340' },
'Nebulae': { hex: '#424379' }, 'Nebulae': { hex: '#424379' },
'Nebulane': { hex: '#424379' },
'Neon City': { hex: '#0047BB' }, 'Neon City': { hex: '#0047BB' },
'Neon Green': { hex: '#ABFF1E' }, 'Neon Green': { hex: '#ABFF1E' },
'Neon Orange': { hex: '#F68A1B' }, 'Neon Orange': { hex: '#F68A1B' },
@@ -147,8 +144,6 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Yellow': { hex: '#F4EE2A' }, 'Yellow': { hex: '#F4EE2A' },
// ABS Colors // ABS Colors
'ABS GF Yellow': { hex: '#FDD835' },
'ABS GF Orange': { hex: '#F48438' },
'ABS Azure': { hex: '#489FDF' }, 'ABS Azure': { hex: '#489FDF' },
'ABS Olive': { hex: '#748C45' }, 'ABS Olive': { hex: '#748C45' },
'ABS Blue': { hex: '#0A2989' }, 'ABS Blue': { hex: '#0A2989' },
@@ -169,7 +164,7 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Translucent Olive': { hex: '#A4B885' }, 'Translucent Olive': { hex: '#A4B885' },
'Translucent Pink': { hex: '#F9B8D0' }, 'Translucent Pink': { hex: '#F9B8D0' },
'Translucent Light Blue': { hex: '#A8D8F0' }, 'Translucent Light Blue': { hex: '#A8D8F0' },
'Translucent Tea': { hex: '#D9C7A8' }, 'Translucent Teal': { hex: '#008080' },
// PLA Matte Colors // PLA Matte Colors
'Matte Ivory White': { hex: '#FFFFF0' }, 'Matte Ivory White': { hex: '#FFFFF0' },
@@ -199,19 +194,14 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Matte Terracotta': { hex: '#A25A37' }, 'Matte Terracotta': { hex: '#A25A37' },
// PLA Silk Multi-Color // PLA Silk Multi-Color
'Silk Aurora Purple': { hex: ['#7F3696', '#006EC9'], isGradient: true }, 'Phantom Blue': { hex: ['#00629B', '#000000'], isGradient: true },
'Silk Phantom Blue': { hex: ['#00629B', '#000000'], isGradient: true }, 'Mystic Magenta': { hex: ['#720062', '#3A913F'], isGradient: true },
'Silk Mystic Magenta': { hex: ['#720062', '#3A913F'], isGradient: true },
// TPU Colors // TPU Colors
'Flesh': { hex: '#E8C4A2' }, 'Flesh': { hex: '#E8C4A2' },
'Grape Jelly': { hex: '#6B2D75' }, 'Grape Jelly': { hex: '#6B2D75' },
'Crystal Blue': { hex: '#5BC0EB' }, 'Crystal Blue': { hex: '#5BC0EB' },
'Quicksilver': { hex: '#A6A9AA' }, 'Quicksilver': { hex: '#A6A9AA' }
'TPU 95A HF Yellow': { hex: '#F3E600' },
// Default fallback
'Unknown': { hex: '#CCCCCC' }
}; };
export function getFilamentColor(colorName: string): ColorMapping { export function getFilamentColor(colorName: string): ColorMapping {
@@ -240,7 +230,7 @@ export function getFilamentColor(colorName: string): ColorMapping {
} }
// Return default unknown color // Return default unknown color
return bambuLabColors['Unknown']; return { hex: '#CCCCCC' };
} }
export function getColorStyle(colorMapping: ColorMapping): React.CSSProperties { export function getColorStyle(colorMapping: ColorMapping): React.CSSProperties {

View File

@@ -100,9 +100,9 @@ export const bambuLabColors: Record<string, string> = {
"Baby Blue": "#AEC3ED", "Baby Blue": "#AEC3ED",
// PLA Silk Multi-Color // PLA Silk Multi-Color
"Silk Aurora Purple": "#7F3696", "Aurora Purple": "#7F3696",
"Silk Phantom Blue": "#00629B", "Phantom Blue": "#00629B",
"Silk Mystic Magenta": "#720062", "Mystic Magenta": "#720062",
// PLA Metal // PLA Metal
"Iron Gray Metallic": "#6B6C6F", "Iron Gray Metallic": "#6B6C6F",
@@ -162,7 +162,7 @@ export const bambuLabColors: Record<string, string> = {
"Translucent Olive": "#A4B885", "Translucent Olive": "#A4B885",
"Translucent Pink": "#F9B8D0", "Translucent Pink": "#F9B8D0",
"Translucent Light Blue": "#A8D8F0", "Translucent Light Blue": "#A8D8F0",
"Translucent Tea": "#D9C7A8", "Translucent Teal": "#008080",
// PETG CF // PETG CF
"Brick Red": "#9F332A", "Brick Red": "#9F332A",