@@ -124,6 +124,16 @@ function AdminFreeAuditQueueContent({
124124 if ( offer ) {
125125 if ( offer . startsAt ) setStartsAt ( new Date ( offer . startsAt ) . toISOString ( ) . slice ( 0 , 16 ) ) ;
126126 if ( offer . endsAt ) setEndsAt ( new Date ( offer . endsAt ) . toISOString ( ) . slice ( 0 , 16 ) ) ;
127+ } else {
128+ // Set some defaults if no offer exists
129+ const tomorrow = new Date ( ) ;
130+ tomorrow . setDate ( tomorrow . getDate ( ) + 1 ) ;
131+ tomorrow . setHours ( 9 , 0 , 0 , 0 ) ;
132+ setStartsAt ( tomorrow . toISOString ( ) . slice ( 0 , 16 ) ) ;
133+
134+ const nextWeek = new Date ( tomorrow ) ;
135+ nextWeek . setDate ( nextWeek . getDate ( ) + 7 ) ;
136+ setEndsAt ( nextWeek . toISOString ( ) . slice ( 0 , 16 ) ) ;
127137 }
128138 } , [ offer ] ) ;
129139
@@ -148,8 +158,32 @@ function AdminFreeAuditQueueContent({
148158 }
149159 } ) ;
150160
151- const handleUpdateOffer = ( ) => {
152- updateOfferMutation . mutate ( { startsAt, endsAt } ) ;
161+ const createOfferMutation = useMutation ( {
162+ mutationFn : async ( values : { startsAt : string , endsAt : string } ) => {
163+ const res = await fetch ( `/api/admin/promo-offer` , {
164+ method : "POST" ,
165+ headers : { "Content-Type" : "application/json" } ,
166+ body : JSON . stringify ( values ) ,
167+ } ) ;
168+ if ( ! res . ok ) throw new Error ( "Failed to create offer" ) ;
169+ return res . json ( ) ;
170+ } ,
171+ onSuccess : ( ) => {
172+ toast ( { title : "Campaign Created" , description : "A new promo offer has been started." } ) ;
173+ queryClient . invalidateQueries ( { queryKey : [ "/api/admin/promo-offer" ] } ) ;
174+ queryClient . invalidateQueries ( { queryKey : [ "/api/public/promo-offer" ] } ) ;
175+ } ,
176+ onError : ( error : any ) => {
177+ toast ( { title : "Creation Failed" , description : error . message , variant : "destructive" } ) ;
178+ }
179+ } ) ;
180+
181+ const handleSaveOffer = ( ) => {
182+ if ( offer ) {
183+ updateOfferMutation . mutate ( { startsAt, endsAt } ) ;
184+ } else {
185+ createOfferMutation . mutate ( { startsAt, endsAt } ) ;
186+ }
153187 } ;
154188
155189 const requests = data ?. requests || [ ] ;
@@ -197,7 +231,7 @@ function AdminFreeAuditQueueContent({
197231 < div className = "flex items-center gap-2 text-sm text-muted-foreground" >
198232 < Loader2 className = "h-4 w-4 animate-spin" /> Loading campaign data...
199233 </ div >
200- ) : offer ? (
234+ ) : (
201235 < div className = "flex flex-col sm:flex-row items-end gap-4 max-w-2xl" >
202236 < div className = "space-y-1.5 w-full sm:w-auto flex-1" >
203237 < Label htmlFor = "startsAt" className = "text-xs" > Start Date & Time </ Label >
@@ -220,16 +254,18 @@ function AdminFreeAuditQueueContent({
220254 />
221255 </ div >
222256 < Button
223- onClick = { handleUpdateOffer }
224- disabled = { updateOfferMutation . isPending }
257+ onClick = { handleSaveOffer }
258+ disabled = { updateOfferMutation . isPending || createOfferMutation . isPending }
225259 className = "w-full sm:w-auto h-9"
226260 >
227- { updateOfferMutation . isPending ? < Loader2 className = "w-4 h-4 mr-2 animate-spin" /> : < Save className = "w-4 h-4 mr-2" /> }
228- Save Changes
261+ { updateOfferMutation . isPending || createOfferMutation . isPending ? (
262+ < Loader2 className = "w-4 h-4 mr-2 animate-spin" />
263+ ) : (
264+ < Save className = "w-4 h-4 mr-2" />
265+ ) }
266+ { offer ? "Save Changes" : "Create Campaign" }
229267 </ Button >
230268 </ div >
231- ) : (
232- < p className = "text-sm text-muted-foreground" > No active promo offer found. Please seed the database.</ p >
233269 ) }
234270 </ CardContent >
235271 </ Card >
0 commit comments