feat(frontend): update allocation UI and services
Enhance allocation management interface: - Allocations page: modal-based editing, variance display - Updated services: allocationService with bulk ops, projectMonthPlanService - Project and team member pages: reconciliation status indicators - Navigation config: add planning and reports links Part of enhanced-allocation change.
This commit is contained in:
@@ -1,18 +1,39 @@
|
||||
/**
|
||||
* Allocation Service
|
||||
*
|
||||
*
|
||||
* API operations for resource allocation management.
|
||||
*/
|
||||
|
||||
import { api } from './api';
|
||||
|
||||
export type VarianceStatus = 'OVER' | 'UNDER' | 'MATCH' | null;
|
||||
|
||||
export interface RowVariance {
|
||||
allocated_total: number;
|
||||
planned_month: number;
|
||||
variance: number;
|
||||
status: VarianceStatus;
|
||||
}
|
||||
|
||||
export interface ColumnVariance {
|
||||
allocated: number;
|
||||
capacity: number;
|
||||
variance: number;
|
||||
status: VarianceStatus;
|
||||
}
|
||||
|
||||
export interface Allocation {
|
||||
id: string;
|
||||
project_id: string;
|
||||
team_member_id: string | null;
|
||||
month: string;
|
||||
allocated_hours: string;
|
||||
is_untracked?: boolean;
|
||||
row_variance?: RowVariance;
|
||||
column_variance?: ColumnVariance | null;
|
||||
allocation_indicator?: 'green' | 'yellow' | 'red' | 'gray';
|
||||
warnings?: string[];
|
||||
utilization?: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
project?: {
|
||||
@@ -28,7 +49,7 @@ export interface Allocation {
|
||||
|
||||
export interface CreateAllocationRequest {
|
||||
project_id: string;
|
||||
team_member_id: string;
|
||||
team_member_id: string | null;
|
||||
month: string;
|
||||
allocated_hours: number;
|
||||
}
|
||||
@@ -41,6 +62,12 @@ export interface BulkAllocationRequest {
|
||||
allocations: CreateAllocationRequest[];
|
||||
}
|
||||
|
||||
export interface BulkAllocationResponse {
|
||||
data: Array<{ index: number; id: string; status: string }>;
|
||||
failed: Array<{ index: number; errors: Record<string, string[]> }>;
|
||||
summary: { created: number; failed: number };
|
||||
}
|
||||
|
||||
// Allocation API methods
|
||||
export const allocationService = {
|
||||
/**
|
||||
@@ -54,32 +81,29 @@ export const allocationService = {
|
||||
/**
|
||||
* Get a single allocation by ID
|
||||
*/
|
||||
getById: (id: string) =>
|
||||
api.get<Allocation>(`/allocations/${id}`),
|
||||
getById: (id: string) => api.get<Allocation>(`/allocations/${id}`),
|
||||
|
||||
/**
|
||||
* Create a new allocation
|
||||
*/
|
||||
create: (data: CreateAllocationRequest) =>
|
||||
api.post<Allocation>('/allocations', data),
|
||||
create: (data: CreateAllocationRequest) => api.post<Allocation>('/allocations', data),
|
||||
|
||||
/**
|
||||
* Update an existing allocation
|
||||
*/
|
||||
update: (id: string, data: UpdateAllocationRequest) =>
|
||||
update: (id: string, data: UpdateAllocationRequest) =>
|
||||
api.put<Allocation>(`/allocations/${id}`, data),
|
||||
|
||||
/**
|
||||
* Delete an allocation
|
||||
*/
|
||||
delete: (id: string) =>
|
||||
api.delete<{ message: string }>(`/allocations/${id}`),
|
||||
delete: (id: string) => api.delete<{ message: string }>(`/allocations/${id}`),
|
||||
|
||||
/**
|
||||
* Bulk create allocations
|
||||
*/
|
||||
bulkCreate: (data: BulkAllocationRequest) =>
|
||||
api.post<Allocation[]>('/allocations/bulk', data),
|
||||
bulkCreate: (data: BulkAllocationRequest) =>
|
||||
api.post<BulkAllocationResponse>('/allocations/bulk', data),
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,9 @@ import { api } from '$lib/services/api';
|
||||
|
||||
export interface ProjectMonthPlan {
|
||||
project_id: string;
|
||||
project_code: string;
|
||||
project_name: string;
|
||||
project_status: string | null;
|
||||
approved_estimate: number;
|
||||
months: Record<string, {
|
||||
id: string;
|
||||
@@ -13,13 +15,6 @@ export interface ProjectMonthPlan {
|
||||
reconciliation_status: 'OVER' | 'UNDER' | 'MATCH';
|
||||
}
|
||||
|
||||
export interface ProjectMonthPlansResponse {
|
||||
data: ProjectMonthPlan[];
|
||||
meta: {
|
||||
year: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BulkUpdateRequest {
|
||||
year: number;
|
||||
items: Array<{
|
||||
@@ -39,14 +34,13 @@ export interface BulkUpdateResponse {
|
||||
}
|
||||
|
||||
class ProjectMonthPlanService {
|
||||
async getPlans(year: number): Promise<ProjectMonthPlansResponse> {
|
||||
const response = await api.get<ProjectMonthPlansResponse>(`/project-month-plans?year=${year}`);
|
||||
return response.data;
|
||||
// Note: unwrapResponse strips the {data} wrapper, so this returns the array directly
|
||||
async getPlans(year: number): Promise<ProjectMonthPlan[]> {
|
||||
return api.get<ProjectMonthPlan[]>(`/project-month-plans?year=${year}`);
|
||||
}
|
||||
|
||||
async bulkUpdate(request: BulkUpdateRequest): Promise<BulkUpdateResponse> {
|
||||
const response = await api.put<BulkUpdateResponse>('/project-month-plans/bulk', request);
|
||||
return response.data;
|
||||
return api.put<BulkUpdateResponse>('/project-month-plans/bulk', request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ export interface UpdateProjectRequest {
|
||||
code?: string;
|
||||
title?: string;
|
||||
type_id?: number;
|
||||
status_id?: number;
|
||||
approved_estimate?: number | null;
|
||||
}
|
||||
|
||||
export const projectService = {
|
||||
|
||||
Reference in New Issue
Block a user