@@ -7,28 +7,53 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
77import { Plus , Trash2 } from "lucide-react" ;
88import { useRouter } from "next/navigation" ;
99import { useToast } from "@/components/ui/use-toast" ;
10+ import {
11+ mockProblems ,
12+ Problem as ListProblem ,
13+ } from "@/app/[orgId]/problems/mockProblems" ;
1014
1115interface TestCase {
1216 input : string ;
13- expectedOutput : string ;
17+ output : string ;
18+ kind : "example" | "test" ;
1419}
1520
1621interface Problem {
17- id : string ;
22+ id ?: string ;
23+ code : string ;
1824 title : string ;
1925 description : string ;
26+ allowedLanguages : string [ ] ;
2027 testCases : TestCase [ ] ;
2128}
2229
23- export function AddProblem ( ) {
30+ interface ProblemEditorProps {
31+ problem ?: ListProblem | null ;
32+ onClose ?: ( ) => void ;
33+ onSave ?: ( problem : ListProblem ) => void ;
34+ }
35+
36+ export function ProblemEditor ( {
37+ problem,
38+ onClose,
39+ onSave,
40+ } : ProblemEditorProps ) {
2441 const router = useRouter ( ) ;
2542 const { toast } = useToast ( ) ;
2643 const [ problems , setProblems ] = useState < Problem [ ] > ( [
2744 {
28- id : "1" ,
29- title : "" ,
30- description : "" ,
31- testCases : [ { input : "" , expectedOutput : "" } ] ,
45+ id : problem ?. id ?. toString ( ) || "1" ,
46+ code : problem ?. nameId || "" ,
47+ title : problem ?. title || "" ,
48+ description : problem ?. description || "" ,
49+ allowedLanguages : problem ?. allowedLanguages || [
50+ "python" ,
51+ "javascript" ,
52+ "typescript" ,
53+ ] ,
54+ testCases : problem ?. testCases || [
55+ { input : "" , output : "" , kind : "example" } ,
56+ ] ,
3257 } ,
3358 ] ) ;
3459 const [ currentProblemIndex , setCurrentProblemIndex ] = useState ( 0 ) ;
@@ -41,7 +66,7 @@ export function AddProblem() {
4166 ...currentProblem ,
4267 testCases : [
4368 ...currentProblem . testCases ,
44- { input : "" , expectedOutput : "" } ,
69+ { input : "" , output : "" , kind : "example " } ,
4570 ] ,
4671 } ;
4772 setProblems ( updatedProblems ) ;
@@ -58,7 +83,7 @@ export function AddProblem() {
5883
5984 const updateTestCase = (
6085 index : number ,
61- field : "input" | "expectedOutput " ,
86+ field : "input" | "output" | "kind ",
6287 value : string ,
6388 ) => {
6489 const updatedProblems = [ ...problems ] ;
@@ -73,8 +98,8 @@ export function AddProblem() {
7398 } ;
7499
75100 const updateProblemField = (
76- field : "title" | "description" ,
77- value : string ,
101+ field : "code" | " title" | "description" | "allowedLanguages ",
102+ value : string | string [ ] ,
78103 ) => {
79104 const updatedProblems = [ ...problems ] ;
80105 updatedProblems [ currentProblemIndex ] = {
@@ -87,9 +112,11 @@ export function AddProblem() {
87112 const addNewProblem = ( ) => {
88113 const newProblem : Problem = {
89114 id : ( problems . length + 1 ) . toString ( ) ,
115+ code : "" ,
90116 title : "" ,
91117 description : "" ,
92- testCases : [ { input : "" , expectedOutput : "" } ] ,
118+ allowedLanguages : [ "python" , "javascript" , "typescript" ] ,
119+ testCases : [ { input : "" , output : "" , kind : "example" } ] ,
93120 } ;
94121 setProblems ( [ ...problems , newProblem ] ) ;
95122 setCurrentProblemIndex ( problems . length ) ;
@@ -115,9 +142,84 @@ export function AddProblem() {
115142 router . push ( "/contests" ) ;
116143 } ;
117144
145+ const handleSaveProblem = async ( ) => {
146+ try {
147+ // Validate required fields
148+ if ( ! currentProblem . title || ! currentProblem . description ) {
149+ toast ( {
150+ title : "Error" ,
151+ description : "Please fill in all required fields" ,
152+ variant : "destructive" ,
153+ } ) ;
154+ return ;
155+ }
156+
157+ // Validate test cases
158+ if ( currentProblem . testCases . some ( ( tc ) => ! tc . input || ! tc . output ) ) {
159+ toast ( {
160+ title : "Error" ,
161+ description : "Please fill in all test cases" ,
162+ variant : "destructive" ,
163+ } ) ;
164+ return ;
165+ }
166+
167+ // If editing an existing problem
168+ if ( problem ) {
169+ const updatedProblem : ListProblem = {
170+ ...problem ,
171+ title : currentProblem . title ,
172+ allowedLanguages : currentProblem . allowedLanguages ,
173+ } ;
174+ onSave ?.( updatedProblem ) ;
175+ onClose ?.( ) ;
176+ return ;
177+ }
178+
179+ // Creating a new problem
180+ const nameId = Math . random ( ) . toString ( 36 ) . substring ( 2 , 7 ) . toUpperCase ( ) ;
181+ const newProblem : ListProblem = {
182+ id : mockProblems . length + 1 ,
183+ nameId,
184+ title : currentProblem . title ,
185+ allowedLanguages : currentProblem . allowedLanguages ,
186+ createdAt : new Date ( ) . toISOString ( ) . split ( "T" ) [ 0 ] ,
187+ orgId : 1 ,
188+ } ;
189+
190+ mockProblems . push ( newProblem ) ;
191+
192+ toast ( {
193+ title : "Success!" ,
194+ description : "Problem saved successfully" ,
195+ } ) ;
196+
197+ // Get orgId from URL
198+ const pathSegments = window . location . pathname . split ( "/" ) ;
199+ const orgId = pathSegments [ 1 ] ;
200+
201+ // Redirect to problems page
202+ router . push ( `/${ orgId } /problems` ) ;
203+ } catch ( error ) {
204+ toast ( {
205+ title : "Error" ,
206+ description : "Failed to save problem" ,
207+ variant : "destructive" ,
208+ } ) ;
209+ }
210+ } ;
211+
118212 return (
119213 < div className = "min-h-screen bg-background text-foreground flex flex-col" >
120214 < div className = "flex-1 p-6" >
215+ < div className = "flex justify-end mb-4" >
216+ < Button
217+ onClick = { handleSaveProblem }
218+ className = "bg-primary hover:bg-primary/90 text-primary-foreground"
219+ >
220+ Save Problem
221+ </ Button >
222+ </ div >
121223 { /* <div className="flex justify-between items-center mb-6">
122224 <div className="flex gap-2">
123225 {problems.map((problem, index) => (
@@ -172,6 +274,22 @@ export function AddProblem() {
172274
173275 < TabsContent value = "problem" >
174276 < div className = "space-y-4" >
277+ < div >
278+ < label
279+ htmlFor = "code"
280+ className = "block text-sm font-medium mb-1"
281+ >
282+ Problem Code
283+ </ label >
284+ < Input
285+ id = "code"
286+ value = { currentProblem . code }
287+ onChange = { ( e ) => updateProblemField ( "code" , e . target . value ) }
288+ placeholder = "Enter problem code"
289+ className = "bg-muted border-border"
290+ />
291+ </ div >
292+
175293 < div >
176294 < label
177295 htmlFor = "title"
@@ -205,6 +323,27 @@ export function AddProblem() {
205323 className = "bg-muted border-border min-h-[200px]"
206324 />
207325 </ div >
326+
327+ < div >
328+ < label
329+ htmlFor = "allowedLanguages"
330+ className = "block text-sm font-medium mb-1"
331+ >
332+ Allowed Languages
333+ </ label >
334+ < Input
335+ id = "allowedLanguages"
336+ value = { currentProblem . allowedLanguages . join ( ", " ) }
337+ onChange = { ( e ) =>
338+ updateProblemField (
339+ "allowedLanguages" ,
340+ e . target . value . split ( ", " ) ,
341+ )
342+ }
343+ placeholder = "Enter allowed languages"
344+ className = "bg-muted border-border"
345+ />
346+ </ div >
208347 </ div >
209348 </ TabsContent >
210349
@@ -250,9 +389,9 @@ export function AddProblem() {
250389 </ label >
251390 < Textarea
252391 id = { `output-${ index } ` }
253- value = { testCase . expectedOutput }
392+ value = { testCase . output }
254393 onChange = { ( e ) =>
255- updateTestCase ( index , "expectedOutput " , e . target . value )
394+ updateTestCase ( index , "output " , e . target . value )
256395 }
257396 placeholder = "Enter expected output"
258397 className = "bg-muted-foreground/20 border-border"
0 commit comments