11import { zodResolver } from '@hookform/resolvers/zod' ;
22import { Cross2Icon , PlusIcon } from '@radix-ui/react-icons' ;
3- import { useMutation } from '@tanstack/react-query' ;
3+ import { useMutation , useQueryClient } from '@tanstack/react-query' ;
44import { Loader2 } from 'lucide-react' ;
55import { type Dispatch , type FC , type SetStateAction , useState } from 'react' ;
66import { useForm } from 'react-hook-form' ;
@@ -39,54 +39,82 @@ import {
3939} from '@/components/ui/select' ;
4040import { Tabs , TabsContent , TabsList , TabsTrigger } from '@/components/ui/tabs' ;
4141import { Textarea } from '@/components/ui/textarea' ;
42+ import { adminAddQuestion , adminUpdateQuestion } from '@/services/question-service' ;
43+ import { useAuthedRoute } from '@/stores/auth-store' ;
4244import type { IGetQuestionDetailsResponse } from '@/types/question-types' ;
4345
4446type AdminEditFormProps = {
4547 isFormOpen : boolean ;
4648 setIsFormOpen : Dispatch < SetStateAction < boolean > > ;
4749 questionDetails : IGetQuestionDetailsResponse [ 'question' ] ;
50+ mode ?: 'create' | 'update' ;
4851} ;
4952
5053const formSchema = z . object ( {
5154 title : z . string ( ) . min ( 1 ) ,
5255 difficulty : z . enum ( [ 'Easy' , 'Medium' , 'Hard' ] ) ,
53- topic : z . string ( ) . min ( 1 ) . array ( ) . min ( 1 ) ,
56+ topics : z . string ( ) . min ( 1 ) . array ( ) . min ( 1 ) ,
5457 description : z . string ( ) . min ( 1 ) ,
5558} ) ;
5659
5760export const AdminEditForm : FC < AdminEditFormProps > = ( {
5861 questionDetails,
5962 isFormOpen,
6063 setIsFormOpen,
64+ mode = 'update' ,
6165} ) => {
66+ const { userId } = useAuthedRoute ( ) ;
6267 const [ addedTopic , setAddedTopic ] = useState ( '' ) ;
63- const {
64- mutate : sendUpdate ,
65- isPending,
66- isSuccess,
67- } = useMutation ( {
68- mutationFn : async ( values : z . infer < typeof formSchema > ) => { } ,
69- } ) ;
70-
7168 const form = useForm < z . infer < typeof formSchema > > ( {
7269 resolver : zodResolver ( formSchema ) ,
7370 defaultValues : {
7471 ...questionDetails ,
72+ topics : questionDetails . topic ,
7573 description : questionDetails . description ,
7674 difficulty : questionDetails . difficulty as z . infer < typeof formSchema > [ 'difficulty' ] ,
7775 } ,
7876 mode : 'onSubmit' ,
7977 } ) ;
8078
79+ const queryClient = useQueryClient ( ) ;
80+ const {
81+ mutate : sendUpdate ,
82+ isPending,
83+ isSuccess,
84+ } = useMutation ( {
85+ mutationFn : ( values : z . infer < typeof formSchema > ) => {
86+ return mode === 'update'
87+ ? adminUpdateQuestion ( { ...values , questionId : Number . parseInt ( questionDetails . id ! ) } )
88+ : adminAddQuestion ( values ) ;
89+ } ,
90+ onSuccess : ( ) => {
91+ form . reset ( ) ;
92+
93+ if ( mode === 'update' ) {
94+ queryClient . refetchQueries ( {
95+ queryKey : [ 'qn' , 'details' , Number . parseInt ( questionDetails . id ! ) ] ,
96+ } ) ;
97+ } else {
98+ queryClient . refetchQueries ( {
99+ queryKey : [ 'questions' , userId ] ,
100+ } ) ;
101+ }
102+
103+ setTimeout ( ( ) => {
104+ setIsFormOpen ( false ) ;
105+ } , 500 ) ;
106+ } ,
107+ } ) ;
108+
81109 const onSubmit = ( formValues : z . infer < typeof formSchema > ) => {
82110 sendUpdate ( formValues ) ;
83111 } ;
84112
85113 const addTopic = ( topic : string ) => {
86- const val = new Set ( form . getValues ( 'topic ' ) . map ( ( v ) => v . toLowerCase ( ) ) ) ;
114+ const val = new Set ( form . getValues ( 'topics ' ) . map ( ( v ) => v . toLowerCase ( ) ) ) ;
87115 val . add ( topic . toLowerCase ( ) ) ;
88116 form . setValue (
89- 'topic ' ,
117+ 'topics ' ,
90118 Array . from ( val ) . map ( ( v ) => v . replace ( / ^ [ a - z ] / , ( c ) => c . toUpperCase ( ) ) )
91119 ) ;
92120 } ;
@@ -96,7 +124,9 @@ export const AdminEditForm: FC<AdminEditFormProps> = ({
96124 < Dialog open = { isFormOpen } onOpenChange = { setIsFormOpen } >
97125 < DialogContent className = 'border-border flex h-dvh w-dvw max-w-screen-lg flex-col' >
98126 < DialogHeader className = '' >
99- < DialogTitle className = 'text-primary' > Edit Question Details</ DialogTitle >
127+ < DialogTitle className = 'text-primary' >
128+ { mode === 'update' ? 'Edit Question Details' : 'Add a question' }
129+ </ DialogTitle >
100130 </ DialogHeader >
101131 < DialogDescription className = 'h-full' >
102132 < Form { ...form } >
@@ -148,7 +178,7 @@ export const AdminEditForm: FC<AdminEditFormProps> = ({
148178 />
149179 < FormField
150180 control = { form . control }
151- name = 'topic '
181+ name = 'topics '
152182 render = { ( { field } ) => (
153183 < FormItem className = 'flex flex-col gap-1 sm:col-span-2' >
154184 < div className = 'flex items-end gap-2' >
@@ -189,7 +219,7 @@ export const AdminEditForm: FC<AdminEditFormProps> = ({
189219 className = ''
190220 disabled = { isPending }
191221 onClick = { ( ) => {
192- form . resetField ( 'topic ' ) ;
222+ form . resetField ( 'topics ' ) ;
193223 } }
194224 size = 'sm'
195225 >
@@ -211,7 +241,7 @@ export const AdminEditForm: FC<AdminEditFormProps> = ({
211241 }
212242
213243 form . setValue (
214- 'topic ' ,
244+ 'topics ' ,
215245 field . value . filter ( ( _value , idx ) => idx !== index )
216246 ) ;
217247 } }
@@ -257,7 +287,7 @@ export const AdminEditForm: FC<AdminEditFormProps> = ({
257287 < Markdown
258288 rehypePlugins = { [ rehypeKatex ] }
259289 remarkPlugins = { [ remarkMath , remarkGfm ] }
260- className = 'prose prose-neutral text-card-foreground prose-strong:text-card-foreground leading-normal'
290+ className = 'prose prose-neutral text-card-foreground prose-strong:text-card-foreground prose-pre:bg-secondary prose-pre:text-secondary-foreground leading-normal'
261291 components = { {
262292 code : ( { children, className, ...rest } ) => {
263293 return (
0 commit comments