feat: mazanie pripomienok v editore aj na stranke s odkazom
- editor: tlacidlo Zmazat v bubline pripomienky na platne - odkaz: Zmazat v bubline aj ikona kosa v zozname pripomienok - pred zmazanim potvrdenie (zmizne pre vsetkych s odkazom) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cfacf2474b
commit
061e647180
2 files changed
+60
-7
No files matched your search
@@ -928,6 +928,7 @@ export default function Home() {
|
|||||||
selectedId={selectedCommentId}
|
selectedId={selectedCommentId}
|
||||||
onSelect={setSelectedCommentId}
|
onSelect={setSelectedCommentId}
|
||||||
renderActions={(c: ReviewComment) => (
|
renderActions={(c: ReviewComment) => (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => reviews.toggleDone(c)}
|
onClick={() => reviews.toggleDone(c)}
|
||||||
@@ -937,6 +938,19 @@ export default function Home() {
|
|||||||
>
|
>
|
||||||
{c.done ? 'Vrátiť ako neurobené' : '✓ Označiť ako hotové'}
|
{c.done ? 'Vrátiť ako neurobené' : '✓ Označiť ako hotové'}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (confirm('Zmazať túto pripomienku? Zmizne aj pre ostatných s odkazom.')) {
|
||||||
|
reviews.remove(c);
|
||||||
|
setSelectedCommentId(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="text-[11px] font-bold px-2.5 py-1 rounded-lg text-red-700 bg-red-50 hover:bg-red-100"
|
||||||
|
>
|
||||||
|
Zmazať
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Náhľad newslettra na pripomienky (zdieľaný odkaz). Nič sa tu nedá upravovať – len komentovať,
|
// Náhľad newslettra na pripomienky (zdieľaný odkaz). Nič sa tu nedá upravovať – len komentovať,
|
||||||
// písať text priamo do newslettra a kresliť. Pripomienky sa ukladajú k odkazu, vidí ich každý s odkazom.
|
// písať text priamo do newslettra a kresliť. Pripomienky sa ukladajú k odkazu, vidí ich každý s odkazom.
|
||||||
import React, { use, useCallback, useEffect, useRef, useState } from 'react';
|
import React, { use, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { MessageCircle, Type, Pencil, MousePointer2, CheckCircle2, Loader2 } from 'lucide-react';
|
import { MessageCircle, Type, Pencil, MousePointer2, CheckCircle2, Loader2, Trash2 } from 'lucide-react';
|
||||||
import { renderSingleModuleHtml } from '@/lib/emailRenderer';
|
import { renderSingleModuleHtml } from '@/lib/emailRenderer';
|
||||||
import {
|
import {
|
||||||
Review,
|
Review,
|
||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
REVIEW_COLORS,
|
REVIEW_COLORS,
|
||||||
getReviewByToken,
|
getReviewByToken,
|
||||||
listReviewComments,
|
listReviewComments,
|
||||||
addReviewComment
|
addReviewComment,
|
||||||
|
deleteReviewComment
|
||||||
} from '@/lib/reviews';
|
} from '@/lib/reviews';
|
||||||
import { AnnotationLayer, pointToModuleCoords, useModuleLayout } from '@/components/review/AnnotationLayer';
|
import { AnnotationLayer, pointToModuleCoords, useModuleLayout } from '@/components/review/AnnotationLayer';
|
||||||
import { NewsletterCampaign } from '@/types/newsletter';
|
import { NewsletterCampaign } from '@/types/newsletter';
|
||||||
@@ -124,6 +125,18 @@ export default function ReviewPage({ params }: { params: Promise<{ token: string
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Zmazanie pripomienky (zmizne pre všetkých s odkazom aj v editore)
|
||||||
|
const removeComment = async (c: ReviewComment) => {
|
||||||
|
if (!confirm('Zmazať túto pripomienku? Zmizne aj pre ostatných s odkazom.')) return;
|
||||||
|
try {
|
||||||
|
await deleteReviewComment(c.id);
|
||||||
|
setComments((prev) => prev.filter((x) => x.id !== c.id));
|
||||||
|
if (selectedId === c.id) setSelectedId(null);
|
||||||
|
} catch (e) {
|
||||||
|
alert(e instanceof Error ? e.message : 'Pripomienku sa nepodarilo zmazať.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Klik do newslettra: komentár / text → okienko na napísanie
|
// Klik do newslettra: komentár / text → okienko na napísanie
|
||||||
const onCanvasClick = (e: React.MouseEvent) => {
|
const onCanvasClick = (e: React.MouseEvent) => {
|
||||||
if (tool !== 'comment' && tool !== 'text') return;
|
if (tool !== 'comment' && tool !== 'text') return;
|
||||||
@@ -246,7 +259,21 @@ export default function ReviewPage({ params }: { params: Promise<{ token: string
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<AnnotationLayer layout={layout} comments={comments} selectedId={selectedId} onSelect={setSelectedId} />
|
<AnnotationLayer
|
||||||
|
layout={layout}
|
||||||
|
comments={comments}
|
||||||
|
selectedId={selectedId}
|
||||||
|
onSelect={setSelectedId}
|
||||||
|
renderActions={(c) => (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeComment(c)}
|
||||||
|
className="flex items-center gap-1 text-[11px] font-bold px-2.5 py-1 rounded-lg text-red-700 bg-red-50 hover:bg-red-100"
|
||||||
|
>
|
||||||
|
<Trash2 className="w-3 h-3" /> Zmazať
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Plocha na pridávanie pripomienok */}
|
{/* Plocha na pridávanie pripomienok */}
|
||||||
{tool !== 'view' && (
|
{tool !== 'view' && (
|
||||||
@@ -338,11 +365,12 @@ export default function ReviewPage({ params }: { params: Promise<{ token: string
|
|||||||
{comments.map((c) => {
|
{comments.map((c) => {
|
||||||
const number = comments.filter((x) => x.kind === 'comment').indexOf(c) + 1;
|
const number = comments.filter((x) => x.kind === 'comment').indexOf(c) + 1;
|
||||||
return (
|
return (
|
||||||
<button
|
<div
|
||||||
key={c.id}
|
key={c.id}
|
||||||
type="button"
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
onClick={() => setSelectedId(c.id === selectedId ? null : c.id)}
|
onClick={() => setSelectedId(c.id === selectedId ? null : c.id)}
|
||||||
className={`w-full text-left rounded-lg border p-2 transition-colors ${
|
className={`group w-full text-left rounded-lg border p-2 transition-colors cursor-pointer ${
|
||||||
c.id === selectedId ? 'border-gray-900 bg-gray-50' : 'border-gray-200 hover:border-gray-300'
|
c.id === selectedId ? 'border-gray-900 bg-gray-50' : 'border-gray-200 hover:border-gray-300'
|
||||||
} ${c.done ? 'opacity-60' : ''}`}
|
} ${c.done ? 'opacity-60' : ''}`}
|
||||||
>
|
>
|
||||||
@@ -353,11 +381,22 @@ export default function ReviewPage({ params }: { params: Promise<{ token: string
|
|||||||
<span className="text-[11px] font-bold text-gray-900 truncate">{c.author || 'Anonym'}</span>
|
<span className="text-[11px] font-bold text-gray-900 truncate">{c.author || 'Anonym'}</span>
|
||||||
{c.done && <CheckCircle2 className="w-3.5 h-3.5 text-emerald-600 shrink-0" />}
|
{c.done && <CheckCircle2 className="w-3.5 h-3.5 text-emerald-600 shrink-0" />}
|
||||||
<span className="ml-auto text-[10px] text-gray-400 shrink-0">{new Date(c.created_at).toLocaleDateString('sk-SK')}</span>
|
<span className="ml-auto text-[10px] text-gray-400 shrink-0">{new Date(c.created_at).toLocaleDateString('sk-SK')}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
removeComment(c);
|
||||||
|
}}
|
||||||
|
className="text-gray-300 hover:text-red-600 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
|
title="Zmazať pripomienku"
|
||||||
|
>
|
||||||
|
<Trash2 className="w-3.5 h-3.5" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 text-xs text-gray-700 whitespace-pre-wrap line-clamp-3">
|
<p className="mt-1 text-xs text-gray-700 whitespace-pre-wrap line-clamp-3">
|
||||||
{c.text || (c.kind === 'drawing' ? 'Kresba' : '')}
|
{c.text || (c.kind === 'drawing' ? 'Kresba' : '')}
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user