@@ -52,6 +52,7 @@ export class MemberSearchService {
5252 openToWork,
5353 recentlyActive,
5454 verifiedProfile,
55+ profileComplete,
5556 countries,
5657 sortBy = "matchIndex" ,
5758 sortOrder = "desc" ,
@@ -203,7 +204,7 @@ member_address AS (
203204 id DESC
204205)` ) ;
205206
206- // ------------------------------------------------- dynamic WHERE
207+ // ------------------------------------------------- dynamic WHERE (easy filters first)
207208 const where : string [ ] = [ `m.status = 'ACTIVE'` ] ;
208209
209210 if ( openToWork === true ) {
@@ -243,6 +244,75 @@ member_address AS (
243244 ) ;
244245 }
245246
247+ const whereClause = where . join ( " AND " ) ;
248+ ctes . push ( `filtered_members AS (
249+ SELECT m."userId" AS user_id
250+ FROM members.member m
251+ ${ skillJoin }
252+ WHERE ${ whereClause }
253+ )` ) ;
254+
255+ if ( profileComplete === true ) {
256+ ctes . push ( `profile_complete_filtered AS (
257+ SELECT fm.user_id
258+ FROM filtered_members fm
259+ INNER JOIN members.member m2 ON m2."userId" = fm.user_id
260+ WHERE m2.description IS NOT NULL
261+ AND btrim(m2.description) <> ''
262+ AND m2."homeCountryCode" IS NOT NULL
263+ AND EXISTS (
264+ SELECT 1
265+ FROM members."memberAddress" ma2
266+ WHERE ma2."userId" = m2."userId"
267+ AND ma2.city IS NOT NULL
268+ AND btrim(ma2.city) <> ''
269+ )
270+ AND EXISTS (
271+ SELECT 1
272+ FROM members."memberTraits" mt2
273+ INNER JOIN members."memberTraitWork" mw2 ON mw2."memberTraitId" = mt2.id
274+ WHERE mt2."userId" = m2."userId"
275+ )
276+ AND EXISTS (
277+ SELECT 1
278+ FROM members."memberTraits" mt2
279+ INNER JOIN members."memberTraitEducation" me2 ON me2."memberTraitId" = mt2.id
280+ WHERE mt2."userId" = m2."userId"
281+ )
282+ AND EXISTS (
283+ SELECT 1
284+ FROM members."memberTraits" mt2
285+ INNER JOIN members."memberTraitPersonalization" mtp2 ON mtp2."memberTraitId" = mt2.id
286+ WHERE mt2."userId" = m2."userId"
287+ AND mtp2.key = 'openToWork'
288+ AND mtp2.value IS NOT NULL
289+ AND (
290+ NOT (mtp2.value::jsonb ? 'availability')
291+ OR (
292+ mtp2.value::jsonb ? 'availability'
293+ AND mtp2.value::jsonb ? 'preferredRoles'
294+ AND jsonb_typeof(mtp2.value::jsonb -> 'preferredRoles') = 'array'
295+ AND jsonb_array_length(mtp2.value::jsonb -> 'preferredRoles') > 0
296+ )
297+ )
298+ )
299+ AND EXISTS (
300+ SELECT 1
301+ FROM skills.user_skill us2
302+ INNER JOIN skills.user_skill_display_mode usdm2 ON usdm2.id = us2.user_skill_display_mode_id
303+ WHERE us2.user_id = m2."userId"
304+ AND LOWER(usdm2.name) = 'principal'
305+ )
306+ AND EXISTS (
307+ SELECT 1
308+ FROM skills.user_skill us2
309+ INNER JOIN skills.user_skill_display_mode usdm2 ON usdm2.id = us2.user_skill_display_mode_id
310+ WHERE us2.user_id = m2."userId"
311+ AND LOWER(usdm2.name) = 'additional'
312+ )
313+ )` ) ;
314+ }
315+
246316 // Snapshot param count BEFORE adding pagination — count query stops here
247317 const filterParamCount = params . length ;
248318
@@ -251,12 +321,15 @@ member_address AS (
251321
252322 // ---------------------------------------------------------------- queries
253323 const ctesBlock = ctes . join ( ",\n" ) ;
254- const whereClause = where . join ( " AND " ) ;
255324 const direction = sortOrder === "asc" ? "ASC" : "DESC" ;
256325 const orderByClause =
257326 sortBy === "handle"
258327 ? `m.handle ${ direction } , "matchIndex" DESC NULLS LAST`
259328 : `"matchIndex" ${ direction } NULLS LAST, m.handle ASC` ;
329+ const profileCompleteJoin =
330+ profileComplete === true
331+ ? `INNER JOIN profile_complete_filtered pcf ON pcf.user_id = m."userId"`
332+ : "" ;
260333
261334 const dataQuery = `
262335WITH ${ ctesBlock }
@@ -278,18 +351,17 @@ SELECT
278351 ${ matchedSkillsExpr } AS "matchedSkills",
279352 ${ matchIndexExpr } AS "matchIndex"
280353FROM members.member m
354+ INNER JOIN filtered_members fm ON fm.user_id = m."userId"
355+ ${ profileCompleteJoin }
281356${ skillJoin }
282357LEFT JOIN member_address maddr ON maddr."userId" = m."userId"
283- WHERE ${ whereClause }
284358ORDER BY ${ orderByClause }
285359LIMIT ${ pLimit } OFFSET ${ pOffset } ` ;
286360
287361 const countQuery = `
288362WITH ${ ctesBlock }
289363SELECT COUNT(*)::integer AS total
290- FROM members.member m
291- ${ skillJoin }
292- WHERE ${ whereClause } ` ;
364+ FROM ${ profileComplete === true ? "profile_complete_filtered pcf" : "filtered_members fm" } ` ;
293365
294366 const [ rows , countRows ] = await Promise . all ( [
295367 this . db . query < RawMemberRow > ( dataQuery , params ) ,
0 commit comments