1- import { SQL , eq , inArray } from "drizzle-orm" ;
1+ import { SQL , inArray } from "drizzle-orm" ;
22
33import { authHelpers } from "~/authz/helpers" ;
44import { builder } from "~/builder" ;
55import {
66 ScheduleStatus ,
7+ SelectTicketSchema ,
78 selectCommunitySchema ,
89 selectGalleriesSchema ,
910 selectImagesSchema ,
@@ -16,7 +17,6 @@ import {
1617 selectUsersSchema ,
1718 ticketStatusEnum ,
1819 ticketVisibilityEnum ,
19- ticketsSchema ,
2020 usersSchema ,
2121} from "~/datasources/db/schema" ;
2222import { lower } from "~/datasources/db/shared" ;
@@ -342,76 +342,91 @@ export const EventLoadable = builder.loadableObject(EventRef, {
342342 return tags . map ( ( t ) => selectTagsSchema . parse ( t ) ) ;
343343 } ,
344344 } ) ,
345- tickets : t . field ( {
345+ tickets : t . loadableList ( {
346346 description :
347347 "List of tickets for sale or redemption for this event. (If you are looking for a user's tickets, use the usersTickets field)" ,
348- type : [ TicketRef ] ,
348+ type : TicketRef ,
349349 args : {
350350 input : t . arg ( {
351351 type : EventsTicketTemplateSearchInput ,
352352 required : false ,
353353 } ) ,
354354 } ,
355- resolve : async ( root , { input } , { DB , USER } ) => {
356- const wheres : SQL [ ] = [ ] ;
357-
358- wheres . push ( eq ( ticketsSchema . eventId , root . id ) ) ;
359-
360- // If the user is an admin, they can see all tickets, otherwise, only
361- // active tickets are shown.
362- let statusCheck : ( typeof ticketStatusEnum ) [ number ] [ ] = [ "active" ] ;
363- let visibilityCheck : ( typeof ticketVisibilityEnum ) [ number ] [ ] = [
364- "public" ,
365- ] ;
366-
367- if ( USER ) {
368- if ( USER . isSuperAdmin ) {
369- statusCheck = [ "active" , "inactive" ] ;
370-
371- visibilityCheck = [ "public" , "private" , "unlisted" ] ;
372- } else {
373- const isAdmin = await authHelpers . isAdminOfEventCommunity ( {
374- userId : USER . id ,
375- eventId : root . id ,
376- DB ,
377- } ) ;
378-
379- if ( isAdmin ) {
355+ byPath : true ,
356+ load : async ( eventsIds : string [ ] , context , args ) => {
357+ const { DB , USER } = context ;
358+ const { input } = args ;
359+
360+ const idToTicketsMap = new Map <
361+ string ,
362+ SelectTicketSchema [ ] | undefined
363+ > ( ) ;
364+
365+ const ticketsPromises = eventsIds . map ( async ( eventId ) => {
366+ // If the user is an admin, they can see all tickets, otherwise, only
367+ // active tickets are shown.
368+ let statusCheck : ( typeof ticketStatusEnum ) [ number ] [ ] = [ "active" ] ;
369+ let visibilityCheck : ( typeof ticketVisibilityEnum ) [ number ] [ ] = [
370+ "public" ,
371+ ] ;
372+
373+ if ( USER ) {
374+ if ( USER . isSuperAdmin ) {
380375 statusCheck = [ "active" , "inactive" ] ;
381376
382377 visibilityCheck = [ "public" , "private" , "unlisted" ] ;
378+ } else {
379+ const isAdmin = await authHelpers . isAdminOfEventCommunity ( {
380+ userId : USER . id ,
381+ eventId : eventId ,
382+ DB ,
383+ } ) ;
384+
385+ if ( isAdmin ) {
386+ statusCheck = [ "active" , "inactive" ] ;
387+
388+ visibilityCheck = [ "public" , "private" , "unlisted" ] ;
389+ }
383390 }
384391 }
385- }
386392
387- const coupon = input ?. coupon ?. length
388- ? await DB . query . couponsSchema . findFirst ( {
389- where : ( c , { eq, and } ) =>
390- and (
391- eq ( c . eventId , root . id ) ,
392- eq ( c . isActive , true ) ,
393- eq ( lower ( c . code ) , input . coupon ?. toLowerCase ( ) ?? "" ) ,
394- ) ,
395- columns : {
396- id : true ,
397- } ,
398- } )
399- : null ;
400-
401- const tickets = await ticketsFetcher . searchTickets ( {
402- DB ,
403- search : {
404- status : statusCheck ,
405- visibility : visibilityCheck ,
406- eventIds : [ root . id ] ,
407- tags : input ?. tags ? input . tags : undefined ,
408- couponId : coupon ?. id ,
409- } ,
410- sort : [ [ "createdAt" , "asc" ] ] ,
393+ const coupon = input ?. coupon ?. length
394+ ? await DB . query . couponsSchema . findFirst ( {
395+ where : ( c , { eq, and } ) =>
396+ and (
397+ eq ( c . eventId , eventId ) ,
398+ eq ( c . isActive , true ) ,
399+ eq ( lower ( c . code ) , input . coupon ?. toLowerCase ( ) ?? "" ) ,
400+ ) ,
401+ columns : {
402+ id : true ,
403+ } ,
404+ } )
405+ : null ;
406+
407+ const tickets = await ticketsFetcher . searchTickets ( {
408+ DB ,
409+ search : {
410+ status : statusCheck ,
411+ visibility : visibilityCheck ,
412+ eventIds : [ eventId ] ,
413+ tags : input ?. tags ? input . tags : undefined ,
414+ couponId : coupon ?. id ,
415+ } ,
416+ sort : [ [ "createdAt" , "asc" ] ] ,
417+ } ) ;
418+
419+ idToTicketsMap . set (
420+ eventId ,
421+ tickets . map ( ( t ) => selectTicketSchema . parse ( t ) ) ,
422+ ) ;
411423 } ) ;
412424
413- return tickets . map ( ( t ) => selectTicketSchema . parse ( t ) ) ;
425+ await Promise . all ( ticketsPromises ) ;
426+
427+ return eventsIds . map ( ( id ) => idToTicketsMap . get ( id ) || [ ] ) ;
414428 } ,
429+ resolve : ( root ) => root . id ,
415430 } ) ,
416431 schedules : t . field ( {
417432 type : [ ScheduleRef ] ,
0 commit comments