@paro.io/expert-shared-components 1.12.32 → 1.12.33

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.
@@ -121,6 +121,15 @@ const ProfileSection = ({ legacyFreelancerId, imageUrl, shouldAllowEditProfile,
121
121
  " Reviews")))),
122
122
  react_1.default.createElement(core_1.Box, { mt: 1, mb: 1 },
123
123
  react_1.default.createElement(core_1.Divider, null))),
124
+ react_1.default.createElement(core_1.Box, { ml: 1, display: "flex", justifyContent: "space-between", alignItems: "center", "data-testid": "Matching-Id", style: { marginRight: '10px' } },
125
+ react_1.default.createElement(core_1.Typography, { variant: "body2" }, "Paro Tenure"),
126
+ react_1.default.createElement("b", null, paroTenure.length > 0 ? paroTenure : "N/A")),
127
+ react_1.default.createElement(core_1.Box, { ml: 1, mt: 1, display: "flex", justifyContent: "space-between", alignItems: "center", "data-testid": "Matching-Id", style: { marginRight: '10px' } },
128
+ react_1.default.createElement(core_1.Typography, { variant: "body2" }, isInternal ? 'Hourly Expert Rate' : 'Hourly Rate'),
129
+ react_1.default.createElement("b", null, hourlyRate > 0 ? `$ ${hourlyRate.toLocaleString()}` : "N/A")),
130
+ isInternal && react_1.default.createElement(core_1.Box, { ml: 1, mt: 1, display: "flex", justifyContent: "space-between", alignItems: "center", "data-testid": "Matching-Id", style: { marginRight: '10px' } },
131
+ react_1.default.createElement(core_1.Typography, { variant: "body2" }, "Hourly Client Rate"),
132
+ react_1.default.createElement("b", null, hourlyRate > 0 ? `$ ${(hourlyRate * 2).toLocaleString()}` : "N/A")),
124
133
  react_1.default.createElement(core_1.Box, { mt: 2, mb: 1 }),
125
134
  (rates === null || rates === void 0 ? void 0 : rates.length) > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
126
135
  react_1.default.createElement(core_1.Grid, { item: true, container: true, direction: 'row', justifyContent: 'space-evenly' },
@@ -6,7 +6,6 @@ interface DecisionSectionProps {
6
6
  getClientInvoiceSummaryByMonth: any;
7
7
  invoiceSummary: any;
8
8
  updateClientInvoiceDisputeMutation: any;
9
- addClientCredit: any;
10
9
  }
11
- export declare const DecisionSection: ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, addClientCredit }: DecisionSectionProps) => JSX.Element;
10
+ export declare const DecisionSection: ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, }: DecisionSectionProps) => JSX.Element;
12
11
  export {};
@@ -42,15 +42,14 @@ const RESOLUTION_OPTIONS = [
42
42
  { value: 'DECLINED', label: 'Decline Dispute' },
43
43
  { value: 'PARTIAL', label: 'Partial Approval' },
44
44
  ];
45
- const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, addClientCredit }) => {
46
- var _a, _b, _c, _d;
45
+ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, updateClientInvoiceDisputeMutation, invoiceSummary, user, getClientInvoiceSummaryByMonth, }) => {
46
+ var _a, _b;
47
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);
48
48
  const [resolution, setResolution] = (0, react_1.useState)('');
49
49
  const [approvedHours, setApprovedHours] = (0, react_1.useState)(totalDisputeHours);
50
50
  const [projectApprovedHours, setProjectApprovedHours] = (0, react_1.useState)({});
51
51
  const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
52
52
  const [showHoursModal, setShowHoursModal] = (0, react_1.useState)(false);
53
- const isDisputePaid = ((_b = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _b === void 0 ? void 0 : _b.clientInvoiceStatusId) === 4 || ((_c = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _c === void 0 ? void 0 : _c.clientInvoiceStatusId) === 8;
54
53
  // Initialize project approved hours when resolution changes to PARTIAL
55
54
  const handleResolutionChange = (newResolution) => {
56
55
  var _a;
@@ -85,6 +84,7 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
85
84
  const handleApproveClick = () => {
86
85
  if (!resolution)
87
86
  return;
87
+ // Show modal for PARTIAL or APPROVED resolutions regardless of dispute type
88
88
  if (resolution === 'PARTIAL' || resolution === 'APPROVED') {
89
89
  setShowHoursModal(true);
90
90
  }
@@ -100,13 +100,19 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
100
100
  var _a, _b, _c;
101
101
  setIsSubmitting(true);
102
102
  try {
103
+ const resolutionType = resolution === 'APPROVED' ? 'Upheld' : 'Reduced';
104
+ const disputeProjectUpdates = ((_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.map((project) => ({
105
+ projectId: project.projectId,
106
+ resolutionMode: 'Direct',
107
+ resolutionType: resolution === 'DECLINED' ? 'Canceled' : resolutionType
108
+ }))) || [];
103
109
  let calculatedApprovedAmount = 0;
104
- const fullDisputeAmount = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a.reduce((acc, project) => acc + project.disputeAmount, 0);
110
+ const fullDisputeAmount = (_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.reduce((acc, project) => acc + project.disputeAmount, 0);
105
111
  if (resolution === 'APPROVED') {
106
112
  calculatedApprovedAmount = fullDisputeAmount;
107
113
  }
108
114
  else {
109
- (_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.forEach((project) => {
115
+ (_c = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _c === void 0 ? void 0 : _c.forEach((project) => {
110
116
  var _a, _b;
111
117
  const approvedForProject = projectApprovedHours[project.projectId] || 0;
112
118
  if (project.disputeType === 'Hourly') {
@@ -118,50 +124,6 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
118
124
  }
119
125
  });
120
126
  }
121
- if (submissionData) {
122
- if (isDisputePaid) {
123
- yield addClientCredit({
124
- variables: {
125
- input: {
126
- clientId: submissionData.clientId,
127
- amount: calculatedApprovedAmount,
128
- description: `Credit from Dispute #${dispute.disputeId} - Invoice #${dispute.invoice.id}`,
129
- updatedDate: new Date().toISOString()
130
- }
131
- }
132
- });
133
- }
134
- else {
135
- yield updateInvoiceMutation({
136
- variables: {
137
- input: submissionData.input,
138
- clientId: submissionData.clientId,
139
- invoiceId: submissionData.invoiceId,
140
- dateGenerated: submissionData.dateGenerated,
141
- updateDescription: submissionData.updateDescription,
142
- freelancerIds: submissionData.freelancerIds
143
- }
144
- });
145
- }
146
- }
147
- let resolutionType;
148
- if (isDisputePaid) {
149
- resolutionType = 'FutureCredit';
150
- }
151
- else if (resolution === 'APPROVED') {
152
- resolutionType = 'Upheld';
153
- }
154
- else if (resolution === 'PARTIAL') {
155
- resolutionType = 'Reduced';
156
- }
157
- else {
158
- resolutionType = 'Canceled';
159
- }
160
- const disputeProjectUpdates = ((_c = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _c === void 0 ? void 0 : _c.map((project) => ({
161
- projectId: project.projectId,
162
- resolutionMode: 'Direct',
163
- resolutionType: resolutionType
164
- }))) || [];
165
127
  const updateData = {
166
128
  disputeId: dispute.disputeId,
167
129
  status: "Resolved",
@@ -169,17 +131,24 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
169
131
  finalDecisionOwnerId: (user === null || user === void 0 ? void 0 : user.userId) || null,
170
132
  projectDisputes: disputeProjectUpdates
171
133
  };
134
+ if (submissionData) {
135
+ yield updateInvoiceMutation({
136
+ variables: {
137
+ input: submissionData.input,
138
+ clientId: submissionData.clientId,
139
+ invoiceId: submissionData.invoiceId,
140
+ dateGenerated: submissionData.dateGenerated,
141
+ updateDescription: submissionData.updateDescription,
142
+ freelancerIds: submissionData.freelancerIds
143
+ }
144
+ });
145
+ }
172
146
  yield onUpdateDispute({
173
147
  variables: {
174
148
  input: updateData,
175
149
  },
176
150
  });
177
- if (isDisputePaid) {
178
- (0, utils_1.showToast)('success', `Future credit applied: $${calculatedApprovedAmount} to Client ${dispute.client.name}'s balance`);
179
- }
180
- else {
181
- (0, utils_1.showToast)('success', 'Thank you for resolving the dispute. The invoice has been updated with the new hours.');
182
- }
151
+ (0, utils_1.showToast)('success', 'Thank you for resolving the dispute. The invoice has been updated with the new hours.');
183
152
  }
184
153
  catch (error) {
185
154
  console.error('Failed to update dispute:', error);
@@ -189,7 +158,7 @@ const DecisionSection = ({ dispute, onUpdateDispute, updateInvoiceMutation, upda
189
158
  setIsSubmitting(false);
190
159
  }
191
160
  });
192
- const isPartialWithMultipleProjects = resolution === 'PARTIAL' && ((_d = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _d === void 0 ? void 0 : _d.length) > 0;
161
+ const isPartialWithMultipleProjects = resolution === 'PARTIAL' && ((_b = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _b === void 0 ? void 0 : _b.length) > 0;
193
162
  const isValidPartialApproval = () => {
194
163
  if (resolution !== 'PARTIAL')
195
164
  return true;
@@ -13,7 +13,7 @@ interface InvoiceCardProps {
13
13
  isClient?: boolean;
14
14
  bucketName?: string;
15
15
  reactAppUrl?: string;
16
- addClientCredit?: any;
16
+ isLateDisputeAllowed?: boolean;
17
17
  }
18
- export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal, isClient, bucketName, reactAppUrl, addClientCredit }: InvoiceCardProps) => JSX.Element;
18
+ export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal, isClient, bucketName, reactAppUrl, isLateDisputeAllowed, }: InvoiceCardProps) => JSX.Element;
19
19
  export {};
@@ -34,29 +34,25 @@ const DisputeSection_1 = require("./DisputeSection");
34
34
  const DiscussionSection_1 = require("./DiscussionSection");
35
35
  const DecisionSection_1 = require("./DecisionSection");
36
36
  const ClientDisputeProjectCard_1 = require("./ClientDisputeProjectCard");
37
- const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal = false, isClient = false, bucketName, reactAppUrl, addClientCredit }) => {
38
- var _a;
39
- const envUrl = reactAppUrl === null || reactAppUrl === void 0 ? void 0 : reactAppUrl.split('.')[1];
40
- const rolesUrl = `https://app.${envUrl}.io/roles`;
37
+ const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, updateInvoiceMutation, getClientInvoiceSummaryByMonth, invoiceSummary, documentUploadUrl, downloadDocumentUrl, isInternal = false, isClient = false, bucketName, reactAppUrl, isLateDisputeAllowed = false, }) => {
41
38
  const [currentInvoice, setCurrentInvoice] = (0, react_1.useState)(clientInvoice);
42
39
  (0, react_1.useEffect)(() => {
43
40
  setCurrentInvoice(clientInvoice);
44
41
  }, [clientInvoice]);
45
42
  const disputeId = currentInvoice === null || currentInvoice === void 0 ? void 0 : currentInvoice.disputeId;
46
- const hasDisputeAdminRole = (_a = user === null || user === void 0 ? void 0 : user[rolesUrl]) === null || _a === void 0 ? void 0 : _a.includes('disputes_admin');
47
43
  return (react_1.default.createElement(base_ui_1.Card, { className: "w-full bg-white rounded-lg shadow-sm overflow-hidden mb-4" },
48
44
  react_1.default.createElement(core_1.Accordion, null,
49
45
  react_1.default.createElement(core_1.AccordionSummary, { expandIcon: react_1.default.createElement(base_icons_1.IconChevronDown, null), "aria-controls": "invoice-content", id: "invoice-header" },
50
46
  react_1.default.createElement(InvoiceHeader_1.InvoiceHeader, { invoice: currentInvoice, isInternal: isInternal, isClient: isClient })),
51
47
  react_1.default.createElement(core_1.AccordionDetails, null,
52
48
  react_1.default.createElement("div", { className: "p-6 space-y-6 w-full" },
53
- react_1.default.createElement(InvoiceDetails_1.InvoiceDetails, { invoice: currentInvoice, isInternal: isInternal, isClient: isClient, reactAppUrl: reactAppUrl }),
49
+ react_1.default.createElement(InvoiceDetails_1.InvoiceDetails, { invoice: currentInvoice, isInternal: isInternal, isClient: isClient, reactAppUrl: reactAppUrl, isLateDisputeAllowed: isLateDisputeAllowed }),
54
50
  isInternal ?
55
51
  react_1.default.createElement(DisputeSection_1.DisputeSection, { dispute: currentInvoice, documentUploadUrl: documentUploadUrl, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName })
56
52
  :
57
53
  react_1.default.createElement(ClientDisputeProjectCard_1.ClientDisputeProjectCard, { clientInvoice: currentInvoice, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, documentUploadUrl: documentUploadUrl, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName }),
58
54
  (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 })),
59
- isInternal && hasDisputeAdminRole &&
60
- react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: currentInvoice, onUpdateDispute: updateClientInvoiceDisputeMutation, updateInvoiceMutation: updateInvoiceMutation, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, invoiceSummary: invoiceSummary, user: user, getClientInvoiceSummaryByMonth: getClientInvoiceSummaryByMonth, addClientCredit: addClientCredit }))))));
55
+ isInternal &&
56
+ react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: currentInvoice, onUpdateDispute: updateClientInvoiceDisputeMutation, updateInvoiceMutation: updateInvoiceMutation, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation, invoiceSummary: invoiceSummary, user: user, getClientInvoiceSummaryByMonth: getClientInvoiceSummaryByMonth }))))));
61
57
  };
62
58
  exports.InvoiceCard = InvoiceCard;
@@ -3,8 +3,9 @@ interface InvoiceDetailsProps {
3
3
  isInternal: boolean;
4
4
  isClient: boolean;
5
5
  reactAppUrl?: string;
6
+ isLateDisputeAllowed?: boolean;
6
7
  }
7
8
  export declare const getStatusColor: (status: string) => "success" | "primary" | "info" | "warning";
8
9
  export declare const getStatusText: (status: string) => "" | "Resolved" | "In Progress" | "Under Review";
9
- export declare const InvoiceDetails: ({ invoice, isInternal, isClient, reactAppUrl }: InvoiceDetailsProps) => JSX.Element;
10
+ export declare const InvoiceDetails: ({ invoice, isInternal, isClient, reactAppUrl, isLateDisputeAllowed }: InvoiceDetailsProps) => JSX.Element;
10
11
  export {};
@@ -34,15 +34,15 @@ const getStatusText = (status) => {
34
34
  }
35
35
  };
36
36
  exports.getStatusText = getStatusText;
37
- const InvoiceDetails = ({ invoice, isInternal = false, isClient = false, reactAppUrl = 'https://internal.parodev.io' }) => {
37
+ const InvoiceDetails = ({ invoice, isInternal = false, isClient = false, reactAppUrl = 'https://internal.parodev.io', isLateDisputeAllowed = false }) => {
38
38
  var _a, _b, _c, _d, _e, _f, _g;
39
39
  const clientInvoiceUrl = `${reactAppUrl}/invoices/${(_a = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _a === void 0 ? void 0 : _a.id}?month=${(_b = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _b === void 0 ? void 0 : _b.month}&companyId=${(_c = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _c === void 0 ? void 0 : _c.clientId}`;
40
40
  const internalInvoiceUrl = `${reactAppUrl}/client/${(_d = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _d === void 0 ? void 0 : _d.clientId}/invoices/${(_e = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _e === void 0 ? void 0 : _e.id}?month=${(_f = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _f === void 0 ? void 0 : _f.month}`;
41
41
  const today = (0, dayjs_1.default)();
42
42
  const firstDayOfMonth = (0, dayjs_1.default)().startOf('month');
43
- const disputeDaysLeft = 14 - today.diff(firstDayOfMonth, 'day');
43
+ const disputeDaysLeft = isLateDisputeAllowed ? 14 - today.diff(firstDayOfMonth, 'day') : 7 - today.diff(firstDayOfMonth, 'day');
44
44
  const daysLeft = disputeDaysLeft > 0;
45
- const editableDate = (0, dayjs_1.default)().date(14).format("MMM DD");
45
+ const editableDate = (0, dayjs_1.default)().date(isLateDisputeAllowed ? 14 : 7).format("MMM DD");
46
46
  return (react_1.default.createElement("div", { className: "space-y-6" },
47
47
  react_1.default.createElement("div", { className: "flex items-center space-x-4" },
48
48
  react_1.default.createElement(base_ui_1.Tag, { color: (0, exports.getStatusColor)(invoice === null || invoice === void 0 ? void 0 : invoice.status), label: (0, exports.getStatusText)(invoice === null || invoice === void 0 ? void 0 : invoice.status), borderRadius: "full", variant: "subtle" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.12.32",
3
+ "version": "1.12.33",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {