From 720d2d3f9b973bba78bd5f455b0baf8e0a643c16 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 01:16:26 +0000 Subject: [PATCH] refactor file explorer dialog state --- .../file-explorer/FileExplorerDialog.tsx | 80 ++++------------- .../file-explorer/useFileExplorerDialog.ts | 89 +++++++++++++++++++ 2 files changed, 105 insertions(+), 64 deletions(-) create mode 100644 src/components/file-explorer/useFileExplorerDialog.ts diff --git a/src/components/file-explorer/FileExplorerDialog.tsx b/src/components/file-explorer/FileExplorerDialog.tsx index ee0edc8..cde3cf3 100644 --- a/src/components/file-explorer/FileExplorerDialog.tsx +++ b/src/components/file-explorer/FileExplorerDialog.tsx @@ -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 ( diff --git a/src/components/file-explorer/useFileExplorerDialog.ts b/src/components/file-explorer/useFileExplorerDialog.ts new file mode 100644 index 0000000..5bd64e6 --- /dev/null +++ b/src/components/file-explorer/useFileExplorerDialog.ts @@ -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, + } +}