@@ -9,7 +9,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
99import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuLabel , DropdownMenuSeparator , DropdownMenuTrigger } from "@/components/ui/dropdown-menu" ;
1010import { Input } from "@/components/ui/input" ;
1111import { Tabs , TabsContent , TabsList , TabsTrigger } from "@/components/ui/tabs" ;
12- import { Check , Code , FileText , GitMerge , Megaphone , Milestone , MoreHorizontal , Pen , Plus , Settings , ShieldQuestion , Trash2 , Users , Heading1 , Heading2 , Heading3 , Bold , Italic , Strikethrough , List , ListOrdered , Code2 , Link as LinkIcon , Image as ImageIcon , Archive , Clock , AlertTriangle , Loader2 , Send , Server , PlayCircle } from "lucide-react" ;
12+ import { Check , Code , FileText , GitMerge , Megaphone , Milestone , MoreHorizontal , Pen , Plus , Settings , ShieldQuestion , Trash2 , Users , Heading1 , Heading2 , Heading3 , Bold , Italic , Strikethrough , List , ListOrdered , Code2 , Link as LinkIcon , Image as ImageIcon , Archive , Clock , AlertTriangle , Loader2 , Send , Server , PlayCircle , Terminal } from "lucide-react" ;
1313import { Tooltip , TooltipContent , TooltipProvider , TooltipTrigger } from "@/components/ui/tooltip" ;
1414import { DndContext , closestCenter , type DragEndEvent , useSensor , useSensors , PointerSensor } from '@dnd-kit/core' ;
1515import { SortableContext , useSortable , arrayMove , verticalListSortingStrategy } from '@dnd-kit/sortable' ;
@@ -30,6 +30,7 @@ import ReactMarkdown from 'react-markdown';
3030import remarkGfm from 'remark-gfm' ;
3131import { ScrollArea } from "@/components/ui/scroll-area" ;
3232import Link from 'next/link' ;
33+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from '@/components/ui/select' ;
3334
3435export const dynamic = 'force-dynamic' ;
3536
@@ -55,6 +56,72 @@ const urgencyStyles: { [key in TaskUrgency]: string } = {
5556 urgent : "border-red-500" ,
5657}
5758
59+ const SimulatedExecution = ( ) => {
60+ const [ isRunning , setIsRunning ] = useState ( false ) ;
61+ const [ output , setOutput ] = useState < string [ ] > ( [ ] ) ;
62+
63+ const handleRunCode = ( ) => {
64+ setIsRunning ( true ) ;
65+ setOutput ( [
66+ '> node index.js' ,
67+ 'Executing project code in a secure sandbox...' ,
68+ ] ) ;
69+
70+ setTimeout ( ( ) => {
71+ setOutput ( prev => [ ...prev , 'Dependencies installed successfully.' ] ) ;
72+ } , 1000 ) ;
73+
74+ setTimeout ( ( ) => {
75+ setOutput ( prev => [ ...prev , 'Server listening on port 3000.' , '---' , 'Hello from my project!' , 'Test successful.' ] ) ;
76+ setIsRunning ( false ) ;
77+ } , 2500 ) ;
78+ } ;
79+
80+ return (
81+ < Card className = "text-center" >
82+ < CardHeader >
83+ < CardTitle className = "flex items-center justify-center gap-3" > < Terminal className = "h-8 w-8 text-primary" /> Exécution de Code (Simulation)</ CardTitle >
84+ < CardDescription > Testez votre code dans un environnement sécurisé et isolé.</ CardDescription >
85+ </ CardHeader >
86+ < CardContent className = "py-8 flex flex-col items-center gap-6" >
87+ < div className = 'flex items-center gap-4 w-full max-w-lg mx-auto' >
88+ < div className = 'flex-1 space-y-2 text-left' >
89+ < Label > Langage</ Label >
90+ < Select defaultValue = "node" >
91+ < SelectTrigger >
92+ < SelectValue placeholder = "Choisir le langage" />
93+ </ SelectTrigger >
94+ < SelectContent >
95+ < SelectItem value = "node" > Node.js</ SelectItem >
96+ < SelectItem value = "python" > Python</ SelectItem >
97+ < SelectItem value = "bash" > Bash Script</ SelectItem >
98+ </ SelectContent >
99+ </ Select >
100+ </ div >
101+ < div className = 'flex-1 space-y-2 text-left' >
102+ < Label > Fichier d'entrée</ Label >
103+ < Input defaultValue = "index.js" />
104+ </ div >
105+ </ div >
106+
107+ < Button size = "lg" onClick = { handleRunCode } disabled = { isRunning } >
108+ { isRunning ? < Loader2 className = "mr-2 animate-spin" /> : < PlayCircle className = "mr-2" /> }
109+ { isRunning ? "Exécution en cours..." : "Lancer l'Exécution" }
110+ </ Button >
111+
112+ < div className = "w-full max-w-3xl mt-4 text-left font-code bg-gray-900 text-white rounded-lg p-4 h-64 overflow-y-auto" >
113+ < pre >
114+ { output . map ( ( line , i ) => (
115+ < p key = { i } className = 'text-sm' > { line } </ p >
116+ ) ) }
117+ { isRunning && < span className = "animate-pulse" > _</ span > }
118+ </ pre >
119+ </ div >
120+ </ CardContent >
121+ </ Card >
122+ )
123+ }
124+
58125const SortableTaskItem = ( { task, onSetUrgency } : { task : Task , onSetUrgency : ( taskId : string , urgency : TaskUrgency ) => void } ) => {
59126 const {
60127 attributes,
@@ -410,9 +477,10 @@ export default function ProjectWorkspacePage() {
410477 </ div >
411478
412479 < Tabs defaultValue = "tasks" >
413- < TabsList className = "grid w-full grid-cols-4 md:grid-cols-6 " >
480+ < TabsList className = "grid w-full grid-cols-5 md:grid-cols-7 " >
414481 < TabsTrigger value = "tasks" > < Milestone className = "mr-2" /> Tâches</ TabsTrigger >
415482 < TabsTrigger value = "documents" > < FileText className = "mr-2" /> Documents</ TabsTrigger >
483+ < TabsTrigger value = "execution" > < Terminal className = "mr-2" /> Exécution</ TabsTrigger >
416484 < TabsTrigger value = "codespace" > < Code className = "mr-2" /> CodeSpace</ TabsTrigger >
417485 < TabsTrigger value = "settings" > < Settings className = "mr-2" /> Équipe & Paramètres </ TabsTrigger >
418486 { project . isQuestProject && < TabsTrigger value = "quest" > < ShieldQuestion className = "mr-2" /> Cursus</ TabsTrigger > }
@@ -495,6 +563,10 @@ export default function ProjectWorkspacePage() {
495563 </ div >
496564 </ Card >
497565 </ TabsContent >
566+
567+ < TabsContent value = "execution" className = "mt-6" >
568+ < SimulatedExecution />
569+ </ TabsContent >
498570
499571 { project . isQuestProject && (
500572 < TabsContent value = "quest" className = "mt-6" >
@@ -629,4 +701,4 @@ export default function ProjectWorkspacePage() {
629701 ) ;
630702}
631703
632-
704+
0 commit comments