@hed-hog/operations 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +18 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/operations.module.d.ts +3 -0
  6. package/dist/operations.module.d.ts.map +1 -0
  7. package/dist/operations.module.js +28 -0
  8. package/dist/operations.module.js.map +1 -0
  9. package/hedhog/data/menu.yaml +132 -0
  10. package/hedhog/data/role.yaml +7 -0
  11. package/hedhog/data/route.yaml +80 -0
  12. package/hedhog/frontend/app/_components/allocation-calendar.tsx.ejs +56 -0
  13. package/hedhog/frontend/app/_components/kanban-board.tsx.ejs +83 -0
  14. package/hedhog/frontend/app/_components/operations-header.tsx.ejs +29 -0
  15. package/hedhog/frontend/app/_components/section-card.tsx.ejs +32 -0
  16. package/hedhog/frontend/app/_components/status-badge.tsx.ejs +15 -0
  17. package/hedhog/frontend/app/_components/timesheet-entry-dialog.tsx.ejs +142 -0
  18. package/hedhog/frontend/app/_lib/hooks/use-operations-data.ts.ejs +41 -0
  19. package/hedhog/frontend/app/_lib/mocks/allocations.mock.ts.ejs +74 -0
  20. package/hedhog/frontend/app/_lib/mocks/contracts.mock.ts.ejs +74 -0
  21. package/hedhog/frontend/app/_lib/mocks/projects.mock.ts.ejs +60 -0
  22. package/hedhog/frontend/app/_lib/mocks/tasks.mock.ts.ejs +88 -0
  23. package/hedhog/frontend/app/_lib/mocks/timesheets.mock.ts.ejs +84 -0
  24. package/hedhog/frontend/app/_lib/mocks/users.mock.ts.ejs +67 -0
  25. package/hedhog/frontend/app/_lib/services/contracts.service.ts.ejs +10 -0
  26. package/hedhog/frontend/app/_lib/services/projects.service.ts.ejs +10 -0
  27. package/hedhog/frontend/app/_lib/services/tasks.service.ts.ejs +10 -0
  28. package/hedhog/frontend/app/_lib/services/timesheets.service.ts.ejs +10 -0
  29. package/hedhog/frontend/app/_lib/types/operations.ts.ejs +95 -0
  30. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +25 -0
  31. package/hedhog/frontend/app/_lib/utils/metrics.ts.ejs +103 -0
  32. package/hedhog/frontend/app/_lib/utils/status.ts.ejs +80 -0
  33. package/hedhog/frontend/app/allocations/page.tsx.ejs +99 -0
  34. package/hedhog/frontend/app/approvals/page.tsx.ejs +147 -0
  35. package/hedhog/frontend/app/contracts/[id]/page.tsx.ejs +108 -0
  36. package/hedhog/frontend/app/contracts/page.tsx.ejs +124 -0
  37. package/hedhog/frontend/app/layout.tsx.ejs +9 -0
  38. package/hedhog/frontend/app/page.tsx.ejs +177 -0
  39. package/hedhog/frontend/app/projects/[id]/page.tsx.ejs +186 -0
  40. package/hedhog/frontend/app/projects/page.tsx.ejs +111 -0
  41. package/hedhog/frontend/app/tasks/page.tsx.ejs +47 -0
  42. package/hedhog/frontend/app/timesheets/page.tsx.ejs +126 -0
  43. package/hedhog/frontend/messages/en.json +142 -0
  44. package/hedhog/frontend/messages/pt.json +142 -0
  45. package/package.json +37 -0
  46. package/src/index.ts +1 -0
  47. package/src/language/en.json +8 -0
  48. package/src/language/pt.json +8 -0
  49. package/src/operations.module.ts +15 -0
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import { useMemo } from 'react';
4
+ import { allocationsMock } from '../mocks/allocations.mock';
5
+ import { operationsUsersMock } from '../mocks/users.mock';
6
+ import { contractsService } from '../services/contracts.service';
7
+ import { projectsService } from '../services/projects.service';
8
+ import { tasksService } from '../services/tasks.service';
9
+ import { timesheetsService } from '../services/timesheets.service';
10
+ import {
11
+ getApprovalStatusData,
12
+ getDashboardMetrics,
13
+ getDailyTotals,
14
+ getHoursByProject,
15
+ getHoursByUser,
16
+ getPendingApprovalsSummary,
17
+ getRecentTimesheetEntries,
18
+ getWeeklyTrend,
19
+ } from '../utils/metrics';
20
+
21
+ export function useOperationsData() {
22
+ return useMemo(
23
+ () => ({
24
+ users: operationsUsersMock,
25
+ contracts: contractsService.list(),
26
+ projects: projectsService.list(),
27
+ tasks: tasksService.list(),
28
+ timesheets: timesheetsService.list(),
29
+ allocations: allocationsMock,
30
+ dashboardMetrics: getDashboardMetrics(),
31
+ hoursByProject: getHoursByProject(),
32
+ hoursByUser: getHoursByUser(),
33
+ approvalStatusData: getApprovalStatusData(),
34
+ weeklyTrendData: getWeeklyTrend(),
35
+ recentTimesheets: getRecentTimesheetEntries(),
36
+ dailyTotals: getDailyTotals(),
37
+ approvalSummary: getPendingApprovalsSummary(),
38
+ }),
39
+ []
40
+ );
41
+ }
@@ -0,0 +1,74 @@
1
+ import type { Allocation } from '../types/operations';
2
+
3
+ export const allocationsMock: Allocation[] = [
4
+ {
5
+ id: 'alloc-001',
6
+ userId: 'usr-ana',
7
+ role: 'Delivery Manager',
8
+ projectId: 'prj-zenith-cloud',
9
+ weeklyHours: 18,
10
+ allocationPercent: 45,
11
+ startDate: '2026-03-03',
12
+ endDate: '2026-06-30',
13
+ },
14
+ {
15
+ id: 'alloc-002',
16
+ userId: 'usr-bruno',
17
+ role: 'Technical Lead',
18
+ projectId: 'prj-orion-web',
19
+ weeklyHours: 22,
20
+ allocationPercent: 55,
21
+ startDate: '2026-02-10',
22
+ endDate: '2026-06-30',
23
+ },
24
+ {
25
+ id: 'alloc-003',
26
+ userId: 'usr-carla',
27
+ role: 'Project Manager',
28
+ projectId: 'prj-atlas-crm',
29
+ weeklyHours: 24,
30
+ allocationPercent: 60,
31
+ startDate: '2026-03-01',
32
+ endDate: '2026-08-31',
33
+ },
34
+ {
35
+ id: 'alloc-004',
36
+ userId: 'usr-diego',
37
+ role: 'Backend Engineer',
38
+ projectId: 'prj-orion-data',
39
+ weeklyHours: 20,
40
+ allocationPercent: 50,
41
+ startDate: '2026-02-03',
42
+ endDate: '2026-09-15',
43
+ },
44
+ {
45
+ id: 'alloc-005',
46
+ userId: 'usr-elisa',
47
+ role: 'Frontend Engineer',
48
+ projectId: 'prj-orion-web',
49
+ weeklyHours: 30,
50
+ allocationPercent: 75,
51
+ startDate: '2026-01-20',
52
+ endDate: '2026-06-30',
53
+ },
54
+ {
55
+ id: 'alloc-006',
56
+ userId: 'usr-fabio',
57
+ role: 'QA Analyst',
58
+ projectId: 'prj-orion-web',
59
+ weeklyHours: 16,
60
+ allocationPercent: 40,
61
+ startDate: '2026-02-17',
62
+ endDate: '2026-05-30',
63
+ },
64
+ {
65
+ id: 'alloc-007',
66
+ userId: 'usr-gabi',
67
+ role: 'UX Designer',
68
+ projectId: 'prj-orion-data',
69
+ weeklyHours: 14,
70
+ allocationPercent: 35,
71
+ startDate: '2026-02-12',
72
+ endDate: '2026-07-31',
73
+ },
74
+ ];
@@ -0,0 +1,74 @@
1
+ import type { Contract } from '../types/operations';
2
+
3
+ export const contractsMock: Contract[] = [
4
+ {
5
+ id: 'ctr-orion',
6
+ name: 'Orion Platform Expansion',
7
+ client: 'Orion Retail Group',
8
+ type: 'monthly',
9
+ startDate: '2026-01-01',
10
+ endDate: '2026-12-31',
11
+ hourlyRate: 195,
12
+ hourLimit: 640,
13
+ status: 'active',
14
+ billingRules: [
15
+ 'Monthly invoicing on the fifth business day',
16
+ 'Overage billed at blended rate above hour cap',
17
+ 'Change requests approved by client PM',
18
+ ],
19
+ sla: 'P1 response in 2h, P2 in 6h, delivery governance weekly.',
20
+ revisions: ['Revision 1 - January scope uplift', 'Revision 2 - UX squad add-on'],
21
+ linkedProjectIds: ['prj-orion-web', 'prj-orion-data'],
22
+ },
23
+ {
24
+ id: 'ctr-zenith',
25
+ name: 'Zenith Support Retainer',
26
+ client: 'Zenith Health',
27
+ type: 'tm',
28
+ startDate: '2025-10-15',
29
+ endDate: '2026-10-14',
30
+ hourlyRate: 230,
31
+ hourLimit: 420,
32
+ status: 'active',
33
+ billingRules: [
34
+ 'Time and material billing by approved entry',
35
+ 'Emergency work charged at 1.25x after 8pm',
36
+ ],
37
+ sla: '24x7 on-call for critical incidents with monthly ops review.',
38
+ revisions: ['Revision 1 - Added cloud migration stream'],
39
+ linkedProjectIds: ['prj-zenith-cloud'],
40
+ },
41
+ {
42
+ id: 'ctr-atlas',
43
+ name: 'Atlas CRM Rollout',
44
+ client: 'Atlas Logistics',
45
+ type: 'fixed',
46
+ startDate: '2026-02-01',
47
+ endDate: '2026-08-31',
48
+ hourlyRate: 175,
49
+ hourLimit: 520,
50
+ status: 'renewal',
51
+ billingRules: [
52
+ 'Milestone billing split in 30/40/30',
53
+ 'Additional scope converted to change order',
54
+ ],
55
+ sla: 'Business hours support, weekly steering committee.',
56
+ revisions: ['Revision 1 - Extended rollout to LATAM team'],
57
+ linkedProjectIds: ['prj-atlas-crm'],
58
+ },
59
+ {
60
+ id: 'ctr-nova',
61
+ name: 'Nova Discovery Program',
62
+ client: 'Nova Energy',
63
+ type: 'fixed',
64
+ startDate: '2025-06-01',
65
+ endDate: '2025-12-15',
66
+ hourlyRate: 160,
67
+ hourLimit: 320,
68
+ status: 'expired',
69
+ billingRules: ['Single invoice on phase completion'],
70
+ sla: 'Advisory cadence only.',
71
+ revisions: ['Final revision approved in November'],
72
+ linkedProjectIds: [],
73
+ },
74
+ ];
@@ -0,0 +1,60 @@
1
+ import type { Project } from '../types/operations';
2
+
3
+ export const projectsMock: Project[] = [
4
+ {
5
+ id: 'prj-orion-web',
6
+ name: 'Orion Commerce Revamp',
7
+ client: 'Orion Retail Group',
8
+ progress: 72,
9
+ status: 'active',
10
+ teamMemberIds: ['usr-ana', 'usr-bruno', 'usr-elisa', 'usr-fabio'],
11
+ hoursLogged: 386,
12
+ startDate: '2026-01-08',
13
+ endDate: '2026-06-30',
14
+ description: 'Frontend and middleware modernization for the main commerce experience.',
15
+ contractId: 'ctr-orion',
16
+ budget: 128000,
17
+ },
18
+ {
19
+ id: 'prj-orion-data',
20
+ name: 'Orion Data Foundation',
21
+ client: 'Orion Retail Group',
22
+ progress: 48,
23
+ status: 'at-risk',
24
+ teamMemberIds: ['usr-carla', 'usr-diego', 'usr-gabi'],
25
+ hoursLogged: 244,
26
+ startDate: '2026-02-03',
27
+ endDate: '2026-09-15',
28
+ description: 'Data governance and reporting layer for omnichannel operations.',
29
+ contractId: 'ctr-orion',
30
+ budget: 98000,
31
+ },
32
+ {
33
+ id: 'prj-zenith-cloud',
34
+ name: 'Zenith Cloud Stabilization',
35
+ client: 'Zenith Health',
36
+ progress: 61,
37
+ status: 'active',
38
+ teamMemberIds: ['usr-ana', 'usr-diego', 'usr-fabio'],
39
+ hoursLogged: 322,
40
+ startDate: '2026-01-12',
41
+ endDate: '2026-07-31',
42
+ description: 'Ops stabilization and incident reduction program after migration.',
43
+ contractId: 'ctr-zenith',
44
+ budget: 115000,
45
+ },
46
+ {
47
+ id: 'prj-atlas-crm',
48
+ name: 'Atlas CRM Implementation',
49
+ client: 'Atlas Logistics',
50
+ progress: 29,
51
+ status: 'planning',
52
+ teamMemberIds: ['usr-carla', 'usr-elisa', 'usr-gabi'],
53
+ hoursLogged: 104,
54
+ startDate: '2026-03-01',
55
+ endDate: '2026-08-31',
56
+ description: 'Sales and service CRM rollout with operational dashboards.',
57
+ contractId: 'ctr-atlas',
58
+ budget: 89000,
59
+ },
60
+ ];
@@ -0,0 +1,88 @@
1
+ import type { Task } from '../types/operations';
2
+
3
+ export const tasksMock: Task[] = [
4
+ {
5
+ id: 'tsk-101',
6
+ title: 'Finalize checkout journey QA',
7
+ projectId: 'prj-orion-web',
8
+ projectName: 'Orion Commerce Revamp',
9
+ status: 'review',
10
+ labels: ['QA', 'E-commerce'],
11
+ assignedUserId: 'usr-fabio',
12
+ dueDate: '2026-03-18',
13
+ estimatedHours: 10,
14
+ description: 'Regression pass for payment and address validation flows.',
15
+ },
16
+ {
17
+ id: 'tsk-102',
18
+ title: 'Implement pricing API fallback',
19
+ projectId: 'prj-orion-web',
20
+ projectName: 'Orion Commerce Revamp',
21
+ status: 'in-progress',
22
+ labels: ['Backend', 'API'],
23
+ assignedUserId: 'usr-diego',
24
+ dueDate: '2026-03-20',
25
+ estimatedHours: 16,
26
+ description: 'Fallback logic for inventory and pricing sync gaps.',
27
+ },
28
+ {
29
+ id: 'tsk-103',
30
+ title: 'Refine mobile PDP layouts',
31
+ projectId: 'prj-orion-web',
32
+ projectName: 'Orion Commerce Revamp',
33
+ status: 'todo',
34
+ labels: ['UX', 'Frontend'],
35
+ assignedUserId: 'usr-elisa',
36
+ dueDate: '2026-03-21',
37
+ estimatedHours: 14,
38
+ description: 'Polish responsive product detail page spacing and hierarchy.',
39
+ },
40
+ {
41
+ id: 'tsk-104',
42
+ title: 'Map KPI ownership by squad',
43
+ projectId: 'prj-orion-data',
44
+ projectName: 'Orion Data Foundation',
45
+ status: 'backlog',
46
+ labels: ['Discovery'],
47
+ assignedUserId: 'usr-carla',
48
+ dueDate: '2026-03-24',
49
+ estimatedHours: 8,
50
+ description: 'Confirm ownership and cadence for operational KPIs.',
51
+ },
52
+ {
53
+ id: 'tsk-105',
54
+ title: 'Finish warehouse latency dashboard',
55
+ projectId: 'prj-orion-data',
56
+ projectName: 'Orion Data Foundation',
57
+ status: 'in-progress',
58
+ labels: ['BI', 'Ops'],
59
+ assignedUserId: 'usr-gabi',
60
+ dueDate: '2026-03-22',
61
+ estimatedHours: 18,
62
+ description: 'Visualize shipping delay drivers and same-day SLA misses.',
63
+ },
64
+ {
65
+ id: 'tsk-106',
66
+ title: 'Automate alert routing for critical incidents',
67
+ projectId: 'prj-zenith-cloud',
68
+ projectName: 'Zenith Cloud Stabilization',
69
+ status: 'done',
70
+ labels: ['Automation', 'Cloud'],
71
+ assignedUserId: 'usr-bruno',
72
+ dueDate: '2026-03-15',
73
+ estimatedHours: 12,
74
+ description: 'Connect PagerDuty routing rules to service ownership matrix.',
75
+ },
76
+ {
77
+ id: 'tsk-107',
78
+ title: 'Prepare CRM rollout dependency board',
79
+ projectId: 'prj-atlas-crm',
80
+ projectName: 'Atlas CRM Implementation',
81
+ status: 'todo',
82
+ labels: ['PMO'],
83
+ assignedUserId: 'usr-carla',
84
+ dueDate: '2026-03-26',
85
+ estimatedHours: 9,
86
+ description: 'Track implementation dependencies before build phase starts.',
87
+ },
88
+ ];
@@ -0,0 +1,84 @@
1
+ import type { TimesheetEntry } from '../types/operations';
2
+
3
+ export const timesheetsMock: TimesheetEntry[] = [
4
+ {
5
+ id: 'time-001',
6
+ date: '2026-03-10',
7
+ userId: 'usr-elisa',
8
+ projectId: 'prj-orion-web',
9
+ taskId: 'tsk-103',
10
+ hours: 6,
11
+ description: 'Mobile PDP refinements and component spacing updates.',
12
+ status: 'approved',
13
+ },
14
+ {
15
+ id: 'time-002',
16
+ date: '2026-03-10',
17
+ userId: 'usr-diego',
18
+ projectId: 'prj-orion-web',
19
+ taskId: 'tsk-102',
20
+ hours: 7.5,
21
+ description: 'Pricing API fallback implementation and test coverage.',
22
+ status: 'pending',
23
+ },
24
+ {
25
+ id: 'time-003',
26
+ date: '2026-03-11',
27
+ userId: 'usr-fabio',
28
+ projectId: 'prj-orion-web',
29
+ taskId: 'tsk-101',
30
+ hours: 5,
31
+ description: 'Regression testing for checkout and payment flows.',
32
+ status: 'approved',
33
+ },
34
+ {
35
+ id: 'time-004',
36
+ date: '2026-03-11',
37
+ userId: 'usr-gabi',
38
+ projectId: 'prj-orion-data',
39
+ taskId: 'tsk-105',
40
+ hours: 6.5,
41
+ description: 'Dashboard wireframe iteration with supply chain metrics.',
42
+ status: 'pending',
43
+ },
44
+ {
45
+ id: 'time-005',
46
+ date: '2026-03-12',
47
+ userId: 'usr-ana',
48
+ projectId: 'prj-zenith-cloud',
49
+ taskId: 'tsk-106',
50
+ hours: 4,
51
+ description: 'Incident review and action plan with client leadership.',
52
+ status: 'approved',
53
+ },
54
+ {
55
+ id: 'time-006',
56
+ date: '2026-03-12',
57
+ userId: 'usr-carla',
58
+ projectId: 'prj-atlas-crm',
59
+ taskId: 'tsk-107',
60
+ hours: 7,
61
+ description: 'Rollout planning workshop and dependency review.',
62
+ status: 'rejected',
63
+ },
64
+ {
65
+ id: 'time-007',
66
+ date: '2026-03-13',
67
+ userId: 'usr-diego',
68
+ projectId: 'prj-zenith-cloud',
69
+ taskId: 'tsk-106',
70
+ hours: 8,
71
+ description: 'Alert routing automation hardening and validation.',
72
+ status: 'approved',
73
+ },
74
+ {
75
+ id: 'time-008',
76
+ date: '2026-03-14',
77
+ userId: 'usr-carla',
78
+ projectId: 'prj-orion-data',
79
+ taskId: 'tsk-104',
80
+ hours: 3.5,
81
+ description: 'KPI ownership mapping workshop prep.',
82
+ status: 'pending',
83
+ },
84
+ ];
@@ -0,0 +1,67 @@
1
+ import type { OperationsUser } from '../types/operations';
2
+
3
+ export const operationsUsersMock: OperationsUser[] = [
4
+ {
5
+ id: 'usr-ana',
6
+ name: 'Ana Silva',
7
+ role: 'Delivery Manager',
8
+ seniority: 'Lead',
9
+ department: 'Operations',
10
+ hourlyRate: 220,
11
+ utilizationTarget: 78,
12
+ },
13
+ {
14
+ id: 'usr-bruno',
15
+ name: 'Bruno Costa',
16
+ role: 'Technical Lead',
17
+ seniority: 'Senior',
18
+ department: 'Engineering',
19
+ hourlyRate: 210,
20
+ utilizationTarget: 82,
21
+ },
22
+ {
23
+ id: 'usr-carla',
24
+ name: 'Carla Mendes',
25
+ role: 'Project Manager',
26
+ seniority: 'Senior',
27
+ department: 'PMO',
28
+ hourlyRate: 180,
29
+ utilizationTarget: 80,
30
+ },
31
+ {
32
+ id: 'usr-diego',
33
+ name: 'Diego Alves',
34
+ role: 'Backend Engineer',
35
+ seniority: 'Mid-level',
36
+ department: 'Engineering',
37
+ hourlyRate: 145,
38
+ utilizationTarget: 85,
39
+ },
40
+ {
41
+ id: 'usr-elisa',
42
+ name: 'Elisa Rocha',
43
+ role: 'Frontend Engineer',
44
+ seniority: 'Mid-level',
45
+ department: 'Engineering',
46
+ hourlyRate: 140,
47
+ utilizationTarget: 84,
48
+ },
49
+ {
50
+ id: 'usr-fabio',
51
+ name: 'Fabio Lima',
52
+ role: 'QA Analyst',
53
+ seniority: 'Mid-level',
54
+ department: 'Quality',
55
+ hourlyRate: 110,
56
+ utilizationTarget: 76,
57
+ },
58
+ {
59
+ id: 'usr-gabi',
60
+ name: 'Gabriela Torres',
61
+ role: 'UX Designer',
62
+ seniority: 'Senior',
63
+ department: 'Design',
64
+ hourlyRate: 150,
65
+ utilizationTarget: 72,
66
+ },
67
+ ];
@@ -0,0 +1,10 @@
1
+ import { contractsMock } from '../mocks/contracts.mock';
2
+
3
+ export const contractsService = {
4
+ list() {
5
+ return contractsMock;
6
+ },
7
+ getById(id: string) {
8
+ return contractsMock.find((contract) => contract.id === id) ?? null;
9
+ },
10
+ };
@@ -0,0 +1,10 @@
1
+ import { projectsMock } from '../mocks/projects.mock';
2
+
3
+ export const projectsService = {
4
+ list() {
5
+ return projectsMock;
6
+ },
7
+ getById(id: string) {
8
+ return projectsMock.find((project) => project.id === id) ?? null;
9
+ },
10
+ };
@@ -0,0 +1,10 @@
1
+ import { tasksMock } from '../mocks/tasks.mock';
2
+
3
+ export const tasksService = {
4
+ list() {
5
+ return tasksMock;
6
+ },
7
+ byProject(projectId: string) {
8
+ return tasksMock.filter((task) => task.projectId === projectId);
9
+ },
10
+ };
@@ -0,0 +1,10 @@
1
+ import { timesheetsMock } from '../mocks/timesheets.mock';
2
+
3
+ export const timesheetsService = {
4
+ list() {
5
+ return timesheetsMock;
6
+ },
7
+ byProject(projectId: string) {
8
+ return timesheetsMock.filter((entry) => entry.projectId === projectId);
9
+ },
10
+ };
@@ -0,0 +1,95 @@
1
+ export type ApprovalStatus = 'approved' | 'pending' | 'rejected';
2
+
3
+ export type ProjectStatus =
4
+ | 'planning'
5
+ | 'active'
6
+ | 'at-risk'
7
+ | 'paused'
8
+ | 'completed';
9
+
10
+ export type ContractType = 'tm' | 'monthly' | 'fixed';
11
+
12
+ export type ContractStatus = 'active' | 'draft' | 'expired' | 'renewal';
13
+
14
+ export type TaskStatus =
15
+ | 'backlog'
16
+ | 'todo'
17
+ | 'in-progress'
18
+ | 'review'
19
+ | 'done';
20
+
21
+ export interface OperationsUser {
22
+ id: string;
23
+ name: string;
24
+ role: string;
25
+ seniority: string;
26
+ department: string;
27
+ hourlyRate: number;
28
+ utilizationTarget: number;
29
+ }
30
+
31
+ export interface Contract {
32
+ id: string;
33
+ name: string;
34
+ client: string;
35
+ type: ContractType;
36
+ startDate: string;
37
+ endDate: string;
38
+ hourlyRate: number;
39
+ hourLimit: number;
40
+ status: ContractStatus;
41
+ billingRules: string[];
42
+ sla: string;
43
+ revisions: string[];
44
+ linkedProjectIds: string[];
45
+ }
46
+
47
+ export interface Project {
48
+ id: string;
49
+ name: string;
50
+ client: string;
51
+ progress: number;
52
+ status: ProjectStatus;
53
+ teamMemberIds: string[];
54
+ hoursLogged: number;
55
+ startDate: string;
56
+ endDate: string;
57
+ description: string;
58
+ contractId: string;
59
+ budget: number;
60
+ }
61
+
62
+ export interface Task {
63
+ id: string;
64
+ title: string;
65
+ projectId: string;
66
+ projectName: string;
67
+ status: TaskStatus;
68
+ labels: string[];
69
+ assignedUserId: string;
70
+ dueDate: string;
71
+ estimatedHours: number;
72
+ description: string;
73
+ }
74
+
75
+ export interface TimesheetEntry {
76
+ id: string;
77
+ date: string;
78
+ userId: string;
79
+ projectId: string;
80
+ taskId: string;
81
+ hours: number;
82
+ description: string;
83
+ status: ApprovalStatus;
84
+ }
85
+
86
+ export interface Allocation {
87
+ id: string;
88
+ userId: string;
89
+ role: string;
90
+ projectId: string;
91
+ weeklyHours: number;
92
+ allocationPercent: number;
93
+ startDate: string;
94
+ endDate: string;
95
+ }
@@ -0,0 +1,25 @@
1
+ export const operationsCurrency = new Intl.NumberFormat('en-US', {
2
+ style: 'currency',
3
+ currency: 'USD',
4
+ maximumFractionDigits: 0,
5
+ });
6
+
7
+ export function formatCurrency(value: number) {
8
+ return operationsCurrency.format(value);
9
+ }
10
+
11
+ export function formatDate(value: string) {
12
+ return new Date(`${value}T00:00:00`).toLocaleDateString('en-US', {
13
+ month: 'short',
14
+ day: 'numeric',
15
+ year: 'numeric',
16
+ });
17
+ }
18
+
19
+ export function formatPercent(value: number) {
20
+ return `${value}%`;
21
+ }
22
+
23
+ export function formatHours(value: number) {
24
+ return `${value.toFixed(1)}h`;
25
+ }