fix confirm dialog not working on mobile

This commit is contained in:
Stefan Hardegger
2026-06-22 10:53:25 +02:00
parent 70661ed3b2
commit acf4d815e8
3 changed files with 98 additions and 11 deletions

View File

@@ -12,6 +12,7 @@ import ImageUpload from '../../../../components/ui/ImageUpload';
import AuthorSelector from '../../../../components/stories/AuthorSelector';
import SeriesSelector from '../../../../components/stories/SeriesSelector';
import LoadingSpinner from '../../../../components/ui/LoadingSpinner';
import ConfirmDialog from '../../../../components/ui/ConfirmDialog';
import { storyApi } from '../../../../lib/api';
import { Story } from '../../../../types/api';
@@ -26,6 +27,7 @@ export default function EditStoryPage() {
const [processingImages, setProcessingImages] = useState(false);
const [resetingPosition, setResetingPosition] = useState(false);
const [errors, setErrors] = useState<Record<string, string>>({});
const [confirmDialog, setConfirmDialog] = useState<{ type: 'delete' | 'reset' } | null>(null);
const [formData, setFormData] = useState({
title: '',
@@ -252,18 +254,18 @@ export default function EditStoryPage() {
}
};
const handleResetReadingPosition = async () => {
if (!story || !confirm('Are you sure you want to reset the reading position to the beginning? This will remove your current place in the story.')) {
return;
}
const handleResetReadingPosition = () => {
if (!story || !story.readingPosition || story.readingPosition === 0) return;
setConfirmDialog({ type: 'reset' });
};
const confirmResetReadingPosition = async () => {
setConfirmDialog(null);
try {
setResetingPosition(true);
await storyApi.updateReadingProgress(storyId, 0);
setStory(prev => prev ? { ...prev, readingPosition: 0 } : null);
// Show success feedback
setErrors({ resetSuccess: 'Reading position reset! The story will start from the beginning next time you read it.' });
// Clear success message after 4 seconds
setTimeout(() => {
setErrors(prev => {
const { resetSuccess, ...rest } = prev;
@@ -278,11 +280,13 @@ export default function EditStoryPage() {
}
};
const handleDelete = async () => {
if (!story || !confirm('Are you sure you want to delete this story? This action cannot be undone.')) {
return;
}
const handleDelete = () => {
if (!story) return;
setConfirmDialog({ type: 'delete' });
};
const confirmDelete = async () => {
setConfirmDialog(null);
try {
setSaving(true);
await storyApi.deleteStory(storyId);
@@ -525,6 +529,25 @@ export default function EditStoryPage() {
</div>
</form>
</div>
<ConfirmDialog
isOpen={confirmDialog?.type === 'reset'}
title="Reset Reading Position"
message="Are you sure you want to reset the reading position to the beginning? This will remove your current place in the story."
confirmLabel="Reset"
onConfirm={confirmResetReadingPosition}
onCancel={() => setConfirmDialog(null)}
/>
<ConfirmDialog
isOpen={confirmDialog?.type === 'delete'}
title="Delete Story"
message="Are you sure you want to delete this story? This action cannot be undone."
confirmLabel="Delete"
danger
onConfirm={confirmDelete}
onCancel={() => setConfirmDialog(null)}
/>
</AppLayout>
);
}

View File

@@ -0,0 +1,64 @@
'use client';
import { useEffect } from 'react';
import Button from './Button';
interface ConfirmDialogProps {
isOpen: boolean;
title: string;
message: string;
confirmLabel?: string;
cancelLabel?: string;
danger?: boolean;
onConfirm: () => void;
onCancel: () => void;
}
export default function ConfirmDialog({
isOpen,
title,
message,
confirmLabel = 'Confirm',
cancelLabel = 'Cancel',
danger = false,
onConfirm,
onCancel,
}: ConfirmDialogProps) {
useEffect(() => {
if (!isOpen) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') onCancel();
};
document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
}, [isOpen, onCancel]);
if (!isOpen) return null;
return (
<div
className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
onClick={onCancel}
>
<div
className="theme-card rounded-lg shadow-xl max-w-md w-full p-6"
onClick={(e) => e.stopPropagation()}
>
<h2 className="text-lg font-semibold theme-header mb-2">{title}</h2>
<p className="theme-text text-sm mb-6">{message}</p>
<div className="flex justify-end gap-3">
<Button type="button" variant="ghost" onClick={onCancel}>
{cancelLabel}
</Button>
<Button
type="button"
variant={danger ? 'danger' : 'primary'}
onClick={onConfirm}
>
{confirmLabel}
</Button>
</div>
</div>
</div>
);
}

File diff suppressed because one or more lines are too long