@paro.io/expert-shared-components 1.12.18 → 1.12.19
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.
|
@@ -55,10 +55,12 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
55
55
|
var _a;
|
|
56
56
|
setResolution(newResolution);
|
|
57
57
|
if (newResolution === 'PARTIAL' && ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
58
|
-
// Initialize with dispute hours for each project
|
|
58
|
+
// Initialize with dispute hours/amount for each project based on dispute type
|
|
59
59
|
const initialProjectHours = {};
|
|
60
60
|
dispute.disputeProjects.forEach((project) => {
|
|
61
|
-
initialProjectHours[project.projectId] = project.
|
|
61
|
+
initialProjectHours[project.projectId] = project.disputeType === 'Hourly'
|
|
62
|
+
? project.disputeHours
|
|
63
|
+
: project.disputeAmount;
|
|
62
64
|
});
|
|
63
65
|
setProjectApprovedHours(initialProjectHours);
|
|
64
66
|
}
|
|
@@ -77,12 +79,10 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
77
79
|
return approvedHours;
|
|
78
80
|
};
|
|
79
81
|
const handleApproveClick = () => {
|
|
80
|
-
var _a;
|
|
81
82
|
if (!resolution)
|
|
82
83
|
return;
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
if (hasHourlyDisputes) {
|
|
84
|
+
// Show modal for PARTIAL or APPROVED resolutions regardless of dispute type
|
|
85
|
+
if (resolution === 'PARTIAL' || resolution === 'APPROVED') {
|
|
86
86
|
setShowHoursModal(true);
|
|
87
87
|
}
|
|
88
88
|
else {
|
|
@@ -94,7 +94,7 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
94
94
|
handleFinalSubmit(submissionData);
|
|
95
95
|
};
|
|
96
96
|
const handleFinalSubmit = (submissionData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
|
-
var _a;
|
|
97
|
+
var _a, _b;
|
|
98
98
|
setIsSubmitting(true);
|
|
99
99
|
try {
|
|
100
100
|
const finalApprovedHours = getTotalApprovedHours();
|
|
@@ -105,14 +105,18 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
105
105
|
// Update dispute projects with resolution details
|
|
106
106
|
const disputeProjectUpdates = ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.map((project) => ({
|
|
107
107
|
projectId: project.projectId,
|
|
108
|
-
status: 'Resolved',
|
|
109
108
|
resolutionMode: 'Direct',
|
|
110
109
|
resolutionType: resolutionType
|
|
111
110
|
}))) || [];
|
|
111
|
+
// Calculate approved amount based on dispute types
|
|
112
|
+
const hasNonHourlyProjects = (_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.some((project) => project.disputeType !== 'Hourly');
|
|
113
|
+
const calculatedApprovedAmount = hasNonHourlyProjects
|
|
114
|
+
? finalApprovedHours // For non-hourly projects, finalApprovedHours contains the dollar amount
|
|
115
|
+
: finalApprovedHours * ((submissionData === null || submissionData === void 0 ? void 0 : submissionData.freelancerRate) || 0); // For hourly projects, multiply by rate
|
|
112
116
|
const updateData = {
|
|
113
117
|
disputeId: dispute.disputeId,
|
|
114
118
|
status: "Resolved",
|
|
115
|
-
approvedAmount:
|
|
119
|
+
approvedAmount: calculatedApprovedAmount,
|
|
116
120
|
finalDecisionOwnerId: (user === null || user === void 0 ? void 0 : user.userId) || null,
|
|
117
121
|
projectDisputes: disputeProjectUpdates
|
|
118
122
|
};
|
|
@@ -149,10 +153,11 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
149
153
|
const isValidPartialApproval = () => {
|
|
150
154
|
if (resolution !== 'PARTIAL')
|
|
151
155
|
return true;
|
|
152
|
-
// Check each project's approved hours
|
|
156
|
+
// Check each project's approved hours/amount
|
|
153
157
|
return dispute.disputeProjects.every((project) => {
|
|
154
158
|
const approvedForProject = projectApprovedHours[project.projectId] || 0;
|
|
155
|
-
|
|
159
|
+
const maxAllowed = project.disputeType === 'Hourly' ? project.disputeHours : project.disputeAmount;
|
|
160
|
+
return approvedForProject >= 0 && approvedForProject <= maxAllowed;
|
|
156
161
|
});
|
|
157
162
|
};
|
|
158
163
|
return (react_1.default.createElement("div", { className: "space-y-6" },
|
|
@@ -167,21 +172,48 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
|
|
|
167
172
|
react_1.default.createElement("option", { value: "" }, "Select Resolution"),
|
|
168
173
|
RESOLUTION_OPTIONS.map((option) => (react_1.default.createElement("option", { key: option.value, value: option.value }, option.label))))))),
|
|
169
174
|
isPartialWithMultipleProjects && (react_1.default.createElement("div", { className: "space-y-4" },
|
|
170
|
-
react_1.default.createElement("div", { className: "text-sm font-bold text-[#666666]" }, "Approved
|
|
171
|
-
react_1.default.createElement("div", { className: "grid grid-cols-1 gap-4" }, dispute.disputeProjects.map((project) =>
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
react_1.default.createElement("div", { className: "
|
|
175
|
-
"
|
|
176
|
-
project.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
react_1.default.createElement("div", { className: "text-sm font-bold text-[#666666]" }, "Approved Values per Project:"),
|
|
176
|
+
react_1.default.createElement("div", { className: "grid grid-cols-1 gap-4" }, dispute.disputeProjects.map((project) => {
|
|
177
|
+
var _a;
|
|
178
|
+
return (react_1.default.createElement("div", { key: project.projectId, className: "flex items-center justify-between p-4 bg-white rounded-lg border border-[#CCCCCC]" },
|
|
179
|
+
react_1.default.createElement("div", { className: "flex-1" },
|
|
180
|
+
react_1.default.createElement("div", { className: "font-medium text-sm" }, project.project.name),
|
|
181
|
+
react_1.default.createElement("div", { className: "text-xs text-gray-500" }, project.disputeType === 'Hourly'
|
|
182
|
+
? `Disputed Hours: ${project.disputeHours}`
|
|
183
|
+
: `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: "0.01", min: "0", max: project.disputeHours, value: projectApprovedHours[project.projectId] || 0, 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
|
+
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: "0.01", min: "0", max: project.disputeAmount, value: projectApprovedHours[project.projectId] || 0, 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
|
+
})),
|
|
188
|
+
react_1.default.createElement("div", { className: "text-sm text-gray-600" }, dispute.disputeProjects.some((p) => p.disputeType === 'Hourly') &&
|
|
189
|
+
dispute.disputeProjects.some((p) => p.disputeType !== 'Hourly') ? (
|
|
190
|
+
// Mixed dispute types
|
|
191
|
+
react_1.default.createElement(react_1.default.Fragment, null,
|
|
180
192
|
"Total Approved Hours: ",
|
|
181
|
-
|
|
193
|
+
dispute.disputeProjects
|
|
194
|
+
.filter((p) => p.disputeType === 'Hourly')
|
|
195
|
+
.reduce((sum, p) => sum + (projectApprovedHours[p.projectId] || 0), 0)
|
|
196
|
+
.toFixed(2),
|
|
182
197
|
" / ",
|
|
183
|
-
|
|
184
|
-
|
|
198
|
+
dispute.disputeProjects
|
|
199
|
+
.filter((p) => p.disputeType === 'Hourly')
|
|
200
|
+
.reduce((sum, p) => sum + p.disputeHours, 0),
|
|
201
|
+
" hours",
|
|
202
|
+
react_1.default.createElement("br", null),
|
|
203
|
+
"Total Approved Amount: $",
|
|
204
|
+
dispute.disputeProjects
|
|
205
|
+
.filter((p) => p.disputeType !== 'Hourly')
|
|
206
|
+
.reduce((sum, p) => sum + (projectApprovedHours[p.projectId] || 0), 0)
|
|
207
|
+
.toFixed(2),
|
|
208
|
+
" / $",
|
|
209
|
+
dispute.disputeProjects
|
|
210
|
+
.filter((p) => p.disputeType !== 'Hourly')
|
|
211
|
+
.reduce((sum, p) => sum + p.disputeAmount, 0)
|
|
212
|
+
.toFixed(2))) : dispute.disputeProjects.every((p) => p.disputeType === 'Hourly') ? (
|
|
213
|
+
// All hourly disputes
|
|
214
|
+
`Total Approved Hours: ${getTotalApprovedHours().toFixed(2)} / ${totalDisputeHours} hours`) : (
|
|
215
|
+
// All non-hourly disputes
|
|
216
|
+
`Total Approved Amount: $${getTotalApprovedHours().toFixed(2)} / $${dispute.disputeProjects.reduce((sum, p) => sum + p.disputeAmount, 0).toFixed(2)}`)))),
|
|
185
217
|
react_1.default.createElement("div", { className: "flex justify-end space-x-4" },
|
|
186
218
|
react_1.default.createElement(base_ui_1.Button, { label: "Decline Dispute", color: "error", onClick: () => handleResolutionChange('DECLINED'), disabled: isSubmitting, size: "md" }),
|
|
187
219
|
react_1.default.createElement(base_ui_1.Button, { label: "Approve & Resolve", color: "primary", onClick: handleApproveClick, isLoading: isSubmitting, disabled: !resolution || (resolution === 'PARTIAL' && !isValidPartialApproval()), size: "md" }))),
|
|
@@ -82,6 +82,9 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
82
82
|
projectId: disputeProject.projectId,
|
|
83
83
|
projectName: disputeProject.project.name,
|
|
84
84
|
disputeHours: disputeProject.disputeHours,
|
|
85
|
+
disputeType: disputeProject.disputeType,
|
|
86
|
+
disputeAmount: disputeProject.disputeAmount,
|
|
87
|
+
totalProjectAmount: invoiceProject.totalProjectAmount || 0,
|
|
85
88
|
tasks: invoiceProject.tasks.map((task) => (Object.assign(Object.assign({}, task), { projectName: disputeProject.project.name })))
|
|
86
89
|
});
|
|
87
90
|
}
|
|
@@ -136,8 +139,28 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
136
139
|
return total + (type === 'original' ? adjustment.originalHours : adjustment.newHours);
|
|
137
140
|
}, 0);
|
|
138
141
|
};
|
|
142
|
+
const getProjectTotalAmount = (projectId, type) => {
|
|
143
|
+
const section = projectSections.find(s => s.projectId === projectId);
|
|
144
|
+
if (!section)
|
|
145
|
+
return 0;
|
|
146
|
+
return section.tasks.reduce((total, task) => {
|
|
147
|
+
const adjustment = adjustedHours[task.projectHourId];
|
|
148
|
+
if (!adjustment)
|
|
149
|
+
return total;
|
|
150
|
+
const hours = type === 'original' ? adjustment.originalHours : adjustment.newHours;
|
|
151
|
+
return total + (hours * task.rate); // Calculate amount based on hours * rate
|
|
152
|
+
}, 0);
|
|
153
|
+
};
|
|
139
154
|
const getProjectReduction = (projectId) => {
|
|
140
|
-
|
|
155
|
+
const section = projectSections.find(s => s.projectId === projectId);
|
|
156
|
+
if (!section)
|
|
157
|
+
return 0;
|
|
158
|
+
if (section.disputeType === 'Hourly') {
|
|
159
|
+
return getProjectTotalHours(projectId, 'original') - getProjectTotalHours(projectId, 'new');
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return getProjectTotalAmount(projectId, 'original') - getProjectTotalAmount(projectId, 'new');
|
|
163
|
+
}
|
|
141
164
|
};
|
|
142
165
|
const validateAndSubmit = () => {
|
|
143
166
|
var _a, _b, _c, _d;
|
|
@@ -151,7 +174,9 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
151
174
|
// Use project-specific approved hours if available, otherwise use dispute hours
|
|
152
175
|
const maxAllowedReduction = projectApprovedHours[projectId] !== undefined
|
|
153
176
|
? projectApprovedHours[projectId]
|
|
154
|
-
:
|
|
177
|
+
: section.disputeType === 'Hourly'
|
|
178
|
+
? section.disputeHours
|
|
179
|
+
: section.disputeAmount;
|
|
155
180
|
// Validate individual hours within this project
|
|
156
181
|
section.tasks.forEach(task => {
|
|
157
182
|
var _a, _b;
|
|
@@ -171,7 +196,8 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
171
196
|
const projectReduction = getProjectReduction(projectId);
|
|
172
197
|
if (Math.abs(projectReduction - maxAllowedReduction) > 0.01) {
|
|
173
198
|
const reductionType = projectApprovedHours[projectId] !== undefined ? 'approved' : 'disputed';
|
|
174
|
-
|
|
199
|
+
const unit = section.disputeType === 'Hourly' ? 'hours' : 'amount';
|
|
200
|
+
newProjectErrors[projectId] = `Hour reduction for this project (${projectReduction.toFixed(2)}) must equal ${reductionType} ${unit} (${maxAllowedReduction})`;
|
|
175
201
|
hasErrors = true;
|
|
176
202
|
}
|
|
177
203
|
});
|
|
@@ -186,6 +212,26 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
186
212
|
const projectHourId = task.projectHourId;
|
|
187
213
|
const adjustedHour = adjustedHours[projectHourId];
|
|
188
214
|
freelancerRate = task.freelancerRate;
|
|
215
|
+
// Calculate hours based on dispute type
|
|
216
|
+
let calculatedHours = (adjustedHour === null || adjustedHour === void 0 ? void 0 : adjustedHour.newHours) || 0;
|
|
217
|
+
if (section.disputeType !== 'Hourly') {
|
|
218
|
+
// For non-hourly projects, calculate hour equivalent based on approved dispute amount ratio
|
|
219
|
+
const approvedDisputeAmount = projectApprovedHours[section.projectId] !== undefined
|
|
220
|
+
? projectApprovedHours[section.projectId]
|
|
221
|
+
: section.disputeAmount;
|
|
222
|
+
const totalProjectAmount = section.totalProjectAmount;
|
|
223
|
+
if (totalProjectAmount > 0) {
|
|
224
|
+
// Calculate the ratio of approved dispute amount to total project amount
|
|
225
|
+
const disputeRatio = approvedDisputeAmount / totalProjectAmount;
|
|
226
|
+
// Apply this ratio to the original hours for this task
|
|
227
|
+
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
|
+
const hourReduction = originalTaskHours * disputeRatio;
|
|
230
|
+
calculatedHours = originalTaskHours - hourReduction;
|
|
231
|
+
// Ensure hours don't go negative
|
|
232
|
+
calculatedHours = Math.max(0, calculatedHours);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
189
235
|
// Generate expert name
|
|
190
236
|
const expertName = (dispute === null || dispute === void 0 ? void 0 : dispute.freelancer) ?
|
|
191
237
|
`${dispute.freelancer.firstName} ${dispute.freelancer.lastName}` : '';
|
|
@@ -195,7 +241,7 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
195
241
|
inputArray.push({
|
|
196
242
|
clientRate: task.rate,
|
|
197
243
|
freelancerRate: task.freelancerRate,
|
|
198
|
-
hours:
|
|
244
|
+
hours: calculatedHours,
|
|
199
245
|
projectId: section.projectId,
|
|
200
246
|
projectHourId: task.projectHourId,
|
|
201
247
|
projectName: section.projectName,
|
|
@@ -229,7 +275,9 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
229
275
|
const projectReduction = getProjectReduction(section.projectId);
|
|
230
276
|
const maxAllowedReduction = projectApprovedHours[section.projectId] !== undefined
|
|
231
277
|
? projectApprovedHours[section.projectId]
|
|
232
|
-
: section.
|
|
278
|
+
: section.disputeType === 'Hourly'
|
|
279
|
+
? section.disputeHours
|
|
280
|
+
: section.disputeAmount;
|
|
233
281
|
return Math.abs(projectReduction - maxAllowedReduction) <= 0.01;
|
|
234
282
|
});
|
|
235
283
|
};
|
|
@@ -248,12 +296,17 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
248
296
|
}
|
|
249
297
|
return (react_1.default.createElement(base_ui_1.Modal, { open: isOpen, onClose: onClose, size: "lg", className: "z-[100]" },
|
|
250
298
|
react_1.default.createElement("div", { className: "max-h-[80vh] overflow-y-auto" },
|
|
251
|
-
react_1.default.createElement("div", { className: "font-bold text-xl mb-6" },
|
|
299
|
+
react_1.default.createElement("div", { className: "font-bold text-xl mb-6" }, projectSections.every(section => section.disputeType !== 'Hourly')
|
|
300
|
+
? "Please enter the new dollar amount to settle the dispute for each of the project time log entries below"
|
|
301
|
+
: "Please enter the new hours to settle the dispute for each of the project time log entries below"),
|
|
252
302
|
react_1.default.createElement("div", { className: "space-y-8" }, projectSections.map((section) => {
|
|
303
|
+
var _a, _b;
|
|
253
304
|
const projectReduction = getProjectReduction(section.projectId);
|
|
254
305
|
const maxAllowedReduction = projectApprovedHours[section.projectId] !== undefined
|
|
255
306
|
? projectApprovedHours[section.projectId]
|
|
256
|
-
: section.
|
|
307
|
+
: section.disputeType === 'Hourly'
|
|
308
|
+
? section.disputeHours
|
|
309
|
+
: section.disputeAmount;
|
|
257
310
|
const isProjectValid = Math.abs(projectReduction - maxAllowedReduction) <= 0.01;
|
|
258
311
|
const isPartialApproval = projectApprovedHours[section.projectId] !== undefined;
|
|
259
312
|
return (react_1.default.createElement("div", { key: section.projectId, className: "border border-gray-200 rounded-lg p-6" },
|
|
@@ -261,49 +314,71 @@ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute
|
|
|
261
314
|
react_1.default.createElement("div", { className: "font-bold text-lg mb-2" }, section.projectName),
|
|
262
315
|
react_1.default.createElement("div", { className: "bg-gray-50 p-4 rounded-lg" },
|
|
263
316
|
react_1.default.createElement("div", { className: "font-semibold text-md mb-2" }, isPartialApproval
|
|
264
|
-
?
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
317
|
+
? section.disputeType === 'Hourly'
|
|
318
|
+
? `Approved Hours for Project: ${maxAllowedReduction}`
|
|
319
|
+
: `Total Approved Amount for Project: $${(maxAllowedReduction === null || maxAllowedReduction === void 0 ? void 0 : maxAllowedReduction.toFixed(2)) || '0.00'}`
|
|
320
|
+
: section.disputeType === 'Hourly'
|
|
321
|
+
? `Total Disputed Hours for Project: ${section.disputeHours}`
|
|
322
|
+
: `Total Dispute Amount for Project: $${((_a = section.disputeAmount) === null || _a === void 0 ? void 0 : _a.toFixed(2)) || '0.00'}`),
|
|
323
|
+
isPartialApproval && (react_1.default.createElement("div", { className: "text-sm text-blue-600 mb-2" }, section.disputeType === 'Hourly'
|
|
324
|
+
? `Original Disputed Hours: ${section.disputeHours}`
|
|
325
|
+
: `Original Dispute Amount: $${((_b = section.disputeAmount) === null || _b === void 0 ? void 0 : _b.toFixed(2)) || '0.00'}`)),
|
|
269
326
|
react_1.default.createElement("div", { className: "text-sm text-gray-600 grid grid-cols-2 gap-4" },
|
|
270
|
-
react_1.default.createElement("div", null,
|
|
327
|
+
react_1.default.createElement("div", null, section.disputeType === 'Hourly' ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
271
328
|
react_1.default.createElement("div", null,
|
|
272
329
|
"Original Hours: ",
|
|
273
330
|
getProjectTotalHours(section.projectId, 'original').toFixed(2)),
|
|
274
331
|
react_1.default.createElement("div", null,
|
|
275
332
|
"Adjusted Hours: ",
|
|
276
|
-
getProjectTotalHours(section.projectId, 'new').toFixed(2))),
|
|
333
|
+
getProjectTotalHours(section.projectId, 'new').toFixed(2)))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
334
|
+
react_1.default.createElement("div", null,
|
|
335
|
+
"Original Project Invoiced amount: $",
|
|
336
|
+
section.totalProjectAmount.toFixed(2)),
|
|
337
|
+
react_1.default.createElement("div", null,
|
|
338
|
+
"Adjusted $ Amount: $",
|
|
339
|
+
getProjectTotalAmount(section.projectId, 'new').toFixed(2))))),
|
|
277
340
|
react_1.default.createElement("div", null,
|
|
278
341
|
react_1.default.createElement("div", null,
|
|
279
|
-
|
|
280
|
-
|
|
342
|
+
section.disputeType === 'Hourly' ? 'Hour' : 'Dollar',
|
|
343
|
+
" Reduction: ",
|
|
344
|
+
section.disputeType === 'Hourly' ? projectReduction.toFixed(2) : `$${projectReduction.toFixed(2)}`),
|
|
281
345
|
react_1.default.createElement("div", null,
|
|
282
346
|
"Required Reduction: ",
|
|
283
|
-
maxAllowedReduction))),
|
|
347
|
+
section.disputeType === 'Hourly' ? maxAllowedReduction : `$${maxAllowedReduction}`))),
|
|
284
348
|
projectErrors[section.projectId] && (react_1.default.createElement(base_ui_1.Alert, { color: "danger", icon: "danger", label: projectErrors[section.projectId], className: "mt-2" })),
|
|
285
|
-
isProjectValid && (react_1.default.createElement("div", { className: "text-green-600 text-sm mt-2 font-medium" },
|
|
349
|
+
isProjectValid && (react_1.default.createElement("div", { className: "text-green-600 text-sm mt-2 font-medium" },
|
|
350
|
+
"\u2713 Project ",
|
|
351
|
+
section.disputeType === 'Hourly' ? 'hours' : 'amounts',
|
|
352
|
+
" are correctly adjusted")))),
|
|
286
353
|
react_1.default.createElement("div", { className: "overflow-x-auto" },
|
|
287
354
|
react_1.default.createElement("table", { className: "w-full border-collapse border border-gray-300" },
|
|
288
355
|
react_1.default.createElement("thead", null,
|
|
289
356
|
react_1.default.createElement("tr", { className: "bg-gray-100" },
|
|
290
357
|
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, "Date"),
|
|
291
358
|
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, "Project Hour Entry"),
|
|
292
|
-
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" },
|
|
293
|
-
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" },
|
|
359
|
+
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, section.disputeType === 'Hourly' ? 'Original Hours' : 'Original Dispute $'),
|
|
360
|
+
react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, section.disputeType === 'Hourly' ? 'Adjusted Hours' : 'Adjusted $ Amount'))),
|
|
294
361
|
react_1.default.createElement("tbody", null, section.tasks.map((task) => {
|
|
295
|
-
var _a;
|
|
362
|
+
var _a, _b;
|
|
296
363
|
const projectHourId = task.projectHourId;
|
|
297
364
|
const originalHours = task.hours;
|
|
365
|
+
const originalAmount = task.hours * task.rate;
|
|
298
366
|
const newHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.newHours) || 0;
|
|
367
|
+
const newAmount = newHours * task.rate;
|
|
299
368
|
const hasError = errors[projectHourId];
|
|
300
369
|
return (react_1.default.createElement("tr", { key: projectHourId, className: hasError ? 'bg-red-50' : '' },
|
|
301
370
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, formatDate(task.date)),
|
|
302
371
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, task.description),
|
|
303
|
-
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" },
|
|
372
|
+
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, section.disputeType === 'Hourly'
|
|
373
|
+
? originalHours.toFixed(2)
|
|
374
|
+
: `$${((_b = section.disputeAmount) === null || _b === void 0 ? void 0 : _b.toFixed(2)) || '0.00'}`),
|
|
304
375
|
react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" },
|
|
305
376
|
react_1.default.createElement("div", null,
|
|
306
|
-
react_1.default.createElement("input", { type: "number", step: "0.01", min: "0", max: originalHours, value: 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'}` }),
|
|
377
|
+
section.disputeType === 'Hourly' ? (react_1.default.createElement("input", { type: "number", step: "0.01", min: "0", max: originalHours, value: 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
|
+
react_1.default.createElement("span", { className: "mr-1" }, "$"),
|
|
379
|
+
react_1.default.createElement("span", null, newAmount.toFixed(2)),
|
|
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"))),
|
|
307
382
|
hasError && (react_1.default.createElement("div", { className: "text-red-500 text-xs mt-1" }, hasError))))));
|
|
308
383
|
}))))));
|
|
309
384
|
})),
|