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