diff --git a/src/app/studio/page.tsx b/src/app/studio/page.tsx index e7af4cd..63eba7c 100644 --- a/src/app/studio/page.tsx +++ b/src/app/studio/page.tsx @@ -198,6 +198,11 @@ export default function StudioPage() { router.push(`/studio/${id}`) } + const handleDeletePrompt = (id: string) => { + // Remove the prompt from the local state + setPrompts(prev => prev.filter(p => p.id !== id)) + } + const handleUpdatePermissions = async (promptId: string, newPermissions: 'private' | 'public') => { if (!user) return @@ -753,6 +758,7 @@ export default function StudioPage() { isOpen={isEditModalOpen} onClose={handleEditModalClose} onSave={handleEditModalSave} + onDelete={handleDeletePrompt} userId={user?.id || ''} /> )} @@ -764,6 +770,8 @@ export default function StudioPage() { onClose={handleDetailModalClose} onEdit={handleEditPrompt} onDebug={handleDebugPrompt} + onDelete={handleDeletePrompt} + userId={user?.id} /> {/* Bulk Add Modal */} diff --git a/src/components/studio/EditPromptModal.tsx b/src/components/studio/EditPromptModal.tsx index c48d026..afdd166 100644 --- a/src/components/studio/EditPromptModal.tsx +++ b/src/components/studio/EditPromptModal.tsx @@ -7,11 +7,13 @@ import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { LoadingSpinner } from '@/components/ui/loading-spinner' +import { DeleteConfirmationDialog } from '@/components/ui/delete-confirmation-dialog' import { X, Save, Tag, - Plus + Plus, + Trash2 } from 'lucide-react' interface Prompt { @@ -29,6 +31,7 @@ interface EditPromptModalProps { isOpen: boolean onClose: () => void onSave: (updatedPrompt: Prompt) => void + onDelete?: (id: string) => void userId: string } @@ -37,6 +40,7 @@ export function EditPromptModal({ isOpen, onClose, onSave, + onDelete, userId }: EditPromptModalProps) { const t = useTranslations('studio') @@ -48,6 +52,8 @@ export function EditPromptModal({ const [newTag, setNewTag] = useState('') const [isSaving, setIsSaving] = useState(false) const [availableTags, setAvailableTags] = useState([]) + const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false) + const [isDeleting, setIsDeleting] = useState(false) useEffect(() => { if (isOpen) { @@ -114,6 +120,29 @@ export function EditPromptModal({ } } + const handleDelete = async () => { + if (!onDelete) return + + setIsDeleting(true) + try { + const response = await fetch(`/api/prompts/${prompt.id}?userId=${userId}`, { + method: 'DELETE' + }) + + if (response.ok) { + onDelete(prompt.id) + setIsDeleteDialogOpen(false) + onClose() + } else { + console.error('Failed to delete prompt') + } + } catch (error) { + console.error('Error deleting prompt:', error) + } finally { + setIsDeleting(false) + } + } + const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { handleSave() @@ -258,28 +287,54 @@ export function EditPromptModal({ {/* Footer */} -
- - +
+ {/* Delete button on the left */} + {onDelete && ( + + )} + + {/* Save and Cancel buttons on the right */} +
+ + +
+ + {/* Delete Confirmation Dialog */} + setIsDeleteDialogOpen(false)} + onConfirm={handleDelete} + title={t('deletePrompt')} + itemName={prompt.name} + isDeleting={isDeleting} + /> ) } diff --git a/src/components/studio/PromptDetailModal.tsx b/src/components/studio/PromptDetailModal.tsx index 8e21795..bdfe83b 100644 --- a/src/components/studio/PromptDetailModal.tsx +++ b/src/components/studio/PromptDetailModal.tsx @@ -1,8 +1,10 @@ 'use client' +import { useState } from 'react' import { useTranslations } from 'next-intl' import { Button } from '@/components/ui/button' -import { X, Edit, Play, Calendar, Tag } from 'lucide-react' +import { DeleteConfirmationDialog } from '@/components/ui/delete-confirmation-dialog' +import { X, Edit, Play, Calendar, Tag, Trash2 } from 'lucide-react' interface Prompt { id: string @@ -23,6 +25,8 @@ interface PromptDetailModalProps { onClose: () => void onEdit: (id: string) => void onDebug: (id: string) => void + onDelete?: (id: string) => void + userId?: string } export function PromptDetailModal({ @@ -30,11 +34,16 @@ export function PromptDetailModal({ isOpen, onClose, onEdit, - onDebug + onDebug, + onDelete, + userId }: PromptDetailModalProps) { const t = useTranslations('studio') const tCommon = useTranslations('common') + const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false) + const [isDeleting, setIsDeleting] = useState(false) + const formatDate = (dateString: string) => { return new Intl.DateTimeFormat('default', { year: 'numeric', @@ -45,6 +54,29 @@ export function PromptDetailModal({ }).format(new Date(dateString)) } + const handleDelete = async () => { + if (!prompt || !userId || !onDelete) return + + setIsDeleting(true) + try { + const response = await fetch(`/api/prompts/${prompt.id}?userId=${userId}`, { + method: 'DELETE' + }) + + if (response.ok) { + onDelete(prompt.id) + setIsDeleteDialogOpen(false) + onClose() + } else { + console.error('Failed to delete prompt') + } + } catch (error) { + console.error('Error deleting prompt:', error) + } finally { + setIsDeleting(false) + } + } + if (!isOpen || !prompt) return null return ( @@ -147,36 +179,61 @@ export function PromptDetailModal({ {/* Footer Actions */} -
- - - +
+ {/* Delete button on the left */} + {onDelete && userId && ( + + )} + + {/* Other actions on the right */} +
+ + + +
+ + {/* Delete Confirmation Dialog */} + setIsDeleteDialogOpen(false)} + onConfirm={handleDelete} + title={t('deletePrompt')} + itemName={prompt?.name} + isDeleting={isDeleting} + /> ) } \ No newline at end of file diff --git a/src/components/ui/delete-confirmation-dialog.tsx b/src/components/ui/delete-confirmation-dialog.tsx new file mode 100644 index 0000000..c11c527 --- /dev/null +++ b/src/components/ui/delete-confirmation-dialog.tsx @@ -0,0 +1,106 @@ +'use client' + +import { useTranslations } from 'next-intl' +import { Button } from '@/components/ui/button' +import { LoadingSpinner } from '@/components/ui/loading-spinner' +import { AlertTriangle, X } from 'lucide-react' + +interface DeleteConfirmationDialogProps { + isOpen: boolean + onClose: () => void + onConfirm: () => void + title: string + description?: string + itemName?: string + isDeleting?: boolean +} + +export function DeleteConfirmationDialog({ + isOpen, + onClose, + onConfirm, + title, + description, + itemName, + isDeleting = false +}: DeleteConfirmationDialogProps) { + const t = useTranslations('studio') + const tCommon = useTranslations('common') + + if (!isOpen) return null + + return ( +
+ {/* Backdrop */} +
+ + {/* Dialog */} +
+ {/* Header */} +
+
+
+ +
+

+ {title} +

+
+ +
+ + {/* Content */} +
+
+ {description || t('confirmDelete')} +
+ + {itemName && ( +
+
+ {itemName} +
+
+ )} + +
+ {t('deleteWarning')} +
+
+ + {/* Footer */} +
+ + +
+
+
+ ) +}