@paro.io/expert-shared-components 1.12.16 → 1.12.18

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.
@@ -4,9 +4,10 @@ interface UploadFileParams {
4
4
  disputeId?: number;
5
5
  projectId: number;
6
6
  documentUploadUrl: string;
7
+ bucketName: string;
7
8
  updateClientInvoiceDisputeMutation: any;
8
9
  previousFiles: string | string[];
9
10
  isExpert: boolean;
10
11
  }
11
- export declare const fileUploader: ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, disputeId, previousFiles, isExpert, }: UploadFileParams) => Promise<any>;
12
+ export declare const fileUploader: ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, bucketName, disputeId, previousFiles, isExpert, }: UploadFileParams) => Promise<any>;
12
13
  export {};
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.fileUploader = void 0;
16
16
  const UploadClient_1 = __importDefault(require("../shared/UploadClient"));
17
17
  const utils_1 = require("../shared/utils");
18
- const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, disputeId, previousFiles, isExpert, }) {
18
+ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, bucketName, disputeId, previousFiles, isExpert, }) {
19
19
  const documentLinks = previousFiles ? (typeof previousFiles === 'string' ? previousFiles.split(',') : [...previousFiles]) : [];
20
20
  try {
21
21
  (0, utils_1.showToast)('success', 'Starting Document Upload');
@@ -24,7 +24,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
24
24
  fileName: file.name,
25
25
  projectId,
26
26
  documentUploadUrl,
27
- bucketName: 'expert-client-dispute-files',
27
+ bucketName: bucketName,
28
28
  });
29
29
  yield uploadClient.triggerMultipartUpload().then((res) => __awaiter(void 0, void 0, void 0, function* () {
30
30
  const resParsed = JSON.parse(res);
@@ -200,6 +200,7 @@ const ClientDisputeProjectCard = ({ clientInvoice, updateClientInvoiceDisputeMut
200
200
  disputeId: clientInvoice.disputeId,
201
201
  projectId: Number((_b = (_a = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.disputeProjects) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.projectId),
202
202
  documentUploadUrl: documentUploadUrl,
203
+ bucketName: bucketName,
203
204
  updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation,
204
205
  previousFiles: (_e = (_d = (_c = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.disputeProjects) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.clientDocumentLinks) !== null && _e !== void 0 ? _e : [],
205
206
  isExpert: false,
@@ -1,7 +1,11 @@
1
1
  interface DecisionSectionProps {
2
2
  dispute: any;
3
3
  onUpdateDispute: (variables: any) => Promise<any>;
4
+ updateInvoiceMutation: any;
4
5
  user: any;
6
+ getClientInvoiceSummaryByMonth: any;
7
+ invoiceSummary: any;
8
+ updateClientInvoiceDisputeMutation: any;
5
9
  }
6
- export declare const DecisionSection: ({ dispute, onUpdateDispute, user }: DecisionSectionProps) => JSX.Element;
10
+ export declare const DecisionSection: ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, }: DecisionSectionProps) => JSX.Element;
7
11
  export {};
@@ -36,33 +36,106 @@ exports.DecisionSection = void 0;
36
36
  const react_1 = __importStar(require("react"));
37
37
  const base_ui_1 = require("@paro.io/base-ui");
38
38
  const utils_1 = require("../shared/utils");
39
+ const ProjectHoursAdjustmentModal_1 = require("./ProjectHoursAdjustmentModal");
39
40
  const RESOLUTION_OPTIONS = [
40
41
  { value: 'APPROVED', label: 'Approve Dispute' },
41
42
  { value: 'DECLINED', label: 'Decline Dispute' },
42
43
  { value: 'PARTIAL', label: 'Partial Approval' },
43
44
  ];
44
- const DecisionSection = ({ dispute, onUpdateDispute, user }) => {
45
- var _a;
46
- const disputeAmount = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.reduce((acc, project) => acc + (project === null || project === void 0 ? void 0 : project.disputeAmount), 0);
45
+ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, }) => {
46
+ var _a, _b;
47
+ const totalDisputeHours = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.reduce((acc, project) => acc + (project === null || project === void 0 ? void 0 : project.disputeHours), 0);
47
48
  const [resolution, setResolution] = (0, react_1.useState)('');
48
- const [amount, setAmount] = (0, react_1.useState)(disputeAmount);
49
+ const [approvedHours, setApprovedHours] = (0, react_1.useState)(totalDisputeHours);
50
+ const [projectApprovedHours, setProjectApprovedHours] = (0, react_1.useState)({});
49
51
  const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
50
- const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
52
+ const [showHoursModal, setShowHoursModal] = (0, react_1.useState)(false);
53
+ // Initialize project approved hours when resolution changes to PARTIAL
54
+ const handleResolutionChange = (newResolution) => {
55
+ var _a;
56
+ setResolution(newResolution);
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
59
+ const initialProjectHours = {};
60
+ dispute.disputeProjects.forEach((project) => {
61
+ initialProjectHours[project.projectId] = project.disputeHours;
62
+ });
63
+ setProjectApprovedHours(initialProjectHours);
64
+ }
65
+ else {
66
+ setProjectApprovedHours({});
67
+ }
68
+ };
69
+ const handleProjectHoursChange = (projectId, hours) => {
70
+ setProjectApprovedHours(prev => (Object.assign(Object.assign({}, prev), { [projectId]: hours })));
71
+ };
72
+ const getTotalApprovedHours = () => {
73
+ var _a;
74
+ if (resolution === 'PARTIAL' && ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.length) > 0) {
75
+ return Object.values(projectApprovedHours).reduce((sum, hours) => sum + hours, 0);
76
+ }
77
+ return approvedHours;
78
+ };
79
+ const handleApproveClick = () => {
80
+ var _a;
51
81
  if (!resolution)
52
82
  return;
83
+ // Check if any dispute projects have hourly disputes that need hour adjustments
84
+ const hasHourlyDisputes = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.some((project) => project.disputeType === 'Hourly');
85
+ if (hasHourlyDisputes) {
86
+ setShowHoursModal(true);
87
+ }
88
+ else {
89
+ handleFinalSubmit();
90
+ }
91
+ };
92
+ const handleHoursSubmit = (submissionData) => {
93
+ setShowHoursModal(false);
94
+ handleFinalSubmit(submissionData);
95
+ };
96
+ const handleFinalSubmit = (submissionData) => __awaiter(void 0, void 0, void 0, function* () {
97
+ var _a;
53
98
  setIsSubmitting(true);
54
99
  try {
100
+ const finalApprovedHours = getTotalApprovedHours();
101
+ // Determine resolution type based on approval
102
+ const isFullApproval = resolution === 'APPROVED' ||
103
+ (resolution === 'PARTIAL' && Math.abs(finalApprovedHours - totalDisputeHours) <= 0.01);
104
+ const resolutionType = isFullApproval ? 'Upheld' : 'Reduced';
105
+ // Update dispute projects with resolution details
106
+ const disputeProjectUpdates = ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.map((project) => ({
107
+ projectId: project.projectId,
108
+ status: 'Resolved',
109
+ resolutionMode: 'Direct',
110
+ resolutionType: resolutionType
111
+ }))) || [];
112
+ const updateData = {
113
+ disputeId: dispute.disputeId,
114
+ status: "Resolved",
115
+ approvedAmount: finalApprovedHours * ((submissionData === null || submissionData === void 0 ? void 0 : submissionData.freelancerRate) || 0), //Calculate this dynamically based on rate
116
+ finalDecisionOwnerId: (user === null || user === void 0 ? void 0 : user.userId) || null,
117
+ projectDisputes: disputeProjectUpdates
118
+ };
119
+ // If we have adjusted hours, include them in the update
120
+ if (submissionData) {
121
+ // Call the updateInvoiceMutation with the submission data
122
+ yield updateInvoiceMutation({
123
+ variables: {
124
+ input: submissionData.input,
125
+ clientId: submissionData.clientId,
126
+ invoiceId: submissionData.invoiceId,
127
+ dateGenerated: submissionData.dateGenerated,
128
+ updateDescription: submissionData.updateDescription,
129
+ freelancerIds: submissionData.freelancerIds
130
+ }
131
+ });
132
+ }
55
133
  yield onUpdateDispute({
56
134
  variables: {
57
- input: {
58
- disputeId: dispute.disputeId,
59
- status: "Resolved", //To-Do - Fix with actual status
60
- approvedAmount: amount ? parseFloat(amount) : undefined,
61
- finalDecisionOwnerId: (user === null || user === void 0 ? void 0 : user.userId) || null
62
- },
135
+ input: updateData,
63
136
  },
64
137
  });
65
- (0, utils_1.showToast)('success', 'Thank you for resolving the dispute');
138
+ (0, utils_1.showToast)('success', 'Thank you for resolving the dispute. The invoice has been updated with the new hours.');
66
139
  }
67
140
  catch (error) {
68
141
  console.error('Failed to update dispute:', error);
@@ -72,6 +145,16 @@ const DecisionSection = ({ dispute, onUpdateDispute, user }) => {
72
145
  setIsSubmitting(false);
73
146
  }
74
147
  });
148
+ const isPartialWithMultipleProjects = resolution === 'PARTIAL' && ((_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.length) > 0;
149
+ const isValidPartialApproval = () => {
150
+ if (resolution !== 'PARTIAL')
151
+ return true;
152
+ // Check each project's approved hours
153
+ return dispute.disputeProjects.every((project) => {
154
+ const approvedForProject = projectApprovedHours[project.projectId] || 0;
155
+ return approvedForProject >= 0 && approvedForProject <= project.disputeHours;
156
+ });
157
+ };
75
158
  return (react_1.default.createElement("div", { className: "space-y-6" },
76
159
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
77
160
  react_1.default.createElement("div", { className: "text-lg font-bold text-[#333333]" }, "Make Decision")),
@@ -80,16 +163,28 @@ const DecisionSection = ({ dispute, onUpdateDispute, user }) => {
80
163
  react_1.default.createElement("div", null,
81
164
  react_1.default.createElement("label", { className: "block text-sm text-[#666666] font-bold mb-2" }, "Resolution:"),
82
165
  react_1.default.createElement("div", { className: "w-full" },
83
- react_1.default.createElement("select", { value: resolution, onChange: (e) => setResolution(e.target.value), className: "w-full px-3 py-2 border border-[#CCCCCC] rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#248384] bg-white" },
166
+ react_1.default.createElement("select", { value: resolution, onChange: (e) => handleResolutionChange(e.target.value), className: "w-full px-3 py-2 border border-[#CCCCCC] rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#248384] bg-white" },
84
167
  react_1.default.createElement("option", { value: "" }, "Select Resolution"),
85
- RESOLUTION_OPTIONS.map((option) => (react_1.default.createElement("option", { key: option.value, value: option.value }, option.label)))))),
86
- resolution === 'PARTIAL' && (react_1.default.createElement("div", null,
87
- react_1.default.createElement("label", { className: "block text-sm text-[#666666] font-bold mb-2" }, "Approved Amount:"),
88
- react_1.default.createElement("div", { className: "relative" },
89
- react_1.default.createElement("span", { className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-[#333333]" }, "$"),
90
- react_1.default.createElement("input", { type: "number", value: amount, onChange: (e) => setAmount(e.target.value), className: "w-full pl-8 pr-3 py-2 border border-[#CCCCCC] rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-[#248384]", placeholder: "Enter amount" }))))),
168
+ RESOLUTION_OPTIONS.map((option) => (react_1.default.createElement("option", { key: option.value, value: option.value }, option.label))))))),
169
+ isPartialWithMultipleProjects && (react_1.default.createElement("div", { className: "space-y-4" },
170
+ react_1.default.createElement("div", { className: "text-sm font-bold text-[#666666]" }, "Approved Hours per Project:"),
171
+ react_1.default.createElement("div", { className: "grid grid-cols-1 gap-4" }, dispute.disputeProjects.map((project) => (react_1.default.createElement("div", { key: project.projectId, className: "flex items-center justify-between p-4 bg-white rounded-lg border border-[#CCCCCC]" },
172
+ react_1.default.createElement("div", { className: "flex-1" },
173
+ react_1.default.createElement("div", { className: "font-medium text-sm" }, project.project.name),
174
+ react_1.default.createElement("div", { className: "text-xs text-gray-500" },
175
+ "Disputed Hours: ",
176
+ project.disputeHours)),
177
+ react_1.default.createElement("div", { className: "w-32" },
178
+ 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" })))))),
179
+ react_1.default.createElement("div", { className: "text-sm text-gray-600" },
180
+ "Total Approved Hours: ",
181
+ getTotalApprovedHours().toFixed(2),
182
+ " / ",
183
+ totalDisputeHours,
184
+ " hours"))),
91
185
  react_1.default.createElement("div", { className: "flex justify-end space-x-4" },
92
- react_1.default.createElement(base_ui_1.Button, { label: "Decline Dispute", color: "error", onClick: () => setResolution('DECLINED'), disabled: isSubmitting, size: "md" }),
93
- react_1.default.createElement(base_ui_1.Button, { label: "Approve & Resolve", color: "primary", onClick: handleSubmit, isLoading: isSubmitting, disabled: !resolution || (resolution === 'PARTIAL' && !amount), size: "md" })))));
186
+ react_1.default.createElement(base_ui_1.Button, { label: "Decline Dispute", color: "error", onClick: () => handleResolutionChange('DECLINED'), disabled: isSubmitting, size: "md" }),
187
+ react_1.default.createElement(base_ui_1.Button, { label: "Approve & Resolve", color: "primary", onClick: handleApproveClick, isLoading: isSubmitting, disabled: !resolution || (resolution === 'PARTIAL' && !isValidPartialApproval()), size: "md" }))),
188
+ 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 })));
94
189
  };
95
190
  exports.DecisionSection = DecisionSection;
@@ -74,6 +74,8 @@ const DisputeProjectCard = ({ project, client, disputeDate, disputeUpdatedDate }
74
74
  react_1.default.createElement("span", { className: "text-sm text-[#333333]" }, (0, dayjs_1.default)(disputeUpdatedDate).format('MMM D, YYYY'))),
75
75
  react_1.default.createElement("div", null,
76
76
  react_1.default.createElement("span", { className: "text-sm text-[#666666] font-bold" }, "Days Left: "),
77
- react_1.default.createElement("span", { className: "text-sm text-[#F44336] font-bold" }, "5 days left to resolve"))))));
77
+ react_1.default.createElement("span", { className: "text-sm text-[#F44336] font-bold" },
78
+ Math.max(0, 14 - (0, dayjs_1.default)().date()),
79
+ " days left to resolve"))))));
78
80
  };
79
81
  exports.DisputeProjectCard = DisputeProjectCard;
@@ -80,6 +80,7 @@ const DisputeSection = ({ dispute, documentUploadUrl, downloadDocumentUrl, bucke
80
80
  documentName: selectedFile.name,
81
81
  projectId: Number((_b = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.projectId),
82
82
  documentUploadUrl: documentUploadUrl,
83
+ bucketName: bucketName,
83
84
  updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation,
84
85
  disputeId: dispute === null || dispute === void 0 ? void 0 : dispute.disputeId,
85
86
  previousFiles: isExpert ? expertDocumentLinks : clientDocumentLinks,
@@ -6,10 +6,13 @@ interface InvoiceCardProps {
6
6
  updateClientInvoiceDisputeMutation: any;
7
7
  documentUploadUrl: string;
8
8
  downloadDocumentUrl: string;
9
+ updateInvoiceMutation?: any;
10
+ getClientInvoiceSummaryByMonth?: any;
11
+ invoiceSummary?: any;
9
12
  isInternal?: boolean;
10
13
  isClient?: boolean;
11
14
  bucketName?: string;
12
15
  reactAppUrl?: string;
13
16
  }
14
- export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, documentUploadUrl, downloadDocumentUrl, isInternal, isClient, bucketName, reactAppUrl }: InvoiceCardProps) => JSX.Element;
17
+ export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal, isClient, bucketName, reactAppUrl }: InvoiceCardProps) => JSX.Element;
15
18
  export {};
@@ -45,7 +45,7 @@ const useStyles = (0, core_1.makeStyles)((theme) => ({
45
45
  },
46
46
  },
47
47
  }));
48
- const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, documentUploadUrl, downloadDocumentUrl, isInternal = false, isClient = false, bucketName, reactAppUrl }) => {
48
+ const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal = false, isClient = false, bucketName, reactAppUrl }) => {
49
49
  const [currentInvoice, setCurrentInvoice] = (0, react_1.useState)(clientInvoice);
50
50
  const classes = useStyles();
51
51
  (0, react_1.useEffect)(() => {
@@ -65,6 +65,6 @@ const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessag
65
65
  react_1.default.createElement(ClientDisputeProjectCard_1.ClientDisputeProjectCard, { clientInvoice: currentInvoice, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, documentUploadUrl: documentUploadUrl, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName }),
66
66
  (currentInvoice === null || currentInvoice === void 0 ? void 0 : currentInvoice.chatEnabled) && disputeId && (react_1.default.createElement(DiscussionSection_1.DiscussionSection, { disputeId: disputeId, currentUser: user, messages: chatMessages, onCreateMessage: createDisputeChatMessage, isInternal: isInternal })),
67
67
  isInternal &&
68
- react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: currentInvoice, onUpdateDispute: updateClientInvoiceDisputeMutation, user: user }))))));
68
+ react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: currentInvoice, onUpdateDispute: updateClientInvoiceDisputeMutation, updateInvoiceMutation: updateInvoiceMutation, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, invoiceSummary: invoiceSummary, user: user, getClientInvoiceSummaryByMonth: getClientInvoiceSummaryByMonth }))))));
69
69
  };
70
70
  exports.InvoiceCard = InvoiceCard;
@@ -0,0 +1,37 @@
1
+ interface DisputeProject {
2
+ __typename: string;
3
+ id: number;
4
+ projectId: number;
5
+ disputeAmount: number;
6
+ disputeHours: number;
7
+ disputeType: string;
8
+ disputeReasonCode: string;
9
+ clientExplanation: string;
10
+ clientDocumentLinks: string;
11
+ expertDocumentLinks: string;
12
+ resolutionMode: string | null;
13
+ resolutionType: string | null;
14
+ project: {
15
+ __typename: string;
16
+ name: string;
17
+ freelancerRate: number | null;
18
+ clientRate: number | null;
19
+ };
20
+ }
21
+ interface ProjectHoursAdjustmentModalProps {
22
+ isOpen: boolean;
23
+ onClose: () => void;
24
+ disputeProjects: DisputeProject[];
25
+ dispute: any;
26
+ onSubmit: (adjustedHours: any) => void;
27
+ isSubmitting: boolean;
28
+ getClientInvoiceSummaryByMonth: any;
29
+ invoiceSummary: any;
30
+ approvedHours: number;
31
+ projectApprovedHours: {
32
+ [projectId: number]: number;
33
+ };
34
+ user: any;
35
+ }
36
+ export declare const ProjectHoursAdjustmentModal: ({ isOpen, onClose, disputeProjects, dispute, onSubmit, isSubmitting, getClientInvoiceSummaryByMonth, invoiceSummary, approvedHours, projectApprovedHours, user, }: ProjectHoursAdjustmentModalProps) => JSX.Element;
37
+ export {};
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.ProjectHoursAdjustmentModal = void 0;
36
+ const react_1 = __importStar(require("react"));
37
+ const base_ui_1 = require("@paro.io/base-ui");
38
+ const ProjectHoursAdjustmentModal = ({ isOpen, onClose, disputeProjects, dispute, onSubmit, isSubmitting, getClientInvoiceSummaryByMonth, invoiceSummary, approvedHours, projectApprovedHours, user, }) => {
39
+ var _a, _b;
40
+ const [adjustedHours, setAdjustedHours] = (0, react_1.useState)({});
41
+ const [errors, setErrors] = (0, react_1.useState)({});
42
+ const [projectErrors, setProjectErrors] = (0, react_1.useState)({});
43
+ const [projectSections, setProjectSections] = (0, react_1.useState)([]);
44
+ const [loading, setLoading] = (0, react_1.useState)(false);
45
+ const [fetchError, setFetchError] = (0, react_1.useState)(null);
46
+ const clientId = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _a === void 0 ? void 0 : _a.clientId;
47
+ const month = (_b = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _b === void 0 ? void 0 : _b.month;
48
+ // Fetch project hours when modal opens
49
+ (0, react_1.useEffect)(() => {
50
+ if (isOpen && disputeProjects.length > 0) {
51
+ fetchInvoiceSummary();
52
+ fetchProjectHours();
53
+ }
54
+ }, [isOpen, disputeProjects]);
55
+ (0, react_1.useEffect)(() => {
56
+ if (invoiceSummary) {
57
+ fetchProjectHours();
58
+ }
59
+ }, [invoiceSummary]);
60
+ const fetchInvoiceSummary = () => __awaiter(void 0, void 0, void 0, function* () {
61
+ setLoading(true);
62
+ yield Promise.all([
63
+ getClientInvoiceSummaryByMonth({ variables: { clientId: +clientId, month }, fetchPolicy: 'network-only' }),
64
+ ]);
65
+ });
66
+ const fetchProjectHours = () => __awaiter(void 0, void 0, void 0, function* () {
67
+ var _a;
68
+ setFetchError(null);
69
+ setLoading(true);
70
+ try {
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
+ const projectSectionsData = [];
74
+ disputeProjects.forEach(disputeProject => {
75
+ // Find matching project in invoice summary
76
+ const invoiceProject = invoiceSummary.getClientInvoiceSummaryByMonth.projects.find((proj) => {
77
+ // Match by project name since we don't have direct projectId mapping
78
+ return proj.projectName === disputeProject.project.name;
79
+ });
80
+ if (invoiceProject) {
81
+ projectSectionsData.push({
82
+ projectId: disputeProject.projectId,
83
+ projectName: disputeProject.project.name,
84
+ disputeHours: disputeProject.disputeHours,
85
+ tasks: invoiceProject.tasks.map((task) => (Object.assign(Object.assign({}, task), { projectName: disputeProject.project.name })))
86
+ });
87
+ }
88
+ });
89
+ setProjectSections(projectSectionsData);
90
+ // Initialize adjusted hours for all tasks
91
+ const initialAdjustedHours = {};
92
+ projectSectionsData.forEach(section => {
93
+ section.tasks.forEach(task => {
94
+ initialAdjustedHours[task.projectHourId] = {
95
+ originalHours: task.hours,
96
+ newHours: task.hours
97
+ };
98
+ });
99
+ });
100
+ setAdjustedHours(initialAdjustedHours);
101
+ setErrors({});
102
+ setProjectErrors({});
103
+ }
104
+ }
105
+ catch (error) {
106
+ console.error('Failed to fetch project hours:', error);
107
+ setFetchError('Failed to load project hours. Please try again.');
108
+ }
109
+ finally {
110
+ setLoading(false);
111
+ }
112
+ });
113
+ const handleHourChange = (projectHourId, newHours) => {
114
+ var _a;
115
+ const numericValue = parseFloat(newHours) || 0;
116
+ const originalHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.originalHours) || 0;
117
+ setAdjustedHours(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: Object.assign(Object.assign({}, prev[projectHourId]), { newHours: numericValue }) })));
118
+ // Clear individual hour error
119
+ setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: '' })));
120
+ // Validate individual hour
121
+ if (numericValue > originalHours) {
122
+ setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'New hours cannot exceed original hours' })));
123
+ }
124
+ else if (numericValue < 0) {
125
+ setErrors(prev => (Object.assign(Object.assign({}, prev), { [projectHourId]: 'Hours cannot be negative' })));
126
+ }
127
+ };
128
+ const getProjectTotalHours = (projectId, type) => {
129
+ const section = projectSections.find(s => s.projectId === projectId);
130
+ if (!section)
131
+ return 0;
132
+ return section.tasks.reduce((total, task) => {
133
+ const adjustment = adjustedHours[task.projectHourId];
134
+ if (!adjustment)
135
+ return total;
136
+ return total + (type === 'original' ? adjustment.originalHours : adjustment.newHours);
137
+ }, 0);
138
+ };
139
+ const getProjectReduction = (projectId) => {
140
+ return getProjectTotalHours(projectId, 'original') - getProjectTotalHours(projectId, 'new');
141
+ };
142
+ const validateAndSubmit = () => {
143
+ var _a, _b, _c, _d;
144
+ let hasErrors = false;
145
+ const newErrors = {};
146
+ const newProjectErrors = {};
147
+ // Validate each project section
148
+ projectSections.forEach(section => {
149
+ const projectId = section.projectId;
150
+ const disputeHours = section.disputeHours;
151
+ // Use project-specific approved hours if available, otherwise use dispute hours
152
+ const maxAllowedReduction = projectApprovedHours[projectId] !== undefined
153
+ ? projectApprovedHours[projectId]
154
+ : disputeHours;
155
+ // Validate individual hours within this project
156
+ section.tasks.forEach(task => {
157
+ var _a, _b;
158
+ const projectHourId = task.projectHourId;
159
+ const originalHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.originalHours) || 0;
160
+ const newHours = ((_b = adjustedHours[projectHourId]) === null || _b === void 0 ? void 0 : _b.newHours) || 0;
161
+ if (newHours > originalHours) {
162
+ newErrors[projectHourId] = 'New hours cannot exceed original hours';
163
+ hasErrors = true;
164
+ }
165
+ else if (newHours < 0) {
166
+ newErrors[projectHourId] = 'Hours cannot be negative';
167
+ hasErrors = true;
168
+ }
169
+ });
170
+ // Validate project-level hour reduction
171
+ const projectReduction = getProjectReduction(projectId);
172
+ if (Math.abs(projectReduction - maxAllowedReduction) > 0.01) {
173
+ const reductionType = projectApprovedHours[projectId] !== undefined ? 'approved' : 'disputed';
174
+ newProjectErrors[projectId] = `Hour reduction for this project (${projectReduction.toFixed(2)}) must equal ${reductionType} hours (${maxAllowedReduction})`;
175
+ hasErrors = true;
176
+ }
177
+ });
178
+ setErrors(newErrors);
179
+ setProjectErrors(newProjectErrors);
180
+ if (!hasErrors) {
181
+ // Generate the submission data in the required format
182
+ let freelancerRate = 0;
183
+ const inputArray = [];
184
+ projectSections.forEach(section => {
185
+ section.tasks.forEach(task => {
186
+ const projectHourId = task.projectHourId;
187
+ const adjustedHour = adjustedHours[projectHourId];
188
+ freelancerRate = task.freelancerRate;
189
+ // Generate expert name
190
+ const expertName = (dispute === null || dispute === void 0 ? void 0 : dispute.freelancer) ?
191
+ `${dispute.freelancer.firstName} ${dispute.freelancer.lastName}` : '';
192
+ // Generate internal user name
193
+ const internalUser = user ?
194
+ `${user.firstName} ${user.lastName}` : '';
195
+ inputArray.push({
196
+ clientRate: task.rate,
197
+ freelancerRate: task.freelancerRate,
198
+ hours: (adjustedHour === null || adjustedHour === void 0 ? void 0 : adjustedHour.newHours) || 0,
199
+ projectId: section.projectId,
200
+ projectHourId: task.projectHourId,
201
+ projectName: section.projectName,
202
+ projectDescription: task.description,
203
+ expertName: expertName,
204
+ internalUser: internalUser
205
+ });
206
+ });
207
+ });
208
+ const submissionData = {
209
+ input: inputArray,
210
+ clientId: ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _a === void 0 ? void 0 : _a.clientId) || 0,
211
+ invoiceId: ((_b = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _b === void 0 ? void 0 : _b.id) || 0,
212
+ dateGenerated: ((_c = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _c === void 0 ? void 0 : _c.month) || '',
213
+ updateDescription: `Updating hours based on dispute ID#:${dispute === null || dispute === void 0 ? void 0 : dispute.disputeId}`,
214
+ freelancerIds: [((_d = dispute === null || dispute === void 0 ? void 0 : dispute.freelancer) === null || _d === void 0 ? void 0 : _d.id) || 0],
215
+ freelancerRate: freelancerRate
216
+ };
217
+ onSubmit(submissionData);
218
+ }
219
+ };
220
+ const formatDate = (dateString) => {
221
+ return new Date(dateString).toLocaleDateString();
222
+ };
223
+ const hasAnyErrors = () => {
224
+ return Object.values(errors).some(error => error !== '') ||
225
+ Object.values(projectErrors).some(error => error !== '');
226
+ };
227
+ const areAllProjectsValid = () => {
228
+ return projectSections.every(section => {
229
+ const projectReduction = getProjectReduction(section.projectId);
230
+ const maxAllowedReduction = projectApprovedHours[section.projectId] !== undefined
231
+ ? projectApprovedHours[section.projectId]
232
+ : section.disputeHours;
233
+ return Math.abs(projectReduction - maxAllowedReduction) <= 0.01;
234
+ });
235
+ };
236
+ if (loading) {
237
+ return (react_1.default.createElement(base_ui_1.Modal, { open: isOpen, onClose: onClose, size: "lg", className: "z-[100]" },
238
+ react_1.default.createElement("div", { className: "flex justify-center items-center py-8" },
239
+ react_1.default.createElement("div", null, "Loading project hours..."))));
240
+ }
241
+ if (fetchError) {
242
+ return (react_1.default.createElement(base_ui_1.Modal, { open: isOpen, onClose: onClose, size: "lg", className: "z-[100]" },
243
+ react_1.default.createElement("div", { className: "py-8" },
244
+ react_1.default.createElement(base_ui_1.Alert, { color: "danger", icon: "danger", label: fetchError, className: "mb-4" }),
245
+ react_1.default.createElement("div", { className: "flex justify-end space-x-4" },
246
+ react_1.default.createElement(base_ui_1.Button, { label: "Retry", color: "primary", onClick: fetchProjectHours }),
247
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", color: "default", onClick: onClose })))));
248
+ }
249
+ return (react_1.default.createElement(base_ui_1.Modal, { open: isOpen, onClose: onClose, size: "lg", className: "z-[100]" },
250
+ 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" }, "Please enter the new hours to settle the dispute for each of the project time log entries below"),
252
+ react_1.default.createElement("div", { className: "space-y-8" }, projectSections.map((section) => {
253
+ const projectReduction = getProjectReduction(section.projectId);
254
+ const maxAllowedReduction = projectApprovedHours[section.projectId] !== undefined
255
+ ? projectApprovedHours[section.projectId]
256
+ : section.disputeHours;
257
+ const isProjectValid = Math.abs(projectReduction - maxAllowedReduction) <= 0.01;
258
+ const isPartialApproval = projectApprovedHours[section.projectId] !== undefined;
259
+ return (react_1.default.createElement("div", { key: section.projectId, className: "border border-gray-200 rounded-lg p-6" },
260
+ react_1.default.createElement("div", { className: "mb-4" },
261
+ react_1.default.createElement("div", { className: "font-bold text-lg mb-2" }, section.projectName),
262
+ react_1.default.createElement("div", { className: "bg-gray-50 p-4 rounded-lg" },
263
+ react_1.default.createElement("div", { className: "font-semibold text-md mb-2" }, isPartialApproval
264
+ ? `Approved Hours for Project: ${maxAllowedReduction}`
265
+ : `Total Disputed Hours for Project: ${section.disputeHours}`),
266
+ isPartialApproval && (react_1.default.createElement("div", { className: "text-sm text-blue-600 mb-2" },
267
+ "Original Disputed Hours: ",
268
+ section.disputeHours)),
269
+ react_1.default.createElement("div", { className: "text-sm text-gray-600 grid grid-cols-2 gap-4" },
270
+ react_1.default.createElement("div", null,
271
+ react_1.default.createElement("div", null,
272
+ "Original Hours: ",
273
+ getProjectTotalHours(section.projectId, 'original').toFixed(2)),
274
+ react_1.default.createElement("div", null,
275
+ "Adjusted Hours: ",
276
+ getProjectTotalHours(section.projectId, 'new').toFixed(2))),
277
+ react_1.default.createElement("div", null,
278
+ react_1.default.createElement("div", null,
279
+ "Hour Reduction: ",
280
+ projectReduction.toFixed(2)),
281
+ react_1.default.createElement("div", null,
282
+ "Required Reduction: ",
283
+ maxAllowedReduction))),
284
+ 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" }, "\u2713 Project hours are correctly adjusted")))),
286
+ react_1.default.createElement("div", { className: "overflow-x-auto" },
287
+ react_1.default.createElement("table", { className: "w-full border-collapse border border-gray-300" },
288
+ react_1.default.createElement("thead", null,
289
+ react_1.default.createElement("tr", { className: "bg-gray-100" },
290
+ react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, "Date"),
291
+ 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" }, "Original Hours"),
293
+ react_1.default.createElement("th", { className: "border border-gray-300 px-4 py-2 text-left" }, "Adjusted Hours"))),
294
+ react_1.default.createElement("tbody", null, section.tasks.map((task) => {
295
+ var _a;
296
+ const projectHourId = task.projectHourId;
297
+ const originalHours = task.hours;
298
+ const newHours = ((_a = adjustedHours[projectHourId]) === null || _a === void 0 ? void 0 : _a.newHours) || 0;
299
+ const hasError = errors[projectHourId];
300
+ return (react_1.default.createElement("tr", { key: projectHourId, className: hasError ? 'bg-red-50' : '' },
301
+ react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" }, formatDate(task.date)),
302
+ 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" }, originalHours.toFixed(2)),
304
+ react_1.default.createElement("td", { className: "border border-gray-300 px-4 py-2" },
305
+ 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'}` }),
307
+ hasError && (react_1.default.createElement("div", { className: "text-red-500 text-xs mt-1" }, hasError))))));
308
+ }))))));
309
+ })),
310
+ react_1.default.createElement("div", { className: "flex justify-end space-x-4 mt-6 pt-4 border-t" },
311
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", color: "default", onClick: onClose, disabled: isSubmitting }),
312
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit Adjustments", color: "primary", onClick: validateAndSubmit, isLoading: isSubmitting, disabled: hasAnyErrors() || projectSections.length === 0 || !areAllProjectsValid() })))));
313
+ };
314
+ exports.ProjectHoursAdjustmentModal = ProjectHoursAdjustmentModal;
@@ -0,0 +1 @@
1
+ export declare const TestDecisionSection: () => JSX.Element;
@@ -0,0 +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,2 +1,4 @@
1
1
  export { InvoiceCard } from './InvoiceCard';
2
2
  export { DiscussionSection } from './DiscussionSection';
3
+ export { DecisionSection } from './DecisionSection';
4
+ export { ProjectHoursAdjustmentModal } from './ProjectHoursAdjustmentModal';
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DiscussionSection = exports.InvoiceCard = void 0;
3
+ exports.ProjectHoursAdjustmentModal = exports.DecisionSection = exports.DiscussionSection = exports.InvoiceCard = void 0;
4
4
  var InvoiceCard_1 = require("./InvoiceCard");
5
5
  Object.defineProperty(exports, "InvoiceCard", { enumerable: true, get: function () { return InvoiceCard_1.InvoiceCard; } });
6
6
  var DiscussionSection_1 = require("./DiscussionSection");
7
7
  Object.defineProperty(exports, "DiscussionSection", { enumerable: true, get: function () { return DiscussionSection_1.DiscussionSection; } });
8
+ var DecisionSection_1 = require("./DecisionSection");
9
+ Object.defineProperty(exports, "DecisionSection", { enumerable: true, get: function () { return DecisionSection_1.DecisionSection; } });
10
+ var ProjectHoursAdjustmentModal_1 = require("./ProjectHoursAdjustmentModal");
11
+ Object.defineProperty(exports, "ProjectHoursAdjustmentModal", { enumerable: true, get: function () { return ProjectHoursAdjustmentModal_1.ProjectHoursAdjustmentModal; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.12.16",
3
+ "version": "1.12.18",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {