@@ -4,6 +4,9 @@ import { GenericListing, ColumnDef } from "@/mint/generic-listing";
44import { GenericEditor , Field } from "@/mint/generic-editor" ;
55import { Contest , mockContests } from "./mockData" ;
66import { useEffect , useState } from "react" ;
7+ import { useParams } from "next/navigation" ;
8+ import { useToast } from "@/hooks/use-toast" ;
9+ import { formatValidationErrors } from "@/utils/error" ;
710import { z } from "zod" ;
811
912const columns : ColumnDef < Contest > [ ] = [
@@ -53,38 +56,113 @@ const injectProblemsCount = (contests: Contest[]) => {
5356} ;
5457
5558export default function ContestsPage ( ) {
59+ const params = useParams ( ) ;
60+ const orgId = params . orgId as string ;
61+ const { toast } = useToast ( ) ;
62+
5663 const [ contests , setContests ] = useState < Contest [ ] > ( [ ] ) ;
5764 const [ selectedContest , setSelectedContest ] = useState < Contest | null > ( null ) ;
5865 const [ isEditorOpen , setIsEditorOpen ] = useState ( false ) ;
5966
6067 useEffect ( ( ) => {
61- setContests ( injectProblemsCount ( mockContests ) ) ;
62- } , [ ] ) ;
68+ const fetchContests = async ( ) => {
69+ try {
70+ const response = await fetch ( `/api/orgs/${ orgId } /contests` ) ;
71+ if ( ! response . ok ) {
72+ const errorData = await response . json ( ) . catch ( ( ) => ( { } ) ) ;
73+ throw new Error ( formatValidationErrors ( errorData ) ) ;
74+ }
75+ const data = await response . json ( ) ;
76+ setContests ( injectProblemsCount ( data ) ) ;
77+ } catch ( error ) {
78+ console . error ( "Error fetching contests:" , error ) ;
79+ toast ( {
80+ variant : "destructive" ,
81+ title : "Error" ,
82+ description : error instanceof Error ? error . message : "Failed to fetch contests" ,
83+ } ) ;
84+ // Fallback to mock data in case of error
85+ setContests ( injectProblemsCount ( mockContests ) ) ;
86+ }
87+ } ;
88+ fetchContests ( ) ;
89+ } , [ orgId , toast ] ) ;
6390
6491 const deleteContest = async ( contest : Contest ) => {
6592 try {
66- // Simulate API call
67- await new Promise ( ( resolve ) => setTimeout ( resolve , 500 ) ) ;
93+ const response = await fetch ( `/api/orgs/${ orgId } /contests/${ contest . nameId } ` , {
94+ method : "DELETE" ,
95+ } ) ;
96+
97+ if ( ! response . ok ) {
98+ const errorData = await response . json ( ) . catch ( ( ) => ( { } ) ) ;
99+ throw new Error ( formatValidationErrors ( errorData ) ) ;
100+ }
68101
69- // Update the state after successful API call
70102 setContests ( ( prevContests ) =>
71103 prevContests . filter ( ( c ) => c . id !== contest . id ) ,
72104 ) ;
105+ toast ( {
106+ title : "Success" ,
107+ description : "Contest deleted successfully" ,
108+ } ) ;
73109 return Promise . resolve ( ) ;
74110 } catch ( error ) {
111+ console . error ( "Error deleting contest:" , error ) ;
112+ toast ( {
113+ variant : "destructive" ,
114+ title : "Error" ,
115+ description : error instanceof Error ? error . message : "Failed to delete contest" ,
116+ } ) ;
75117 return Promise . reject ( error ) ;
76118 }
77119 } ;
78120
79121 const saveContest = async ( contest : Contest ) => {
80- if ( selectedContest ) {
81- // Update existing contest
82- setContests ( contests . map ( ( c ) => ( c . id === contest . id ? contest : c ) ) ) ;
83- } else {
84- // Add new contest
85- setContests ( [ ...contests , { ...contest , id : Date . now ( ) } ] ) ;
122+ try {
123+ const url = selectedContest
124+ ? `/api/orgs/${ orgId } /contests/${ contest . nameId } `
125+ : `/api/orgs/${ orgId } /contests` ;
126+
127+ const response = await fetch ( url , {
128+ method : selectedContest ? "PATCH" : "POST" ,
129+ headers : {
130+ "Content-Type" : "application/json" ,
131+ } ,
132+ body : JSON . stringify ( contest ) ,
133+ } ) ;
134+
135+ if ( ! response . ok ) {
136+ const errorData = await response . json ( ) . catch ( ( ) => ( { } ) ) ;
137+ throw new Error ( formatValidationErrors ( errorData ) ) ;
138+ }
139+
140+ const savedContest = await response . json ( ) ;
141+
142+ if ( selectedContest ) {
143+ setContests ( contests . map ( ( c ) => ( c . id === savedContest . id ? savedContest : c ) ) ) ;
144+ toast ( {
145+ title : "Success" ,
146+ description : "Contest updated successfully" ,
147+ } ) ;
148+ } else {
149+ setContests ( [ ...contests , savedContest ] ) ;
150+ toast ( {
151+ title : "Success" ,
152+ description : "Contest created successfully" ,
153+ } ) ;
154+ }
155+
156+ setIsEditorOpen ( false ) ;
157+ } catch ( error ) {
158+ console . error ( "Error saving contest:" , error ) ;
159+ toast ( {
160+ variant : "destructive" ,
161+ title : "Validation Error" ,
162+ description : error instanceof Error ? error . message : "Failed to save contest" ,
163+ } ) ;
164+ throw error ;
86165 }
87- setIsEditorOpen ( false ) ;
88166 } ;
89167
90168 return (
0 commit comments