feat: pripomienky cez zdielany odkaz; predvolena poloha stitkov a pouzit na vsetky
Pripomienky: - odkaz /review/<token> so snimkou newslettra: nic sa neda upravit, da sa komentovat (spendlik), pisat text do newslettra a kreslit; meno autora sa pamata - pripomienky su ukotvene k modulu a ulozene k odkazu - vidi ich kazdy s odkazom - v editore: tlacidlo Pripomienky (pocet otvorenych), vytvorenie a kopirovanie odkazu, aktualizacia nahladu v odkaze, zoznam pripomienok, Hotovo a mazanie; pripomienky sa zobrazuju aj priamo na platne a daju sa tam oznacit ako hotove - supabase/migrations/002_reviews.sql (tabulky reviews, review_comments) - pismo Poppins v layoute (nahlad vernejsi e-mailu) Stitky predajni: - predvolena poloha -15 vodorovne / +5 zvisle od praveho horneho rohu pozadia cenovky - tlacidlo Polohu stitkov pouzit na vsetky produkty Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b0a050bd12
commit
cfacf2474b
13 files changed
+1162
-10
No files matched your search
@@ -0,0 +1,94 @@
|
||||
'use client';
|
||||
|
||||
// Pripomienky aktuálnej kampane v editore: odkaz, zoznam pripomienok (pravidelne obnovovaný), akcie
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { NewsletterCampaign } from '@/types/newsletter';
|
||||
import {
|
||||
Review,
|
||||
ReviewComment,
|
||||
createReview,
|
||||
deleteReviewComment,
|
||||
getReviewForTemplate,
|
||||
listReviewComments,
|
||||
setReviewCommentDone,
|
||||
updateReviewSnapshot
|
||||
} from '@/lib/reviews';
|
||||
|
||||
const POLL_MS = 20000;
|
||||
|
||||
export function useCampaignReview(campaign: NewsletterCampaign) {
|
||||
const [review, setReview] = useState<Review | null>(null);
|
||||
const [comments, setComments] = useState<ReviewComment[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const templateId = campaign.id;
|
||||
|
||||
const refresh = useCallback(async (reviewId: string) => {
|
||||
try {
|
||||
setComments(await listReviewComments(reviewId));
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Odkaz kampane sa načíta pri otvorení kampane; pripomienky sa obnovujú pravidelne
|
||||
useEffect(() => {
|
||||
let timer: ReturnType<typeof setInterval> | undefined;
|
||||
let cancelled = false;
|
||||
if (!templateId) return;
|
||||
(async () => {
|
||||
try {
|
||||
const r = await getReviewForTemplate(templateId);
|
||||
if (cancelled) return;
|
||||
setReview(r);
|
||||
setComments([]);
|
||||
setError(null);
|
||||
if (!r) return;
|
||||
await refresh(r.id);
|
||||
timer = setInterval(() => refresh(r.id), POLL_MS);
|
||||
} catch (e) {
|
||||
if (!cancelled) setError(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, [templateId, refresh]);
|
||||
|
||||
const run = async (action: () => Promise<void>) => {
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
await action();
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : String(e));
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
review,
|
||||
comments,
|
||||
error,
|
||||
busy,
|
||||
openCount: comments.filter((c) => !c.done).length,
|
||||
create: () => run(async () => setReview(await createReview(campaign))),
|
||||
updateSnapshot: () =>
|
||||
run(async () => {
|
||||
if (review) setReview(await updateReviewSnapshot(review.id, campaign));
|
||||
}),
|
||||
toggleDone: (c: ReviewComment) =>
|
||||
run(async () => {
|
||||
await setReviewCommentDone(c.id, !c.done);
|
||||
setComments((prev) => prev.map((x) => (x.id === c.id ? { ...x, done: !c.done } : x)));
|
||||
}),
|
||||
remove: (c: ReviewComment) =>
|
||||
run(async () => {
|
||||
await deleteReviewComment(c.id);
|
||||
setComments((prev) => prev.filter((x) => x.id !== c.id));
|
||||
}),
|
||||
refresh: () => review && refresh(review.id)
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user