Align catalog with Bambu Lab product line, add conditional filters and admin sidebar
All checks were successful
Deploy / deploy (push) Successful in 2m24s

- Add master catalog (bambuLabCatalog.ts) as single source of truth for materials, finishes, colors, and refill/spool availability
- Fix incorrect finish-per-material mappings (remove PLA: 85A/90A/95A HF/FR/GF/HF, add ASA: Basic/CF/Aero, fix PETG/PC)
- Implement cascading filters on public site: material restricts finish, finish restricts color
- Add AdminSidebar component across all admin pages
- Redirect /upadaj to /dashboard when already authenticated
- Update color hex mappings and tests to match official Bambu Lab names
This commit is contained in:
DaX
2026-03-05 01:04:06 +01:00
parent ff6abdeef0
commit 65ae493d54
15 changed files with 817 additions and 467 deletions

View File

@@ -0,0 +1,42 @@
'use client'
import { usePathname } from 'next/navigation'
const navItems = [
{ href: '/dashboard', label: 'Filamenti' },
{ href: '/upadaj/colors', label: 'Boje' },
{ href: '/upadaj/requests', label: 'Zahtevi za boje' },
{ href: '/upadaj/sales', label: 'Prodaja' },
{ href: '/upadaj/customers', label: 'Kupci' },
{ href: '/upadaj/analytics', label: 'Analitika' },
]
export function AdminSidebar() {
const pathname = usePathname()
return (
<div className="w-64 bg-white dark:bg-gray-800 shadow-lg h-screen sticky top-0 flex-shrink-0">
<div className="p-6">
<h2 className="text-xl font-bold text-gray-900 dark:text-white mb-6">Admin Panel</h2>
<nav className="space-y-2">
{navItems.map((item) => {
const isActive = pathname === item.href
return (
<a
key={item.href}
href={item.href}
className={`block px-4 py-2 rounded ${
isActive
? 'bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300'
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700'
}`}
>
{item.label}
</a>
)
})}
</nav>
</div>
</div>
)
}

View File

@@ -1,6 +1,8 @@
import React from 'react';
import React, { useMemo } from 'react';
import '@/src/styles/select.css';
import { trackEvent } from './MatomoAnalytics';
import { getFinishesForMaterial, getAllFinishes, getMaterialOptions } from '@/src/data/bambuLabCatalog';
import { Filament } from '@/src/types/filament';
interface EnhancedFiltersProps {
filters: {
@@ -8,22 +10,74 @@ interface EnhancedFiltersProps {
finish: string;
color: string;
};
onFilterChange: (filters: any) => void;
onFilterChange: (filters: { material: string; finish: string; color: string }) => void;
uniqueValues: {
materials: string[];
finishes: string[];
colors: string[];
};
inventoryFilaments?: Filament[];
}
export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
filters,
onFilterChange,
uniqueValues
export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
filters,
onFilterChange,
uniqueValues,
inventoryFilaments = []
}) => {
// Check if any filters are active
const hasActiveFilters = filters.material || filters.finish || filters.color;
// Catalog-aware material list (static from catalog)
const materialOptions = useMemo(() => getMaterialOptions(), []);
// Finish options: conditional on selected material
const finishOptions = useMemo(() => {
const inStock = inventoryFilaments.filter(f => f.kolicina > 0);
if (filters.material) {
// Show finishes from catalog for this material, but only if they exist in inventory
const catalogFinishes = getFinishesForMaterial(filters.material);
const inventoryFinishes = new Set(
inStock.filter(f => f.tip === filters.material).map(f => f.finish)
);
return catalogFinishes.filter(f => inventoryFinishes.has(f));
}
// No material selected: show all finishes from inventory
if (inStock.length > 0) {
return [...new Set(inStock.map(f => f.finish))].sort();
}
return getAllFinishes();
}, [filters.material, inventoryFilaments]);
// Color options: conditional on selected material + finish
const colorOptions = useMemo(() => {
const inStock = inventoryFilaments.filter(f => f.kolicina > 0);
let filtered = inStock;
if (filters.material) {
filtered = filtered.filter(f => f.tip === filters.material);
}
if (filters.finish) {
filtered = filtered.filter(f => f.finish === filters.finish);
}
return [...new Set(filtered.map(f => f.boja))].sort();
}, [filters.material, filters.finish, inventoryFilaments]);
const handleMaterialChange = (value: string) => {
// Reset finish and color when material changes
onFilterChange({ material: value, finish: '', color: '' });
trackEvent('Filter', 'Material', value || 'All');
};
const handleFinishChange = (value: string) => {
// Reset color when finish changes
onFilterChange({ ...filters, finish: value, color: '' });
trackEvent('Filter', 'Finish', value || 'All');
};
const handleColorChange = (value: string) => {
onFilterChange({ ...filters, color: value });
trackEvent('Filter', 'Color', value || 'All');
};
return (
<div className="p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
{/* Filters Grid */}
@@ -35,26 +89,15 @@ export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
</label>
<select
value={filters.material}
onChange={(e) => {
onFilterChange({ ...filters, material: e.target.value });
trackEvent('Filter', 'Material', e.target.value || 'All');
}}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
onChange={(e) => handleMaterialChange(e.target.value)}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">Svi materijali</option>
<option value="ABS">ABS</option>
<option value="ASA">ASA</option>
<option value="PA6">PA6</option>
<option value="PAHT">PAHT</option>
<option value="PC">PC</option>
<option value="PET">PET</option>
<option value="PETG">PETG</option>
<option value="PLA">PLA</option>
<option value="PPA">PPA</option>
<option value="PPS">PPS</option>
<option value="TPU">TPU</option>
{materialOptions.map(mat => (
<option key={mat} value={mat}>{mat}</option>
))}
</select>
</div>
@@ -65,35 +108,15 @@ export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
</label>
<select
value={filters.finish}
onChange={(e) => {
onFilterChange({ ...filters, finish: e.target.value });
trackEvent('Filter', 'Finish', e.target.value || 'All');
}}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
onChange={(e) => handleFinishChange(e.target.value)}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">Svi finish tipovi</option>
<option value="85A">85A</option>
<option value="90A">90A</option>
<option value="95A HF">95A HF</option>
<option value="Aero">Aero</option>
<option value="Basic">Basic</option>
<option value="Basic Gradient">Basic Gradient</option>
<option value="CF">CF</option>
<option value="FR">FR</option>
<option value="Galaxy">Galaxy</option>
<option value="GF">GF</option>
<option value="Glow">Glow</option>
<option value="HF">HF</option>
<option value="Marble">Marble</option>
<option value="Matte">Matte</option>
<option value="Metal">Metal</option>
<option value="Silk Multi-Color">Silk Multi-Color</option>
<option value="Silk+">Silk+</option>
<option value="Sparkle">Sparkle</option>
<option value="Translucent">Translucent</option>
<option value="Wood">Wood</option>
{finishOptions.map(finish => (
<option key={finish} value={finish}>{finish}</option>
))}
</select>
</div>
@@ -104,16 +127,13 @@ export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
</label>
<select
value={filters.color}
onChange={(e) => {
onFilterChange({ ...filters, color: e.target.value });
trackEvent('Filter', 'Color', e.target.value || 'All');
}}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
onChange={(e) => handleColorChange(e.target.value)}
className="custom-select w-full px-3 py-2 border border-gray-300 dark:border-gray-600
bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">Sve boje</option>
{uniqueValues.colors.map(color => (
{colorOptions.map(color => (
<option key={color} value={color}>{color}</option>
))}
</select>
@@ -141,4 +161,4 @@ export const EnhancedFilters: React.FC<EnhancedFiltersProps> = ({
)}
</div>
);
};
};

View File

@@ -141,10 +141,11 @@ const FilamentTableV2: React.FC<FilamentTableV2Props> = ({ filaments }) => {
</div>
{/* Enhanced Filters */}
<EnhancedFilters
<EnhancedFilters
filters={filters}
onFilterChange={setFilters}
uniqueValues={uniqueValues}
inventoryFilaments={filaments}
/>

407
src/data/bambuLabCatalog.ts Normal file
View File

@@ -0,0 +1,407 @@
// Master Bambu Lab product catalog — single source of truth
// Material → Finish → Color[] with refill/spool availability
export interface CatalogColorEntry {
name: string;
refill: boolean;
spool: boolean;
}
export interface CatalogFinish {
colors: CatalogColorEntry[];
}
export type BambuLabCatalog = Record<string, Record<string, CatalogFinish>>;
export const BAMBU_LAB_CATALOG: BambuLabCatalog = {
PLA: {
Basic: {
colors: [
{ name: 'Jade White', refill: true, spool: true },
{ name: 'Black', refill: true, spool: true },
{ name: 'Red', refill: true, spool: true },
{ name: 'Bambu Green', refill: true, spool: true },
{ name: 'Blue', refill: true, spool: true },
{ name: 'Scarlet Red', refill: true, spool: true },
{ name: 'Lemon Yellow', refill: true, spool: true },
{ name: 'Cyan', refill: true, spool: true },
{ name: 'Sakura Pink', refill: true, spool: true },
{ name: 'Cobalt Blue', refill: true, spool: true },
{ name: 'Mistletoe Green', refill: true, spool: true },
{ name: 'Dark Red', refill: true, spool: true },
{ name: 'Hot Pink', refill: true, spool: true },
{ name: 'Lavender', refill: true, spool: true },
{ name: 'Light Blue', refill: true, spool: true },
{ name: 'Sky Blue', refill: true, spool: true },
{ name: 'Sunflower Yellow', refill: true, spool: true },
{ name: 'Pumpkin Orange', refill: true, spool: true },
{ name: 'Lime', refill: true, spool: true },
{ name: 'Blue Grey', refill: true, spool: false },
{ name: 'Beige', refill: true, spool: false },
{ name: 'Light Gray', refill: true, spool: false },
{ name: 'Yellow', refill: true, spool: false },
{ name: 'Orange', refill: true, spool: false },
{ name: 'Gold', refill: true, spool: false },
{ name: 'Bright Green', refill: true, spool: false },
{ name: 'Pink', refill: true, spool: false },
{ name: 'Magenta', refill: true, spool: false },
{ name: 'Maroon Red', refill: true, spool: false },
{ name: 'Purple', refill: true, spool: false },
{ name: 'Turquoise', refill: true, spool: false },
{ name: 'Brown', refill: true, spool: false },
{ name: 'Bronze', refill: true, spool: false },
{ name: 'Silver', refill: true, spool: false },
{ name: 'Dark Gray', refill: true, spool: false },
],
},
'Basic Gradient': {
colors: [
{ name: 'Neon City', refill: false, spool: true },
{ name: 'Midnight Blaze', refill: false, spool: true },
{ name: 'South Beach', refill: false, spool: true },
{ name: 'Arctic Whisper', refill: false, spool: true },
{ name: 'Cotton Candy Cloud', refill: false, spool: true },
{ name: 'Ocean to Meadow', refill: false, spool: true },
{ name: 'Solar Breeze', refill: false, spool: true },
{ name: 'Velvet Eclipse', refill: false, spool: true },
{ name: 'Dawn Radiance', refill: false, spool: true },
{ name: 'Dusk Glare', refill: false, spool: true },
{ name: 'Blueberry Bubblegum', refill: false, spool: true },
{ name: 'Blue Hawaii', refill: false, spool: true },
{ name: 'Gilded Rose', refill: false, spool: true },
{ name: 'Pink Citrus', refill: false, spool: true },
{ name: 'Mint Lime', refill: false, spool: true },
],
},
Matte: {
colors: [
{ name: 'Matte Ivory White', refill: true, spool: false },
{ name: 'Matte Charcoal', refill: true, spool: false },
{ name: 'Matte Scarlet Red', refill: true, spool: false },
{ name: 'Matte Marine Blue', refill: true, spool: false },
{ name: 'Matte Mandarin Orange', refill: true, spool: false },
{ name: 'Matte Ash Gray', refill: true, spool: false },
{ name: 'Matte Desert Tan', refill: true, spool: false },
{ name: 'Matte Nardo Gray', refill: true, spool: false },
{ name: 'Matte Apple Green', refill: true, spool: false },
{ name: 'Matte Bone White', refill: true, spool: false },
{ name: 'Matte Caramel', refill: true, spool: false },
{ name: 'Matte Dark Blue', refill: true, spool: false },
{ name: 'Matte Dark Brown', refill: true, spool: false },
{ name: 'Matte Dark Chocolate', refill: true, spool: false },
{ name: 'Matte Dark Green', refill: true, spool: false },
{ name: 'Matte Dark Red', refill: true, spool: false },
{ name: 'Matte Grass Green', refill: true, spool: false },
{ name: 'Matte Ice Blue', refill: true, spool: false },
{ name: 'Matte Lemon Yellow', refill: true, spool: false },
{ name: 'Matte Lilac Purple', refill: true, spool: false },
{ name: 'Matte Plum', refill: true, spool: false },
{ name: 'Matte Sakura Pink', refill: true, spool: false },
{ name: 'Matte Sky Blue', refill: true, spool: false },
{ name: 'Matte Latte Brown', refill: true, spool: false },
{ name: 'Matte Terracotta', refill: true, spool: false },
],
},
'Silk+': {
colors: [
{ name: 'Candy Green', refill: false, spool: true },
{ name: 'Candy Red', refill: false, spool: true },
{ name: 'Mint', refill: false, spool: true },
{ name: 'Titan Gray', refill: false, spool: true },
{ name: 'Rose Gold', refill: false, spool: true },
{ name: 'Champagne', refill: false, spool: true },
{ name: 'Baby Blue', refill: false, spool: true },
],
},
'Silk Multi-Color': {
colors: [
{ name: 'Silk Aurora Purple', refill: false, spool: true },
{ name: 'Silk Phantom Blue', refill: false, spool: true },
{ name: 'Silk Mystic Magenta', refill: false, spool: true },
],
},
Metal: {
colors: [
{ name: 'Iron Gray Metallic', refill: false, spool: true },
{ name: 'Iridium Gold Metallic', refill: false, spool: true },
{ name: 'Cobalt Blue Metallic', refill: false, spool: true },
{ name: 'Copper Brown Metallic', refill: false, spool: true },
{ name: 'Oxide Green Metallic', refill: false, spool: true },
],
},
Sparkle: {
colors: [
{ name: 'Onyx Black Sparkle', refill: false, spool: true },
{ name: 'Classic Gold Sparkle', refill: false, spool: true },
{ name: 'Crimson Red Sparkle', refill: false, spool: true },
{ name: 'Royal Purple Sparkle', refill: false, spool: true },
{ name: 'Slate Gray Sparkle', refill: false, spool: true },
{ name: 'Alpine Green Sparkle', refill: false, spool: true },
],
},
Galaxy: {
colors: [
{ name: 'Nebulae', refill: true, spool: true },
],
},
Marble: {
colors: [
{ name: 'White Marble', refill: false, spool: true },
{ name: 'Red Granite', refill: false, spool: true },
],
},
Glow: {
colors: [
{ name: 'Glow Blue', refill: false, spool: true },
{ name: 'Glow Green', refill: false, spool: true },
{ name: 'Glow Orange', refill: false, spool: true },
{ name: 'Glow Pink', refill: false, spool: true },
{ name: 'Glow Yellow', refill: false, spool: true },
],
},
Wood: {
colors: [
{ name: 'Ochre Yellow', refill: false, spool: true },
{ name: 'White Oak', refill: false, spool: true },
{ name: 'Clay Brown', refill: false, spool: true },
],
},
'Tough+': {
colors: [
{ name: 'Black', refill: true, spool: true },
],
},
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
{ name: 'Burgundy Red', refill: false, spool: true },
{ name: 'Jeans Blue', refill: false, spool: true },
{ name: 'Lava Gray', refill: false, spool: true },
{ name: 'Matcha Green', refill: false, spool: true },
{ name: 'Royal Blue', refill: false, spool: true },
{ name: 'Iris Purple', refill: false, spool: true },
],
},
},
PETG: {
HF: {
colors: [
{ name: 'Jade White', refill: true, spool: true },
{ name: 'Black', refill: true, spool: true },
{ name: 'Red', refill: true, spool: true },
{ name: 'Green', refill: true, spool: true },
{ name: 'Blue', refill: true, spool: true },
{ name: 'Gray', refill: true, spool: true },
{ name: 'Orange', refill: true, spool: true },
{ name: 'Cream', refill: true, spool: true },
{ name: 'Forest Green', refill: true, spool: true },
{ name: 'Lake Blue', refill: true, spool: true },
{ name: 'Lime Green', refill: true, spool: true },
{ name: 'Peanut Brown', refill: true, spool: true },
],
},
Translucent: {
colors: [
{ name: 'Clear', refill: false, spool: true },
{ name: 'Translucent Gray', refill: false, spool: true },
{ name: 'Translucent Brown', refill: false, spool: true },
{ name: 'Translucent Purple', refill: false, spool: true },
{ name: 'Translucent Orange', refill: false, spool: true },
{ name: 'Translucent Olive', refill: false, spool: true },
{ name: 'Translucent Pink', refill: false, spool: true },
{ name: 'Translucent Light Blue', refill: false, spool: true },
{ name: 'Translucent Tea', refill: false, spool: true },
],
},
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
{ name: 'Brick Red', refill: false, spool: true },
{ name: 'Indigo Blue', refill: false, spool: true },
{ name: 'Malachite Green', refill: false, spool: true },
{ name: 'Titan Gray', refill: false, spool: true },
{ name: 'Violet Purple', refill: false, spool: true },
],
},
},
ABS: {
Basic: {
colors: [
{ name: 'ABS Azure', refill: true, spool: true },
{ name: 'ABS Black', refill: true, spool: true },
{ name: 'ABS Blue', refill: true, spool: true },
{ name: 'ABS Olive', refill: true, spool: true },
{ name: 'ABS Tangerine Yellow', refill: true, spool: true },
{ name: 'ABS Navy Blue', refill: true, spool: true },
{ name: 'ABS Orange', refill: true, spool: true },
{ name: 'ABS Bambu Green', refill: true, spool: true },
{ name: 'ABS Red', refill: true, spool: true },
{ name: 'ABS White', refill: true, spool: true },
{ name: 'ABS Silver', refill: true, spool: true },
],
},
GF: {
colors: [
{ name: 'ABS GF Yellow', refill: true, spool: false },
{ name: 'ABS GF Orange', refill: true, spool: false },
],
},
},
TPU: {
'85A': {
colors: [
{ name: 'Black', refill: false, spool: true },
{ name: 'White', refill: false, spool: true },
{ name: 'Flesh', refill: false, spool: true },
{ name: 'Light Cyan', refill: false, spool: true },
{ name: 'Neon Orange', refill: false, spool: true },
],
},
'90A': {
colors: [
{ name: 'Black', refill: false, spool: true },
{ name: 'White', refill: false, spool: true },
{ name: 'Red', refill: false, spool: true },
{ name: 'Blaze', refill: false, spool: true },
{ name: 'Frozen', refill: false, spool: true },
{ name: 'Grape Jelly', refill: false, spool: true },
{ name: 'Crystal Blue', refill: false, spool: true },
{ name: 'Quicksilver', refill: false, spool: true },
{ name: 'Cocoa Brown', refill: false, spool: true },
],
},
'95A HF': {
colors: [
{ name: 'Black', refill: true, spool: false },
{ name: 'White', refill: true, spool: false },
{ name: 'TPU 95A HF Yellow', refill: true, spool: false },
],
},
},
ASA: {
Basic: {
colors: [
{ name: 'Black', refill: true, spool: true },
{ name: 'Blue', refill: true, spool: true },
{ name: 'Gray', refill: true, spool: true },
{ name: 'Green', refill: true, spool: true },
{ name: 'Red', refill: true, spool: true },
{ name: 'White', refill: true, spool: true },
],
},
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
Aero: {
colors: [
{ name: 'White', refill: false, spool: true },
],
},
},
PA6: {
GF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
PAHT: {
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
PC: {
Basic: {
colors: [
{ name: 'Clear Black', refill: false, spool: true },
{ name: 'Transparent', refill: false, spool: true },
],
},
FR: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
PET: {
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
PPA: {
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
PPS: {
CF: {
colors: [
{ name: 'Black', refill: false, spool: true },
],
},
},
};
// Helper functions
export function getMaterialOptions(): string[] {
return Object.keys(BAMBU_LAB_CATALOG).sort();
}
export function getFinishesForMaterial(material: string): string[] {
const materialData = BAMBU_LAB_CATALOG[material];
if (!materialData) return [];
return Object.keys(materialData).sort();
}
export function getAllFinishes(): string[] {
const finishes = new Set<string>();
for (const material of Object.values(BAMBU_LAB_CATALOG)) {
for (const finish of Object.keys(material)) {
finishes.add(finish);
}
}
return [...finishes].sort();
}
export function getColorsForMaterialFinish(material: string, finish: string): CatalogColorEntry[] {
return BAMBU_LAB_CATALOG[material]?.[finish]?.colors ?? [];
}
export function getColorsForMaterial(material: string): CatalogColorEntry[] {
const materialData = BAMBU_LAB_CATALOG[material];
if (!materialData) return [];
const seen = new Set<string>();
const result: CatalogColorEntry[] = [];
for (const finish of Object.values(materialData)) {
for (const color of finish.colors) {
if (!seen.has(color.name)) {
seen.add(color.name);
result.push(color);
}
}
}
return result.sort((a, b) => a.name.localeCompare(b.name));
}
export function catalogIsSpoolOnly(material: string, finish: string, color: string): boolean {
const entry = BAMBU_LAB_CATALOG[material]?.[finish]?.colors.find(c => c.name === color);
return entry ? (entry.spool && !entry.refill) : false;
}
export function catalogIsRefillOnly(material: string, finish: string, color: string): boolean {
const entry = BAMBU_LAB_CATALOG[material]?.[finish]?.colors.find(c => c.name === color);
return entry ? (entry.refill && !entry.spool) : false;
}
export function getFinishOptionsForType(type: string): string[] {
return getFinishesForMaterial(type);
}

View File

@@ -147,11 +147,8 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Yellow': { hex: '#F4EE2A' },
// ABS Colors
// ABS GF Colors
'ABS GF Yellow': { hex: '#FDD835' },
'ABS GF Orange': { hex: '#F48438' },
// ABS Colors
'ABS Azure': { hex: '#489FDF' },
'ABS Olive': { hex: '#748C45' },
'ABS Blue': { hex: '#0A2989' },
@@ -164,7 +161,7 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'ABS Black': { hex: '#000000' },
'ABS Silver': { hex: '#A6A9AA' },
// Translucent Colors
// PETG Translucent Colors
'Translucent Gray': { hex: '#B8B8B8' },
'Translucent Brown': { hex: '#C89A74' },
'Translucent Purple': { hex: '#C5A8D8' },
@@ -174,7 +171,15 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Translucent Light Blue': { hex: '#A8D8F0' },
'Translucent Tea': { hex: '#D9C7A8' },
// PLA Matte - New Colors (2025)
// PLA Matte Colors
'Matte Ivory White': { hex: '#FFFFF0' },
'Matte Charcoal': { hex: '#333333' },
'Matte Scarlet Red': { hex: '#DE4343' },
'Matte Marine Blue': { hex: '#0078BF' },
'Matte Mandarin Orange': { hex: '#F99963' },
'Matte Ash Gray': { hex: '#9B9EA0' },
'Matte Desert Tan': { hex: '#E8DBB7' },
'Matte Nardo Gray': { hex: '#747474' },
'Matte Apple Green': { hex: '#C6E188' },
'Matte Bone White': { hex: '#C8C5B6' },
'Matte Caramel': { hex: '#A4845C' },
@@ -185,7 +190,6 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Matte Dark Red': { hex: '#BB3D43' },
'Matte Grass Green': { hex: '#7CB342' },
'Matte Ice Blue': { hex: '#A3D8E1' },
'Matte Ivory': { hex: '#FFFFF0' },
'Matte Lemon Yellow': { hex: '#F7D959' },
'Matte Lilac Purple': { hex: '#AE96D4' },
'Matte Plum': { hex: '#851A52' },
@@ -199,7 +203,11 @@ export const bambuLabColors: Record<string, ColorMapping> = {
'Silk Phantom Blue': { hex: ['#00629B', '#000000'], isGradient: true },
'Silk Mystic Magenta': { hex: ['#720062', '#3A913F'], isGradient: true },
// TPU 95A HF Colors
// TPU Colors
'Flesh': { hex: '#E8C4A2' },
'Grape Jelly': { hex: '#6B2D75' },
'Crystal Blue': { hex: '#5BC0EB' },
'Quicksilver': { hex: '#A6A9AA' },
'TPU 95A HF Yellow': { hex: '#F3E600' },
// Default fallback

View File

@@ -1,6 +1,12 @@
// Complete Bambu Lab color database with hex codes
export const bambuLabColors = {
// Basic Colors
// Re-exports catalog-aligned color groupings
import { BAMBU_LAB_CATALOG } from './bambuLabCatalog';
// Flat hex lookup (for backwards compatibility)
export const bambuLabColors: Record<string, string> = {
// PLA Basic
"Jade White": "#FFFFFF",
"Black": "#000000",
"White": "#FFFFFF",
"Red": "#E53935",
@@ -8,39 +14,64 @@ export const bambuLabColors = {
"Green": "#43A047",
"Yellow": "#FDD835",
"Orange": "#FB8C00",
"Purple": "#8E24AA",
"Pink": "#EC407A",
"Grey": "#757575",
"Brown": "#6D4C41",
"Light Blue": "#64B5F6",
"Light Green": "#81C784",
"Mint Green": "#4DB6AC",
"Lime Green": "#C0CA33",
"Sky Blue": "#81D4FA",
"Navy Blue": "#283593",
"Magenta": "#E91E63",
"Violet": "#7B1FA2",
"Beige": "#F5DEB3",
"Ivory": "#FFFFF0",
// Matte Colors
"Matte Black": "#212121",
"Matte White": "#FAFAFA",
"Matte Red": "#C62828",
"Matte Blue": "#1565C0",
"Matte Green": "#2E7D32",
"Matte Yellow": "#F9A825",
"Matte Orange": "#EF6C00",
"Matte Purple": "#6A1B9A",
"Matte Pink": "#D81B60",
"Matte Grey": "#616161",
"Matte Brown": "#4E342E",
"Matte Mint": "#26A69A",
"Matte Lime": "#9E9D24",
"Matte Navy": "#1A237E",
"Matte Coral": "#FF5252",
"Purple": "#5E43B7",
"Pink": "#F55A74",
"Gray": "#8E9089",
"Brown": "#9D432C",
"Light Blue": "#61B0FF",
"Light Gray": "#D0D2D4",
"Sky Blue": "#73B2E5",
"Navy Blue": "#0C2340",
"Magenta": "#EC008C",
"Beige": "#F7E6DE",
"Bambu Green": "#00AE42",
"Scarlet Red": "#DE4343",
"Lemon Yellow": "#F7D959",
"Cyan": "#0086D6",
"Sakura Pink": "#E8AFCF",
"Cobalt Blue": "#0055B8",
"Mistletoe Green": "#3F8E43",
"Dark Red": "#BB3D43",
"Hot Pink": "#F5547D",
"Lavender": "#B5AAD5",
"Sunflower Yellow": "#FEC601",
"Pumpkin Orange": "#FF8E16",
"Lime": "#C5ED48",
"Blue Grey": "#5B6579",
"Gold": "#E4BD68",
"Bright Green": "#BDCF00",
"Maroon Red": "#0A2989",
"Turquoise": "#00B1B7",
"Bronze": "#847D48",
"Silver": "#A6A9AA",
"Dark Gray": "#555555",
// Matte Colors - New 2025
// PLA Basic Gradient
"Neon City": "#0047BB",
"Midnight Blaze": "#0047BB",
"South Beach": "#468791",
"Arctic Whisper": "#ECF7F8",
"Cotton Candy Cloud": "#E9E2EC",
"Ocean to Meadow": "#A1E4CA",
"Solar Breeze": "#F3D9D5",
"Velvet Eclipse": "#000000",
"Dawn Radiance": "#C472A1",
"Dusk Glare": "#F6B790",
"Blueberry Bubblegum": "#BADCF4",
"Blue Hawaii": "#739FE6",
"Gilded Rose": "#ED982C",
"Pink Citrus": "#F8C4BC",
"Mint Lime": "#BAF382",
// PLA Matte
"Matte Ivory White": "#FFFFF0",
"Matte Charcoal": "#333333",
"Matte Scarlet Red": "#DE4343",
"Matte Marine Blue": "#0078BF",
"Matte Mandarin Orange": "#F99963",
"Matte Ash Gray": "#9B9EA0",
"Matte Desert Tan": "#E8DBB7",
"Matte Nardo Gray": "#747474",
"Matte Apple Green": "#C6E188",
"Matte Bone White": "#C8C5B6",
"Matte Caramel": "#A4845C",
@@ -49,7 +80,7 @@ export const bambuLabColors = {
"Matte Dark Chocolate": "#4A3729",
"Matte Dark Green": "#68724D",
"Matte Dark Red": "#BB3D43",
"Matte Grass Green": "#61C680",
"Matte Grass Green": "#7CB342",
"Matte Ice Blue": "#A3D8E1",
"Matte Lemon Yellow": "#F7D959",
"Matte Lilac Purple": "#AE96D4",
@@ -58,132 +89,147 @@ export const bambuLabColors = {
"Matte Sky Blue": "#73B2E5",
"Matte Latte Brown": "#D3B7A7",
"Matte Terracotta": "#A25A37",
// Silk Colors
"Silk White": "#FEFEFE",
"Silk Black": "#0A0A0A",
"Silk Red": "#F44336",
"Silk Blue": "#2196F3",
"Silk Green": "#4CAF50",
"Silk Gold": "#FFD54F",
"Silk Silver": "#CFD8DC",
"Silk Purple": "#9C27B0",
"Silk Pink": "#F06292",
"Silk Orange": "#FF9800",
"Silk Bronze": "#A1887F",
"Silk Copper": "#BF6F3F",
"Silk Jade": "#00897B",
"Silk Rose Gold": "#E8A09A",
"Silk Pearl": "#F8F8FF",
"Silk Ruby": "#E91E63",
"Silk Sapphire": "#1976D2",
"Silk Emerald": "#00695C",
// Silk Multi-Color
// PLA Silk+
"Candy Green": "#408619",
"Candy Red": "#BB3A2E",
"Mint": "#A5DAB7",
"Titan Gray": "#606367",
"Rose Gold": "#B29593",
"Champagne": "#EBD0B1",
"Baby Blue": "#AEC3ED",
// PLA Silk Multi-Color
"Silk Aurora Purple": "#7F3696",
"Silk Phantom Blue": "#00629B",
"Silk Mystic Magenta": "#720062",
// Metal Colors
"Metal Grey": "#9E9E9E",
"Metal Silver": "#B0BEC5",
"Metal Gold": "#D4AF37",
"Metal Copper": "#B87333",
"Metal Bronze": "#CD7F32",
// Sparkle Colors
"Sparkle Red": "#EF5350",
"Sparkle Blue": "#42A5F5",
"Sparkle Green": "#66BB6A",
"Sparkle Purple": "#AB47BC",
"Sparkle Gold": "#FFCA28",
"Sparkle Silver": "#E0E0E0",
// Glow Colors
"Glow in the Dark Green": "#C8E6C9",
"Glow in the Dark Blue": "#BBDEFB",
// Transparent Colors
"Clear": "#FFFFFF",
"Transparent Red": "#EF5350",
"Transparent Blue": "#42A5F5",
"Transparent Green": "#66BB6A",
"Transparent Yellow": "#FFEE58",
"Transparent Orange": "#FFA726",
"Transparent Purple": "#AB47BC",
// Support Materials
"Natural": "#F5F5DC",
"Support White": "#F5F5F5",
"Support G": "#90CAF9",
// Metal Colors (PLA)
// PLA Metal
"Iron Gray Metallic": "#6B6C6F",
"Iridium Gold Metallic": "#B39B84",
"Cobalt Blue Metallic": "#39699E",
"Copper Brown Metallic": "#AA6443",
"Oxide Green Metallic": "#1D7C6A",
// ABS GF Colors
// PLA Sparkle
"Onyx Black Sparkle": "#2D2B28",
"Classic Gold Sparkle": "#E4BD68",
"Crimson Red Sparkle": "#792B36",
"Royal Purple Sparkle": "#483D8B",
"Slate Gray Sparkle": "#8E9089",
"Alpine Green Sparkle": "#3F5443",
// PLA Galaxy
"Nebulae": "#424379",
// PLA Marble
"White Marble": "#F7F3F0",
"Red Granite": "#AD4E38",
// PLA Glow
"Glow Blue": "#7AC0E9",
"Glow Green": "#A1FFAC",
"Glow Orange": "#FF9D5B",
"Glow Pink": "#F17B8F",
"Glow Yellow": "#F8FF80",
// PLA Wood
"Ochre Yellow": "#BC8B39",
"White Oak": "#D2CCA2",
"Clay Brown": "#8E621A",
// PLA CF
"Burgundy Red": "#951E23",
"Jeans Blue": "#6E88BC",
"Lava Gray": "#4D5054",
"Matcha Green": "#5C9748",
"Royal Blue": "#2842AD",
"Iris Purple": "#69398E",
// PETG HF
"Cream": "#F3E0B8",
"Forest Green": "#415520",
"Lake Blue": "#4672E4",
"Lime Green": "#8EE43D",
"Peanut Brown": "#7E5A1F",
// PETG Translucent
"Clear": "#FAFAFA",
"Translucent Gray": "#B8B8B8",
"Translucent Brown": "#C89A74",
"Translucent Purple": "#C5A8D8",
"Translucent Orange": "#FFB380",
"Translucent Olive": "#A4B885",
"Translucent Pink": "#F9B8D0",
"Translucent Light Blue": "#A8D8F0",
"Translucent Tea": "#D9C7A8",
// PETG CF
"Brick Red": "#9F332A",
"Indigo Blue": "#324585",
"Malachite Green": "#16B08E",
"Violet Purple": "#583061",
// ABS
"ABS Azure": "#489FDF",
"ABS Black": "#000000",
"ABS Blue": "#0A2989",
"ABS Olive": "#748C45",
"ABS Tangerine Yellow": "#FFC72C",
"ABS Navy Blue": "#0C2340",
"ABS Orange": "#FF6A13",
"ABS Bambu Green": "#00AE42",
"ABS Red": "#C12E1F",
"ABS White": "#FFFFFF",
"ABS Silver": "#A6A9AA",
"ABS GF Yellow": "#FDD835",
"ABS GF Orange": "#F48438",
// TPU 95A HF Colors
// TPU
"Flesh": "#E8C4A2",
"Light Cyan": "#B9E3DF",
"Neon Orange": "#F68A1B",
"Blaze": "#E78390",
"Frozen": "#A6DEF3",
"Grape Jelly": "#6B2D75",
"Crystal Blue": "#5BC0EB",
"Quicksilver": "#A6A9AA",
"Cocoa Brown": "#6F5034",
"TPU 95A HF Yellow": "#F3E600",
// Wood Colors
"Ochre Yellow": "#BC8B39",
"White Oak": "#D2CCA2",
"Clay Brown": "#8E621A"
// PC
"Clear Black": "#5A5161",
"Transparent": "#FFFFFF",
};
// Colors grouped by finish type for easier selection
export const colorsByFinish = {
"Basic": [
"Black", "White", "Red", "Blue", "Green", "Yellow", "Orange",
"Purple", "Pink", "Grey", "Brown", "Light Blue", "Light Green",
"Mint Green", "Lime Green", "Sky Blue", "Navy Blue", "Magenta",
"Violet", "Beige", "Ivory"
],
"Matte": [
"Matte Black", "Matte White", "Matte Red", "Matte Blue", "Matte Green",
"Matte Yellow", "Matte Orange", "Matte Purple", "Matte Pink", "Matte Grey",
"Matte Brown", "Matte Mint", "Matte Lime", "Matte Navy", "Matte Coral",
"Matte Apple Green", "Matte Bone White", "Matte Caramel", "Matte Dark Blue",
"Matte Dark Brown", "Matte Dark Chocolate", "Matte Dark Green", "Matte Dark Red",
"Matte Grass Green", "Matte Ice Blue", "Matte Lemon Yellow", "Matte Lilac Purple",
"Matte Latte Brown", "Matte Plum", "Matte Sakura Pink", "Matte Sky Blue", "Matte Terracotta"
],
"Silk": [
"Silk White", "Silk Black", "Silk Red", "Silk Blue", "Silk Green",
"Silk Gold", "Silk Silver", "Silk Purple", "Silk Pink", "Silk Orange",
"Silk Bronze", "Silk Copper", "Silk Jade", "Silk Rose Gold", "Silk Pearl",
"Silk Ruby", "Silk Sapphire", "Silk Emerald"
],
"Metal": [
"Metal Grey", "Metal Silver", "Metal Gold", "Metal Copper", "Metal Bronze"
],
"Sparkle": [
"Sparkle Red", "Sparkle Blue", "Sparkle Green", "Sparkle Purple",
"Sparkle Gold", "Sparkle Silver"
],
"Glow": [
"Glow in the Dark Green", "Glow in the Dark Blue"
],
"Transparent": [
"Clear", "Transparent Red", "Transparent Blue", "Transparent Green",
"Transparent Yellow", "Transparent Orange", "Transparent Purple"
],
"Support": [
"Natural", "Support White", "Support G"
],
"Wood": [
"Ochre Yellow", "White Oak", "Clay Brown"
]
};
// Colors grouped by finish type — derived from catalog
export const colorsByFinish: Record<string, string[]> = {};
// Build colorsByFinish from catalog
for (const [, finishes] of Object.entries(BAMBU_LAB_CATALOG)) {
for (const [finishName, finishData] of Object.entries(finishes)) {
if (!colorsByFinish[finishName]) {
colorsByFinish[finishName] = [];
}
for (const color of finishData.colors) {
if (!colorsByFinish[finishName].includes(color.name)) {
colorsByFinish[finishName].push(color.name);
}
}
}
}
// Sort each finish's colors
for (const finish of Object.keys(colorsByFinish)) {
colorsByFinish[finish].sort();
}
// Function to get hex code for a color
export function getColorHex(colorName: string): string {
return bambuLabColors[colorName as keyof typeof bambuLabColors] || "#000000";
return bambuLabColors[colorName] || "#000000";
}
// Function to get colors for a specific finish
export function getColorsForFinish(finish: string): string[] {
return colorsByFinish[finish as keyof typeof colorsByFinish] || [];
}
return colorsByFinish[finish] || [];
}