Fix color synchronization between admin panel and frontend

Fixed field name mismatch causing colors to display incorrectly:
- Frontend uses 'bojaHex' while backend expects 'boja_hex'
- Added bidirectional field transformation in API service layer
- Ensures hex color codes are properly saved and retrieved
- Also prevents editing of Bambu Lab predefined color hex codes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DaX
2025-06-23 21:45:20 +02:00
parent 1eec8c8b4a
commit 791195eba1
2 changed files with 40 additions and 9 deletions

View File

@@ -3,6 +3,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { colorService } from '@/src/services/api'; import { colorService } from '@/src/services/api';
import { bambuLabColors, getColorHex } from '@/src/data/bambuLabColorsComplete';
import '@/src/styles/select.css'; import '@/src/styles/select.css';
interface Color { interface Color {
@@ -308,6 +309,10 @@ function ColorForm({
hex: color.hex || '#000000', hex: color.hex || '#000000',
}); });
// Check if this is a Bambu Lab predefined color
const isBambuLabColor = !!(formData.name && bambuLabColors.hasOwnProperty(formData.name));
const bambuHex = formData.name ? getColorHex(formData.name) : null;
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target; const { name, value } = e.target;
setFormData({ setFormData({
@@ -318,9 +323,12 @@ function ColorForm({
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
// Use Bambu Lab hex if it's a predefined color
const hexToSave = isBambuLabColor && bambuHex ? bambuHex : formData.hex;
onSave({ onSave({
...color, ...color,
...formData name: formData.name,
hex: hexToSave
}); });
}; };
@@ -351,22 +359,29 @@ function ColorForm({
<input <input
type="color" type="color"
name="hex" name="hex"
value={formData.hex} value={isBambuLabColor && bambuHex ? bambuHex : formData.hex}
onChange={handleChange} onChange={handleChange}
className="w-12 h-12 p-1 border-2 border-gray-300 dark:border-gray-600 rounded-md cursor-pointer" disabled={isBambuLabColor}
style={{ backgroundColor: formData.hex }} className={`w-12 h-12 p-1 border-2 border-gray-300 dark:border-gray-600 rounded-md ${isBambuLabColor ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'}`}
style={{ backgroundColor: isBambuLabColor && bambuHex ? bambuHex : formData.hex }}
/> />
<input <input
type="text" type="text"
name="hex" name="hex"
value={formData.hex} value={isBambuLabColor && bambuHex ? bambuHex : formData.hex}
onChange={handleChange} onChange={handleChange}
required required
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" 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' : ''}`}
/> />
</div> </div>
{isBambuLabColor && (
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
Bambu Lab predefinisana boja - hex kod se ne može menjati
</p>
)}
</div> </div>
<div className="md:col-span-2 flex justify-end gap-4 mt-4"> <div className="md:col-span-2 flex justify-end gap-4 mt-4">

View File

@@ -70,16 +70,32 @@ export const colorService = {
export const filamentService = { export const filamentService = {
getAll: async () => { getAll: async () => {
const response = await api.get('/filaments'); const response = await api.get('/filaments');
return response.data; // Transform boja_hex to bojaHex for frontend compatibility
return response.data.map((f: any) => ({
...f,
bojaHex: f.boja_hex || f.bojaHex
}));
}, },
create: async (filament: any) => { create: async (filament: any) => {
const response = await api.post('/filaments', filament); // Transform bojaHex to boja_hex for backend
const data = {
...filament,
boja_hex: filament.bojaHex || filament.boja_hex
};
delete data.bojaHex; // Remove the frontend field
const response = await api.post('/filaments', data);
return response.data; return response.data;
}, },
update: async (id: string, filament: any) => { update: async (id: string, filament: any) => {
const response = await api.put(`/filaments/${id}`, filament); // Transform bojaHex to boja_hex for backend
const data = {
...filament,
boja_hex: filament.bojaHex || filament.boja_hex
};
delete data.bojaHex; // Remove the frontend field
const response = await api.put(`/filaments/${id}`, data);
return response.data; return response.data;
}, },