@@ -182,6 +182,15 @@ export interface GQLOpportunityPreviewConnection {
182182 result : GQLOpportunityPreviewResult ;
183183}
184184
185+ export interface GQLOpportunityStats {
186+ matched : number ;
187+ reached : number ;
188+ considered : number ;
189+ decided : number ;
190+ forReview : number ;
191+ introduced : number ;
192+ }
193+
185194export const typeDefs = /* GraphQL */ `
186195 ${ toGQLEnum ( OpportunityMatchStatus , 'OpportunityMatchStatus' ) }
187196 ${ toGQLEnum ( OrganizationLinkType , 'OrganizationLinkType' ) }
@@ -477,6 +486,38 @@ export const typeDefs = /* GraphQL */ `
477486 result: OpportunityPreviewResult
478487 }
479488
489+ type OpportunityStats {
490+ """
491+ Mock value for matched candidates
492+ """
493+ matched: Int!
494+
495+ """
496+ Total count of all matches regardless of status
497+ """
498+ reached: Int!
499+
500+ """
501+ Count of matches that are not pending (all statuses except pending)
502+ """
503+ considered: Int!
504+
505+ """
506+ Count of candidate_rejected matches
507+ """
508+ decided: Int!
509+
510+ """
511+ Count of candidate_accepted matches
512+ """
513+ forReview: Int!
514+
515+ """
516+ Count of recruiter_accepted matches
517+ """
518+ introduced: Int!
519+ }
520+
480521 extend type Query {
481522 """
482523 Get the public information about a Opportunity listing
@@ -575,6 +616,16 @@ export const typeDefs = /* GraphQL */ `
575616 """
576617 opportunityId: ID
577618 ): OpportunityPreviewConnection!
619+
620+ """
621+ Get statistics for an opportunity's matches
622+ """
623+ opportunityStats(
624+ """
625+ Id of the Opportunity
626+ """
627+ opportunityId: ID!
628+ ): OpportunityStats! @auth
578629 }
579630
580631 input SalaryExpectationInput {
@@ -1332,6 +1383,75 @@ export const resolvers: IResolvers<unknown, BaseContext> = traceResolvers<
13321383 } ,
13331384 } ;
13341385 } ,
1386+ opportunityStats : async (
1387+ _ ,
1388+ { opportunityId } : { opportunityId : string } ,
1389+ ctx : AuthContext ,
1390+ ) : Promise < GQLOpportunityStats > => {
1391+ // Verify the user has access to this opportunity
1392+ await ensureOpportunityPermissions ( {
1393+ con : ctx . con . manager ,
1394+ userId : ctx . userId ,
1395+ opportunityId,
1396+ permission : OpportunityPermissions . UpdateState ,
1397+ isTeamMember : ctx . isTeamMember ,
1398+ } ) ;
1399+
1400+ const result = await queryReadReplica ( ctx . con , ( { queryRunner } ) =>
1401+ queryRunner . manager
1402+ . getRepository ( OpportunityMatch )
1403+ . createQueryBuilder ( 'match' )
1404+ . select ( 'COUNT(*)' , 'reached' )
1405+ . addSelect (
1406+ `COUNT(CASE WHEN match.status != :pending THEN 1 END)` ,
1407+ 'considered' ,
1408+ )
1409+ . addSelect (
1410+ `COUNT(CASE WHEN match.status = :candidateRejected THEN 1 END)` ,
1411+ 'decided' ,
1412+ )
1413+ . addSelect (
1414+ `COUNT(CASE WHEN match.status = :candidateAccepted THEN 1 END)` ,
1415+ 'forReview' ,
1416+ )
1417+ . addSelect (
1418+ `COUNT(CASE WHEN match.status = :recruiterAccepted THEN 1 END)` ,
1419+ 'introduced' ,
1420+ )
1421+ . where ( 'match.opportunityId = :opportunityId' , { opportunityId } )
1422+ . setParameter ( 'pending' , OpportunityMatchStatus . Pending )
1423+ . setParameter (
1424+ 'candidateRejected' ,
1425+ OpportunityMatchStatus . CandidateRejected ,
1426+ )
1427+ . setParameter (
1428+ 'candidateAccepted' ,
1429+ OpportunityMatchStatus . CandidateAccepted ,
1430+ )
1431+ . setParameter (
1432+ 'recruiterAccepted' ,
1433+ OpportunityMatchStatus . RecruiterAccepted ,
1434+ )
1435+ . getRawOne < {
1436+ reached : string ;
1437+ considered : string ;
1438+ decided : string ;
1439+ forReview : string ;
1440+ introduced : string ;
1441+ } > ( ) ,
1442+ ) ;
1443+
1444+ // Get counts per status using SQL aggregation
1445+
1446+ return {
1447+ matched : 12_000 , // Mock value as requested
1448+ reached : parseInt ( result ?. reached || '0' , 10 ) ,
1449+ considered : parseInt ( result ?. considered || '0' , 10 ) ,
1450+ decided : parseInt ( result ?. decided || '0' , 10 ) ,
1451+ forReview : parseInt ( result ?. forReview || '0' , 10 ) ,
1452+ introduced : parseInt ( result ?. introduced || '0' , 10 ) ,
1453+ } ;
1454+ } ,
13351455 } ,
13361456 Mutation : {
13371457 updateCandidatePreferences : async (
0 commit comments