fix: auto-save nevytvara pri nacitani stranky kopie kampani

- auto-save sa spusti az po nacitani kampane z databazy (predtym sa pri
  pomalsom nacitani ulozila predvolena kampan ako nova kopia a dalsie zmeny
  sli do nej)
- pocas vkladania novej kampane sa nespusti druhe vlozenie
- id novej kampane sa nastavi, len ak medzitym nebola otvorena ina
- nacita sa naposledy upravena kampan bez ohladu na pocet modulov

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub_HostacnyandClaude Opus 5.5 committed 2026-10-19 17:15:56 +02:00
1 parent 25771afc79
commit 109d65a690
1 file changed
+17 -4
+17 -4
View File
@@ -1,6 +1,6 @@
'use client'; 'use client';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { NewsletterCampaign, NewsletterModule, ProductItem, BadgeTemplate } from '@/types/newsletter'; import { NewsletterCampaign, NewsletterModule, ProductItem, BadgeTemplate } from '@/types/newsletter';
import { DEFAULT_CAMPAIGN, SUPABASE_ASSETS_BASE, ensureValidityBar } from '@/lib/defaultCampaign'; import { DEFAULT_CAMPAIGN, SUPABASE_ASSETS_BASE, ensureValidityBar } from '@/lib/defaultCampaign';
import { renderEmailHtml, renderSingleModuleHtml, getCampaignValidity } from '@/lib/emailRenderer'; import { renderEmailHtml, renderSingleModuleHtml, getCampaignValidity } from '@/lib/emailRenderer';
@@ -124,6 +124,12 @@ export default function Home() {
return [...topMods, ...middleMods, ...flyerMods, ...recipeMods, ...footerMods]; return [...topMods, ...middleMods, ...flyerMods, ...recipeMods, ...footerMods];
}; };
// Auto-save sa spustí až po načítaní kampane z databázy. Inak by sa pri pomalšom načítaní
// predvolená kampaň uložila ako nová kópia a ďalšie zmeny by sa ukladali do nej.
const [isLoaded, setIsLoaded] = useState(false);
// Prebiehajúce vloženie novej kampane – kým nemáme jej id, ďalšie vloženie by vytvorilo duplikát
const insertInFlight = useRef(false);
// Načítanie existujúceho draftu z databázy pri štarte // Načítanie existujúceho draftu z databázy pri štarte
useEffect(() => { useEffect(() => {
async function loadInitial() { async function loadInitial() {
@@ -136,7 +142,7 @@ export default function Home() {
if (data && data.length > 0) { if (data && data.length > 0) {
const dbItem = data[0]; const dbItem = data[0];
if (dbItem.data && dbItem.data.modules && dbItem.data.modules.length >= 7) { if (Array.isArray(dbItem.data?.modules) && dbItem.data.modules.length > 0) {
setCampaign({ setCampaign({
id: dbItem.id, id: dbItem.id,
title: dbItem.title, title: dbItem.title,
@@ -152,6 +158,8 @@ export default function Home() {
} }
} catch (err) { } catch (err) {
console.error('Error loading template from Supabase:', err); console.error('Error loading template from Supabase:', err);
} finally {
setIsLoaded(true);
} }
} }
loadInitial(); loadInitial();
@@ -159,10 +167,13 @@ export default function Home() {
// Auto-save s debounce (1 sekunda) // Auto-save s debounce (1 sekunda)
useEffect(() => { useEffect(() => {
if (!isLoaded) return;
const timer = setTimeout(async () => { const timer = setTimeout(async () => {
if (!campaign.id && insertInFlight.current) return;
setIsSaving(true); setIsSaving(true);
try { try {
if (!campaign.id) { if (!campaign.id) {
insertInFlight.current = true;
const { data } = await supabase const { data } = await supabase
.from('templates') .from('templates')
.insert([ .insert([
@@ -178,7 +189,8 @@ export default function Home() {
.select(); .select();
if (data && data.length > 0) { if (data && data.length > 0) {
setCampaign((prev) => ({ ...prev, id: data[0].id })); // id nastavíme len ak medzitým nebola otvorená iná kampaň
setCampaign((prev) => (prev.id ? prev : { ...prev, id: data[0].id }));
} }
} else { } else {
await supabase await supabase
@@ -196,12 +208,13 @@ export default function Home() {
} catch (err) { } catch (err) {
console.error('Auto-save error:', err); console.error('Auto-save error:', err);
} finally { } finally {
insertInFlight.current = false;
setIsSaving(false); setIsSaving(false);
} }
}, 1000); }, 1000);
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [campaign.title, campaign.preheader, campaign.modules, campaign.id]); }, [isLoaded, campaign.title, campaign.preheader, campaign.modules, campaign.id]);
const selectedModule = campaign.modules.find((m) => m.id === selectedModuleId) || null; const selectedModule = campaign.modules.find((m) => m.id === selectedModuleId) || null;