FrederickSundeep commited on
Commit
5cb8e2c
Β·
1 Parent(s): 08f236e

commit initial 09-12-2025 013

Browse files
Files changed (2) hide show
  1. src/App.css +96 -1
  2. src/App.js +104 -63
src/App.css CHANGED
@@ -545,4 +545,99 @@
545
  border-radius: 4px;
546
  max-height: 120px;
547
  overflow-y: auto;
548
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  border-radius: 4px;
546
  max-height: 120px;
547
  overflow-y: auto;
548
+ }
549
+
550
+ /* Ensure body is flex row: left tree, center editor, right AI */
551
+ .ide-body {
552
+ display: flex;
553
+ flex: 1;
554
+ overflow: hidden;
555
+ }
556
+
557
+ /* Center main area already exists, ensure it flexes */
558
+ .ide-main {
559
+ flex: 1;
560
+ display: flex;
561
+ flex-direction: column;
562
+ position: relative;
563
+ }
564
+
565
+ /* Editor wrapper to fill center */
566
+ .ide-editor-wrapper {
567
+ flex: 1;
568
+ min-height: 0;
569
+ }
570
+
571
+ /* Right AI panel */
572
+ .ide-right-panel {
573
+ width: 280px;
574
+ border-left: 1px solid #444;
575
+ background: #252526;
576
+ padding: 8px;
577
+ display: flex;
578
+ flex-direction: column;
579
+ gap: 8px;
580
+ font-size: 13px;
581
+ }
582
+
583
+ .ide-ai-header {
584
+ font-weight: 600;
585
+ margin-bottom: 4px;
586
+ }
587
+
588
+ .ide-ai-section {
589
+ display: flex;
590
+ flex-direction: column;
591
+ gap: 4px;
592
+ }
593
+
594
+ .ide-ai-label {
595
+ font-size: 12px;
596
+ text-transform: uppercase;
597
+ letter-spacing: 0.06em;
598
+ opacity: 0.8;
599
+ }
600
+
601
+ .ide-agent-textarea {
602
+ width: 100%;
603
+ min-height: 80px;
604
+ max-height: 160px;
605
+ resize: vertical;
606
+ padding: 6px;
607
+ border-radius: 4px;
608
+ border: 1px solid #444;
609
+ background: #1e1e1e;
610
+ color: #eee;
611
+ font-family: Consolas, monospace;
612
+ font-size: 12px;
613
+ }
614
+
615
+ .ide-ai-buttons {
616
+ display: flex;
617
+ gap: 6px;
618
+ }
619
+
620
+ .ide-ai-buttons button {
621
+ flex: 1;
622
+ padding: 4px 6px;
623
+ font-size: 12px;
624
+ border-radius: 4px;
625
+ border: 1px solid #555;
626
+ background: #0e639c;
627
+ color: #fff;
628
+ cursor: pointer;
629
+ }
630
+
631
+ .ide-ai-buttons button:hover {
632
+ background: #1177bb;
633
+ }
634
+
635
+ .ide-explain {
636
+ max-height: 180px;
637
+ overflow-y: auto;
638
+ padding: 6px;
639
+ border-radius: 4px;
640
+ background: #1e1e1e;
641
+ border: 1px solid #444;
642
+ font-size: 12px;
643
+ }
src/App.js CHANGED
@@ -2,7 +2,17 @@ import { useState, useEffect, useRef } from "react";
2
  import Editor from "@monaco-editor/react";
3
  import { askAgent } from "./agent/assistant";
4
  import { runCode } from "./agent/runner";
5
- import { loadTree, saveTree, addFile, addFolder, renameNode, deleteNode, getNodeByPath, updateFileContent, searchTree } from "./fileStore";
 
 
 
 
 
 
 
 
 
 
6
  import { downloadProjectZip } from "./zipExport";
7
  import { parseProblems } from "./problemParser";
8
  import "./App.css";
@@ -40,9 +50,8 @@ function App() {
40
 
41
  const currentFile = getNodeByPath(tree, activePath);
42
  const langMeta =
43
- LANGUAGE_OPTIONS.find((l) =>
44
- currentFile?.name.endsWith(l.ext)
45
- ) || LANGUAGE_OPTIONS[0];
46
 
47
  // Save after tree change
48
  useEffect(() => {
@@ -78,7 +87,9 @@ function App() {
78
 
79
  const downloadFile = () => {
80
  if (!currentFile?.content) return;
81
- const blob = new Blob([currentFile.content], { type: "text/plain;charset=utf-8" });
 
 
82
  const a = document.createElement("a");
83
  a.href = URL.createObjectURL(blob);
84
  a.download = currentFile.name;
@@ -102,38 +113,40 @@ function App() {
102
 
103
  // =================== AI ===================
104
  const handleAskFix = async () => {
105
- const userHint = prompt.trim() ? `User request: ${prompt}` : "";
106
- const reply = await askAgent(
107
- `Improve, debug, or refactor this ${langMeta.id} file.
 
108
  ${userHint}
109
  Return ONLY updated code, no explanation.
110
 
111
  CODE:
112
  ${currentFile.content}`
113
- );
114
- updateActiveFileContent(reply);
115
- };
116
-
117
 
118
  const handleExplainSelection = async () => {
119
- const editor = editorRef.current;
120
- const selected = editor.getModel().getValueInRange(editor.getSelection());
121
- const code = selected.trim() || currentFile.content;
 
 
 
122
 
123
- const userHint = prompt.trim()
124
- ? `Focus on: ${prompt}`
125
- : "Give a clear and simple explanation.";
126
 
127
- const reply = await askAgent(
128
- `Explain what this ${langMeta.id} code does, any risks, and improvements.
129
  ${userHint}
130
 
131
  CODE:
132
  ${code}`
133
- );
134
- setExplanation(reply);
135
- };
136
-
137
 
138
  const updateActiveFileContent = (value) => {
139
  const updated = updateFileContent(tree, activePath, value);
@@ -142,7 +155,7 @@ ${code}`
142
 
143
  // ===== AI Autocomplete Suggestions (Popup) =====
144
  const fetchAiSuggestions = async (code) => {
145
- if (!code.trim()) return;
146
  const reply = await askAgent(
147
  `Suggest possible next lines for continuation. Return 3 short snippets.\n${code}`
148
  );
@@ -165,7 +178,11 @@ ${code}`
165
 
166
  // =================== UI ===================
167
  return (
168
- <div className={`ide-root ${theme === "vs-dark" ? "ide-dark" : "ide-light"}`}>
 
 
 
 
169
  {/* ==== TOP BAR ==== */}
170
  <div className="ide-menubar">
171
  <div className="ide-menubar-left">
@@ -183,7 +200,11 @@ ${code}`
183
  <button onClick={handleRun}>β–Ά Run</button>
184
  <button onClick={handleAskFix}>πŸ€– Fix</button>
185
  <button onClick={handleExplainSelection}>πŸ“– Explain</button>
186
- <button onClick={() => setTheme(theme === "vs-dark" ? "light" : "vs-dark")}>
 
 
 
 
187
  {theme === "vs-dark" ? "β˜€οΈ" : "πŸŒ™"}
188
  </button>
189
  </div>
@@ -191,23 +212,24 @@ ${code}`
191
 
192
  {/* ==== BODY ==== */}
193
  <div className="ide-body">
194
-
195
- {/* ==== TREE VIEW ==== */}
196
  <div className="ide-sidebar">
197
  {renderTree(tree, setActivePath, setContextMenu)}
198
  </div>
199
 
200
- {/* ==== EDITOR ==== */}
201
  <div className="ide-main">
202
- <Editor
203
- height="100%"
204
- theme={theme}
205
- language={langMeta.monaco}
206
- value={currentFile?.content || ""}
207
- onChange={updateActiveFileContent}
208
- onMount={(editor) => (editorRef.current = editor)}
209
- onBlur={() => fetchAiSuggestions(currentFile?.content)}
210
- />
 
 
211
 
212
  {/* AI Suggestions Tooltip */}
213
  {aiSuggestions.length > 0 && (
@@ -216,7 +238,11 @@ ${code}`
216
  <div
217
  key={i}
218
  className="ai-suggest"
219
- onClick={() => updateActiveFileContent(currentFile.content + "\n" + s)}
 
 
 
 
220
  >
221
  {s}
222
  </div>
@@ -224,7 +250,7 @@ ${code}`
224
  </div>
225
  )}
226
 
227
- {/* Bottom Panels */}
228
  <div className="ide-panels">
229
  <pre className="ide-output">{output}</pre>
230
 
@@ -235,29 +261,44 @@ ${code}`
235
  onChange={(e) => setStdin(e.target.value)}
236
  />
237
 
238
- {/* NEW AI PROMPT INPUT */}
239
- <textarea
240
- className="ide-agent-textarea"
241
- placeholder="Ask the AI (e.g., 'optimize', 'add docstring', 'convert to JS'...)"
242
- value={prompt}
243
- onChange={(e) => setPrompt(e.target.value)}
244
- />
245
-
246
- {/* EXPLANATION PANEL */}
247
- {explanation && (
248
- <div className="ide-explain">{explanation}</div>
249
- )}
250
-
251
- {/* PROBLEMS PANEL */}
252
- {problems.length > 0 && (
253
- <div className="ide-problems-panel">
254
- <div>🚨 Problems ({problems.length})</div>
255
- {problems.map((p, i) => (
256
- <div key={i}>{p.file}:{p.line} β€” {p.message}</div>
257
- ))}
258
- </div>
259
- )}
 
 
 
 
 
 
 
 
260
  </div>
 
 
 
 
 
 
 
261
  </div>
262
  </div>
263
 
 
2
  import Editor from "@monaco-editor/react";
3
  import { askAgent } from "./agent/assistant";
4
  import { runCode } from "./agent/runner";
5
+ import {
6
+ loadTree,
7
+ saveTree,
8
+ addFile,
9
+ addFolder,
10
+ renameNode,
11
+ deleteNode,
12
+ getNodeByPath,
13
+ updateFileContent,
14
+ searchTree,
15
+ } from "./fileStore";
16
  import { downloadProjectZip } from "./zipExport";
17
  import { parseProblems } from "./problemParser";
18
  import "./App.css";
 
50
 
51
  const currentFile = getNodeByPath(tree, activePath);
52
  const langMeta =
53
+ LANGUAGE_OPTIONS.find((l) => currentFile?.name.endsWith(l.ext)) ||
54
+ LANGUAGE_OPTIONS[0];
 
55
 
56
  // Save after tree change
57
  useEffect(() => {
 
87
 
88
  const downloadFile = () => {
89
  if (!currentFile?.content) return;
90
+ const blob = new Blob([currentFile.content], {
91
+ type: "text/plain;charset=utf-8",
92
+ });
93
  const a = document.createElement("a");
94
  a.href = URL.createObjectURL(blob);
95
  a.download = currentFile.name;
 
113
 
114
  // =================== AI ===================
115
  const handleAskFix = async () => {
116
+ if (!currentFile) return;
117
+ const userHint = prompt.trim() ? `User request: ${prompt}` : "";
118
+ const reply = await askAgent(
119
+ `Improve, debug, or refactor this ${langMeta.id} file.
120
  ${userHint}
121
  Return ONLY updated code, no explanation.
122
 
123
  CODE:
124
  ${currentFile.content}`
125
+ );
126
+ updateActiveFileContent(reply);
127
+ };
 
128
 
129
  const handleExplainSelection = async () => {
130
+ if (!currentFile) return;
131
+ const editor = editorRef.current;
132
+ const selected = editor
133
+ .getModel()
134
+ .getValueInRange(editor.getSelection());
135
+ const code = selected.trim() || currentFile.content;
136
 
137
+ const userHint = prompt.trim()
138
+ ? `Focus on: ${prompt}`
139
+ : "Give a clear and simple explanation.";
140
 
141
+ const reply = await askAgent(
142
+ `Explain what this ${langMeta.id} code does, any risks, and improvements.
143
  ${userHint}
144
 
145
  CODE:
146
  ${code}`
147
+ );
148
+ setExplanation(reply);
149
+ };
 
150
 
151
  const updateActiveFileContent = (value) => {
152
  const updated = updateFileContent(tree, activePath, value);
 
155
 
156
  // ===== AI Autocomplete Suggestions (Popup) =====
157
  const fetchAiSuggestions = async (code) => {
158
+ if (!code?.trim()) return;
159
  const reply = await askAgent(
160
  `Suggest possible next lines for continuation. Return 3 short snippets.\n${code}`
161
  );
 
178
 
179
  // =================== UI ===================
180
  return (
181
+ <div
182
+ className={`ide-root ${
183
+ theme === "vs-dark" ? "ide-dark" : "ide-light"
184
+ }`}
185
+ >
186
  {/* ==== TOP BAR ==== */}
187
  <div className="ide-menubar">
188
  <div className="ide-menubar-left">
 
200
  <button onClick={handleRun}>β–Ά Run</button>
201
  <button onClick={handleAskFix}>πŸ€– Fix</button>
202
  <button onClick={handleExplainSelection}>πŸ“– Explain</button>
203
+ <button
204
+ onClick={() =>
205
+ setTheme(theme === "vs-dark" ? "light" : "vs-dark")
206
+ }
207
+ >
208
  {theme === "vs-dark" ? "β˜€οΈ" : "πŸŒ™"}
209
  </button>
210
  </div>
 
212
 
213
  {/* ==== BODY ==== */}
214
  <div className="ide-body">
215
+ {/* ==== TREE VIEW (LEFT) ==== */}
 
216
  <div className="ide-sidebar">
217
  {renderTree(tree, setActivePath, setContextMenu)}
218
  </div>
219
 
220
+ {/* ==== MAIN CENTER (EDITOR + OUTPUT) ==== */}
221
  <div className="ide-main">
222
+ <div className="ide-editor-wrapper">
223
+ <Editor
224
+ height="100%"
225
+ theme={theme}
226
+ language={langMeta.monaco}
227
+ value={currentFile?.content || ""}
228
+ onChange={updateActiveFileContent}
229
+ onMount={(editor) => (editorRef.current = editor)}
230
+ onBlur={() => fetchAiSuggestions(currentFile?.content)}
231
+ />
232
+ </div>
233
 
234
  {/* AI Suggestions Tooltip */}
235
  {aiSuggestions.length > 0 && (
 
238
  <div
239
  key={i}
240
  className="ai-suggest"
241
+ onClick={() =>
242
+ updateActiveFileContent(
243
+ (currentFile?.content || "") + "\n" + s
244
+ )
245
+ }
246
  >
247
  {s}
248
  </div>
 
250
  </div>
251
  )}
252
 
253
+ {/* Bottom Panels: Output + stdin + Problems */}
254
  <div className="ide-panels">
255
  <pre className="ide-output">{output}</pre>
256
 
 
261
  onChange={(e) => setStdin(e.target.value)}
262
  />
263
 
264
+ {problems.length > 0 && (
265
+ <div className="ide-problems-panel">
266
+ <div>🚨 Problems ({problems.length})</div>
267
+ {problems.map((p, i) => (
268
+ <div key={i}>
269
+ {p.file}:{p.line} β€” {p.message}
270
+ </div>
271
+ ))}
272
+ </div>
273
+ )}
274
+ </div>
275
+ </div>
276
+
277
+ {/* ==== RIGHT AI PANEL ==== */}
278
+ <div className="ide-right-panel">
279
+ <div className="ide-ai-header">πŸ€– AI Assistant</div>
280
+
281
+ <div className="ide-ai-section">
282
+ <label className="ide-ai-label">Instruction</label>
283
+ <textarea
284
+ className="ide-agent-textarea"
285
+ placeholder="Ask the AI (e.g., 'optimize this function', 'add comments', 'convert to JS'...)"
286
+ value={prompt}
287
+ onChange={(e) => setPrompt(e.target.value)}
288
+ />
289
+ </div>
290
+
291
+ <div className="ide-ai-buttons">
292
+ <button onClick={handleAskFix}>πŸ’‘ Apply Fix</button>
293
+ <button onClick={handleExplainSelection}>πŸ“– Explain Code</button>
294
  </div>
295
+
296
+ {explanation && (
297
+ <div className="ide-ai-section">
298
+ <label className="ide-ai-label">Explanation</label>
299
+ <div className="ide-explain">{explanation}</div>
300
+ </div>
301
+ )}
302
  </div>
303
  </div>
304