import { useState, useEffect, useRef } from 'react'
import { IoCloseOutline, IoDocumentTextOutline, IoFolderOutline, IoTrashOutline } from 'react-icons/io5'
interface CreateFileDialogProps {
isOpen: boolean
onClose: () => void
onSubmit: (name: string, content?: string) => Promise<void>
type: 'file' | 'folder'
parentName?: string
loading?: boolean
}
interface RenameDialogProps {
isOpen: boolean
onClose: () => void
onSubmit: (newName: string) => Promise<void>
currentName: string
type: 'file' | 'folder'
loading?: boolean
}
interface DeleteConfirmDialogProps {
isOpen: boolean
onClose: () => void
onConfirm: () => Promise<void>
itemName: string
itemType: 'file' | 'folder'
loading?: boolean
}
export function CreateFileDialog({
isOpen,
onClose,
onSubmit,
type,
parentName,
loading = false
}: CreateFileDialogProps) {
const [name, setName] = useState('')
const [content, setContent] = useState('')
const [error, setError] = useState('')
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
if (isOpen) {
setName('')
setContent('')
setError('')
setTimeout(() => inputRef.current?.focus(), 100)
}
}, [isOpen])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!name.trim()) {
setError('Name is required')
return
}
try {
await onSubmit(name.trim(), type === 'file' ? content : undefined)
onClose()
} catch (error) {
setError(error instanceof Error ? error.message : 'Failed to create item')
}
}
if (!isOpen) return null
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-slate-800 rounded-lg border border-slate-700 w-full max-w-md">
<div className="flex items-center justify-between p-4 border-b border-slate-700">
<div className="flex items-center gap-2">
{type === 'file' ? (
<IoDocumentTextOutline className="w-5 h-5 text-blue-400" />
) : (
<IoFolderOutline className="w-5 h-5 text-yellow-400" />
)}
<h2 className="text-lg font-semibold text-white">
Create New {type === 'file' ? 'File' : 'Folder'}
</h2>
</div>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-200 transition-colors"
disabled={loading}
>
<IoCloseOutline className="w-5 h-5" />
</button>
</div>
<form onSubmit={handleSubmit} className="p-4 space-y-4">
{parentName && (
<p className="text-sm text-slate-400">
Creating in: <span className="text-slate-300">{parentName}</span>
</p>
)}
<div>
<label htmlFor="name" className="block text-sm font-medium text-slate-300 mb-1">
{type === 'file' ? 'File name' : 'Folder name'}
</label>
<input
ref={inputRef}
type="text"
id="name"
value={name}
onChange={(e) => {
setName(e.target.value)
setError('')
}}
placeholder={type === 'file' ? 'chapter-1' : 'characters'}
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-white placeholder-slate-400"
disabled={loading}
/>
</div>
{type === 'file' && (
<div>
<label htmlFor="content" className="block text-sm font-medium text-slate-300 mb-1">
Initial content (optional)
</label>
<textarea
id="content"
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="# Chapter 1 Write your content here..."
rows={4}
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-white placeholder-slate-400 resize-none"
disabled={loading}
/>
</div>
)}
{error && (
<div className="text-red-400 text-sm">{error}</div>
)}
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={onClose}
className="flex-1 px-4 py-2 text-sm font-medium text-slate-300 bg-slate-700 border border-slate-600 rounded-md hover:bg-slate-600 transition-colors"
disabled={loading}
>
Cancel
</button>
<button
type="submit"
disabled={loading || !name.trim()}
className="flex-1 px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-blue-600 rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{loading ? 'Creating...' : `Create ${type === 'file' ? 'File' : 'Folder'}`}
</button>
</div>
</form>
</div>
</div>
)
}
export function RenameDialog({
isOpen,
onClose,
onSubmit,
currentName,
type,
loading = false
}: RenameDialogProps) {
const [name, setName] = useState('')
const [error, setError] = useState('')
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
if (isOpen) {
setName(currentName)
setError('')
setTimeout(() => {
inputRef.current?.focus()
inputRef.current?.select()
}, 100)
}
}, [isOpen, currentName])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!name.trim()) {
setError('Name is required')
return
}
if (name.trim() === currentName) {
onClose()
return
}
try {
await onSubmit(name.trim())
onClose()
} catch (error) {
setError(error instanceof Error ? error.message : 'Failed to rename item')
}
}
if (!isOpen) return null
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-slate-800 rounded-lg border border-slate-700 w-full max-w-md">
<div className="flex items-center justify-between p-4 border-b border-slate-700">
<div className="flex items-center gap-2">
{type === 'file' ? (
<IoDocumentTextOutline className="w-5 h-5 text-blue-400" />
) : (
<IoFolderOutline className="w-5 h-5 text-yellow-400" />
)}
<h2 className="text-lg font-semibold text-white">
Rename {type === 'file' ? 'File' : 'Folder'}
</h2>
</div>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-200 transition-colors"
disabled={loading}
>
<IoCloseOutline className="w-5 h-5" />
</button>
</div>
<form onSubmit={handleSubmit} className="p-4 space-y-4">
<div>
<label htmlFor="name" className="block text-sm font-medium text-slate-300 mb-1">
New name
</label>
<input
ref={inputRef}
type="text"
id="name"
value={name}
onChange={(e) => {
setName(e.target.value)
setError('')
}}
className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-white"
disabled={loading}
/>
</div>
{error && (
<div className="text-red-400 text-sm">{error}</div>
)}
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={onClose}
className="flex-1 px-4 py-2 text-sm font-medium text-slate-300 bg-slate-700 border border-slate-600 rounded-md hover:bg-slate-600 transition-colors"
disabled={loading}
>
Cancel
</button>
<button
type="submit"
disabled={loading || !name.trim() || name.trim() === currentName}
className="flex-1 px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-blue-600 rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{loading ? 'Renaming...' : 'Rename'}
</button>
</div>
</form>
</div>
</div>
)
}
export function DeleteConfirmDialog({
isOpen,
onClose,
onConfirm,
itemName,
itemType,
loading = false
}: DeleteConfirmDialogProps) {
const handleConfirm = async () => {
try {
await onConfirm()
onClose()
} catch (error) {
// Error handling is done in the parent component
}
}
if (!isOpen) return null
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-slate-800 rounded-lg border border-slate-700 w-full max-w-md">
<div className="flex items-center justify-between p-4 border-b border-slate-700">
<div className="flex items-center gap-2">
<IoTrashOutline className="w-5 h-5 text-red-400" />
<h2 className="text-lg font-semibold text-white">
Delete {itemType === 'file' ? 'File' : 'Folder'}
</h2>
</div>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-200 transition-colors"
disabled={loading}
>
<IoCloseOutline className="w-5 h-5" />
</button>
</div>
<div className="p-4 space-y-4">
<div className="flex items-center gap-3">
{itemType === 'file' ? (
<IoDocumentTextOutline className="w-8 h-8 text-blue-400 flex-shrink-0" />
) : (
<IoFolderOutline className="w-8 h-8 text-yellow-400 flex-shrink-0" />
)}
<div>
<p className="text-white font-medium">{itemName}</p>
<p className="text-sm text-slate-400">
{itemType === 'file'
? 'Are you sure you want to delete this file? This action cannot be undone.'
: 'Are you sure you want to delete this folder and all its contents? This action cannot be undone.'
}
</p>
</div>
</div>
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={onClose}
className="flex-1 px-4 py-2 text-sm font-medium text-slate-300 bg-slate-700 border border-slate-600 rounded-md hover:bg-slate-600 transition-colors"
disabled={loading}
>
Cancel
</button>
<button
onClick={handleConfirm}
disabled={loading}
className="flex-1 px-4 py-2 text-sm font-medium text-white bg-red-600 border border-red-600 rounded-md hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{loading ? 'Deleting...' : 'Delete'}
</button>
</div>
</div>
</div>
</div>
)
}