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,
};
@@ -0,0 +1,62 @@
import { ProblemDetails } from './models';
/**
* Extracts comma-delimited error messages from the ProblemDetails `detail` field
* or falls back to message/title/string.
*/
export function extractApiErrors(error: unknown): string[] {
if (!error) {
return ['An unknown error occurred.'];
}
// Handle Axios / Fetch response error structures
const axiosError = error as any;
const responseData: ProblemDetails | string | undefined = axiosError?.response?.data || axiosError?.data;
if (responseData) {
if (typeof responseData === 'object') {
if (responseData.detail && typeof responseData.detail === 'string') {
const parsed = responseData.detail
.split(',')
.map((item) => item.trim())
.filter((item) => item.length > 0);
if (parsed.length > 0) return parsed;
}
if (responseData.title && typeof responseData.title === 'string') {
return [responseData.title.trim()];
}
if ((responseData as any).message && typeof (responseData as any).message === 'string') {
return [(responseData as any).message.trim()];
}
} else if (typeof responseData === 'string' && responseData.trim()) {
return [responseData.trim()];
}
}
if (typeof error === 'object' && error !== null) {
if ('detail' in error && typeof (error as any).detail === 'string') {
const parsed = (error as any).detail
.split(',')
.map((item: string) => item.trim())
.filter((item: string) => item.length > 0);
if (parsed.length > 0) return parsed;
}
if ('message' in error && typeof (error as any).message === 'string') {
return [(error as any).message.trim()];
}
}
if (typeof error === 'string') {
return [error.trim()];
}
return ['An unexpected error occurred while communicating with the server.'];
}
/**
* Returns a formatted single message from the extracted comma-delimited errors.
*/
export function formatApiErrorMessage(error: unknown): string {
const errors = extractApiErrors(error);
return errors.join('\n• ');
}
@@ -0,0 +1,3 @@
export * from './models';
export * from './errorHelper';
export * from './endpoints';
@@ -0,0 +1,692 @@
/**
* OpenAPI TypeScript Models for PostFundManagement.Api v1
* Synchronized from https://api.ifri.khongisa.co.za/openapi/v1/
*/
export interface ProblemDetails {
type?: string | null;
title?: string | null;
status?: number | string | null;
detail?: string | null;
instance?: string | null;
[key: string]: any;
}
export type ActivityStatus = 0 | 1 | 2 | 3 | 4 | 'Planned' | 'InProgress' | 'Completed' | 'Delayed' | 'Cancelled' | number | string;
export type ApprovalStatus = 0 | 1 | 2 | 3 | 'Draft' | 'PendingApproval' | 'Approved' | 'Rejected' | number | string;
export type ContractStatus = 0 | 1 | 2 | 3 | 4 | 'Draft' | 'Active' | 'Executed' | 'Terminated' | 'Expired' | number | string;
export type EvidenceType = 0 | 1 | 2 | 3 | 4 | 5 | 'Document' | 'Invoice' | 'Receipt' | 'SitePhoto' | 'Report' | 'Other' | number | string;
export type IndustrySector = number | string;
export type NotificationPlatform = 0 | 1 | 2 | 'Email' | 'SMS' | 'InApp' | number | string;
export type NotificationStatus = 0 | 1 | 2 | 3 | 'Queued' | 'Sent' | 'Failed' | 'Delivered' | number | string;
export type OrganisationType = 0 | 1 | 2 | 3 | 'Grantee' | 'Funder' | 'Partner' | 'Auditor' | number | string;
export type Priority = 0 | 1 | 2 | 3 | 'Low' | 'Medium' | 'High' | 'Critical' | number | string;
export type ProjectType = 0 | 1 | 2 | 3 | 'Grant' | 'Loan' | 'Equity' | 'Hybrid' | number | string;
export type RiskImpact = 0 | 1 | 2 | 3 | 'Low' | 'Medium' | 'High' | 'Critical' | number | string;
export type RiskLikelihood = 0 | 1 | 2 | 3 | 'Rare' | 'Unlikely' | 'Possible' | 'Likely' | number | string;
export type UnitOfMeasure = number | string;
export interface Pagination {
page?: number;
pageSize?: number;
totalRecords?: number;
totalPages?: number;
}
export interface User {
id?: string;
sub?: string;
email?: string;
name?: string;
role?: string;
tenant?: string;
tenant_id?: number | string;
status?: string | number;
createdAt?: string;
updatedAt?: string;
[key: string]: any;
}
export interface UserFilterRequest {
email?: string;
name?: string;
role?: string;
status?: string;
}
export interface Activity {
id?: string | number;
projectId?: string | number;
title?: string;
description?: string;
status?: ActivityStatus;
startDate?: string;
endDate?: string;
progressPercentage?: number;
[key: string]: any;
}
export interface CreateActivityRequest {
projectId: string | number;
title: string;
description?: string;
startDate?: string;
endDate?: string;
status?: ActivityStatus;
}
export interface Beneficiary {
id?: string | number;
projectId?: string | number;
name?: string;
identificationNumber?: string;
contactNumber?: string;
email?: string;
location?: string;
gender?: string;
age?: number;
[key: string]: any;
}
export interface CreateBeneficiaryRequest {
projectId: string | number;
name: string;
identificationNumber?: string;
contactNumber?: string;
email?: string;
location?: string;
gender?: string;
age?: number;
}
export interface UpdateBeneficiaryRequest {
id: string | number;
projectId?: string | number;
name?: string;
identificationNumber?: string;
contactNumber?: string;
email?: string;
location?: string;
gender?: string;
age?: number;
}
export interface Outcome {
id?: string | number;
beneficiaryId?: string | number;
projectId?: string | number;
title?: string;
description?: string;
targetMetric?: string;
achievedMetric?: string;
dateRecorded?: string;
[key: string]: any;
}
export interface CreateOutcomeRequest {
beneficiaryId?: string | number;
projectId?: string | number;
title: string;
description?: string;
targetMetric?: string;
achievedMetric?: string;
dateRecorded?: string;
}
export interface UpdateOutcomeRequest {
id: string | number;
title?: string;
description?: string;
targetMetric?: string;
achievedMetric?: string;
}
export interface ChangeRequest {
id?: string | number;
projectId?: string | number;
reason?: string;
proposedChanges?: string;
requestedBy?: string;
status?: ApprovalStatus;
requestDate?: string;
approvalDate?: string;
[key: string]: any;
}
export interface CreateChangeRequest {
projectId: string | number;
reason: string;
proposedChanges: string;
}
export interface UpdateChangeRequest {
id: string | number;
reason?: string;
proposedChanges?: string;
status?: ApprovalStatus;
}
export interface ComplianceItem {
id?: string | number;
projectId?: string | number;
title?: string;
description?: string;
isCompliant?: boolean;
dueDate?: string;
verifiedAt?: string;
verifiedBy?: string;
[key: string]: any;
}
export interface CreateComplianceItemRequest {
projectId: string | number;
title: string;
description?: string;
dueDate?: string;
}
export interface UpdateComplianceItemRequest {
id: string | number;
title?: string;
description?: string;
isCompliant?: boolean;
dueDate?: string;
}
export interface Issue {
id?: string | number;
projectId?: string | number;
title?: string;
description?: string;
priority?: Priority;
status?: string;
reportedBy?: string;
resolvedAt?: string;
[key: string]: any;
}
export interface CreateIssueRequest {
projectId: string | number;
title: string;
description?: string;
priority?: Priority;
}
export interface UpdateIssueRequest {
id: string | number;
title?: string;
description?: string;
priority?: Priority;
status?: string;
}
export interface Milestone {
id?: string | number;
projectId?: string | number;
title?: string;
description?: string;
dueDate?: string;
amount?: number;
status?: ApprovalStatus;
completionPercentage?: number;
[key: string]: any;
}
export interface CreateMilestoneRequest {
projectId: string | number;
title: string;
description?: string;
dueDate?: string;
amount?: number;
}
export interface UpdateMilestoneRequest {
id: string | number;
title?: string;
description?: string;
dueDate?: string;
amount?: number;
status?: ApprovalStatus;
completionPercentage?: number;
}
export interface Project {
id?: string | number;
programmeId?: string | number;
organisationId?: string | number;
name?: string;
code?: string;
description?: string;
type?: ProjectType;
startDate?: string;
endDate?: string;
budget?: number;
status?: string;
[key: string]: any;
}
export interface CreateProjectRequest {
programmeId: string | number;
organisationId: string | number;
name: string;
code?: string;
description?: string;
type?: ProjectType;
startDate?: string;
endDate?: string;
budget?: number;
}
export interface UpdateProjectRequest {
id: string | number;
name?: string;
description?: string;
budget?: number;
startDate?: string;
endDate?: string;
}
export interface UpdateProjectStatusRequest {
projectId: string | number;
status: string | number;
}
export interface SiteVisit {
id?: string | number;
projectId?: string | number;
visitDate?: string;
visitorName?: string;
findings?: string;
recommendations?: string;
[key: string]: any;
}
export interface CreateSiteVisitRequest {
projectId: string | number;
visitDate: string;
visitorName: string;
findings?: string;
recommendations?: string;
}
export interface UpdateSiteVisitRequest {
id: string | number;
visitDate?: string;
visitorName?: string;
findings?: string;
recommendations?: string;
}
export interface Award {
id?: string | number;
projectId?: string | number;
amount?: number;
awardDate?: string;
conditions?: string;
[key: string]: any;
}
export interface CreateAwardRequest {
projectId: string | number;
amount: number;
awardDate?: string;
conditions?: string;
}
export interface Budget {
id?: string | number;
projectId?: string | number;
category?: string;
allocatedAmount?: number;
spentAmount?: number;
notes?: string;
[key: string]: any;
}
export interface CreateBudgetRequest {
projectId: string | number;
category: string;
allocatedAmount: number;
notes?: string;
}
export interface UpdateBudgetRequest {
id: string | number;
category?: string;
allocatedAmount?: number;
spentAmount?: number;
notes?: string;
}
export interface Contract {
id?: string | number;
projectId?: string | number;
title?: string;
contractNumber?: string;
status?: ContractStatus;
signedDate?: string;
expiryDate?: string;
value?: number;
[key: string]: any;
}
export interface CreateContractRequest {
projectId: string | number;
title: string;
contractNumber?: string;
signedDate?: string;
expiryDate?: string;
value?: number;
}
export interface UpdateContractRequest {
id: string | number;
title?: string;
status?: ContractStatus;
expiryDate?: string;
value?: number;
}
export interface ExecuteContractRequest {
contractId: string | number;
executionDate: string;
notes?: string;
}
export interface Instrument {
id?: string | number;
programmeId?: string | number;
name?: string;
type?: string;
description?: string;
terms?: string;
[key: string]: any;
}
export interface CreateInstrumentRequest {
programmeId: string | number;
name: string;
type?: string;
description?: string;
terms?: string;
}
export interface UpdateInstrumentRequest {
id: string | number;
name?: string;
type?: string;
description?: string;
terms?: string;
}
export interface Organisation {
id?: string | number;
name?: string;
registrationNumber?: string;
type?: OrganisationType;
email?: string;
phone?: string;
address?: string;
[key: string]: any;
}
export interface CreateOrganisationRequest {
name: string;
registrationNumber?: string;
type?: OrganisationType;
email?: string;
phone?: string;
address?: string;
}
export interface UpdateOrganisationRequest {
id: string | number;
name?: string;
registrationNumber?: string;
type?: OrganisationType;
email?: string;
phone?: string;
address?: string;
}
export interface Portfolio {
id?: string | number;
organisationId?: string | number;
name?: string;
description?: string;
totalValue?: number;
[key: string]: any;
}
export interface CreatePortfolioRequest {
organisationId: string | number;
name: string;
description?: string;
}
export interface UpdatePortfolioRequest {
id: string | number;
name?: string;
description?: string;
}
export interface Programme {
id?: string | number;
portfolioId?: string | number;
name?: string;
description?: string;
budget?: number;
startDate?: string;
endDate?: string;
[key: string]: any;
}
export interface CreateProgrammeRequest {
portfolioId: string | number;
name: string;
description?: string;
budget?: number;
startDate?: string;
endDate?: string;
}
export interface UpdateProgrammeRequest {
id: string | number;
name?: string;
description?: string;
budget?: number;
}
export interface Tenant {
id?: string | number;
name?: string;
code?: string;
isActive?: boolean;
createdDate?: string;
[key: string]: any;
}
export interface CreateTenantRequest {
name: string;
code?: string;
isActive?: boolean;
}
export interface UpdateTenantRequest {
id: string | number;
name?: string;
code?: string;
isActive?: boolean;
}
export interface Dashboard {
totalProjects?: number;
totalCommittedCapital?: number;
totalDisbursedCapital?: number;
activeMilestonesCount?: number;
complianceRate?: number;
recentActivities?: any[];
[key: string]: any;
}
export interface AuditLog {
id?: string | number;
entityName?: string;
entityId?: string | number;
action?: string;
timestamp?: string;
performedBy?: string;
details?: string;
[key: string]: any;
}
export interface Disbursement {
id?: string | number;
projectId?: string | number;
milestoneId?: string | number;
amount?: number;
disbursementDate?: string;
status?: ApprovalStatus;
referenceNumber?: string;
[key: string]: any;
}
export interface CreateDisbursementRequest {
projectId: string | number;
milestoneId?: string | number;
amount: number;
referenceNumber?: string;
}
export interface UpdateDisbursementRequest {
id: string | number;
amount?: number;
status?: ApprovalStatus;
referenceNumber?: string;
}
export interface Risk {
id?: string | number;
projectId?: string | number;
title?: string;
description?: string;
likelihood?: RiskLikelihood;
impact?: RiskImpact;
mitigationPlan?: string;
status?: string;
[key: string]: any;
}
export interface CreateRiskRequest {
projectId: string | number;
title: string;
description?: string;
likelihood?: RiskLikelihood;
impact?: RiskImpact;
mitigationPlan?: string;
}
export interface UpdateRiskRequest {
id: string | number;
title?: string;
description?: string;
likelihood?: RiskLikelihood;
impact?: RiskImpact;
mitigationPlan?: string;
status?: string;
}
export interface Rule {
id?: string | number;
programmeId?: string | number;
name?: string;
expression?: string;
description?: string;
isActive?: boolean;
[key: string]: any;
}
export interface CreateRuleRequest {
programmeId: string | number;
name: string;
expression: string;
description?: string;
isActive?: boolean;
}
export interface UpdateRuleRequest {
id: string | number;
name?: string;
expression?: string;
description?: string;
isActive?: boolean;
}
export interface Evidence {
id?: string | number;
projectId?: string | number;
milestoneId?: string | number;
title?: string;
description?: string;
type?: EvidenceType;
fileUrl?: string;
fileName?: string;
fileSize?: number;
uploadedAt?: string;
verified?: boolean;
[key: string]: any;
}
export interface UpdateEvidenceRequest {
id: string | number;
title?: string;
description?: string;
type?: EvidenceType;
verified?: boolean;
}
export interface Indicator {
id?: string | number;
projectId?: string | number;
name?: string;
description?: string;
targetValue?: number;
actualValue?: number;
unit?: UnitOfMeasure;
[key: string]: any;
}
export interface CreateIndicatorRequest {
projectId: string | number;
name: string;
description?: string;
targetValue: number;
unit?: UnitOfMeasure;
}
export interface Invite {
id?: string | number;
email?: string;
role?: string;
organisationId?: string | number;
status?: string;
expiresAt?: string;
[key: string]: any;
}
export interface InviteRequest {
email: string;
role?: string;
organisationId?: string | number;
}
export interface Notification {
id?: string | number;
organisationId?: string | number;
platform?: NotificationPlatform;
status?: NotificationStatus;
message?: string;
recipient?: string;
sentAt?: string;
[key: string]: any;
}
File diff suppressed because it is too large Load Diff