refactor file explorer dialog state

This commit is contained in:
2026-01-18 01:16:26 +00:00
parent b14a0a0403
commit 720d2d3f9b
2 changed files with 105 additions and 64 deletions

View File

@@ -1,4 +1,3 @@
import { useState } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
@@ -19,78 +18,31 @@ import {
SelectValue,
} from '@/components/ui/select'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { AIService } from '@/lib/ai-service'
import { ProjectFile } from '@/types/project'
import { toast } from 'sonner'
import fileExplorerCopy from '@/data/file-explorer.json'
import { Plus } from '@phosphor-icons/react'
import { useFileExplorerDialog } from '@/components/file-explorer/useFileExplorerDialog'
interface FileExplorerDialogProps {
onFileAdd: (file: ProjectFile) => void
}
export function FileExplorerDialog({ onFileAdd }: FileExplorerDialogProps) {
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false)
const [newFileName, setNewFileName] = useState('')
const [newFileLanguage, setNewFileLanguage] = useState('typescript')
const [aiDescription, setAiDescription] = useState('')
const [aiFileType, setAiFileType] = useState<'component' | 'page' | 'api' | 'utility'>(
'component'
)
const [isGenerating, setIsGenerating] = useState(false)
const handleAddFile = () => {
if (!newFileName.trim()) return
const newFile: ProjectFile = {
id: `file-${Date.now()}`,
name: newFileName,
path: `/src/${newFileName}`,
content: '',
language: newFileLanguage,
}
onFileAdd(newFile)
setNewFileName('')
setIsAddDialogOpen(false)
}
const handleGenerateFileWithAI = async () => {
if (!aiDescription.trim() || !newFileName.trim()) {
toast.error(fileExplorerCopy.toast.missingFields)
return
}
try {
setIsGenerating(true)
toast.info(fileExplorerCopy.toast.generating)
const code = await AIService.generateCodeFromDescription(aiDescription, aiFileType)
if (code) {
const newFile: ProjectFile = {
id: `file-${Date.now()}`,
name: newFileName,
path: `/src/${newFileName}`,
content: code,
language: newFileLanguage,
}
onFileAdd(newFile)
setNewFileName('')
setAiDescription('')
setIsAddDialogOpen(false)
toast.success(fileExplorerCopy.toast.generated)
} else {
toast.error(fileExplorerCopy.toast.generationFailed)
}
} catch (error) {
toast.error(fileExplorerCopy.toast.generationError)
console.error(error)
} finally {
setIsGenerating(false)
}
}
const {
isAddDialogOpen,
setIsAddDialogOpen,
newFileName,
setNewFileName,
newFileLanguage,
setNewFileLanguage,
aiDescription,
setAiDescription,
aiFileType,
setAiFileType,
isGenerating,
handleAddFile,
handleGenerateFileWithAI,
} = useFileExplorerDialog({ onFileAdd })
return (
<Dialog open={isAddDialogOpen} onOpenChange={setIsAddDialogOpen}>

View File

@@ -0,0 +1,89 @@
import { useState } from 'react'
import { AIService } from '@/lib/ai-service'
import { ProjectFile } from '@/types/project'
import { toast } from 'sonner'
import fileExplorerCopy from '@/data/file-explorer.json'
interface UseFileExplorerDialogProps {
onFileAdd: (file: ProjectFile) => void
}
export function useFileExplorerDialog({ onFileAdd }: UseFileExplorerDialogProps) {
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false)
const [newFileName, setNewFileName] = useState('')
const [newFileLanguage, setNewFileLanguage] = useState('typescript')
const [aiDescription, setAiDescription] = useState('')
const [aiFileType, setAiFileType] = useState<'component' | 'page' | 'api' | 'utility'>(
'component'
)
const [isGenerating, setIsGenerating] = useState(false)
const handleAddFile = () => {
if (!newFileName.trim()) return
const newFile: ProjectFile = {
id: `file-${Date.now()}`,
name: newFileName,
path: `/src/${newFileName}`,
content: '',
language: newFileLanguage,
}
onFileAdd(newFile)
setNewFileName('')
setIsAddDialogOpen(false)
}
const handleGenerateFileWithAI = async () => {
if (!aiDescription.trim() || !newFileName.trim()) {
toast.error(fileExplorerCopy.toast.missingFields)
return
}
try {
setIsGenerating(true)
toast.info(fileExplorerCopy.toast.generating)
const code = await AIService.generateCodeFromDescription(aiDescription, aiFileType)
if (code) {
const newFile: ProjectFile = {
id: `file-${Date.now()}`,
name: newFileName,
path: `/src/${newFileName}`,
content: code,
language: newFileLanguage,
}
onFileAdd(newFile)
setNewFileName('')
setAiDescription('')
setIsAddDialogOpen(false)
toast.success(fileExplorerCopy.toast.generated)
} else {
toast.error(fileExplorerCopy.toast.generationFailed)
}
} catch (error) {
toast.error(fileExplorerCopy.toast.generationError)
console.error(error)
} finally {
setIsGenerating(false)
}
}
return {
isAddDialogOpen,
setIsAddDialogOpen,
newFileName,
setNewFileName,
newFileLanguage,
setNewFileLanguage,
aiDescription,
setAiDescription,
aiFileType,
setAiFileType,
isGenerating,
handleAddFile,
handleGenerateFileWithAI,
}
}