Files
Coop-NL/src/components/editor/BadgeManagerModal.tsx
T

197 lines
7.3 KiB
TypeScript

'use client';
import React, { useState, useEffect } from 'react';
import { BadgeTemplate } from '@/types/newsletter';
import { supabase } from '@/lib/supabase';
import { Tag, Plus, Check, Trash2, X } from 'lucide-react';
interface BadgeManagerModalProps {
isOpen: boolean;
onClose: () => void;
onSelectBadge: (badge: BadgeTemplate) => void;
}
export const BadgeManagerModal: React.FC<BadgeManagerModalProps> = ({
isOpen,
onClose,
onSelectBadge
}) => {
const [badges, setBadges] = useState<BadgeTemplate[]>([]);
const [loading, setLoading] = useState(false);
const [creating, setCreating] = useState(false);
const [newBadgeName, setNewBadgeName] = useState('');
const [newBadgeColor, setNewBadgeColor] = useState('#e2001a');
const [newBadgeText, setNewBadgeText] = useState('SUPER CENA');
useEffect(() => {
if (isOpen) {
loadBadges();
}
}, [isOpen]);
const loadBadges = async () => {
setLoading(true);
try {
const { data, error } = await supabase.from('badges').select('*').order('created_at', { ascending: false });
if (data && !error) {
setBadges(
data.map((d: any) => ({
id: d.id,
name: d.name,
svgRaw: d.svg_raw,
layersConfig: d.layers_config || []
}))
);
}
} catch (err) {
console.error('Error loading badges:', err);
} finally {
setLoading(false);
}
};
const createBadge = async () => {
if (!newBadgeName) return;
const svg = `<svg viewBox="0 0 160 80" xmlns="http://www.w3.org/2000/svg"><rect width="160" height="80" rx="8" fill="${newBadgeColor}"/></svg>`;
const layers = [
{ id: 'l1', type: 'text', text: newBadgeText, x: 80, y: 35, fontSize: 18, fontWeight: '900', fill: '#ffffff', align: 'center' },
{ id: 'l2', type: 'text', text: '{zlava}', x: 80, y: 65, fontSize: 24, fontWeight: '900', fill: '#ffd100', align: 'center' }
];
try {
const { data, error } = await supabase.from('badges').insert([
{
name: newBadgeName,
svg_raw: svg,
layers_config: layers
}
]).select();
if (data && !error) {
loadBadges();
setCreating(false);
setNewBadgeName('');
}
} catch (err) {
console.error('Error creating badge:', err);
}
};
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 bg-black/60 backdrop-blur-xs flex items-center justify-center p-4">
<div className="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[85vh] overflow-hidden flex flex-col">
{/* Header */}
<div className="px-6 py-4 border-b border-gray-100 flex items-center justify-between">
<div className="flex items-center gap-2">
<Tag className="w-5 h-5 text-red-600" />
<h2 className="text-lg font-bold text-gray-900">Správca grafických cenoviek</h2>
</div>
<button onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600 rounded-lg">
<X className="w-5 h-5" />
</button>
</div>
{/* Content */}
<div className="p-6 overflow-y-auto space-y-4">
<div className="flex justify-between items-center mb-2">
<p className="text-sm text-gray-500">
Vyberte cenovku pre produkt alebo navrhnite vlastnú.
</p>
<button
onClick={() => setCreating(!creating)}
className="text-xs font-bold text-red-600 hover:text-red-700 flex items-center gap-1 border border-red-200 px-3 py-1.5 rounded-lg hover:bg-red-50"
>
<Plus className="w-3.5 h-3.5" />
Nová cenovka
</button>
</div>
{/* Create Form */}
{creating && (
<div className="p-4 bg-gray-50 rounded-xl border border-gray-200 space-y-3">
<h3 className="text-xs font-bold text-gray-800 uppercase tracking-wider">Vytvoriť cenovku</h3>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="block text-xs font-semibold text-gray-600 mb-1">Názov cenovky</label>
<input
type="text"
value={newBadgeName}
onChange={(e) => setNewBadgeName(e.target.value)}
placeholder="Napr. Modrá novinka"
className="w-full text-sm border border-gray-300 rounded-lg p-2"
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 mb-1">Text cenovky</label>
<input
type="text"
value={newBadgeText}
onChange={(e) => setNewBadgeText(e.target.value)}
placeholder="Napr. EXTRA CENA"
className="w-full text-sm border border-gray-300 rounded-lg p-2"
/>
</div>
<div>
<label className="block text-xs font-semibold text-gray-600 mb-1">Farba pozadia</label>
<div className="flex items-center gap-2">
<input
type="color"
value={newBadgeColor}
onChange={(e) => setNewBadgeColor(e.target.value)}
className="w-8 h-8 rounded-md cursor-pointer border-0"
/>
<span className="text-xs font-mono">{newBadgeColor}</span>
</div>
</div>
</div>
<div className="flex justify-end gap-2 pt-2">
<button
onClick={() => setCreating(false)}
className="px-3 py-1.5 text-xs font-semibold text-gray-600"
>
Zrušiť
</button>
<button
onClick={createBadge}
className="px-4 py-1.5 text-xs font-bold bg-red-600 text-white rounded-lg hover:bg-red-700"
>
Uložiť do databázy
</button>
</div>
</div>
)}
{/* Badges List */}
<div className="grid grid-cols-2 gap-4">
{badges.map((b) => (
<div
key={b.id}
className="border border-gray-200 rounded-xl p-4 flex flex-col items-center justify-between hover:border-red-400 hover:shadow-md transition-all group bg-white"
>
<span className="text-xs font-bold text-gray-700 mb-2">{b.name}</span>
<div
className="w-36 h-20 flex items-center justify-center relative my-2 overflow-hidden rounded-lg shadow-xs"
dangerouslySetInnerHTML={{ __html: b.svgRaw || '' }}
/>
<button
onClick={() => {
onSelectBadge(b);
onClose();
}}
className="mt-3 w-full py-1.5 text-xs font-bold text-white bg-gray-900 group-hover:bg-red-600 rounded-lg transition-colors flex items-center justify-center gap-1.5"
>
<Check className="w-3.5 h-3.5" />
Použiť na produkt
</button>
</div>
))}
</div>
</div>
</div>
</div>
);
};