Refactored dashboard

This commit is contained in:
2026-09-29 11:41:14 +02:00
parent c805a31824
commit 8643b2625b
11 changed files with 11906 additions and 15 deletions
@@ -0,0 +1,425 @@
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 | number) =>
apiClient.get<Models.User>(`/v1/api/users/${hashParam(userId)}`),
getUsersPaged: (page: number, pageSize: number, filter?: Models.UserFilterRequest) =>
apiClient.post<Models.User[]>(`/v1/api/users/${page}/${pageSize}`, filter || {}),
syncIntegration: (payload: any) =>
apiClient.post<any>('/v1/api/integration/sync', payload),
updateUserStatus: (userId: string | number, status: string | number) =>
apiClient.get<any>(`/v1/api/users/${hashParam(userId)}/status/${status}`),
};
// ----------------------------------------------------------------------
// Projects & Sub-resources Endpoints
// ----------------------------------------------------------------------
export const projectsApi = {
// Projects
getProjects: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Project[]>('/v1/api/projects', { params }),
getProject: (projectId: string | number) =>
apiClient.get<Models.Project>(`/v1/api/projects/${hashParam(projectId)}`),
createProject: (payload: Models.CreateProjectRequest) =>
apiClient.post<Models.Project>('/v1/api/projects', payload),
updateProject: (payload: Models.UpdateProjectRequest) =>
apiClient.put<Models.Project>('/v1/api/projects', payload),
updateProjectStatus: (payload: Models.UpdateProjectStatusRequest) =>
apiClient.put<any>('/v1/api/projects/status', payload),
// Activities
createActivity: (payload: Models.CreateActivityRequest) =>
apiClient.post<Models.Activity>('/v1/api/projects/activities', payload),
getProjectActivities: (projectId: string | number) =>
apiClient.get<Models.Activity[]>(`/v1/api/projects/${hashParam(projectId)}/activities`),
getActivity: (activityId: string | number) =>
apiClient.get<Models.Activity>(`/v1/api/projects/activities/${hashParam(activityId)}`),
// Beneficiaries
createBeneficiary: (payload: Models.CreateBeneficiaryRequest) =>
apiClient.post<Models.Beneficiary>('/v1/api/projects/beneficiaries', payload),
updateBeneficiary: (payload: Models.UpdateBeneficiaryRequest) =>
apiClient.put<Models.Beneficiary>('/v1/api/projects/beneficiaries', payload),
getProjectBeneficiaries: (projectId: string | number) =>
apiClient.get<Models.Beneficiary[]>(`/v1/api/projects/${hashParam(projectId)}/beneficiaries`),
getBeneficiary: (beneficiaryId: string | number) =>
apiClient.get<Models.Beneficiary>(`/v1/api/projects/beneficiaries/${hashParam(beneficiaryId)}`),
// Outcomes
createOutcome: (payload: Models.CreateOutcomeRequest) =>
apiClient.post<Models.Outcome>('/v1/api/projects/beneficiaris/outcomes', payload),
updateOutcome: (payload: Models.UpdateOutcomeRequest) =>
apiClient.put<Models.Outcome>('/v1/api/projects/outcomes', payload),
getOutcome: (outcomeId: string | number) =>
apiClient.get<Models.Outcome>(`/v1/api/projects/outcomes/${hashParam(outcomeId)}`),
getBeneficiaryOutcomes: (beneficiaryId: string | number) =>
apiClient.get<Models.Outcome[]>(`/v1/api/projects/outcomes/${hashParam(beneficiaryId)}`),
// Change Requests
createChangeRequest: (payload: Models.CreateChangeRequest) =>
apiClient.post<Models.ChangeRequest>('/v1/api/projects/changerequests', payload),
updateChangeRequest: (payload: Models.UpdateChangeRequest) =>
apiClient.put<Models.ChangeRequest>('/v1/api/projects/changerequests', payload),
getProjectChangeRequests: (projectId: string | number) =>
apiClient.get<Models.ChangeRequest[]>(`/v1/api/projects/${hashParam(projectId)}/changerequests`),
getChangeRequest: (changeRequestId: string | number) =>
apiClient.get<Models.ChangeRequest>(`/v1/api/projects/changerequests/${hashParam(changeRequestId)}`),
// Compliance
createComplianceItem: (payload: Models.CreateComplianceItemRequest) =>
apiClient.post<Models.ComplianceItem>('/v1/api/projects/complianceitems', payload),
updateComplianceItem: (payload: Models.UpdateComplianceItemRequest) =>
apiClient.put<Models.ComplianceItem>('/v1/api/projects/complianceitems', payload),
getProjectComplianceItems: (projectId: string | number) =>
apiClient.get<Models.ComplianceItem[]>(`/v1/api/projects/${hashParam(projectId)}/complianceitems`),
getComplianceItem: (complianceItemId: string | number) =>
apiClient.get<Models.ComplianceItem>(`/v1/api/projects/complianceitems/${hashParam(complianceItemId)}`),
// Issues
createIssue: (payload: Models.CreateIssueRequest) =>
apiClient.post<Models.Issue>('/v1/api/projects/issues', payload),
updateIssue: (payload: Models.UpdateIssueRequest) =>
apiClient.put<Models.Issue>('/v1/api/projects/issues', payload),
getProjectIssues: (projectId: string | number) =>
apiClient.get<Models.Issue[]>(`/v1/api/projects/${hashParam(projectId)}/issues`),
getIssue: (issueId: string | number) =>
apiClient.get<Models.Issue>(`/v1/api/projects/issues/${hashParam(issueId)}`),
// Milestones
getProjectMilestones: (projectId: string | number) =>
apiClient.get<Models.Milestone[]>(`/v1/api/projects/${hashParam(projectId)}/milestones`),
getMilestone: (milestoneId: string | number) =>
apiClient.get<Models.Milestone>(`/v1/api/projects/milestones/${hashParam(milestoneId)}`),
getMilestonesPaged: (page: number, pageSize: number) =>
apiClient.get<Models.Milestone[]>(`/v1/api/projects/milestones/${page}/${pageSize}`),
updateMilestone: (payload: Models.UpdateMilestoneRequest) =>
apiClient.put<Models.Milestone>('/v1/api/projects/milestone', payload),
// Indicators & Risks & Site Visits
getProjectIndicators: (projectId: string | number) =>
apiClient.get<Models.Indicator[]>(`/v1/api/projects/indicators/project/${hashParam(projectId)}`),
getProjectRisks: (projectId: string | number) =>
apiClient.get<Models.Risk[]>(`/v1/api/projects/${hashParam(projectId)}/risks`),
getProjectSiteVisits: (projectId: string | number) =>
apiClient.get<Models.SiteVisit[]>(`/v1/api/projects/${hashParam(projectId)}/sitevisits`),
getSiteVisit: (siteVisitId: string | number) =>
apiClient.get<Models.SiteVisit>(`/v1/api/projects/sitevisits/${hashParam(siteVisitId)}`),
createSiteVisit: (payload: Models.CreateSiteVisitRequest) =>
apiClient.post<Models.SiteVisit>('/v1/api/projects/sitevisits', payload),
updateSiteVisit: (payload: Models.UpdateSiteVisitRequest) =>
apiClient.put<Models.SiteVisit>('/v1/api/projects/sitevisits', payload),
// Programmes under projects
createProgramme: (payload: Models.CreateProgrammeRequest) =>
apiClient.post<Models.Programme>('/v1/api/projects/programme', payload),
updateProgramme: (payload: Models.UpdateProgrammeRequest) =>
apiClient.put<Models.Programme>('/v1/api/projects/programme', payload),
getProgrammeProjects: (programmeId: string | number) =>
apiClient.get<Models.Project[]>(`/v1/api/projects/${hashParam(programmeId)}/programme`),
getProgrammeById: (programmeId: string | number) =>
apiClient.get<Models.Programme>(`/v1/api/projects/programme/${hashParam(programmeId)}`),
getProgrammesPaged: (page: number, pageSize: number) =>
apiClient.get<Models.Programme[]>(`/v1/api/projects/programme/${page}/${pageSize}`),
};
// ----------------------------------------------------------------------
// Grants Endpoints
// ----------------------------------------------------------------------
export const grantsApi = {
// Awards
createAward: (payload: Models.CreateAwardRequest) =>
apiClient.post<Models.Award>('/v1/api/grants/awards', payload),
getAwards: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Award[]>('/v1/api/grants/awards', { params }),
getAward: (awardId: string | number) =>
apiClient.get<Models.Award>(`/v1/api/grants/awards/${hashParam(awardId)}`),
// Budgets
createBudget: (payload: Models.CreateBudgetRequest) =>
apiClient.post<Models.Budget>('/v1/api/grants/budgets', payload),
getBudgets: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Budget[]>('/v1/api/grants/budgets', { params }),
updateBudget: (payload: Models.UpdateBudgetRequest) =>
apiClient.put<Models.Budget>('/v1/api/grants/budgets', payload),
getBudget: (budgetId: string | number) =>
apiClient.get<Models.Budget>(`/v1/api/grants/budgets/${hashParam(budgetId)}`),
// Contracts
createContract: (payload: Models.CreateContractRequest) =>
apiClient.post<Models.Contract>('/v1/api/grants/contracts', payload),
getContracts: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Contract[]>('/v1/api/grants/contracts', { params }),
updateContract: (payload: Models.UpdateContractRequest) =>
apiClient.put<Models.Contract>('/v1/api/grants/contracts', payload),
executeContract: (payload: Models.ExecuteContractRequest) =>
apiClient.post<any>('/v1/api/grants/contracts/execute', payload),
getContract: (contractId: string | number) =>
apiClient.get<Models.Contract>(`/v1/api/grants/contracts/${hashParam(contractId)}`),
uploadContractFile: (contractId: string | number, formData: FormData) =>
apiClient.post<any>(`/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<Models.Dashboard>('/v1/api/governance/dashboard'),
getAuditLogs: (payload?: any) =>
apiClient.post<Models.AuditLog[]>('/v1/api/governance/auditlog', payload || {}),
// Instruments
createInstrument: (payload: Models.CreateInstrumentRequest) =>
apiClient.post<Models.Instrument>('/v1/api/governance/instruments', payload),
updateInstrument: (payload: Models.UpdateInstrumentRequest) =>
apiClient.put<Models.Instrument>('/v1/api/governance/instruments', payload),
getProgrammeInstruments: (programmeId: string | number) =>
apiClient.get<Models.Instrument[]>(`/v1/api/governance/instruments/${hashParam(programmeId)}`),
// Organisations
createOrganisation: (payload: Models.CreateOrganisationRequest) =>
apiClient.post<Models.Organisation>('/v1/api/governance/organisations', payload),
getOrganisations: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Organisation[]>('/v1/api/governance/organisations', { params }),
updateOrganisation: (payload: Models.UpdateOrganisationRequest) =>
apiClient.put<Models.Organisation>('/v1/api/governance/organisations', payload),
getOrganisation: (organisationId: string | number) =>
apiClient.get<Models.Organisation>(`/v1/api/governance/organisations/${hashParam(organisationId)}`),
getOrganisationPortfolios: (organisationId: string | number) =>
apiClient.get<Models.Portfolio[]>(`/v1/api/governance/organisations/${hashParam(organisationId)}/portfolio`),
createOrganisationPortfolio: (payload: Models.CreatePortfolioRequest) =>
apiClient.post<Models.Portfolio>('/v1/api/governance/organisations/portfolio', payload),
updateOrganisationPortfolio: (payload: Models.UpdatePortfolioRequest) =>
apiClient.put<Models.Portfolio>('/v1/api/governance/organisations/portfolio', payload),
getOrganisationsPortfoliosList: (payload?: any) =>
apiClient.post<Models.Portfolio[]>('/v1/api/governance/organisations/portfolios', payload || {}),
// Portfolios
getPortfolio: (portfolioId: string | number) =>
apiClient.get<Models.Portfolio>(`/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<Models.Programme[]>(`/v1/api/governance/portfolios/${hashParam(portfolioId)}/programmes`),
// Programmes under governance
getProgrammesByPortfolio: (portfolioId: string | number) =>
apiClient.get<Models.Programme[]>(`/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<Models.Tenant>('/v1/api/governance/tenants', payload),
getTenants: () =>
apiClient.get<Models.Tenant[]>('/v1/api/governance/tenants'),
updateTenant: (payload: Models.UpdateTenantRequest) =>
apiClient.put<Models.Tenant>('/v1/api/governance/tenants', payload),
getTenant: (tenantId: string | number) =>
apiClient.get<Models.Tenant>(`/v1/api/governance/tenants/${hashParam(tenantId)}`),
};
// ----------------------------------------------------------------------
// Execution Endpoints
// ----------------------------------------------------------------------
export const executionApi = {
// Disbursements
getDisbursements: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Disbursement[]>('/v1/api/execution/disbursements', { params }),
getDisbursement: (disbursementId: string | number) =>
apiClient.get<Models.Disbursement>(`/v1/api/execution/disbursements/${hashParam(disbursementId)}`),
createDisbursement: (payload: Models.CreateDisbursementRequest) =>
apiClient.post<Models.Disbursement>('/v1/api/execution/disbursements', payload),
updateDisbursement: (payload: Models.UpdateDisbursementRequest) =>
apiClient.put<Models.Disbursement>('/v1/api/execution/disbursements', payload),
approveDisbursement: (disbursementId: string | number) =>
apiClient.post<any>(`/v1/api/execution/disbursements/${hashParam(disbursementId)}/approve`),
// Risks
getRisks: (params?: { page?: number; pageSize?: number }) =>
apiClient.get<Models.Risk[]>('/v1/api/execution/risks', { params }),
getRisk: (riskId: string | number) =>
apiClient.get<Models.Risk>(`/v1/api/execution/risks/${hashParam(riskId)}`),
createRisk: (payload: Models.CreateRiskRequest) =>
apiClient.post<Models.Risk>('/v1/api/execution/risks', payload),
updateRisk: (payload: Models.UpdateRiskRequest) =>
apiClient.put<Models.Risk>('/v1/api/execution/risks', payload),
// Rules
getRule: (ruleId: string | number) =>
apiClient.get<Models.Rule>(`/v1/api/execution/rules/${hashParam(ruleId)}`),
createRule: (payload: Models.CreateRuleRequest) =>
apiClient.post<Models.Rule>('/v1/api/execution/rules', payload),
updateRule: (payload: Models.UpdateRuleRequest) =>
apiClient.put<Models.Rule>('/v1/api/execution/rules', payload),
getProgrammeRules: (payload?: any) =>
apiClient.post<Models.Rule[]>('/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<Models.Evidence>('/v1/api/evidence/file', payload, {
headers: isFormData ? { 'Content-Type': 'multipart/form-data' } : undefined,
});
},
updateEvidence: (payload: Models.UpdateEvidenceRequest) =>
apiClient.put<Models.Evidence>('/v1/api/evidence', payload),
getEvidence: (evidenceId: string | number) =>
apiClient.get<Models.Evidence>(`/v1/api/evidence/${hashParam(evidenceId)}`),
getEvidenceFilesPaged: (page: number, pageSize: number) =>
apiClient.get<Models.Evidence[]>(`/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<Models.Evidence[]>(`/v1/api/evidence/milestone/${hashParam(milestoneId)}`),
getProjectEvidence: (projectId: string | number) =>
apiClient.get<Models.Evidence[]>(`/v1/api/evidence/${hashParam(projectId)}`),
createMilestoneRequest: (payload: Models.CreateMilestoneRequest) =>
apiClient.post<Models.Milestone>('/v1/api/evidence/milestones', payload),
// Indicators
createIndicator: (payload: Models.CreateIndicatorRequest) =>
apiClient.post<Models.Indicator>('/v1/api/evidence/indicators', payload),
getIndicator: (indicatorId: string | number) =>
apiClient.get<Models.Indicator>(`/v1/api/evidence/indicators/${hashParam(indicatorId)}`),
getIndicatorsPaged: (page: number, pageSize: number) =>
apiClient.get<Models.Indicator[]>(`/v1/api/evidence/indicators/${page}/${pageSize}`),
recordIndicatorActualAmount: (indicatorId: string | number, actualAmount: number) =>
apiClient.post<any>(`/v1/api/evidence/indicators/${hashParam(indicatorId)}/actuals/${actualAmount}`),
};
// ----------------------------------------------------------------------
// Communications Endpoints
// ----------------------------------------------------------------------
export const communicationsApi = {
sendInvite: (payload: Models.InviteRequest) =>
apiClient.post<Models.Invite>('/v1/api/communications/invites', payload),
getInvitesPaged: (page: number, pageSize: number) =>
apiClient.get<Models.Invite[]>(`/v1/api/communications/invites/${page}/${pageSize}`),
getApplicantInvites: (applicantUserId: string | number) =>
apiClient.get<Models.Invite[]>(`/v1/api/communications/invites/${hashParam(applicantUserId)}`),
getApplicantInvite: (applicantUserId: string | number) =>
apiClient.get<Models.Invite>(`/v1/api/communications/invites/applicants/${hashParam(applicantUserId)}`),
getNotifications: (organisationId: string | number) =>
apiClient.get<Models.Notification[]>(`/v1/api/communications/norifications/${hashParam(organisationId)}`),
};
// Consolidated export
export const api = {
users: usersApi,
projects: projectsApi,
grants: grantsApi,
governance: governanceApi,
execution: executionApi,
evidence: evidenceApi,
communications: communicationsApi,
};