@paro.io/expert-shared-components 1.12.20 → 1.12.22
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.
- package/LICENSE +21 -21
- package/README.md +2 -2
- package/lib/components/ClientReferencesSection/DeleteButton.js +11 -11
- package/lib/components/ClientReferencesSection/ParoError.js +10 -10
- package/lib/components/ClientReferencesSection/TagsSection.js +2 -2
- package/lib/components/ClientReferencesSection/styles/BrandedTypography.js +2 -2
- package/lib/components/ClientReferencesSection/styles/Buttons.js +15 -15
- package/lib/components/ClientReferencesSection/styles/Name.js +5 -5
- package/lib/components/ClientReferencesSection/styles/NullContentConditionalColor.js +4 -4
- package/lib/components/ClientReferencesSection/styles/SectionBody.js +11 -11
- package/lib/components/ClientReferencesSection/styles/SectionTitle.js +6 -6
- package/lib/components/ClientReferencesSection/styles/Tags.js +2 -2
- package/lib/components/DiscussionThread/chat.d.ts +22 -22
- package/lib/components/DiscussionThread/chat.js +106 -106
- package/lib/components/DocumentCenter/DocumentTable.d.ts +15 -15
- package/lib/components/DocumentCenter/DocumentTable.js +350 -350
- package/lib/components/DocumentCenter/UploadFilesButton.d.ts +6 -6
- package/lib/components/DocumentCenter/UploadFilesButton.js +29 -29
- package/lib/components/EarningsTracker/ActiveProjectCard.d.ts +52 -52
- package/lib/components/EarningsTracker/ActiveProjectCard.js +161 -161
- package/lib/components/EarningsTracker/CenterCardUI.d.ts +13 -13
- package/lib/components/EarningsTracker/CenterCardUI.js +134 -134
- package/lib/components/EarningsTracker/EarningsTracker.d.ts +52 -52
- package/lib/components/EarningsTracker/EarningsTracker.js +508 -508
- package/lib/components/EarningsTracker/EditDateModal.d.ts +22 -22
- package/lib/components/EarningsTracker/EditDateModal.js +149 -149
- package/lib/components/EarningsTracker/EmailModal.d.ts +14 -14
- package/lib/components/EarningsTracker/EmailModal.js +79 -79
- package/lib/components/EarningsTracker/EndProjectModal.d.ts +56 -56
- package/lib/components/EarningsTracker/EndProjectModal.js +221 -221
- package/lib/components/EarningsTracker/LeftCardUI.d.ts +18 -18
- package/lib/components/EarningsTracker/LeftCardUI.js +189 -189
- package/lib/components/EarningsTracker/LogTimeModalAuthenticated.d.ts +52 -52
- package/lib/components/EarningsTracker/LogTimeModalAuthenticated.js +358 -358
- package/lib/components/EarningsTracker/ProgressBar.d.ts +4 -4
- package/lib/components/EarningsTracker/ProgressBar.js +66 -66
- package/lib/components/EarningsTracker/ReviewRequestModal.d.ts +17 -17
- package/lib/components/EarningsTracker/ReviewRequestModal.js +135 -135
- package/lib/components/EarningsTracker/RightCardUI.d.ts +46 -46
- package/lib/components/EarningsTracker/RightCardUI.js +231 -231
- package/lib/components/EarningsTracker/index.d.ts +1 -1
- package/lib/components/EarningsTracker/index.js +5 -5
- package/lib/components/ExpertProfileHeader/ActionButtonSection.js +6 -6
- package/lib/components/ExpertProfileHeader/ProfileSection.js +7 -7
- package/lib/components/Invoices/DecisionSection.js +6 -4
- package/lib/components/Invoices/InvoiceHeader.js +22 -19
- package/lib/components/Invoices/ProjectHoursAdjustmentModal.js +57 -47
- package/lib/components/Invoices/TestDecisionSection.d.ts +1 -1
- package/lib/components/Invoices/TestDecisionSection.js +126 -126
- package/lib/components/OrganizationChart/OrganizationChart.d.ts +15 -15
- package/lib/components/OrganizationChart/OrganizationChart.js +312 -312
- package/lib/components/OrganizationChart/PersonCard.js +5 -5
- package/lib/components/OrganizationChart/utils.js +79 -79
- package/lib/components/ProjectCard/ActiveProjectCard.js +7 -23
- package/lib/components/ProjectCard/ProgressBar.js +4 -4
- package/lib/components/ProjectCard/ReviewRequestModal.js +5 -5
- package/lib/components/ProjectCard/RightCardUI.d.ts +1 -2
- package/lib/components/ProjectCard/RightCardUI.js +2 -2
- package/lib/components/Reviews/Pagination.js +6 -6
- package/lib/components/ReviewsTab/RatingHeader.js +6 -6
- package/lib/components/ReviewsTab/expert-shared-components.code-workspace +20 -20
- package/lib/components/ReviewsTab/reviewRequestModal.js +5 -5
- package/lib/components/shared/Image.js +13 -13
- package/lib/components/shared/ProfileTextField.d.ts +18 -18
- package/lib/components/shared/ProfileTextField.js +16 -16
- package/lib/components/shared/StyledActionButtons.d.ts +7 -7
- package/lib/components/shared/StyledActionButtons.js +15 -15
- package/lib/components/shared/ToastNotification.d.ts +10 -10
- package/lib/components/shared/ToastNotification.js +63 -63
- package/package.json +61 -61
|
@@ -73,6 +73,9 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
73
73
|
};
|
|
74
74
|
const getTotalApprovedHours = () => {
|
|
75
75
|
var _a;
|
|
76
|
+
if (resolution === 'DECLINED') {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
76
79
|
if (resolution === 'PARTIAL' && ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
77
80
|
return Object.values(projectApprovedHours).reduce((sum, hours) => sum + hours, 0);
|
|
78
81
|
}
|
|
@@ -106,7 +109,7 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
106
109
|
const disputeProjectUpdates = ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.map((project) => ({
|
|
107
110
|
projectId: project.projectId,
|
|
108
111
|
resolutionMode: 'Direct',
|
|
109
|
-
resolutionType: resolutionType
|
|
112
|
+
resolutionType: resolution === 'DECLINED' ? 'Canceled' : resolutionType
|
|
110
113
|
}))) || [];
|
|
111
114
|
// Calculate approved amount based on dispute types
|
|
112
115
|
const hasNonHourlyProjects = (_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.some((project) => project.disputeType !== 'Hourly');
|
|
@@ -181,9 +184,9 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
181
184
|
react_1.default.createElement("div", { className: "text-xs text-gray-500" }, project.disputeType === 'Hourly'
|
|
182
185
|
? `Disputed Hours: ${project.disputeHours}`
|
|
183
186
|
: `Dispute Amount: $${((_a = project.disputeAmount) === null || _a === void 0 ? void 0 : _a.toFixed(2)) || '0.00'}`)),
|
|
184
|
-
react_1.default.createElement("div", { className: "w-32" }, project.disputeType === 'Hourly' ? (react_1.default.createElement("input", { type: "number", step: "
|
|
187
|
+
react_1.default.createElement("div", { className: "w-32" }, project.disputeType === 'Hourly' ? (react_1.default.createElement("input", { type: "number", step: "1", min: "0", max: project.disputeHours, value: projectApprovedHours[project.projectId] || '', onChange: (e) => handleProjectHoursChange(project.projectId, parseFloat(e.target.value) || 0), className: "w-full px-2 py-1 border border-[#CCCCCC] rounded text-sm focus:outline-none focus:ring-2 focus:ring-[#248384]", placeholder: "Hours" })) : (react_1.default.createElement("div", { className: "relative" },
|
|
185
188
|
react_1.default.createElement("span", { className: "absolute left-2 top-1/2 transform -translate-y-1/2 text-gray-500" }, "$"),
|
|
186
|
-
react_1.default.createElement("input", { type: "number", step: "
|
|
189
|
+
react_1.default.createElement("input", { type: "number", step: "1", min: "0", max: project.disputeAmount, value: projectApprovedHours[project.projectId] || '', onChange: (e) => handleProjectHoursChange(project.projectId, parseFloat(e.target.value) || 0), className: "w-full pl-2 pr-2 py-1 border border-[#CCCCCC] rounded text-sm focus:outline-none focus:ring-2 focus:ring-[#248384]", placeholder: "0.00" }))))));
|
|
187
190
|
})),
|
|
188
191
|
react_1.default.createElement("div", { className: "text-sm text-gray-600" }, dispute.disputeProjects.some((p) => p.disputeType === 'Hourly') &&
|
|
189
192
|
dispute.disputeProjects.some((p) => p.disputeType !== 'Hourly') ? (
|
|
@@ -215,7 +218,6 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
215
218
|
// All non-hourly disputes
|
|
216
219
|
`Total Approved Amount: $${getTotalApprovedHours().toFixed(2)} / $${dispute.disputeProjects.reduce((sum, p) => sum + p.disputeAmount, 0).toFixed(2)}`)))),
|
|
217
220
|
react_1.default.createElement("div", { className: "flex justify-end space-x-4" },
|
|
218
|
-
react_1.default.createElement(base_ui_1.Button, { label: "Decline Dispute", color: "error", onClick: () => handleResolutionChange('DECLINED'), disabled: isSubmitting, size: "md" }),
|
|
219
221
|
react_1.default.createElement(base_ui_1.Button, { label: "Approve & Resolve", color: "primary", onClick: handleApproveClick, isLoading: isSubmitting, disabled: !resolution || (resolution === 'PARTIAL' && !isValidPartialApproval()), size: "md" }))),
|
|
220
222
|
react_1.default.createElement(ProjectHoursAdjustmentModal_1.ProjectHoursAdjustmentModal, { isOpen: showHoursModal, onClose: () => setShowHoursModal(false), disputeProjects: (dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) || [], dispute: dispute, onSubmit: handleHoursSubmit, isSubmitting: isSubmitting, getClientInvoiceSummaryByMonth: getClientInvoiceSummaryByMonth, invoiceSummary: invoiceSummary, approvedHours: resolution === 'PARTIAL' ? getTotalApprovedHours() : totalDisputeHours, projectApprovedHours: isPartialWithMultipleProjects ? projectApprovedHours : {}, user: user })));
|
|
221
223
|
};
|
|
@@ -10,35 +10,38 @@ const InvoiceHeader = ({ invoice, isInternal = false, isClient = false }) => {
|
|
|
10
10
|
var _a, _b, _c, _d, _e, _f;
|
|
11
11
|
const disputeAmount = (_a = invoice === null || invoice === void 0 ? void 0 : invoice.disputeProjects) === null || _a === void 0 ? void 0 : _a.reduce((acc, project) => acc + (project === null || project === void 0 ? void 0 : project.disputeAmount), 0);
|
|
12
12
|
return (react_1.default.createElement("div", { className: "bg-[#0F172A] w-full text-white px-6 py-4 rounded-t-lg flex items-center justify-between font-arial" },
|
|
13
|
-
react_1.default.createElement("div", { className: "flex items-center space-x-
|
|
13
|
+
react_1.default.createElement("div", { className: "flex items-center space-x-4 overflow-x-auto" },
|
|
14
|
+
react_1.default.createElement("div", { className: "flex-shrink-0" },
|
|
15
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Dispute #:"),
|
|
16
|
+
react_1.default.createElement("span", { className: "ml-1" }, invoice === null || invoice === void 0 ? void 0 : invoice.disputeId)),
|
|
17
|
+
react_1.default.createElement("div", { className: "flex-shrink-0" },
|
|
18
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Invoice #:"),
|
|
19
|
+
react_1.default.createElement("span", { className: "ml-1" }, (_b = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _b === void 0 ? void 0 : _b.id)),
|
|
20
|
+
!isClient && (react_1.default.createElement("div", { className: "flex-shrink-0" },
|
|
21
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Client:"),
|
|
22
|
+
react_1.default.createElement("span", { className: "ml-1" }, (_c = invoice === null || invoice === void 0 ? void 0 : invoice.client) === null || _c === void 0 ? void 0 : _c.name))),
|
|
14
23
|
react_1.default.createElement("div", null,
|
|
15
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "
|
|
16
|
-
react_1.default.createElement("span", { className: "ml-
|
|
17
|
-
!isClient && (react_1.default.createElement("div", null,
|
|
18
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Client: "),
|
|
19
|
-
react_1.default.createElement("span", { className: "ml-2" }, (_c = invoice === null || invoice === void 0 ? void 0 : invoice.client) === null || _c === void 0 ? void 0 : _c.name))),
|
|
20
|
-
react_1.default.createElement("div", null,
|
|
21
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Amount: "),
|
|
22
|
-
react_1.default.createElement("span", { className: "ml-2" },
|
|
24
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Amount:"),
|
|
25
|
+
react_1.default.createElement("span", { className: "ml-1" },
|
|
23
26
|
"$",
|
|
24
27
|
disputeAmount)),
|
|
25
28
|
react_1.default.createElement("div", null,
|
|
26
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "
|
|
27
|
-
react_1.default.createElement("span", { className: "ml-
|
|
29
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Date:"),
|
|
30
|
+
react_1.default.createElement("span", { className: "ml-1" }, (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeDate).format('MMM D, YYYY'))),
|
|
28
31
|
react_1.default.createElement("div", null,
|
|
29
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Invoice Date:
|
|
30
|
-
react_1.default.createElement("span", { className: "ml-
|
|
32
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Invoice Date:"),
|
|
33
|
+
react_1.default.createElement("span", { className: "ml-1" }, (0, dayjs_1.default)((_d = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _d === void 0 ? void 0 : _d.dateGenerated).format('MMM D, YYYY'))),
|
|
31
34
|
react_1.default.createElement("div", null,
|
|
32
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "
|
|
33
|
-
react_1.default.createElement("span", { className: "ml-
|
|
34
|
-
(invoice === null || invoice === void 0 ? void 0 : invoice.approvedAmount) && (react_1.default.createElement("div", null,
|
|
35
|
-
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Approved Amount:
|
|
36
|
-
react_1.default.createElement("span", { className: "ml-
|
|
35
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Status:"),
|
|
36
|
+
react_1.default.createElement("span", { className: "ml-1" }, (invoice === null || invoice === void 0 ? void 0 : invoice.status) === "InProgress" ? "In Progress" : invoice === null || invoice === void 0 ? void 0 : invoice.status)),
|
|
37
|
+
(invoice === null || invoice === void 0 ? void 0 : invoice.approvedAmount) >= 0 && (invoice === null || invoice === void 0 ? void 0 : invoice.status) === 'Resolved' && (react_1.default.createElement("div", null,
|
|
38
|
+
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Approved Amount:"),
|
|
39
|
+
react_1.default.createElement("span", { className: "ml-1" },
|
|
37
40
|
"$", invoice === null || invoice === void 0 ? void 0 :
|
|
38
41
|
invoice.approvedAmount))),
|
|
39
42
|
!isInternal && (react_1.default.createElement("div", null,
|
|
40
43
|
react_1.default.createElement("span", { className: "text-sm font-bold" }, "Expert Name: "),
|
|
41
|
-
react_1.default.createElement("span", { className: "ml-
|
|
44
|
+
react_1.default.createElement("span", { className: "ml-1" }, (_e = invoice === null || invoice === void 0 ? void 0 : invoice.freelancer) === null || _e === void 0 ? void 0 :
|
|
42
45
|
_e.firstName,
|
|
43
46
|
" ", (_f = invoice === null || invoice === void 0 ? void 0 : invoice.freelancer) === null || _f === void 0 ? void 0 :
|
|
44
47
|
_f.lastName))))));
|
|
@@ -69,12 +69,9 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
69
69
|
setLoading(true);
|
|
70
70
|
try {
|
|
71
71
|
if ((_a = invoiceSummary === null || invoiceSummary === void 0 ? void 0 : invoiceSummary.getClientInvoiceSummaryByMonth) === null || _a === void 0 ? void 0 : _a.projects) {
|
|
72
|
-
// Group tasks by project based on disputeProjects
|
|
73
72
|
const projectSectionsData = [];
|
|
74
73
|
disputeProjects.forEach(disputeProject => {
|
|
75
|
-
// Find matching project in invoice summary
|
|
76
74
|
const invoiceProject = invoiceSummary.getClientInvoiceSummaryByMonth.projects.find((proj) => {
|
|
77
|
-
// Match by project name since we don't have direct projectId mapping
|
|
78
75
|
return proj.projectName === disputeProject.project.name;
|
|
79
76
|
});
|
|
80
77
|
if (invoiceProject) {
|
|
@@ -90,14 +87,23 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
90
87
|
}
|
|
91
88
|
});
|
|
92
89
|
setProjectSections(projectSectionsData);
|
|
93
|
-
// Initialize adjusted hours for all tasks
|
|
94
90
|
const initialAdjustedHours = {};
|
|
95
91
|
projectSectionsData.forEach(section => {
|
|
96
92
|
section.tasks.forEach(task => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
93
|
+
if (section.disputeType !== 'Hourly') {
|
|
94
|
+
initialAdjustedHours[task.projectHourId] = {
|
|
95
|
+
originalAmount: parseFloat((task.hours * task.rate).toFixed(2)),
|
|
96
|
+
newAmount: parseFloat((task.hours * task.rate).toFixed(2)),
|
|
97
|
+
originalHours: parseFloat(task.hours.toFixed(2)),
|
|
98
|
+
newHours: parseFloat(task.hours.toFixed(2))
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
initialAdjustedHours[task.projectHourId] = {
|
|
103
|
+
originalHours: parseFloat(task.hours.toFixed(2)),
|
|
104
|
+
newHours: parseFloat(task.hours.toFixed(2))
|
|
105
|
+
};
|
|
106
|
+
}
|
|
101
107
|
});
|
|
102
108
|
});
|
|
103
109
|
setAdjustedHours(initialAdjustedHours);
|
|
@@ -115,12 +121,10 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
115
121
|
});
|
|
116
122
|
const handleHourChange = (projectHourId, newHours) => {
|
|
117
123
|
var _a;
|
|
118
|
-
const numericValue = parseFloat(newHours)
|
|
124
|
+
const numericValue = parseFloat(newHours);
|
|
119
125
|
const originalHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.originalHours) || 0;
|
|
120
126
|
setAdjustedHours(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: Object.assign(Object.assign({}, prev[projectHourId]), { newHours: numericValue }) })));
|
|
121
|
-
// Clear individual hour error
|
|
122
127
|
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: '' })));
|
|
123
|
-
// Validate individual hour
|
|
124
128
|
if (numericValue > originalHours) {
|
|
125
129
|
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'New hours cannot exceed original hours' })));
|
|
126
130
|
}
|
|
@@ -128,6 +132,19 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
128
132
|
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'Hours cannot be negative' })));
|
|
129
133
|
}
|
|
130
134
|
};
|
|
135
|
+
const handleAmountChange = (projectHourId, newAmount) => {
|
|
136
|
+
var _a;
|
|
137
|
+
const numericValue = parseFloat(newAmount);
|
|
138
|
+
const originalAmount = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.originalAmount) || 0;
|
|
139
|
+
setAdjustedHours(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: Object.assign(Object.assign({}, prev[projectHourId]), { newAmount: numericValue }) })));
|
|
140
|
+
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: '' })));
|
|
141
|
+
if (numericValue > originalAmount) {
|
|
142
|
+
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'New Dispute Amount cannot exceed original Amount' })));
|
|
143
|
+
}
|
|
144
|
+
else if (numericValue < 0) {
|
|
145
|
+
setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'Dispute Amount cannot be negative' })));
|
|
146
|
+
}
|
|
147
|
+
};
|
|
131
148
|
const getProjectTotalHours = (projectId, type) => {
|
|
132
149
|
const section = projectSections.find(s => s.projectId === projectId);
|
|
133
150
|
if (!section)
|
|
@@ -136,7 +153,7 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
136
153
|
const adjustment = adjustedHours[task.projectHourId];
|
|
137
154
|
if (!adjustment)
|
|
138
155
|
return total;
|
|
139
|
-
return total + (type === 'original' ? adjustment.originalHours : adjustment.newHours);
|
|
156
|
+
return total + (type === 'original' ? adjustment.originalHours || 0 : adjustment.newHours || 0);
|
|
140
157
|
}, 0);
|
|
141
158
|
};
|
|
142
159
|
const getProjectTotalAmount = (projectId, type) => {
|
|
@@ -147,8 +164,8 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
147
164
|
const adjustment = adjustedHours[task.projectHourId];
|
|
148
165
|
if (!adjustment)
|
|
149
166
|
return total;
|
|
150
|
-
const
|
|
151
|
-
return total +
|
|
167
|
+
const newAmount = type === 'original' ? adjustment.originalAmount || 0 : adjustment.newAmount || 0;
|
|
168
|
+
return total + newAmount; // Calculate amount based on hours * rate
|
|
152
169
|
}, 0);
|
|
153
170
|
};
|
|
154
171
|
const getProjectReduction = (projectId) => {
|
|
@@ -167,32 +184,37 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
167
184
|
let hasErrors = false;
|
|
168
185
|
const newErrors = {};
|
|
169
186
|
const newProjectErrors = {};
|
|
170
|
-
// Validate each project section
|
|
171
187
|
projectSections.forEach(section => {
|
|
172
188
|
const projectId = section.projectId;
|
|
173
|
-
const disputeHours = section.disputeHours;
|
|
174
|
-
// Use project-specific approved hours if available, otherwise use dispute hours
|
|
175
189
|
const maxAllowedReduction = projectApprovedHours[projectId] !== undefined
|
|
176
190
|
? projectApprovedHours[projectId]
|
|
177
191
|
: section.disputeType === 'Hourly'
|
|
178
192
|
? section.disputeHours
|
|
179
193
|
: section.disputeAmount;
|
|
180
|
-
// Validate individual hours within this project
|
|
181
194
|
section.tasks.forEach(task => {
|
|
182
|
-
var _a, _b;
|
|
195
|
+
var _a, _b, _c, _d;
|
|
183
196
|
const projectHourId = task.projectHourId;
|
|
184
197
|
const originalHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.originalHours) || 0;
|
|
185
|
-
const newHours = (
|
|
186
|
-
|
|
198
|
+
const newHours = (_b = adjustedHours[projectHourId]) === null || _b === void 0 ? void 0 : _b.newHours;
|
|
199
|
+
const newAmount = (_c = adjustedHours[projectHourId]) === null || _c === void 0 ? void 0 : _c.newAmount;
|
|
200
|
+
const originalAmount = ((_d = adjustedHours[projectHourId]) === null || _d === void 0 ? void 0 : _d.originalAmount) || 0;
|
|
201
|
+
if (newHours && newHours > originalHours) {
|
|
187
202
|
newErrors[projectHourId] = 'New hours cannot exceed original hours';
|
|
188
203
|
hasErrors = true;
|
|
189
204
|
}
|
|
190
|
-
else if (newHours < 0) {
|
|
205
|
+
else if (newHours && newHours < 0) {
|
|
191
206
|
newErrors[projectHourId] = 'Hours cannot be negative';
|
|
192
207
|
hasErrors = true;
|
|
193
208
|
}
|
|
209
|
+
else if (newAmount && newAmount < 0) {
|
|
210
|
+
newErrors[projectHourId] = 'Dispute Amount cannot be negative';
|
|
211
|
+
hasErrors = true;
|
|
212
|
+
}
|
|
213
|
+
else if (newAmount && newAmount > originalAmount) {
|
|
214
|
+
newErrors[projectHourId] = 'New Dispute Amount cannot exceed original Amount';
|
|
215
|
+
hasErrors = true;
|
|
216
|
+
}
|
|
194
217
|
});
|
|
195
|
-
// Validate project-level hour reduction
|
|
196
218
|
const projectReduction = getProjectReduction(projectId);
|
|
197
219
|
if (Math.abs(projectReduction - maxAllowedReduction) > 0.01) {
|
|
198
220
|
const reductionType = projectApprovedHours[projectId] !== undefined ? 'approved' : 'disputed';
|
|
@@ -204,40 +226,30 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
204
226
|
setErrors(newErrors);
|
|
205
227
|
setProjectErrors(newProjectErrors);
|
|
206
228
|
if (!hasErrors) {
|
|
207
|
-
// Generate the submission data in the required format
|
|
208
229
|
let freelancerRate = 0;
|
|
209
230
|
const inputArray = [];
|
|
210
231
|
projectSections.forEach(section => {
|
|
211
232
|
section.tasks.forEach(task => {
|
|
212
233
|
const projectHourId = task.projectHourId;
|
|
213
234
|
const adjustedHour = adjustedHours[projectHourId];
|
|
235
|
+
const newHours = adjustedHour === null || adjustedHour === void 0 ? void 0 : adjustedHour.newHours;
|
|
214
236
|
freelancerRate = task.freelancerRate;
|
|
215
|
-
|
|
216
|
-
let calculatedHours = (adjustedHour === null || adjustedHour === void 0 ? void 0 : adjustedHour.newHours) || 0;
|
|
237
|
+
let calculatedHours = newHours || 0;
|
|
217
238
|
if (section.disputeType !== 'Hourly') {
|
|
218
|
-
// For non-hourly projects, calculate hour equivalent based on approved dispute amount ratio
|
|
219
239
|
const approvedDisputeAmount = projectApprovedHours[section.projectId] !== undefined
|
|
220
240
|
? projectApprovedHours[section.projectId]
|
|
221
241
|
: section.disputeAmount;
|
|
222
242
|
const totalProjectAmount = section.totalProjectAmount;
|
|
223
243
|
if (totalProjectAmount > 0) {
|
|
224
|
-
// Calculate the ratio of approved dispute amount to total project amount
|
|
225
244
|
const disputeRatio = approvedDisputeAmount / totalProjectAmount;
|
|
226
|
-
// Apply this ratio to the original hours for this task
|
|
227
245
|
const originalTaskHours = (adjustedHour === null || adjustedHour === void 0 ? void 0 : adjustedHour.originalHours) || 0;
|
|
228
|
-
// The reduction in hours should be proportional to the dispute ratio
|
|
229
246
|
const hourReduction = originalTaskHours * disputeRatio;
|
|
230
247
|
calculatedHours = originalTaskHours - hourReduction;
|
|
231
|
-
|
|
232
|
-
calculatedHours = Math.max(0, calculatedHours);
|
|
248
|
+
calculatedHours = Number(Math.max(0, calculatedHours).toFixed(4));
|
|
233
249
|
}
|
|
234
250
|
}
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
`${dispute.freelancer.firstName} ${dispute.freelancer.lastName}` : '';
|
|
238
|
-
// Generate internal user name
|
|
239
|
-
const internalUser = user ?
|
|
240
|
-
`${user.firstName} ${user.lastName}` : '';
|
|
251
|
+
const expertName = (dispute === null || dispute === void 0 ? void 0 : dispute.freelancer) ? `${dispute.freelancer.firstName} ${dispute.freelancer.lastName}` : '';
|
|
252
|
+
const internalUser = user ? `${user.firstName} ${user.lastName}` : '';
|
|
241
253
|
inputArray.push({
|
|
242
254
|
clientRate: task.rate,
|
|
243
255
|
freelancerRate: task.freelancerRate,
|
|
@@ -301,7 +313,7 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
301
313
|
: "Please enter the new hours to settle the dispute for each of the project time log entries below"),
|
|
302
314
|
react_1.default.createElement("div", { className: "space-y-8" }, projectSections.map((section) => {
|
|
303
315
|
var _a, _b;
|
|
304
|
-
const projectReduction = getProjectReduction(section.projectId);
|
|
316
|
+
const projectReduction = getProjectReduction(section.projectId) || 0;
|
|
305
317
|
const maxAllowedReduction = projectApprovedHours[section.projectId] !== undefined
|
|
306
318
|
? projectApprovedHours[section.projectId]
|
|
307
319
|
: section.disputeType === 'Hourly'
|
|
@@ -359,26 +371,24 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
359
371
|
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, section.disputeType === 'Hourly' ? 'Original Hours' : 'Original Dispute $'),
|
|
360
372
|
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, section.disputeType === 'Hourly' ? 'Adjusted Hours' : 'Adjusted $ Amount'))),
|
|
361
373
|
react_1.default.createElement("tbody", null, section.tasks.map((task) => {
|
|
362
|
-
var _a, _b;
|
|
374
|
+
var _a, _b, _c;
|
|
363
375
|
const projectHourId = task.projectHourId;
|
|
364
376
|
const originalHours = task.hours;
|
|
365
377
|
const originalAmount = task.hours * task.rate;
|
|
366
|
-
const newHours = (
|
|
367
|
-
const newAmount =
|
|
378
|
+
const newHours = (_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.newHours;
|
|
379
|
+
const newAmount = (_b = adjustedHours[projectHourId]) === null || _b === void 0 ? void 0 : _b.newAmount;
|
|
368
380
|
const hasError = errors[projectHourId];
|
|
369
381
|
return (react_1.default.createElement("tr", { key: projectHourId, className: hasError ? 'bg-red-50' : '' },
|
|
370
382
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, formatDate(task.date)),
|
|
371
383
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, task.description),
|
|
372
384
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, section.disputeType === 'Hourly'
|
|
373
385
|
? originalHours.toFixed(2)
|
|
374
|
-
: `$${((
|
|
386
|
+
: `$${((_c = section.disputeAmount) === null || _c === void 0 ? void 0 : _c.toFixed(2)) || '0.00'}`),
|
|
375
387
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" },
|
|
376
388
|
react_1.default.createElement("div", null,
|
|
377
|
-
section.disputeType === 'Hourly' ? (react_1.default.createElement("input", { type: "number", step: "
|
|
389
|
+
section.disputeType === 'Hourly' ? (react_1.default.createElement("input", { type: "number", step: "1", max: originalHours, value: newHours !== undefined && newHours >= 0 ? newHours : '', onChange: (e) => handleHourChange(projectHourId, e.target.value), className: `w-full px-2 py-1 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 ${hasError ? 'border-red-500' : 'border-gray-300'}` })) : (react_1.default.createElement("div", { className: "flex items-center" },
|
|
378
390
|
react_1.default.createElement("span", { className: "mr-1" }, "$"),
|
|
379
|
-
react_1.default.createElement("
|
|
380
|
-
react_1.default.createElement("input", { type: "number", step: "0.01", min: "0", max: originalHours, value: newHours, onChange: (e) => handleHourChange(projectHourId, e.target.value), className: `ml-2 w-20 px-2 py-1 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 ${hasError ? 'border-red-500' : 'border-gray-300'}`, placeholder: "hrs" }),
|
|
381
|
-
react_1.default.createElement("span", { className: "ml-1 text-xs text-gray-500" }, "hrs"))),
|
|
391
|
+
react_1.default.createElement("input", { type: "number", step: "1", min: "0", max: originalAmount, value: newAmount !== undefined && newAmount >= 0 ? newAmount : '', onChange: (e) => handleAmountChange(projectHourId, (e.target.value).toString()), className: `w-32 px-2 py-1 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 ${hasError ? 'border-red-500' : 'border-gray-300'}`, placeholder: "$0.00" }))),
|
|
382
392
|
hasError && (react_1.default.createElement("div", { className: "text-red-500 text-xs mt-1" }, hasError))))));
|
|
383
393
|
}))))));
|
|
384
394
|
})),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const TestDecisionSection: () => JSX.Element;
|
|
1
|
+
export declare const TestDecisionSection: () => JSX.Element;
|
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.TestDecisionSection = void 0;
|
|
16
|
-
const react_1 = __importDefault(require("react"));
|
|
17
|
-
const DecisionSection_1 = require("./DecisionSection");
|
|
18
|
-
// Test data from the provided JSON
|
|
19
|
-
const testDispute = {
|
|
20
|
-
"__typename": "ClientInvoiceDispute",
|
|
21
|
-
"disputeId": 35,
|
|
22
|
-
"approvedAmount": 450,
|
|
23
|
-
"chatEnabled": true,
|
|
24
|
-
"disputeDate": "2025-05-22",
|
|
25
|
-
"disputeUpdatedDate": "2025-05-23",
|
|
26
|
-
"freelancerId": 8081,
|
|
27
|
-
"freelancer": {
|
|
28
|
-
"__typename": "User",
|
|
29
|
-
"id": 8081,
|
|
30
|
-
"email": "andpande@gmail.com",
|
|
31
|
-
"firstName": "William",
|
|
32
|
-
"lastName": "Annon"
|
|
33
|
-
},
|
|
34
|
-
"status": "Resolved",
|
|
35
|
-
"finalDecisionOwnerId": 29005,
|
|
36
|
-
"invoice": {
|
|
37
|
-
"__typename": "ClientInvoice",
|
|
38
|
-
"amount": 450,
|
|
39
|
-
"balanceDue": 450,
|
|
40
|
-
"clientId": 4433,
|
|
41
|
-
"dateGenerated": "2025-04-14",
|
|
42
|
-
"id": 175325,
|
|
43
|
-
"month": "2025-04-01"
|
|
44
|
-
},
|
|
45
|
-
"disputeProjects": [
|
|
46
|
-
{
|
|
47
|
-
"__typename": "ClientInvoiceDisputeProject",
|
|
48
|
-
"id": 37,
|
|
49
|
-
"projectId": 19158,
|
|
50
|
-
"disputeAmount": 450,
|
|
51
|
-
"disputeHours": 30,
|
|
52
|
-
"disputeType": "Hourly",
|
|
53
|
-
"disputeReasonCode": "Incorrect Hours Logged",
|
|
54
|
-
"clientExplanation": "I have a dispute over this expert for the current invoice 175325",
|
|
55
|
-
"clientDocumentLinks": "https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2Ftesting.pdf,https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2F_Carmelita_Resume-Graduation__1_.docx",
|
|
56
|
-
"expertDocumentLinks": "https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2F0eb4b31b-b6d8-4cd1-b6ac-39b807ea4577.pdf",
|
|
57
|
-
"resolutionMode": null,
|
|
58
|
-
"resolutionType": null,
|
|
59
|
-
"project": {
|
|
60
|
-
"__typename": "Project",
|
|
61
|
-
"name": "Ongoing Ad-Hoc Support",
|
|
62
|
-
"freelancerRate": null,
|
|
63
|
-
"clientRate": null,
|
|
64
|
-
"projectHours": [
|
|
65
|
-
{
|
|
66
|
-
"__typename": "ProjectHour",
|
|
67
|
-
"id": 136605,
|
|
68
|
-
"date": "2022-02-11",
|
|
69
|
-
"description": "Ate Tacos",
|
|
70
|
-
"hours": 8
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"__typename": "ProjectHour",
|
|
74
|
-
"id": 136606,
|
|
75
|
-
"date": "2022-02-12",
|
|
76
|
-
"description": "Worked on project analysis",
|
|
77
|
-
"hours": 6
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"__typename": "ProjectHour",
|
|
81
|
-
"id": 136607,
|
|
82
|
-
"date": "2022-02-13",
|
|
83
|
-
"description": "Client meeting and documentation",
|
|
84
|
-
"hours": 4
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"__typename": "ProjectHour",
|
|
88
|
-
"id": 136608,
|
|
89
|
-
"date": "2022-02-14",
|
|
90
|
-
"description": "Code review and testing",
|
|
91
|
-
"hours": 7
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"__typename": "ProjectHour",
|
|
95
|
-
"id": 136609,
|
|
96
|
-
"date": "2022-02-15",
|
|
97
|
-
"description": "Final deliverable preparation",
|
|
98
|
-
"hours": 5
|
|
99
|
-
}
|
|
100
|
-
]
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
],
|
|
104
|
-
"lastMessageAt": "2025-05-23T10:56:53.000Z",
|
|
105
|
-
"messageCount": 5,
|
|
106
|
-
"client": {
|
|
107
|
-
"__typename": "Client",
|
|
108
|
-
"name": "Vessel Advisors"
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const testUser = {
|
|
112
|
-
userId: 29005,
|
|
113
|
-
firstName: "Test",
|
|
114
|
-
lastName: "User"
|
|
115
|
-
};
|
|
116
|
-
const TestDecisionSection = () => {
|
|
117
|
-
const mockOnUpdateDispute = (variables) => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
-
console.log('Mock update dispute called with:', variables);
|
|
119
|
-
return Promise.resolve({ success: true });
|
|
120
|
-
});
|
|
121
|
-
const mockUpdateInvoiceMutation = {};
|
|
122
|
-
return (react_1.default.createElement("div", { className: "p-8 max-w-4xl mx-auto" },
|
|
123
|
-
react_1.default.createElement("h1", { className: "text-2xl font-bold mb-6" }, "Test Decision Section with Hours Modal"),
|
|
124
|
-
react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: testDispute, onUpdateDispute: mockOnUpdateDispute, updateInvoiceMutation: mockUpdateInvoiceMutation, user: testUser })));
|
|
125
|
-
};
|
|
126
|
-
exports.TestDecisionSection = TestDecisionSection;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.TestDecisionSection = void 0;
|
|
16
|
+
const react_1 = __importDefault(require("react"));
|
|
17
|
+
const DecisionSection_1 = require("./DecisionSection");
|
|
18
|
+
// Test data from the provided JSON
|
|
19
|
+
const testDispute = {
|
|
20
|
+
"__typename": "ClientInvoiceDispute",
|
|
21
|
+
"disputeId": 35,
|
|
22
|
+
"approvedAmount": 450,
|
|
23
|
+
"chatEnabled": true,
|
|
24
|
+
"disputeDate": "2025-05-22",
|
|
25
|
+
"disputeUpdatedDate": "2025-05-23",
|
|
26
|
+
"freelancerId": 8081,
|
|
27
|
+
"freelancer": {
|
|
28
|
+
"__typename": "User",
|
|
29
|
+
"id": 8081,
|
|
30
|
+
"email": "andpande@gmail.com",
|
|
31
|
+
"firstName": "William",
|
|
32
|
+
"lastName": "Annon"
|
|
33
|
+
},
|
|
34
|
+
"status": "Resolved",
|
|
35
|
+
"finalDecisionOwnerId": 29005,
|
|
36
|
+
"invoice": {
|
|
37
|
+
"__typename": "ClientInvoice",
|
|
38
|
+
"amount": 450,
|
|
39
|
+
"balanceDue": 450,
|
|
40
|
+
"clientId": 4433,
|
|
41
|
+
"dateGenerated": "2025-04-14",
|
|
42
|
+
"id": 175325,
|
|
43
|
+
"month": "2025-04-01"
|
|
44
|
+
},
|
|
45
|
+
"disputeProjects": [
|
|
46
|
+
{
|
|
47
|
+
"__typename": "ClientInvoiceDisputeProject",
|
|
48
|
+
"id": 37,
|
|
49
|
+
"projectId": 19158,
|
|
50
|
+
"disputeAmount": 450,
|
|
51
|
+
"disputeHours": 30,
|
|
52
|
+
"disputeType": "Hourly",
|
|
53
|
+
"disputeReasonCode": "Incorrect Hours Logged",
|
|
54
|
+
"clientExplanation": "I have a dispute over this expert for the current invoice 175325",
|
|
55
|
+
"clientDocumentLinks": "https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2Ftesting.pdf,https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2F_Carmelita_Resume-Graduation__1_.docx",
|
|
56
|
+
"expertDocumentLinks": "https://expert-client-dispute-files.s3.amazonaws.com/project-19158%2F0eb4b31b-b6d8-4cd1-b6ac-39b807ea4577.pdf",
|
|
57
|
+
"resolutionMode": null,
|
|
58
|
+
"resolutionType": null,
|
|
59
|
+
"project": {
|
|
60
|
+
"__typename": "Project",
|
|
61
|
+
"name": "Ongoing Ad-Hoc Support",
|
|
62
|
+
"freelancerRate": null,
|
|
63
|
+
"clientRate": null,
|
|
64
|
+
"projectHours": [
|
|
65
|
+
{
|
|
66
|
+
"__typename": "ProjectHour",
|
|
67
|
+
"id": 136605,
|
|
68
|
+
"date": "2022-02-11",
|
|
69
|
+
"description": "Ate Tacos",
|
|
70
|
+
"hours": 8
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"__typename": "ProjectHour",
|
|
74
|
+
"id": 136606,
|
|
75
|
+
"date": "2022-02-12",
|
|
76
|
+
"description": "Worked on project analysis",
|
|
77
|
+
"hours": 6
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"__typename": "ProjectHour",
|
|
81
|
+
"id": 136607,
|
|
82
|
+
"date": "2022-02-13",
|
|
83
|
+
"description": "Client meeting and documentation",
|
|
84
|
+
"hours": 4
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"__typename": "ProjectHour",
|
|
88
|
+
"id": 136608,
|
|
89
|
+
"date": "2022-02-14",
|
|
90
|
+
"description": "Code review and testing",
|
|
91
|
+
"hours": 7
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"__typename": "ProjectHour",
|
|
95
|
+
"id": 136609,
|
|
96
|
+
"date": "2022-02-15",
|
|
97
|
+
"description": "Final deliverable preparation",
|
|
98
|
+
"hours": 5
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"lastMessageAt": "2025-05-23T10:56:53.000Z",
|
|
105
|
+
"messageCount": 5,
|
|
106
|
+
"client": {
|
|
107
|
+
"__typename": "Client",
|
|
108
|
+
"name": "Vessel Advisors"
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const testUser = {
|
|
112
|
+
userId: 29005,
|
|
113
|
+
firstName: "Test",
|
|
114
|
+
lastName: "User"
|
|
115
|
+
};
|
|
116
|
+
const TestDecisionSection = () => {
|
|
117
|
+
const mockOnUpdateDispute = (variables) => __awaiter(void 0, void 0, void 0, function* () {
|
|
118
|
+
console.log('Mock update dispute called with:', variables);
|
|
119
|
+
return Promise.resolve({ success: true });
|
|
120
|
+
});
|
|
121
|
+
const mockUpdateInvoiceMutation = {};
|
|
122
|
+
return (react_1.default.createElement("div", { className: "p-8 max-w-4xl mx-auto" },
|
|
123
|
+
react_1.default.createElement("h1", { className: "text-2xl font-bold mb-6" }, "Test Decision Section with Hours Modal"),
|
|
124
|
+
react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: testDispute, onUpdateDispute: mockOnUpdateDispute, updateInvoiceMutation: mockUpdateInvoiceMutation, user: testUser })));
|
|
125
|
+
};
|
|
126
|
+
exports.TestDecisionSection = TestDecisionSection;
|