@@ -51,10 +51,19 @@ export const listUsers = query({
5151 page : v . optional ( v . number ( ) ) ,
5252 } ) ,
5353 emailFilter : v . optional ( v . string ( ) ) ,
54+ nameFilter : v . optional ( v . string ( ) ) ,
5455 capabilityFilter : v . optional (
55- v . union ( v . literal ( 'admin' ) , v . literal ( 'disableAds' ) , v . literal ( 'builder' ) )
56+ v . array (
57+ v . union (
58+ v . literal ( 'admin' ) ,
59+ v . literal ( 'disableAds' ) ,
60+ v . literal ( 'builder' )
61+ )
62+ )
5663 ) ,
64+ noCapabilitiesFilter : v . optional ( v . boolean ( ) ) ,
5765 adsDisabledFilter : v . optional ( v . boolean ( ) ) ,
66+ interestedInHidingAdsFilter : v . optional ( v . boolean ( ) ) ,
5867 } ,
5968 handler : async ( ctx , args ) => {
6069 // Validate admin capability
@@ -80,17 +89,40 @@ export const listUsers = query({
8089 candidates . sort ( ( a : any , b : any ) => b . _creationTime - a . _creationTime )
8190
8291 const filtered = candidates . filter ( ( user : any ) => {
83- if ( args . capabilityFilter ) {
92+ // Name filter (in-memory search on name and displayUsername)
93+ if ( args . nameFilter && args . nameFilter . length > 0 ) {
94+ const name = ( user . name || user . displayUsername || '' ) . toLowerCase ( )
95+ const searchTerm = args . nameFilter . toLowerCase ( )
96+ if ( ! name . includes ( searchTerm ) ) {
97+ return false
98+ }
99+ }
100+
101+ // No capabilities filter
102+ if ( args . noCapabilitiesFilter === true ) {
103+ if ( ! Array . isArray ( user . capabilities ) || user . capabilities . length > 0 ) {
104+ return false
105+ }
106+ }
107+
108+ if ( args . capabilityFilter && args . capabilityFilter . length > 0 ) {
84109 if (
85110 ! Array . isArray ( user . capabilities ) ||
86- ! user . capabilities . includes ( args . capabilityFilter )
111+ ! args . capabilityFilter . some ( ( cap ) => user . capabilities . includes ( cap ) )
87112 ) {
88113 return false
89114 }
90115 }
91116 if ( typeof args . adsDisabledFilter === 'boolean' ) {
92117 if ( Boolean ( user . adsDisabled ) !== args . adsDisabledFilter ) return false
93118 }
119+ if ( typeof args . interestedInHidingAdsFilter === 'boolean' ) {
120+ if (
121+ Boolean ( user . interestedInHidingAds ) !==
122+ args . interestedInHidingAdsFilter
123+ )
124+ return false
125+ }
94126 return true
95127 } )
96128
@@ -171,3 +203,23 @@ export const adminSetAdsDisabled = mutation({
171203 return { success : true }
172204 } ,
173205} )
206+
207+ // Set interest in hiding ads (for opt-in waitlist)
208+ export const setInterestedInHidingAds = mutation ( {
209+ args : {
210+ interested : v . boolean ( ) ,
211+ } ,
212+ handler : async ( ctx , args ) => {
213+ const user = await getCurrentUserConvex ( ctx )
214+ if ( ! user ) {
215+ throw new Error ( 'Not authenticated' )
216+ }
217+
218+ // Update user's interestedInHidingAds flag
219+ await ctx . db . patch ( user . userId as Id < 'users' > , {
220+ interestedInHidingAds : args . interested ,
221+ } )
222+
223+ return { success : true }
224+ } ,
225+ } )
0 commit comments