Files
Pigmento/js/collection.js

253 lines
7.7 KiB
JavaScript

import { hslToHex } from './converter.js';
const STORAGE_KEY = 'pigmento';
const HISTORY_MAX = 20;
function load() {
try {
return JSON.parse(localStorage.getItem(STORAGE_KEY)) || { favoriten: [], history: [], schemata: [] };
} catch {
return { favoriten: [], history: [], schemata: [] };
}
}
function save(data) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}
export function addFavorit(hsl) {
const data = load();
const hex = hslToHex(hsl);
if (!data.favoriten.some(f => hslToHex(f) === hex)) {
data.favoriten.push(hsl);
save(data);
renderSammlung();
}
}
export function removeFavorit(hex) {
const data = load();
data.favoriten = data.favoriten.filter(f => hslToHex(f) !== hex);
save(data);
renderSammlung();
}
export function addToHistory(hsl) {
const data = load();
const hex = hslToHex(hsl);
data.history = data.history.filter(h => hslToHex(h) !== hex);
data.history.unshift(hsl);
if (data.history.length > HISTORY_MAX) data.history = data.history.slice(0, HISTORY_MAX);
save(data);
}
export function addColorToSchema(hsl) {
const name = prompt('Schema-Name (leer = letztes Schema):');
if (name === null) return; // user pressed Cancel — do nothing
const data = load();
if (name) {
const existing = data.schemata.find(s => s.name === name);
if (existing) {
if (existing.farben.length < 4) {
existing.farben.push(hsl);
save(data);
renderSammlung();
} else {
alert('Schema hat bereits 4 Farben.');
}
} else {
data.schemata.push({ name, farben: [hsl] });
save(data);
renderSammlung();
}
} else if (data.schemata.length > 0) {
const last = data.schemata[data.schemata.length - 1];
if (last.farben.length < 4) {
last.farben.push(hsl);
save(data);
renderSammlung();
} else {
alert('Letztes Schema hat bereits 4 Farben.');
}
} else {
alert('Kein Schema vorhanden. Bitte Name eingeben.');
}
}
export function saveSchema(name, farben) {
const data = load();
const existing = data.schemata.find(s => s.name === name);
if (existing) {
existing.farben = farben;
} else {
data.schemata.push({ name, farben });
}
save(data);
renderSammlung();
}
export function deleteSchema(name) {
const data = load();
data.schemata = data.schemata.filter(s => s.name !== name);
save(data);
renderSammlung();
}
export function exportCollection() {
const data = load();
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'pigmento-sammlung.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
export function importCollection() {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.onchange = (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (ev) => {
try {
const imported = JSON.parse(ev.target.result);
const data = load();
const existingFavHexes = new Set(data.favoriten.map(hslToHex));
(imported.favoriten || []).forEach(hsl => {
if (!hsl || typeof hsl.h !== 'number' || typeof hsl.s !== 'number' || typeof hsl.l !== 'number') return;
if (!existingFavHexes.has(hslToHex(hsl))) data.favoriten.push(hsl);
});
const existingSchemaNames = new Set(data.schemata.map(s => s.name));
(imported.schemata || []).forEach(s => {
if (!s || typeof s.name !== 'string' || !Array.isArray(s.farben)) return;
if (!existingSchemaNames.has(s.name)) data.schemata.push(s);
});
const existingHistHexes = new Set(data.history.map(hslToHex));
(imported.history || []).forEach(hsl => {
if (!hsl || typeof hsl.h !== 'number' || typeof hsl.s !== 'number' || typeof hsl.l !== 'number') return;
if (!existingHistHexes.has(hslToHex(hsl))) data.history.push(hsl);
});
if (data.history.length > 20) data.history = data.history.slice(0, 20);
save(data);
renderSammlung();
alert('Import erfolgreich.');
} catch {
alert('Ungültige Datei.');
}
};
reader.readAsText(file);
};
input.click();
}
function makeSwatch(hsl) {
const hex = hslToHex(hsl);
const wrapper = document.createElement('div');
wrapper.className = 'swatch-cell';
const swatch = document.createElement('div');
swatch.className = 'swatch';
swatch.style.background = hex;
swatch.title = hex;
const label = document.createElement('span');
label.style.cssText = 'font-size:0.75rem;font-family:monospace';
label.textContent = hex;
wrapper.appendChild(swatch);
wrapper.appendChild(label);
return wrapper;
}
export function renderSammlung() {
const data = load();
// Favoriten
const favContainer = document.getElementById('sammlung-favoriten');
if (favContainer) {
favContainer.textContent = '';
if (data.favoriten.length === 0) {
const msg = document.createElement('p');
msg.style.cssText = 'color:#999;font-size:0.85rem';
msg.textContent = 'Noch keine Favoriten.';
favContainer.appendChild(msg);
} else {
data.favoriten.forEach(hsl => {
const hex = hslToHex(hsl);
const cell = makeSwatch(hsl);
const del = document.createElement('button');
del.className = 'action-btn';
del.textContent = 'Löschen';
del.style.fontSize = '0.7rem';
del.addEventListener('click', () => removeFavorit(hex));
cell.appendChild(del);
favContainer.appendChild(cell);
});
}
}
// Historie
const histContainer = document.getElementById('sammlung-history');
if (histContainer) {
histContainer.textContent = '';
if (data.history.length === 0) {
const msg = document.createElement('p');
msg.style.cssText = 'color:#999;font-size:0.85rem';
msg.textContent = 'Noch kein Verlauf.';
histContainer.appendChild(msg);
} else {
data.history.forEach(hsl => {
histContainer.appendChild(makeSwatch(hsl));
});
}
}
// Schemata
const schemataContainer = document.getElementById('sammlung-schemata');
if (schemataContainer) {
schemataContainer.textContent = '';
if (data.schemata.length === 0) {
const msg = document.createElement('p');
msg.style.cssText = 'color:#999;font-size:0.85rem';
msg.textContent = 'Noch keine Schemata.';
schemataContainer.appendChild(msg);
} else {
data.schemata.forEach(schema => {
const card = document.createElement('div');
card.style.cssText = 'border:1px solid #ddd;border-radius:8px;padding:1rem;margin-bottom:0.75rem;background:#fff';
const header = document.createElement('div');
header.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:0.5rem';
const nameEl = document.createElement('strong');
nameEl.textContent = schema.name;
const delBtn = document.createElement('button');
delBtn.className = 'action-btn';
delBtn.textContent = 'Schema löschen';
delBtn.style.fontSize = '0.75rem';
delBtn.addEventListener('click', () => deleteSchema(schema.name));
header.appendChild(nameEl);
header.appendChild(delBtn);
const swatchesDiv = document.createElement('div');
swatchesDiv.style.cssText = 'display:flex;gap:0.5rem;flex-wrap:wrap';
schema.farben.forEach(hsl => swatchesDiv.appendChild(makeSwatch(hsl)));
card.appendChild(header);
card.appendChild(swatchesDiv);
schemataContainer.appendChild(card);
});
}
}
}