feat: anchor header/footer, editable header buttons, campaign management, image uploads, badge font customization, and brevo export fix
This commit is contained in:
1 parent
3dc5778155
commit
2b4d3643cb
10 files changed
+1819
-178
No files matched your search
@@ -4,6 +4,7 @@ import React from 'react';
|
||||
import { NewsletterModule, ProductItem } from '@/types/newsletter';
|
||||
import { Plus, Trash2, Image as ImageIcon, Tag, Store } from 'lucide-react';
|
||||
import { SUPABASE_ASSETS_BASE } from '@/lib/defaultCampaign';
|
||||
import { ImageUploadInput } from './ImageUploadInput';
|
||||
|
||||
interface ConfigPanelProps {
|
||||
module: NewsletterModule | null;
|
||||
@@ -85,41 +86,136 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
)}
|
||||
|
||||
{/* HEADER */}
|
||||
{module.type === 'header' && (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">URL Loga</label>
|
||||
<input
|
||||
type="text"
|
||||
{module.type === 'header' && (() => {
|
||||
const navLinks = module.data.navLinks || [
|
||||
{ label: 'Letáky', url: 'https://www.coop.sk/sk/letaky', variant: 'outline' },
|
||||
{ label: 'COOP Klub', url: 'https://www.coopklub.sk', variant: 'filled' }
|
||||
];
|
||||
|
||||
const updateNavLink = (index: number, patch: Partial<typeof navLinks[0]>) => {
|
||||
const updated = [...navLinks];
|
||||
updated[index] = { ...updated[index], ...patch };
|
||||
updateData({ navLinks: updated });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<ImageUploadInput
|
||||
label="Logo COOP Jednota"
|
||||
value={module.data.logoUrl || ''}
|
||||
onChange={(e) => updateData({ logoUrl: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2 font-mono text-xs"
|
||||
onChange={(url) => updateData({ logoUrl: url })}
|
||||
/>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Odkaz loga</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.logoLink || ''}
|
||||
onChange={(e) => updateData({ logoLink: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
placeholder="https://www.coop.sk"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Tlačidlá v hlavičke */}
|
||||
<div className="pt-2 border-t border-gray-200 space-y-4">
|
||||
<span className="text-xs font-bold text-gray-800 uppercase tracking-wider block">
|
||||
Tlačidlá v hlavičke
|
||||
</span>
|
||||
|
||||
{/* Tlačidlo 1 (Letáky) */}
|
||||
<div className="bg-gray-50 p-3 rounded-xl border border-gray-200 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs font-bold text-gray-700">Tlačidlo 1 (Letáky)</span>
|
||||
<span className="text-[10px] bg-red-100 text-red-700 font-bold px-2 py-0.5 rounded">
|
||||
{navLinks[0]?.variant === 'filled' ? 'Plné' : 'Obrys'}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Text tlačidla</label>
|
||||
<input
|
||||
type="text"
|
||||
value={navLinks[0]?.label || ''}
|
||||
onChange={(e) => updateNavLink(0, { label: e.target.value })}
|
||||
className="w-full text-xs font-bold border border-gray-300 rounded-lg p-2 bg-white"
|
||||
placeholder="Letáky"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Cieľový odkaz (URL)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={navLinks[0]?.url || ''}
|
||||
onChange={(e) => updateNavLink(0, { url: e.target.value })}
|
||||
className="w-full text-xs border border-gray-300 rounded-lg p-2 bg-white"
|
||||
placeholder="https://www.coop.sk/sk/letaky"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Štýl zobrazenia</label>
|
||||
<select
|
||||
value={navLinks[0]?.variant || 'outline'}
|
||||
onChange={(e) => updateNavLink(0, { variant: e.target.value as any })}
|
||||
className="w-full text-xs border border-gray-300 rounded-lg p-2 bg-white font-medium"
|
||||
>
|
||||
<option value="outline">Červený obrys (Biele pozadie, červený text)</option>
|
||||
<option value="filled">Modré plné tlačidlo (Biele písmo)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tlačidlo 2 (COOP Klub) */}
|
||||
<div className="bg-gray-50 p-3 rounded-xl border border-gray-200 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs font-bold text-gray-700">Tlačidlo 2 (COOP Klub)</span>
|
||||
<span className="text-[10px] bg-blue-100 text-blue-700 font-bold px-2 py-0.5 rounded">
|
||||
{navLinks[1]?.variant === 'filled' ? 'Plné modré' : 'Obrys'}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Text tlačidla</label>
|
||||
<input
|
||||
type="text"
|
||||
value={navLinks[1]?.label || ''}
|
||||
onChange={(e) => updateNavLink(1, { label: e.target.value })}
|
||||
className="w-full text-xs font-bold border border-gray-300 rounded-lg p-2 bg-white"
|
||||
placeholder="COOP Klub"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Cieľový odkaz (URL)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={navLinks[1]?.url || ''}
|
||||
onChange={(e) => updateNavLink(1, { url: e.target.value })}
|
||||
className="w-full text-xs border border-gray-300 rounded-lg p-2 bg-white"
|
||||
placeholder="https://www.coopklub.sk"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[11px] text-gray-500 mb-1">Štýl zobrazenia</label>
|
||||
<select
|
||||
value={navLinks[1]?.variant || 'filled'}
|
||||
onChange={(e) => updateNavLink(1, { variant: e.target.value as any })}
|
||||
className="w-full text-xs border border-gray-300 rounded-lg p-2 bg-white font-medium"
|
||||
>
|
||||
<option value="filled">Modré plné tlačidlo (Biele písmo)</option>
|
||||
<option value="outline">Červený obrys (Biele pozadie, červený text)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Odkaz loga</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.logoLink || ''}
|
||||
onChange={(e) => updateData({ logoLink: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
);
|
||||
})()}
|
||||
|
||||
{/* BANNER */}
|
||||
{module.type === 'banner' && (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">URL Obrázka bannera</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.imageUrl || ''}
|
||||
onChange={(e) => updateData({ imageUrl: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2 font-mono text-xs"
|
||||
/>
|
||||
</div>
|
||||
<ImageUploadInput
|
||||
label="Obrázok bannera"
|
||||
value={module.data.imageUrl || ''}
|
||||
onChange={(url) => updateData({ imageUrl: url })}
|
||||
/>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Odkaz bannera</label>
|
||||
<input
|
||||
@@ -269,6 +365,32 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ImageUploadInput
|
||||
label="Obrázok produktu"
|
||||
value={p.imageUrl || ''}
|
||||
onChange={(url) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].imageUrl = url;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="https://...produkt.png alebo nahrajte súbor"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-500 font-semibold block mb-0.5">Platnosť akcie pre tento produkt (override)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.validityOverride || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].validityOverride = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder={`Predvolená: ${module.data.globalValidity || '2. 5. – 15. 5. 2026'}`}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white placeholder:text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-500">Cena (€)</label>
|
||||
@@ -407,6 +529,450 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* LOYALTY CLUB (VERNOSTNÉ ZĽAVY) */}
|
||||
{module.type === 'loyalty_club' && (
|
||||
<div className="space-y-5">
|
||||
{/* Toggle zapnuté / vypnuté */}
|
||||
<div className="bg-red-50/60 p-3.5 rounded-xl border border-red-200 flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-xs font-bold text-gray-900 block">Zobraziť v e-maile</span>
|
||||
<span className="text-[11px] text-gray-500">Sekcia Vernostné zľavy</span>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={module.data.enabled !== false}
|
||||
onChange={(e) => updateData({ enabled: e.target.checked })}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-300 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-red-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Názov sekcie</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.sectionTitle || ''}
|
||||
onChange={(e) => updateData({ sectionTitle: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2 font-bold"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ImageUploadInput
|
||||
label="Obrázok banneru Vernostných zliav"
|
||||
value={module.data.headerImageUrl || ''}
|
||||
onChange={(url) => updateData({ headerImageUrl: url })}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Odkaz banneru</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.headerLink || ''}
|
||||
onChange={(e) => updateData({ headerLink: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Globálna platnosť akcie</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.globalValidity || ''}
|
||||
onChange={(e) => updateData({ globalValidity: e.target.value })}
|
||||
placeholder="napr. 2. 5. – 15. 5. 2026"
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 2 Vernostné produkty */}
|
||||
<div className="space-y-4 pt-2">
|
||||
<span className="text-xs font-bold text-gray-800 uppercase tracking-wider block">
|
||||
Vernostné produkty ({module.data.products?.length || 0})
|
||||
</span>
|
||||
|
||||
{(module.data.products || []).map((p: any, pIdx: number) => (
|
||||
<div key={p.id || pIdx} className="p-3 bg-gray-50 rounded-xl border border-gray-200 space-y-3">
|
||||
<span className="text-xs font-bold text-gray-900 block truncate">
|
||||
{p.title || `Vernostný produkt ${pIdx + 1}`}
|
||||
</span>
|
||||
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-500 font-semibold block mb-0.5">Názov produktu</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.title || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].title = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white font-medium"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ImageUploadInput
|
||||
label="Obrázok produktu"
|
||||
value={p.imageUrl || ''}
|
||||
onChange={(url) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].imageUrl = url;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="https://...produkt.png alebo nahrajte súbor"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-500 font-semibold block mb-0.5">Platnosť akcie pre tento produkt (override)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.validityOverride || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].validityOverride = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder={`Predvolená: ${module.data.globalValidity || '2. 5. – 15. 5. 2026'}`}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white placeholder:text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Sekcia Bez karty */}
|
||||
<div className="p-2.5 bg-red-50/40 rounded-lg border border-red-100 space-y-2">
|
||||
<span className="text-[11px] font-bold text-red-700 block">Bez karty</span>
|
||||
<div className="grid grid-cols-3 gap-1.5">
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Zľava</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.noCardDiscount || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].noCardDiscount = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="21%"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Cena (€)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.noCardPriceMain || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].noCardPriceMain = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="0"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Centy</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.noCardPriceSub || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].noCardPriceSub = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="79"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Merná cena (bez karty)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.noCardUnitPrice || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].noCardUnitPrice = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="1kg = 9,88 €"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sekcia S kartou */}
|
||||
<div className="p-2.5 bg-amber-50/50 rounded-lg border border-amber-200 space-y-2">
|
||||
<span className="text-[11px] font-bold text-amber-900 block">S kartou (Klub)</span>
|
||||
<div className="grid grid-cols-3 gap-1.5">
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Zľava</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.cardDiscount || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].cardDiscount = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="38%"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Cena (€)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.cardPriceMain || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].cardPriceMain = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="0"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Centy</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.cardPriceSub || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].cardPriceSub = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="62"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[9px] text-gray-500">Merná cena (s kartou)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={p.cardUnitPrice || ''}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].cardUnitPrice = e.target.value;
|
||||
updateData({ products });
|
||||
}}
|
||||
placeholder="1kg = 7,75 €"
|
||||
className="w-full text-xs border border-gray-300 rounded p-1 bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Predajne */}
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-500 block mb-1">Dostupnosť (Piktogramy)</label>
|
||||
<div className="flex gap-2 text-[10px]">
|
||||
<label className="flex items-center gap-1 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={p.stores?.potraviny}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].stores.potraviny = e.target.checked;
|
||||
updateData({ products });
|
||||
}}
|
||||
/>
|
||||
<span>Potraviny</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-1 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={p.stores?.supermarket}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].stores.supermarket = e.target.checked;
|
||||
updateData({ products });
|
||||
}}
|
||||
/>
|
||||
<span>Supermarket</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-1 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={p.stores?.tempo}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].stores.tempo = e.target.checked;
|
||||
updateData({ products });
|
||||
}}
|
||||
/>
|
||||
<span>Tempo</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Vlajočka SR */}
|
||||
<div className="flex items-center gap-2 pt-1">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`loyalty-flag-${p.id || pIdx}`}
|
||||
checked={p.showSlovakFlag || false}
|
||||
onChange={(e) => {
|
||||
const products = [...module.data.products];
|
||||
products[pIdx].showSlovakFlag = e.target.checked;
|
||||
updateData({ products });
|
||||
}}
|
||||
className="rounded text-red-600"
|
||||
/>
|
||||
<label htmlFor={`loyalty-flag-${p.id || pIdx}`} className="text-xs text-gray-700 cursor-pointer">
|
||||
Zobraziť slovenskú vlajku / srdce
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* ARTICLES ROW (LETÁKY ALEBO ČLÁNKY) */}
|
||||
{module.type === 'articles_row' && (
|
||||
<div className="space-y-5">
|
||||
{module.data.item1?.btnText ? (
|
||||
/* AK SÚ TO LETÁKY */
|
||||
<div className="space-y-4">
|
||||
<div className="p-3 bg-blue-50/50 rounded-xl border border-blue-100">
|
||||
<span className="text-xs font-bold text-blue-900 block mb-1">
|
||||
Leták 1: {module.data.item1?.title || 'Aktuálne letáky'}
|
||||
</span>
|
||||
<p className="text-[11px] text-gray-500 mb-3">Farby, texty a rozloženie sú fixne podľa šablóny. Môžete upraviť odkaz a náhľadový obrázok.</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Cieľová URL (kam to smeruje)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item1?.linkUrl || ''}
|
||||
onChange={(e) => updateData({
|
||||
item1: { ...module.data.item1, linkUrl: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white"
|
||||
/>
|
||||
</div>
|
||||
<ImageUploadInput
|
||||
label="Náhľadový obrázok letáku (PNG/JPG)"
|
||||
value={module.data.item1?.imageUrl || ''}
|
||||
onChange={(url) => updateData({
|
||||
item1: { ...module.data.item1, imageUrl: url }
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-3 bg-amber-50/50 rounded-xl border border-amber-100">
|
||||
<span className="text-xs font-bold text-amber-900 block mb-1">
|
||||
Leták 2: {module.data.item2?.title || 'Rozšírený leták'}
|
||||
</span>
|
||||
<p className="text-[11px] text-gray-500 mb-3">Farby, texty a rozloženie sú fixne podľa šablóny. Môžete upraviť odkaz a náhľadový obrázok.</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Cieľová URL (kam to smeruje)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item2?.linkUrl || ''}
|
||||
onChange={(e) => updateData({
|
||||
item2: { ...module.data.item2, linkUrl: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white"
|
||||
/>
|
||||
</div>
|
||||
<ImageUploadInput
|
||||
label="Náhľadový obrázok letáku (PNG/JPG)"
|
||||
value={module.data.item2?.imageUrl || ''}
|
||||
onChange={(url) => updateData({
|
||||
item2: { ...module.data.item2, imageUrl: url }
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
/* AK SÚ TO ČLÁNKY (VEĽKONOČNÝ BARANČEK / VAJÍČKO AMULET) */
|
||||
<div className="space-y-4">
|
||||
<div className="p-3 bg-orange-50/50 rounded-xl border border-orange-100">
|
||||
<span className="text-xs font-bold text-orange-900 block mb-1">
|
||||
Článok 1 (Recepty)
|
||||
</span>
|
||||
<p className="text-[11px] text-gray-500 mb-3">Logá a gradienty sú na pevno. Môžete upraviť text, odkaz a obrázok v pozadí.</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Názov / Text článku</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item1?.title || ''}
|
||||
onChange={(e) => updateData({
|
||||
item1: { ...module.data.item1, title: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Cieľová URL (odkaz)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item1?.linkUrl || ''}
|
||||
onChange={(e) => updateData({
|
||||
item1: { ...module.data.item1, linkUrl: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white"
|
||||
/>
|
||||
</div>
|
||||
<ImageUploadInput
|
||||
label="Obrázok v pozadí"
|
||||
value={module.data.item1?.imageUrl || ''}
|
||||
onChange={(url) => updateData({
|
||||
item1: { ...module.data.item1, imageUrl: url }
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-3 bg-blue-50/50 rounded-xl border border-blue-100">
|
||||
<span className="text-xs font-bold text-blue-900 block mb-1">
|
||||
Článok 2 (Časopis Jednota)
|
||||
</span>
|
||||
<p className="text-[11px] text-gray-500 mb-3">Logá a gradienty sú na pevno. Môžete upraviť text, odkaz a obrázok v pozadí.</p>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Názov / Text článku</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item2?.title || ''}
|
||||
onChange={(e) => updateData({
|
||||
item2: { ...module.data.item2, title: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white font-bold"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[10px] text-gray-600 font-semibold block mb-0.5">Cieľová URL (odkaz)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.item2?.linkUrl || ''}
|
||||
onChange={(e) => updateData({
|
||||
item2: { ...module.data.item2, linkUrl: e.target.value }
|
||||
})}
|
||||
className="w-full text-xs border border-gray-300 rounded p-1.5 bg-white"
|
||||
/>
|
||||
</div>
|
||||
<ImageUploadInput
|
||||
label="Obrázok v pozadí"
|
||||
value={module.data.item2?.imageUrl || ''}
|
||||
onChange={(url) => updateData({
|
||||
item2: { ...module.data.item2, imageUrl: url }
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* FOOTER */}
|
||||
{module.type === 'footer' && (
|
||||
<div className="space-y-4">
|
||||
@@ -419,11 +985,29 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Text odhlásenia</label>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Odkaz pre odhlásenie (Unsubscribe URL)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.unsubscribeText || ''}
|
||||
onChange={(e) => updateData({ unsubscribeText: e.target.value })}
|
||||
value={module.data.unsubscribeUrl || ''}
|
||||
onChange={(e) => updateData({ unsubscribeUrl: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">Google Play URL</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.googlePlayUrl || ''}
|
||||
onChange={(e) => updateData({ googlePlayUrl: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-gray-700 mb-1">App Store URL</label>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.appStoreUrl || ''}
|
||||
onChange={(e) => updateData({ appStoreUrl: e.target.value })}
|
||||
className="w-full text-sm border border-gray-300 rounded-lg p-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user