feat: duplikovanie sablon cenoviek v editore (uloha 11)
Ikona Duplikovat pri sablone vytvori kopiu "(kopia)", hned ju ulozi a otvori na upravu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
21320e792b
commit
23ac4dc830
1 file changed
+59
-13
@@ -4,7 +4,22 @@ import React, { useState, useRef, useEffect } from 'react';
|
||||
import { BadgeTemplate, BadgeLayer } from '@/types/newsletter';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
import { DEFAULT_BADGE_TEMPLATES, renderCleanBadgeSvg, svgToCleanPng } from '@/lib/badgeUtils';
|
||||
import { Tag, Plus, Check, Trash2, X, Upload, Eye, Move, AlignLeft, AlignCenter, AlignRight, ZoomIn, ZoomOut } from 'lucide-react';
|
||||
import { Tag, Plus, Check, Trash2, X, Upload, Eye, Move, AlignLeft, AlignCenter, AlignRight, ZoomIn, ZoomOut, Copy } from 'lucide-react';
|
||||
|
||||
// Riadok tabuľky badges v Supabase pre danú šablónu
|
||||
function toBadgeDbPayload(badge: BadgeTemplate) {
|
||||
return {
|
||||
name: badge.name,
|
||||
svg_raw: badge.svgRaw,
|
||||
layers_config: {
|
||||
layers: badge.layersConfig,
|
||||
width: badge.width || 110,
|
||||
align: badge.align || 'center',
|
||||
paddingTop: badge.paddingTop ?? 4,
|
||||
paddingBottom: badge.paddingBottom ?? 4
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Priblíženie plátna v editore: rozsah posuvníka a kroky tlačidiel +/−
|
||||
const CANVAS_ZOOM_MIN = 0.5;
|
||||
@@ -401,6 +416,35 @@ export const BadgeEditorModal: React.FC<BadgeEditorModalProps> = ({
|
||||
});
|
||||
};
|
||||
|
||||
// Duplikovanie šablóny: kópia sa hneď uloží (Supabase, inak localStorage) a otvorí na úpravu
|
||||
const duplicateBadgeTemplate = async (badge: BadgeTemplate) => {
|
||||
const copy: BadgeTemplate = {
|
||||
...JSON.parse(JSON.stringify(badge)),
|
||||
id: `badge-${Date.now()}`,
|
||||
name: `${badge.name} (kópia)`
|
||||
};
|
||||
let saved = copy;
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('badges')
|
||||
.insert([toBadgeDbPayload(copy)])
|
||||
.select();
|
||||
if (!error && data && data[0]) {
|
||||
saved = { ...copy, id: data[0].id };
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
const list = [...badges];
|
||||
const idx = list.findIndex((b) => b.id === badge.id);
|
||||
list.splice(idx + 1, 0, saved);
|
||||
setBadges(list);
|
||||
setActiveBadge(saved);
|
||||
setSelectedLayerId(saved.layersConfig?.[0]?.id ?? null);
|
||||
try {
|
||||
localStorage.setItem('coop_custom_badges', JSON.stringify(list));
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
const deleteBadgeTemplate = async (badgeId: string) => {
|
||||
if (confirm('Naozaj chcete zmazať túto šablónu cenovky?')) {
|
||||
// Predvolené šablóny existujú len v prehliadači (localStorage), v databáze nie sú
|
||||
@@ -423,17 +467,7 @@ export const BadgeEditorModal: React.FC<BadgeEditorModalProps> = ({
|
||||
if (!activeBadge) return;
|
||||
setIsSavingDb(true);
|
||||
try {
|
||||
const payload: any = {
|
||||
name: activeBadge.name,
|
||||
svg_raw: activeBadge.svgRaw,
|
||||
layers_config: {
|
||||
layers: activeBadge.layersConfig,
|
||||
width: activeBadge.width || 110,
|
||||
align: activeBadge.align || 'center',
|
||||
paddingTop: activeBadge.paddingTop ?? 4,
|
||||
paddingBottom: activeBadge.paddingBottom ?? 4
|
||||
}
|
||||
};
|
||||
const payload = toBadgeDbPayload(activeBadge);
|
||||
|
||||
let savedBadge: BadgeTemplate | null = null;
|
||||
const isExistingUuid = activeBadge.id && !activeBadge.id.startsWith('badge-');
|
||||
@@ -646,18 +680,30 @@ export const BadgeEditorModal: React.FC<BadgeEditorModalProps> = ({
|
||||
>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<p className="text-xs font-bold text-gray-800 truncate">{b.name}</p>
|
||||
<div className="flex items-center opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
duplicateBadgeTemplate(b);
|
||||
}}
|
||||
className="text-gray-300 hover:text-blue-600 p-1 rounded transition-colors"
|
||||
title="Duplikovať šablónu"
|
||||
>
|
||||
<Copy className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
{/* Zmazať sa dá každá šablóna, aj staršie predvolené (badge-preset-*) uložené v prehliadači */}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
deleteBadgeTemplate(b.id);
|
||||
}}
|
||||
className="text-gray-300 hover:text-red-600 p-1 rounded transition-colors opacity-0 group-hover:opacity-100"
|
||||
className="text-gray-300 hover:text-red-600 p-1 rounded transition-colors"
|
||||
title="Zmazať šablónu"
|
||||
>
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="w-full h-12 flex items-center justify-center transform scale-75 origin-center overflow-hidden pointer-events-none"
|
||||
dangerouslySetInnerHTML={{
|
||||
|
||||
Reference in new issue
Block a user