Skip to content

Commit a2530e2

Browse files
Complete enhanced code editor with responsive design and status feedback
Co-authored-by: Gerome-Elassaad <[email protected]>
1 parent 854e7d4 commit a2530e2

File tree

2 files changed

+93
-43
lines changed

2 files changed

+93
-43
lines changed

components/code-view.tsx

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useEffect, useState } from 'react'
22
import { CodeEditor } from './code-editor'
33
import { Button } from './ui/button'
4+
import { useToast } from './ui/use-toast'
45

56
export function CodeView({
67
code: initialCode,
@@ -12,26 +13,55 @@ export function CodeView({
1213
onSave: (content: string) => void
1314
}) {
1415
const [code, setCode] = useState(initialCode)
16+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
17+
const { toast } = useToast()
1518

1619
useEffect(() => {
1720
setCode(initialCode)
21+
setHasUnsavedChanges(false)
1822
}, [initialCode])
1923

24+
function handleCodeChange(newCode: string | undefined) {
25+
setCode(newCode || '')
26+
setHasUnsavedChanges((newCode || '') !== initialCode)
27+
}
28+
2029
function handleSave() {
2130
onSave(code)
31+
setHasUnsavedChanges(false)
32+
toast({
33+
title: 'File saved',
34+
description: 'Your changes have been saved successfully.',
35+
})
2236
}
2337

2438
return (
25-
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
26-
<div style={{ flex: 1, overflow: 'auto' }}>
39+
<div className="h-full flex flex-col">
40+
<div className="flex-1 min-h-0">
2741
<CodeEditor
2842
code={code}
2943
lang={lang}
30-
onChange={newCode => setCode(newCode || '')}
44+
onChange={handleCodeChange}
3145
/>
3246
</div>
33-
<div className="p-2 flex justify-end">
34-
<Button onClick={handleSave}>Save</Button>
47+
<div className="p-3 border-t bg-muted/20 flex items-center justify-between">
48+
<div className="flex items-center gap-4 text-sm text-muted-foreground">
49+
<span>Lines: {code.split('\n').length}</span>
50+
<span>Characters: {code.length}</span>
51+
<span>Language: {lang || 'text'}</span>
52+
</div>
53+
<div className="flex items-center gap-2">
54+
{hasUnsavedChanges && (
55+
<span className="text-xs text-orange-500">Unsaved changes</span>
56+
)}
57+
<Button
58+
onClick={handleSave}
59+
size="sm"
60+
variant={hasUnsavedChanges ? 'default' : 'outline'}
61+
>
62+
Save {hasUnsavedChanges && '*'}
63+
</Button>
64+
</div>
3565
</div>
3666
</div>
3767
)

components/fragment-code.tsx

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import {
77
TooltipProvider,
88
TooltipTrigger,
99
} from '@/components/ui/tooltip'
10-
import { Download } from 'lucide-react'
10+
import { Download, File as FileIcon } from 'lucide-react'
1111
import { useEffect, useState } from 'react'
1212
import { FileTree, FileSystemNode } from './file-tree'
13-
import { ScrollArea } from './ui/scroll-area'
1413

1514
export function FragmentCode() {
1615
const [fileTree, setFileTree] = useState<FileSystemNode[]>([])
@@ -112,51 +111,72 @@ export function FragmentCode() {
112111
}
113112

114113
return (
115-
<div className="flex h-full">
116-
<ScrollArea className="w-1/4 border-r">
114+
<div className="flex h-full w-full">
115+
<div className="w-full sm:w-1/4 lg:w-1/5 xl:w-1/6 border-r min-w-[200px] max-w-[300px]">
117116
<FileTree
118117
files={fileTree}
119118
onSelectFile={handleSelectFile}
120119
onCreateFile={handleCreateFile}
121120
onDeleteFile={handleDeleteFile}
122121
/>
123-
</ScrollArea>
124-
<div className="flex flex-col flex-1 overflow-x-auto">
122+
</div>
123+
<div className="flex flex-col flex-1 overflow-hidden min-w-0">
125124
{selectedFile && (
126-
<div className="flex items-center justify-end px-2 pt-1 gap-2">
127-
<TooltipProvider>
128-
<Tooltip delayDuration={0}>
129-
<TooltipTrigger asChild>
130-
<CopyButton
131-
content={code}
132-
className="text-muted-foreground"
133-
/>
134-
</TooltipTrigger>
135-
<TooltipContent side="bottom">Copy</TooltipContent>
136-
</Tooltip>
137-
</TooltipProvider>
138-
<TooltipProvider>
139-
<Tooltip delayDuration={0}>
140-
<TooltipTrigger asChild>
141-
<Button
142-
variant="ghost"
143-
size="icon"
144-
className="text-muted-foreground"
145-
onClick={() => download(selectedFile, code)}
146-
>
147-
<Download className="h-4 w-4" />
148-
</Button>
149-
</TooltipTrigger>
150-
<TooltipContent side="bottom">Download</TooltipContent>
151-
</Tooltip>
152-
</TooltipProvider>
125+
<div className="flex items-center justify-between px-4 py-2 border-b bg-muted/30">
126+
<div className="flex items-center gap-2 min-w-0">
127+
<FileIcon className="h-4 w-4 text-muted-foreground flex-shrink-0" />
128+
<span className="text-sm font-medium truncate">{selectedFile.split('/').pop()}</span>
129+
<span className="text-xs text-muted-foreground hidden sm:block">
130+
{selectedFile}
131+
</span>
132+
</div>
133+
<div className="flex items-center gap-2 flex-shrink-0">
134+
<TooltipProvider>
135+
<Tooltip delayDuration={0}>
136+
<TooltipTrigger asChild>
137+
<CopyButton
138+
content={code}
139+
className="text-muted-foreground"
140+
/>
141+
</TooltipTrigger>
142+
<TooltipContent side="bottom">Copy</TooltipContent>
143+
</Tooltip>
144+
</TooltipProvider>
145+
<TooltipProvider>
146+
<Tooltip delayDuration={0}>
147+
<TooltipTrigger asChild>
148+
<Button
149+
variant="ghost"
150+
size="icon"
151+
className="text-muted-foreground"
152+
onClick={() => download(selectedFile, code)}
153+
>
154+
<Download className="h-4 w-4" />
155+
</Button>
156+
</TooltipTrigger>
157+
<TooltipContent side="bottom">Download</TooltipContent>
158+
</Tooltip>
159+
</TooltipProvider>
160+
</div>
153161
</div>
154162
)}
155-
<CodeView
156-
code={code}
157-
lang={selectedFile?.split('.').pop() || ''}
158-
onSave={handleSave}
159-
/>
163+
<div className="flex-1 relative">
164+
{selectedFile ? (
165+
<CodeView
166+
code={code}
167+
lang={selectedFile?.split('.').pop() || ''}
168+
onSave={handleSave}
169+
/>
170+
) : (
171+
<div className="h-full flex items-center justify-center text-muted-foreground">
172+
<div className="text-center">
173+
<FileIcon className="h-12 w-12 mx-auto mb-4 opacity-50" />
174+
<p className="text-lg mb-2">No file selected</p>
175+
<p className="text-sm">Select a file from the tree to start editing</p>
176+
</div>
177+
</div>
178+
)}
179+
</div>
160180
</div>
161181
</div>
162182
)

0 commit comments

Comments
 (0)