Files
Todo/components/DeleteListButton.tsx
Paul Bailey e51e88fddd feat: Add visual feedback and polish (Task 15)
- Implement toast notification system for success/error messages
- Add loading states with skeleton loaders for async operations
- Create smooth CSS transitions and animations
- Enhance empty states with EmptyState component
- Add loading.tsx files for Next.js loading states
- Integrate toast notifications across all CRUD operations
- Add fade-in and scale-in animations for better UX
- Improve visual feedback for user actions
2025-12-01 21:14:14 +00:00

92 lines
2.9 KiB
TypeScript

'use client'
import { useState } from 'react'
import { Trash2 } from 'lucide-react'
import { deleteList } from '@/lib/actions'
import { useRouter } from 'next/navigation'
import Modal from './Modal'
import { useToast } from './ToastContainer'
interface DeleteListButtonProps {
listId: string
listTitle: string
itemCount: number
redirectAfterDelete?: boolean
}
export default function DeleteListButton({
listId,
listTitle,
itemCount,
redirectAfterDelete = false
}: DeleteListButtonProps) {
const router = useRouter()
const { showToast } = useToast()
const [isConfirmOpen, setIsConfirmOpen] = useState(false)
const [isDeleting, setIsDeleting] = useState(false)
const handleDelete = async () => {
setIsDeleting(true)
try {
await deleteList(listId)
showToast('List deleted successfully', 'success')
setIsConfirmOpen(false)
if (redirectAfterDelete) {
router.push('/')
} else {
router.refresh()
}
} catch (err) {
console.error('Failed to delete list:', err)
showToast('Failed to delete list', 'error')
} finally {
setIsDeleting(false)
}
}
return (
<>
<button
onClick={() => setIsConfirmOpen(true)}
className="text-red-600 hover:text-red-700 active:text-red-800 transition-colors tap-target-sm hover:bg-red-50 active:bg-red-100 rounded-lg"
aria-label="Delete list"
>
<Trash2 size={20} />
</button>
<Modal
isOpen={isConfirmOpen}
onClose={() => setIsConfirmOpen(false)}
title="Delete List"
>
<div className="space-y-4">
<p className="text-gray-700 text-sm sm:text-base">
Are you sure you want to delete <strong>{listTitle}</strong>?
</p>
{itemCount > 0 && (
<p className="text-red-600 text-xs sm:text-sm font-medium">
This will permanently delete {itemCount} {itemCount === 1 ? 'item' : 'items'}.
</p>
)}
<div className="flex flex-col-reverse sm:flex-row gap-2 sm:gap-3 justify-end pt-2">
<button
onClick={() => setIsConfirmOpen(false)}
disabled={isDeleting}
className="w-full sm:w-auto px-4 sm:px-5 py-3 text-gray-700 bg-gray-100 hover:bg-gray-200 active:bg-gray-300 rounded-lg transition-colors disabled:opacity-50 tap-target font-medium text-sm sm:text-base"
>
Cancel
</button>
<button
onClick={handleDelete}
disabled={isDeleting}
className="w-full sm:w-auto px-4 sm:px-5 py-3 bg-red-600 hover:bg-red-700 active:bg-red-800 text-white rounded-lg transition-colors disabled:opacity-50 tap-target font-medium text-sm sm:text-base"
>
{isDeleting ? 'Deleting...' : 'Delete'}
</button>
</div>
</div>
</Modal>
</>
)
}