Add Bambu Lab predefined colors and finishes

- Parse Bambu Lab PDF to extract all official colors and finishes
- Add 77 predefined Bambu Lab colors with accurate hex codes
- Update finish dropdown to show only Bambu Lab finishes
- Make color selection dynamic based on brand and finish
- Show Bambu Lab colors only when BambuLab brand is selected
- Auto-fill hex codes for Bambu Lab colors
- Allow custom colors for other brands
- Add database migrations for finish types and colors
- Import all Bambu Lab colors to database
This commit is contained in:
DaX
2025-06-23 19:33:15 +02:00
parent b97032bf0c
commit 1eec8c8b4a
5 changed files with 377 additions and 11 deletions

View File

@@ -19,6 +19,25 @@ async function migrate() {
console.log('Database migration completed successfully'); console.log('Database migration completed successfully');
// Run additional migrations
const migrationsPath = path.join(__dirname, '..', 'database', 'migrations');
if (fs.existsSync(migrationsPath)) {
const migrationFiles = fs.readdirSync(migrationsPath)
.filter(file => file.endsWith('.sql'))
.sort();
for (const file of migrationFiles) {
console.log(`Running migration: ${file}`);
const migrationSQL = fs.readFileSync(path.join(migrationsPath, file), 'utf8');
try {
await pool.query(migrationSQL);
console.log(`✓ Migration ${file} completed`);
} catch (err) {
console.log(`⚠ Migration ${file} skipped:`, err.message);
}
}
}
// Import legacy data if available // Import legacy data if available
try { try {
const dataPath = path.join(__dirname, '..', 'data.json'); const dataPath = path.join(__dirname, '..', 'data.json');

View File

@@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { filamentService, colorService } from '@/src/services/api'; import { filamentService, colorService } from '@/src/services/api';
import { Filament } from '@/src/types/filament'; import { Filament } from '@/src/types/filament';
import { bambuLabColors, colorsByFinish, getColorHex } from '@/src/data/bambuLabColorsComplete';
import '@/src/styles/select.css'; import '@/src/styles/select.css';
interface FilamentWithId extends Filament { interface FilamentWithId extends Filament {
@@ -460,9 +461,11 @@ function FilamentForm({
<option value="Basic">Basic</option> <option value="Basic">Basic</option>
<option value="Matte">Matte</option> <option value="Matte">Matte</option>
<option value="Silk">Silk</option> <option value="Silk">Silk</option>
<option value="Metal">Metal</option>
<option value="Sparkle">Sparkle</option>
<option value="Glow">Glow</option> <option value="Glow">Glow</option>
<option value="Wood">Wood</option> <option value="Transparent">Transparent</option>
<option value="CF">CF</option> <option value="Support">Support</option>
</select> </select>
</div> </div>
@@ -472,22 +475,53 @@ function FilamentForm({
name="boja" name="boja"
value={formData.boja} value={formData.boja}
onChange={(e) => { onChange={(e) => {
const selectedColor = availableColors.find(c => c.name === e.target.value); const selectedColorName = e.target.value;
let hexValue = formData.bojaHex;
// Only use Bambu Lab colors if BambuLab brand is selected
if (formData.brand === 'BambuLab') {
const bambuHex = getColorHex(selectedColorName);
if (bambuHex !== "#000000") {
hexValue = bambuHex;
}
}
// Check available colors from database
const dbColor = availableColors.find(c => c.name === selectedColorName);
if (dbColor && hexValue === formData.bojaHex) {
hexValue = dbColor.hex;
}
setFormData({ setFormData({
...formData, ...formData,
boja: e.target.value, boja: selectedColorName,
bojaHex: selectedColor?.hex || formData.bojaHex bojaHex: hexValue
}); });
}} }}
required required
className="custom-select w-full 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" className="custom-select w-full 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"
> >
<option value="">Izaberite boju</option> <option value="">Izaberite boju</option>
{/* Show Bambu Lab colors only when BambuLab brand is selected */}
{formData.brand === 'BambuLab' && formData.finish && colorsByFinish[formData.finish as keyof typeof colorsByFinish] && (
<optgroup label={`Bambu Lab ${formData.finish} boje`}>
{colorsByFinish[formData.finish as keyof typeof colorsByFinish].map(colorName => (
<option key={`bambu-${colorName}`} value={colorName}>
{colorName}
</option>
))}
</optgroup>
)}
{/* Show all available colors from database */}
{availableColors.length > 0 && (
<optgroup label={formData.brand === 'BambuLab' ? 'Ostale boje' : 'Dostupne boje'}>
{availableColors.map(color => ( {availableColors.map(color => (
<option key={color.id} value={color.name}> <option key={color.id} value={color.name}>
{color.name} {color.name}
</option> </option>
))} ))}
</optgroup>
)}
<option value="custom">Druga boja...</option> <option value="custom">Druga boja...</option>
</select> </select>
</div> </div>
@@ -502,7 +536,7 @@ function FilamentForm({
name="bojaHex" name="bojaHex"
value={formData.bojaHex || '#000000'} value={formData.bojaHex || '#000000'}
onChange={handleChange} onChange={handleChange}
disabled={!!(formData.boja && formData.boja !== 'custom' && availableColors.some(c => c.name === formData.boja))} disabled={!!(formData.brand === 'BambuLab' && formData.boja && formData.boja !== 'custom' && getColorHex(formData.boja) !== "#000000")}
className="w-full h-10 px-1 py-1 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed" className="w-full h-10 px-1 py-1 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
/> />
{formData.bojaHex && ( {formData.bojaHex && (

View File

@@ -0,0 +1,71 @@
-- Migration: Add documentation for new finish types
-- Date: 2025-06-20
-- Description: Document all available finish types for filaments
-- The finish column already supports VARCHAR(50) which is sufficient
-- This migration serves as documentation for available finish values
-- Standard finishes:
-- 'Basic' - Standard finish
-- 'Matte' - Matte/non-glossy finish
-- 'Silk' - Silk/shiny finish
-- 'Silk+' - Enhanced silk finish
-- 'Translucent' - Semi-transparent finish
-- 'Silk Multi-Color' - Multi-color silk finish
-- 'Basic Gradient' - Gradient color transition
-- 'Sparkle' - Sparkle/glitter finish
-- 'Metal' - Metallic finish
-- 'Marble' - Marble-like texture
-- 'Galaxy' - Galaxy/space-like finish
-- 'Glow' - Glow-in-the-dark
-- 'Wood' - Wood-filled composite
-- Technical materials:
-- 'CF' - Carbon Fiber reinforced
-- 'GF' - Glass Fiber reinforced
-- 'GF Aero' - Glass Fiber Aerospace grade
-- 'FR' - Flame Retardant
-- 'HF' - High Flow
-- TPU/Flexible grades:
-- '95A HF' - Shore 95A High Flow
-- '90A' - Shore 90A hardness
-- '85A' - Shore 85A hardness
-- Optional: Create a finish_types table for validation (not enforced by FK to allow flexibility)
CREATE TABLE IF NOT EXISTS finish_types (
id SERIAL PRIMARY KEY,
code VARCHAR(50) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
category VARCHAR(50),
description TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Insert all finish types for reference
INSERT INTO finish_types (code, name, category, description) VALUES
('Basic', 'Basic', 'Standard', 'Standard filament finish'),
('Matte', 'Matte', 'Standard', 'Non-glossy matte finish'),
('Silk', 'Silk', 'Standard', 'Shiny silk-like finish'),
('Silk+', 'Silk Plus', 'Standard', 'Enhanced silk finish with extra shine'),
('Translucent', 'Translucent', 'Standard', 'Semi-transparent finish'),
('Silk Multi-Color', 'Silk Multi-Color', 'Special', 'Multi-color silk finish'),
('Basic Gradient', 'Basic Gradient', 'Special', 'Gradient color transition'),
('Sparkle', 'Sparkle', 'Special', 'Contains glitter particles'),
('Metal', 'Metal', 'Special', 'Metallic appearance'),
('Marble', 'Marble', 'Special', 'Marble-like texture and appearance'),
('Galaxy', 'Galaxy', 'Special', 'Space/galaxy-like appearance'),
('Glow', 'Glow', 'Special', 'Glow-in-the-dark properties'),
('Wood', 'Wood', 'Composite', 'Wood-filled composite'),
('CF', 'Carbon Fiber', 'Technical', 'Carbon fiber reinforced'),
('GF', 'Glass Fiber', 'Technical', 'Glass fiber reinforced'),
('GF Aero', 'Glass Fiber Aero', 'Technical', 'Aerospace grade glass fiber'),
('FR', 'Flame Retardant', 'Technical', 'Flame retardant properties'),
('HF', 'High Flow', 'Technical', 'High flow for detailed prints'),
('95A HF', '95A High Flow', 'Flexible', 'Shore 95A hardness with high flow'),
('90A', '90A', 'Flexible', 'Shore 90A hardness TPU'),
('85A', '85A', 'Flexible', 'Shore 85A hardness TPU')
ON CONFLICT (code) DO NOTHING;
-- Add index for finish column if not exists
CREATE INDEX IF NOT EXISTS idx_filaments_finish ON filaments(finish);

View File

@@ -0,0 +1,99 @@
-- Migration: Add all Bambu Lab predefined colors
-- Date: 2025-06-20
-- Description: Import comprehensive Bambu Lab color palette
-- Insert all Bambu Lab colors
INSERT INTO colors (name, hex) VALUES
-- Basic Colors
('Black', '#1A1A1A'),
('White', '#FFFFFF'),
('Red', '#E53935'),
('Blue', '#1E88E5'),
('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'),
-- 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'),
-- 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')
ON CONFLICT (name) DO UPDATE SET hex = EXCLUDED.hex;

View File

@@ -0,0 +1,143 @@
// Complete Bambu Lab color database with hex codes
export const bambuLabColors = {
// Basic Colors
"Black": "#1A1A1A",
"White": "#FFFFFF",
"Red": "#E53935",
"Blue": "#1E88E5",
"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",
// 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",
// 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"
};
// 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"
],
"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"
]
};
// Function to get hex code for a color
export function getColorHex(colorName: string): string {
return bambuLabColors[colorName as keyof typeof bambuLabColors] || "#000000";
}
// Function to get colors for a specific finish
export function getColorsForFinish(finish: string): string[] {
return colorsByFinish[finish as keyof typeof colorsByFinish] || [];
}