Implement WYSIWYG newsletter editor with live preview, import, Supabase auto-save and Brevo export

This commit is contained in:
Jakub_Hostacny committed 2026-09-24 11:04:13 +02:00
1 parent 8763c5bace
commit 538f2ccae3
10 files changed
+2252 -62

No files matched your search

+139
View File
@@ -0,0 +1,139 @@
'use client';
import React from 'react';
import {
Download,
Send,
ExternalLink,
Smartphone,
Monitor,
Save,
CheckCircle2,
Plus
} from 'lucide-react';
import { NewsletterCampaign } from '@/types/newsletter';
interface TopBarProps {
campaign: NewsletterCampaign;
previewMode: 'desktop' | 'mobile';
setPreviewMode: (m: 'desktop' | 'mobile') => void;
isSaving: boolean;
onSave: () => void;
onExportZip: () => void;
onExportBrevo: () => void;
isExportingBrevo: boolean;
brevoCampaignUrl?: string | null;
onAddModule: (type: any) => void;
}
export const TopBar: React.FC<TopBarProps> = ({
campaign,
previewMode,
setPreviewMode,
isSaving,
onSave,
onExportZip,
onExportBrevo,
isExportingBrevo,
brevoCampaignUrl,
onAddModule
}) => {
return (
<header className="h-16 bg-white border-b border-gray-200 px-6 flex items-center justify-between sticky top-0 z-30 shadow-xs">
{/* Ľavá časť: Logo a názov */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-red-600 flex items-center justify-center text-white font-black text-sm">
CJ
</div>
<div>
<h1 className="text-sm font-bold text-gray-900 leading-tight">
{campaign.title || 'COOP Newsletter'}
</h1>
<div className="flex items-center gap-2">
<span className="text-[10px] text-gray-500">
{isSaving ? (
<span className="text-amber-600 animate-pulse">Ukladám do Supabase...</span>
) : (
<span className="text-emerald-600 flex items-center gap-1">
<CheckCircle2 className="w-3 h-3" /> Uložené v Supabase
</span>
)}
</span>
</div>
</div>
</div>
{/* Pridať modul dropdown */}
<div className="hidden md:flex items-center gap-1.5 ml-4 pl-4 border-l border-gray-200">
<button
onClick={() => onAddModule('banner')}
className="text-xs font-semibold text-gray-700 bg-gray-100 hover:bg-gray-200 px-2.5 py-1.5 rounded-lg flex items-center gap-1 transition-colors"
>
<Plus className="w-3.5 h-3.5 text-gray-500" /> Banner
</button>
<button
onClick={() => onAddModule('products_grid')}
className="text-xs font-semibold text-gray-700 bg-gray-100 hover:bg-gray-200 px-2.5 py-1.5 rounded-lg flex items-center gap-1 transition-colors"
>
<Plus className="w-3.5 h-3.5 text-gray-500" /> Produkty
</button>
</div>
</div>
{/* Stredná časť: Prepínač Desktop / Mobil */}
<div className="flex items-center bg-gray-100 p-1 rounded-xl border border-gray-200">
<button
onClick={() => setPreviewMode('desktop')}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${
previewMode === 'desktop'
? 'bg-white text-gray-900 shadow-xs'
: 'text-gray-500 hover:text-gray-900'
}`}
>
<Monitor className="w-3.5 h-3.5" /> Desktop
</button>
<button
onClick={() => setPreviewMode('mobile')}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${
previewMode === 'mobile'
? 'bg-white text-gray-900 shadow-xs'
: 'text-gray-500 hover:text-gray-900'
}`}
>
<Smartphone className="w-3.5 h-3.5" /> Mobil
</button>
</div>
{/* Pravá časť: Export do ZIP a Brevo */}
<div className="flex items-center gap-2.5">
<button
onClick={onExportZip}
className="flex items-center gap-1.5 text-xs font-bold text-gray-700 bg-white border border-gray-300 hover:bg-gray-50 px-3.5 py-2 rounded-xl transition-all shadow-xs"
>
<Download className="w-3.5 h-3.5 text-gray-600" /> Export ZIP
</button>
{brevoCampaignUrl ? (
<a
href={brevoCampaignUrl}
target="_blank"
rel="noreferrer"
className="flex items-center gap-1.5 text-xs font-bold text-emerald-700 bg-emerald-50 border border-emerald-300 hover:bg-emerald-100 px-3.5 py-2 rounded-xl transition-all"
>
<ExternalLink className="w-3.5 h-3.5" /> Otvoriť v Brevo
</a>
) : (
<button
onClick={onExportBrevo}
disabled={isExportingBrevo}
className="flex items-center gap-1.5 text-xs font-bold text-white bg-blue-600 hover:bg-blue-700 disabled:opacity-50 px-3.5 py-2 rounded-xl transition-all shadow-xs"
>
<Send className="w-3.5 h-3.5" />
{isExportingBrevo ? 'Odosielam...' : 'Odoslať do Brevo'}
</button>
)}
</div>
</header>
);
};