import { apiClient } from '../httpClient'; import { encodeHashIdSync } from '../toolsService'; import * as Models from './models'; /** * Utility helper to ensure URL parameters are encoded using the Hashids service */ export function hashParam(id: number | string | null | undefined): string { if (id === undefined || id === null || id === '') return ''; return encodeHashIdSync(id); } // ---------------------------------------------------------------------- // Users & Integration Endpoints // ---------------------------------------------------------------------- export const usersApi = { getUser: (userId: string) => apiClient.get(`/v1/api/users/${userId}`), getUsersPaged: (page: number, pageSize: number, filter?: Models.UserFilterRequest) => apiClient.post(`/v1/api/users/${page}/${pageSize}`, filter || {}), syncIntegration: (payload: any) => apiClient.post('/v1/api/integration/sync', payload), updateUserStatus: (userId: string, status: string | number) => apiClient.get(`/v1/api/users/${userId}/status/${status}`), }; // ---------------------------------------------------------------------- // Projects & Sub-resources Endpoints // ---------------------------------------------------------------------- export const projectsApi = { // Projects getProjects: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/projects', { params }), getProject: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}`), createProject: (payload: Models.CreateProjectRequest) => apiClient.post('/v1/api/projects', payload), updateProject: (payload: Models.UpdateProjectRequest) => apiClient.put('/v1/api/projects', payload), updateProjectStatus: (payload: Models.UpdateProjectStatusRequest) => apiClient.put('/v1/api/projects/status', payload), // Activities createActivity: (payload: Models.CreateActivityRequest) => apiClient.post('/v1/api/projects/activities', payload), getProjectActivities: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/activities`), getActivity: (activityId: string | number) => apiClient.get(`/v1/api/projects/activities/${hashParam(activityId)}`), // Beneficiaries createBeneficiary: (payload: Models.CreateBeneficiaryRequest) => apiClient.post('/v1/api/projects/beneficiaries', payload), updateBeneficiary: (payload: Models.UpdateBeneficiaryRequest) => apiClient.put('/v1/api/projects/beneficiaries', payload), getProjectBeneficiaries: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/beneficiaries`), getBeneficiary: (beneficiaryId: string | number) => apiClient.get(`/v1/api/projects/beneficiaries/${hashParam(beneficiaryId)}`), // Outcomes createOutcome: (payload: Models.CreateOutcomeRequest) => apiClient.post('/v1/api/projects/beneficiaries/outcomes', payload), updateOutcome: (payload: Models.UpdateOutcomeRequest) => apiClient.put('/v1/api/projects/outcomes', payload), getOutcome: (outcomeId: string | number) => apiClient.get(`/v1/api/projects/outcome/${hashParam(outcomeId)}`), getBeneficiaryOutcomes: (beneficiaryId: string | number) => apiClient.get(`/v1/api/projects/beneficiaries/${hashParam(beneficiaryId)}/outcomes`), // Change Requests createChangeRequest: (payload: Models.CreateChangeRequest) => apiClient.post('/v1/api/projects/changerequests', payload), updateChangeRequest: (payload: Models.UpdateChangeRequest) => apiClient.put('/v1/api/projects/changerequests', payload), getProjectChangeRequests: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/changerequests`), getChangeRequest: (changeRequestId: string | number) => apiClient.get(`/v1/api/projects/changerequests/${hashParam(changeRequestId)}`), // Compliance createComplianceItem: (payload: Models.CreateComplianceItemRequest) => apiClient.post('/v1/api/projects/complianceitems', payload), updateComplianceItem: (payload: Models.UpdateComplianceItemRequest) => apiClient.put('/v1/api/projects/complianceitems', payload), getProjectComplianceItems: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/complianceitems`), getComplianceItem: (complianceItemId: string | number) => apiClient.get(`/v1/api/projects/complianceitems/${hashParam(complianceItemId)}`), // Issues createIssue: (payload: Models.CreateIssueRequest) => apiClient.post('/v1/api/projects/issues', payload), updateIssue: (payload: Models.UpdateIssueRequest) => apiClient.put('/v1/api/projects/issues', payload), getProjectIssues: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/issues`), getIssue: (issueId: string | number) => apiClient.get(`/v1/api/projects/issues/${hashParam(issueId)}`), // Milestones getProjectMilestones: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/milestones`), getMilestone: (milestoneId: string | number) => apiClient.get(`/v1/api/projects/milestones/${hashParam(milestoneId)}`), getMilestonesPaged: (page: number, pageSize: number) => apiClient.get(`/v1/api/projects/milestones/${page}/${pageSize}`), updateMilestone: (payload: Models.UpdateMilestoneRequest) => apiClient.put('/v1/api/projects/milestone', payload), // Indicators & Risks & Site Visits getProjectIndicators: (projectId: string | number) => apiClient.get(`/v1/api/projects/indicators/project/${hashParam(projectId)}`), getProjectRisks: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/risks`), getProjectSiteVisits: (projectId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(projectId)}/sitevisits`), getSiteVisit: (siteVisitId: string | number) => apiClient.get(`/v1/api/projects/sitevisits/${hashParam(siteVisitId)}`), createSiteVisit: (payload: Models.CreateSiteVisitRequest) => apiClient.post('/v1/api/projects/sitevisits', payload), updateSiteVisit: (payload: Models.UpdateSiteVisitRequest) => apiClient.put('/v1/api/projects/sitevisits', payload), // Programmes under projects createProgramme: (payload: Models.CreateProgrammeRequest) => apiClient.post('/v1/api/projects/programme', payload), updateProgramme: (payload: Models.UpdateProgrammeRequest) => apiClient.put('/v1/api/projects/programme', payload), getProgrammeProjects: (programmeId: string | number) => apiClient.get(`/v1/api/projects/${hashParam(programmeId)}/programme`), getProgrammeById: (programmeId: string | number) => apiClient.get(`/v1/api/projects/programme/${hashParam(programmeId)}`), getProgrammesPaged: (page: number, pageSize: number) => apiClient.get(`/v1/api/projects/programme/${page}/${pageSize}`), }; // ---------------------------------------------------------------------- // Grants Endpoints // ---------------------------------------------------------------------- export const grantsApi = { // Awards createAward: (payload: Models.CreateAwardRequest) => apiClient.post('/v1/api/grants/awards', payload), getAwards: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/grants/awards', { params }), getAward: (awardId: string | number) => apiClient.get(`/v1/api/grants/awards/${hashParam(awardId)}`), // Budgets createBudget: (payload: Models.CreateBudgetRequest) => apiClient.post('/v1/api/grants/budgets', payload), getBudgets: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/grants/budgets', { params }), updateBudget: (payload: Models.UpdateBudgetRequest) => apiClient.put('/v1/api/grants/budgets', payload), getBudget: (budgetId: string | number) => apiClient.get(`/v1/api/grants/budgets/${hashParam(budgetId)}`), // Contracts createContract: (payload: Models.CreateContractRequest) => apiClient.post('/v1/api/grants/contracts', payload), getContracts: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/grants/contracts', { params }), updateContract: (payload: Models.UpdateContractRequest) => apiClient.put('/v1/api/grants/contracts', payload), executeContract: (payload: Models.ExecuteContractRequest) => apiClient.post('/v1/api/grants/contracts/execute', payload), getContract: (contractId: string | number) => apiClient.get(`/v1/api/grants/contracts/${hashParam(contractId)}`), uploadContractFile: (contractId: string | number, formData: FormData) => apiClient.post(`/v1/api/grants/contracts/${hashParam(contractId)}`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }), getContractSecureLink: (contractId: string | number) => apiClient.get<{ url: string }>(`/v1/api/grants/contracts/${hashParam(contractId)}/securelink`), }; // ---------------------------------------------------------------------- // Governance Endpoints // ---------------------------------------------------------------------- export const governanceApi = { getDashboard: () => apiClient.get('/v1/api/governance/dashboard'), getAuditLogs: (payload?: any) => apiClient.post('/v1/api/governance/auditlog', payload || {}), // Instruments createInstrument: (payload: Models.CreateInstrumentRequest) => apiClient.post('/v1/api/governance/instruments', payload), updateInstrument: (payload: Models.UpdateInstrumentRequest) => apiClient.put('/v1/api/governance/instruments', payload), getProgrammeInstruments: (programmeId: string | number) => apiClient.get(`/v1/api/governance/instruments/${hashParam(programmeId)}`), // Organisations createOrganisation: (payload: Models.CreateOrganisationRequest) => apiClient.post('/v1/api/governance/organisations', payload), getOrganisations: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/governance/organisations', { params }), updateOrganisation: (payload: Models.UpdateOrganisationRequest) => apiClient.put('/v1/api/governance/organisations', payload), getOrganisation: (organisationId: string | number) => apiClient.get(`/v1/api/governance/organisations/${hashParam(organisationId)}`), getOrganisationPortfolios: (organisationId: string | number) => apiClient.get(`/v1/api/governance/organisations/${hashParam(organisationId)}/portfolio`), createOrganisationPortfolio: (payload: Models.CreatePortfolioRequest) => apiClient.post('/v1/api/governance/organisations/portfolio', payload), updateOrganisationPortfolio: (payload: Models.UpdatePortfolioRequest) => apiClient.put('/v1/api/governance/organisations/portfolio', payload), getOrganisationsPortfoliosList: (payload?: any) => apiClient.post('/v1/api/governance/organisations/portfolios', payload || {}), // Portfolios getPortfolio: (portfolioId: string | number) => apiClient.get(`/v1/api/governance/portfolios/${hashParam(portfolioId)}`), getPortfolioValue: (portfolioId: string | number) => apiClient.get<{ value: number }>(`/v1/api/governance/portfolios/${hashParam(portfolioId)}/value`), getPortfolioProgrammes: (portfolioId: string | number) => apiClient.get(`/v1/api/governance/portfolios/${hashParam(portfolioId)}/programmes`), // Programmes under governance getProgrammesByPortfolio: (portfolioId: string | number) => apiClient.get(`/v1/api/governance/programmes/${hashParam(portfolioId)}`), getProgrammeValue: (programmeId: string | number) => apiClient.get<{ value: number }>(`/v1/api/governance/programmes/${hashParam(programmeId)}/value`), // Tenants createTenant: (payload: Models.CreateTenantRequest) => apiClient.post('/v1/api/governance/tenants', payload), getTenants: () => apiClient.get('/v1/api/governance/tenants'), updateTenant: (payload: Models.UpdateTenantRequest) => apiClient.put('/v1/api/governance/tenants', payload), getTenant: (tenantId: string | number) => apiClient.get(`/v1/api/governance/tenants/${hashParam(tenantId)}`), }; // ---------------------------------------------------------------------- // Execution Endpoints // ---------------------------------------------------------------------- export const executionApi = { // Disbursements getDisbursements: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/execution/disbursements', { params }), getDisbursement: (disbursementId: string | number) => apiClient.get(`/v1/api/execution/disbursements/${hashParam(disbursementId)}`), createDisbursement: (payload: Models.CreateDisbursementRequest) => apiClient.post('/v1/api/execution/disbursements', payload), updateDisbursement: (payload: Models.UpdateDisbursementRequest) => apiClient.put('/v1/api/execution/disbursements', payload), approveDisbursement: (disbursementId: string | number) => apiClient.post(`/v1/api/execution/disbursements/${hashParam(disbursementId)}/approve`), // Risks getRisks: (params?: { page?: number; pageSize?: number }) => apiClient.get('/v1/api/execution/risks', { params }), getRisk: (riskId: string | number) => apiClient.get(`/v1/api/execution/risks/${hashParam(riskId)}`), createRisk: (payload: Models.CreateRiskRequest) => apiClient.post('/v1/api/execution/risks', payload), updateRisk: (payload: Models.UpdateRiskRequest) => apiClient.put('/v1/api/execution/risks', payload), // Rules getRule: (ruleId: string | number) => apiClient.get(`/v1/api/execution/rules/${hashParam(ruleId)}`), createRule: (payload: Models.CreateRuleRequest) => apiClient.post('/v1/api/execution/rules', payload), updateRule: (payload: Models.UpdateRuleRequest) => apiClient.put('/v1/api/execution/rules', payload), getProgrammeRules: (payload?: any) => apiClient.post('/v1/api/execution/programmes/rules', payload || {}), }; // ---------------------------------------------------------------------- // Evidence & M&E Endpoints // ---------------------------------------------------------------------- export const evidenceApi = { // Evidence files & records createEvidenceFile: (payload: FormData | any) => { const isFormData = typeof FormData !== 'undefined' && payload instanceof FormData; return apiClient.put('/v1/api/evidence/file', payload, { headers: isFormData ? { 'Content-Type': 'multipart/form-data' } : undefined, }); }, updateEvidence: (payload: Models.UpdateEvidenceRequest) => apiClient.put('/v1/api/evidence', payload), getEvidence: (evidenceId: string | number) => apiClient.get(`/v1/api/evidence/${hashParam(evidenceId)}`), getEvidenceFilesPaged: (page: number, pageSize: number) => apiClient.get(`/v1/api/evidence/files/${page}/${pageSize}`), getEvidenceSecureLink: (evidenceId: string | number) => apiClient.get<{ url: string }>(`/v1/api/evidence/${hashParam(evidenceId)}/securelink`), getMilestoneEvidence: (milestoneId: string | number) => apiClient.get(`/v1/api/evidence/milestone/${hashParam(milestoneId)}`), getProjectEvidence: (projectId: string | number) => apiClient.get(`/v1/api/evidence/${hashParam(projectId)}`), createMilestoneRequest: (payload: Models.CreateMilestoneRequest) => apiClient.post('/v1/api/evidence/milestones', payload), // Indicators createIndicator: (payload: Models.CreateIndicatorRequest) => apiClient.post('/v1/api/evidence/indicators', payload), getIndicator: (indicatorId: string | number) => apiClient.get(`/v1/api/evidence/indicators/${hashParam(indicatorId)}`), getIndicatorsPaged: (page: number, pageSize: number) => apiClient.get(`/v1/api/evidence/indicators/${page}/${pageSize}`), recordIndicatorActualAmount: (indicatorId: string | number, actualAmount: number) => apiClient.post(`/v1/api/evidence/indicators/${hashParam(indicatorId)}/actuals/${actualAmount}`), }; // ---------------------------------------------------------------------- // Communications Endpoints // ---------------------------------------------------------------------- export const communicationsApi = { sendInvite: (payload: Models.InviteRequest) => apiClient.post('/v1/api/communications/invites', payload), getInvitesPaged: (page: number, pageSize: number) => apiClient.get(`/v1/api/communications/invites/${page}/${pageSize}`), getApplicantData: (applicantUserId: string) => apiClient.get(`/v1/api/communications/applicants/${applicantUserId}/all`), getApplicantInvites: (applicantUserId: string) => apiClient.get(`/v1/api/communications/invites/${applicantUserId}`), getApplicantInvite: (applicantUserId: string) => apiClient.get(`/v1/api/communications/invites/applicants/${applicantUserId}`), getNotifications: (organisationId: string | number) => apiClient.get(`/v1/api/communications/notifications/${hashParam(organisationId)}`), }; // Consolidated export export const api = { users: usersApi, projects: projectsApi, grants: grantsApi, governance: governanceApi, execution: executionApi, evidence: evidenceApi, communications: communicationsApi, };