feat: implement archiving functionality for counters and update related logic

This commit is contained in:
2026-08-25 13:25:21 +02:00
parent 6ccf897fc4
commit 3df1e8d7fa
9 changed files with 182 additions and 35 deletions
+4 -2
View File
@@ -7,6 +7,7 @@ export interface Counter {
image_path: string | null;
group_id: number | null;
order_index: number;
archived_at?: number | null;
}
interface Props {
@@ -69,7 +70,7 @@ export default function CounterCard({ counter, onIncrement, onDecrement, onEdit,
<div className="flex items-center bg-ctp-surface1 rounded-2xl overflow-hidden">
<button
onClick={() => onDecrement(counter.id)}
disabled={counter.value <= 0}
disabled={counter.value <= 0 || !!counter.archived_at}
aria-label="Decrement"
className="w-11 h-11 flex items-center justify-center text-ctp-red hover:bg-ctp-red/20 active:bg-ctp-red/30 active:scale-95 transition-all disabled:opacity-25 disabled:pointer-events-none"
>
@@ -83,7 +84,8 @@ export default function CounterCard({ counter, onIncrement, onDecrement, onEdit,
<button
onClick={() => onIncrement(counter.id)}
aria-label="Increment"
className="w-11 h-11 flex items-center justify-center text-ctp-green hover:bg-ctp-green/20 active:bg-ctp-green/30 active:scale-95 transition-all"
disabled={!!counter.archived_at}
className="w-11 h-11 flex items-center justify-center text-ctp-green hover:bg-ctp-green/20 active:bg-ctp-green/30 active:scale-95 transition-all disabled:opacity-25 disabled:pointer-events-none"
>
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
<line x1="12" y1="5" x2="12" y2="19" />
+45 -23
View File
@@ -21,9 +21,11 @@ interface Props {
image_path: string | null;
}) => void;
onDelete?: (id: number) => void;
onArchive?: (id: number) => void;
onUnarchive?: (id: number) => void;
}
export default function CounterModal({ open, initial, groups, onClose, onSave, onDelete }: Props) {
export default function CounterModal({ open, initial, groups, onClose, onSave, onDelete, onArchive, onUnarchive }: Props) {
const [confirmDelete, setConfirmDelete] = useState(false);
const deleteTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
const [name, setName] = useState('');
@@ -191,28 +193,48 @@ export default function CounterModal({ open, initial, groups, onClose, onSave, o
</div>
<div className="flex items-center justify-between gap-3 pt-2">
{/* Delete — only shown when editing an existing counter */}
{initial && onDelete ? (
<button
type="button"
onClick={() => {
if (confirmDelete) {
if (deleteTimer.current) clearTimeout(deleteTimer.current);
onDelete(initial.id);
onClose();
} else {
setConfirmDelete(true);
deleteTimer.current = setTimeout(() => setConfirmDelete(false), 3000);
}
}}
className={`px-4 py-2 text-sm rounded-lg font-medium transition-colors ${
confirmDelete
? 'bg-ctp-red hover:bg-ctp-maroon text-ctp-base'
: 'text-ctp-red hover:bg-ctp-red/10 border border-ctp-red/30'
}`}
>
{confirmDelete ? 'Confirm delete' : 'Delete counter'}
</button>
{initial ? (
initial.archived_at ? (
<div className="flex gap-2">
<button
type="button"
onClick={() => { onUnarchive?.(initial.id); onClose(); }}
className="px-4 py-2 text-sm rounded-lg font-medium border border-ctp-green/40 text-ctp-green hover:bg-ctp-green/10 transition-colors"
>
Unarchive
</button>
{onDelete && (
<button
type="button"
onClick={() => {
if (confirmDelete) {
if (deleteTimer.current) clearTimeout(deleteTimer.current);
onDelete(initial.id);
onClose();
} else {
setConfirmDelete(true);
deleteTimer.current = setTimeout(() => setConfirmDelete(false), 3000);
}
}}
className={`px-4 py-2 text-sm rounded-lg font-medium transition-colors ${
confirmDelete
? 'bg-ctp-red hover:bg-ctp-maroon text-ctp-base'
: 'text-ctp-red hover:bg-ctp-red/10 border border-ctp-red/30'
}`}
>
{confirmDelete ? 'Confirm delete' : 'Delete'}
</button>
)}
</div>
) : (
<button
type="button"
onClick={() => { onArchive?.(initial.id); onClose(); }}
className="px-4 py-2 text-sm rounded-lg font-medium border border-ctp-overlay1/40 text-ctp-subtext1 hover:bg-ctp-surface1 transition-colors"
>
Archive
</button>
)
) : <span />}
<div className="flex gap-3">