feat(frontend): add planning and reporting UI

Implement management reporting interface:
- New /planning route for monthly resource planning grid
- ReportService with type definitions for did/is/will views
- Allocation report page with aggregate and detailed views
- Date range filters, project/member filtering
- Variance badges and status indicators

Part of enhanced-allocation change.
This commit is contained in:
2026-03-08 18:22:46 -04:00
parent 7fa5b9061c
commit 9b38e28117
3 changed files with 982 additions and 8 deletions

View File

@@ -0,0 +1,131 @@
/**
* Report Service
*
* API operations for management reporting (did/is/will views).
*/
import { api } from './api';
export type ViewType = 'did' | 'is' | 'will';
export type VarianceStatus = 'OVER' | 'UNDER' | 'MATCH';
export interface ReportPeriod {
start: string;
end: string;
}
export interface ProjectMonthData {
month: string;
planned_hours: number | null;
is_blank: boolean;
allocated_hours: number;
variance: number;
status: VarianceStatus;
}
export interface ProjectReportData {
id: string;
code: string;
title: string;
approved_estimate: number;
lifecycle_status: VarianceStatus;
plan_sum: number;
period_planned: number;
period_allocated: number;
period_variance: number;
period_status: VarianceStatus;
months: ProjectMonthData[];
}
export interface MemberProjectAllocation {
project_id: string;
project_code: string;
project_title: string;
total_hours: number;
}
export interface MemberReportData {
id: string;
name: string;
period_allocated: number;
projects: MemberProjectAllocation[];
}
export interface ReportAggregates {
total_planned: number;
total_allocated: number;
total_variance: number;
status: VarianceStatus;
}
export interface ReportResponse {
period: ReportPeriod;
view_type: ViewType;
projects: ProjectReportData[];
members: MemberReportData[];
aggregates: ReportAggregates;
}
export interface ReportFilterParams {
start_date: string;
end_date: string;
project_ids?: string[];
member_ids?: string[];
}
// Report API methods
export const reportService = {
/**
* Get allocation report for the specified date range
* View type (did/is/will) is inferred from dates by the backend
*/
getAllocations: (params: ReportFilterParams) => {
const query = new URLSearchParams();
query.append('start_date', params.start_date);
query.append('end_date', params.end_date);
if (params.project_ids) {
for (const id of params.project_ids) {
query.append('project_ids[]', id);
}
}
if (params.member_ids) {
for (const id of params.member_ids) {
query.append('member_ids[]', id);
}
}
return api.get<ReportResponse>(`/reports/allocations?${query.toString()}`);
},
};
/**
* Format view type for display
*/
export function formatViewType(viewType: ViewType): string {
const labels: Record<ViewType, string> = {
did: 'Did (Past)',
is: 'Is (Current)',
will: 'Will (Future)',
};
return labels[viewType] || viewType;
}
/**
* Get status badge color
*/
export function getStatusBadgeClass(status: VarianceStatus): string {
switch (status) {
case 'OVER':
return 'bg-red-100 text-red-800';
case 'UNDER':
return 'bg-amber-100 text-amber-800';
case 'MATCH':
return 'bg-green-100 text-green-800';
default:
return 'bg-gray-100 text-gray-800';
}
}
export default reportService;