@paro.io/expert-shared-components 1.11.4 → 1.11.6

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.
@@ -0,0 +1,12 @@
1
+ interface UploadFileParams {
2
+ file: File;
3
+ documentName: string;
4
+ disputeId?: number;
5
+ projectId: number;
6
+ documentUploadUrl: string;
7
+ updateClientInvoiceDisputeMutation: any;
8
+ previousFiles: string[];
9
+ isExpert: boolean;
10
+ }
11
+ export declare const fileUploader: ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, disputeId, previousFiles, isExpert, }: UploadFileParams) => Promise<boolean>;
12
+ export {};
@@ -0,0 +1,55 @@
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.fileUploader = void 0;
16
+ const UploadClient_1 = __importDefault(require("../shared/UploadClient"));
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, }) {
19
+ try {
20
+ (0, utils_1.showToast)('success', 'Starting Document Upload');
21
+ const uploadClient = new UploadClient_1.default({
22
+ fileSelected: file,
23
+ fileName: file.name,
24
+ projectId,
25
+ documentUploadUrl,
26
+ bucketName: 'expert-client-dispute-files',
27
+ });
28
+ yield uploadClient.triggerMultipartUpload().then((res) => {
29
+ const resParsed = JSON.parse(res);
30
+ const documentLink = resParsed === null || resParsed === void 0 ? void 0 : resParsed.Location;
31
+ updateClientInvoiceDisputeMutation({
32
+ variables: {
33
+ input: {
34
+ disputeId: disputeId,
35
+ projectDisputes: [
36
+ Object.assign({ projectId: projectId }, (isExpert ? {
37
+ expertDocumentLinks: [...previousFiles, documentLink].join(',')
38
+ } : {
39
+ clientDocumentLinks: [...previousFiles, documentLink].join(',')
40
+ }))
41
+ ]
42
+ },
43
+ },
44
+ });
45
+ console.log(`Multipart File uploaded successfully with ${res}`);
46
+ (0, utils_1.showToast)('success', 'Document Upload Successful');
47
+ });
48
+ return true;
49
+ }
50
+ catch (error) {
51
+ (0, utils_1.showToast)('warning', 'Error uploading file. Please try again.');
52
+ return false;
53
+ }
54
+ });
55
+ exports.fileUploader = fileUploader;
@@ -1,7 +1,6 @@
1
1
  interface DecisionSectionProps {
2
2
  dispute: any;
3
3
  onUpdateDispute: (variables: any) => Promise<any>;
4
- onRefetch: () => Promise<void>;
5
4
  }
6
5
  export declare const DecisionSection: ({ dispute, onUpdateDispute, }: DecisionSectionProps) => JSX.Element;
7
6
  export {};
@@ -40,9 +40,9 @@ const react_1 = __importStar(require("react"));
40
40
  const base_ui_1 = require("@paro.io/base-ui");
41
41
  const react_hot_toast_1 = __importDefault(require("react-hot-toast"));
42
42
  const RESOLUTION_OPTIONS = [
43
- { value: 'Resolved', label: 'Approve Dispute' },
44
- { value: 'Resolved', label: 'Decline Dispute' },
45
- { value: 'Resolved', label: 'Partial Approval' },
43
+ { value: 'APPROVED', label: 'Approve Dispute' },
44
+ { value: 'DECLINED', label: 'Decline Dispute' },
45
+ { value: 'PARTIAL', label: 'Partial Approval' },
46
46
  ];
47
47
  const DecisionSection = ({ dispute, onUpdateDispute, }) => {
48
48
  const [resolution, setResolution] = (0, react_1.useState)('');
@@ -57,7 +57,7 @@ const DecisionSection = ({ dispute, onUpdateDispute, }) => {
57
57
  variables: {
58
58
  input: {
59
59
  disputeId: dispute.disputeId,
60
- status: resolution,
60
+ status: "Resolved",
61
61
  approvedAmount: amount ? parseFloat(amount) : undefined,
62
62
  },
63
63
  },
@@ -14,6 +14,7 @@ interface DiscussionSectionProps {
14
14
  currentUser: any;
15
15
  messages: Message[];
16
16
  onCreateMessage: (variables: any) => Promise<any>;
17
+ isInternal?: boolean;
17
18
  }
18
- export declare const DiscussionSection: ({ disputeId, currentUser, messages, onCreateMessage, }: DiscussionSectionProps) => JSX.Element;
19
+ export declare const DiscussionSection: ({ disputeId, currentUser, messages, onCreateMessage, isInternal }: DiscussionSectionProps) => JSX.Element;
19
20
  export {};
@@ -39,11 +39,11 @@ exports.DiscussionSection = void 0;
39
39
  const react_1 = __importStar(require("react"));
40
40
  const base_ui_1 = require("@paro.io/base-ui");
41
41
  const dayjs_1 = __importDefault(require("dayjs"));
42
- const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage, }) => {
43
- var _a;
42
+ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage, isInternal }) => {
44
43
  const [newMessage, setNewMessage] = (0, react_1.useState)('');
45
44
  const [visibility, setVisibility] = (0, react_1.useState)('ALL');
46
45
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
46
+ const threadsEndRef = (0, react_1.useRef)(null);
47
47
  // Get the sequence of unique userTypeIds to determine alignment
48
48
  const userSequence = (0, react_1.useMemo)(() => {
49
49
  const uniqueUsers = Array.from(new Set(messages.map(m => m.sender.userTypeId)));
@@ -82,11 +82,11 @@ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage,
82
82
  const getSenderTextColor = (userTypeId) => {
83
83
  switch (userTypeId) {
84
84
  case 1:
85
- return '#195C5C';
85
+ return '#643E0C';
86
86
  case 2:
87
87
  return '#2196F3';
88
88
  case 3:
89
- return '#643E0C';
89
+ return '#195C5C';
90
90
  default:
91
91
  return '#333333';
92
92
  }
@@ -94,11 +94,11 @@ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage,
94
94
  const getSenderBackgroundColor = (userTypeId) => {
95
95
  switch (userTypeId) {
96
96
  case 1:
97
- return '#D9EFEF';
97
+ return '#FDD7A5';
98
98
  case 2:
99
99
  return '#E4F0FF';
100
100
  case 3:
101
- return '#FDD7A5';
101
+ return '#D9EFEF';
102
102
  default:
103
103
  return '#F8F9FA';
104
104
  }
@@ -138,12 +138,13 @@ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage,
138
138
  react_1.default.createElement("span", { className: "text-xs text-[#666666]" }, (0, dayjs_1.default)(message.createdAt).format('MMM D, YYYY • h:mm A'))),
139
139
  react_1.default.createElement("div", { style: { backgroundColor: getSenderBackgroundColor(message.sender.userTypeId) }, className: "mt-1 p-3 rounded-lg" },
140
140
  react_1.default.createElement("p", { className: `text-sm ${getHeaderAlignment(message.sender.userTypeId)}`, style: { color: getSenderTextColor(message.sender.userTypeId) } }, message.messageText)))))))),
141
+ react_1.default.createElement("div", { ref: threadsEndRef }),
141
142
  react_1.default.createElement("div", { className: "space-y-4 p-6 space-y-6 rounded mt-4", style: { backgroundColor: '#F5F7F9' } },
142
143
  react_1.default.createElement("div", null,
143
144
  react_1.default.createElement("div", { className: "font-bold text-[#333333] mb-2" }, "Add Comment"),
144
145
  react_1.default.createElement("textarea", { value: newMessage, onChange: (e) => setNewMessage(e.target.value), placeholder: "Type your comment here...", className: "w-full h-24 p-3 border border-[#CCCCCC] rounded-lg text-sm resize-none focus:outline-none focus:ring-2 focus:ring-[#248384]" })),
145
146
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
146
- react_1.default.createElement("div", { className: "flex items-center space-x-4" }, ((_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.app_metadata) === null || _a === void 0 ? void 0 : _a.userTypeId) === 1 && (react_1.default.createElement(react_1.default.Fragment, null,
147
+ react_1.default.createElement("div", { className: "flex items-center space-x-4" }, isInternal && (react_1.default.createElement(react_1.default.Fragment, null,
147
148
  react_1.default.createElement("span", { className: "text-sm text-[#666666]" }, "Visible to:"),
148
149
  react_1.default.createElement("div", { className: "flex items-center space-x-2" },
149
150
  react_1.default.createElement("label", { className: "flex items-center space-x-2 cursor-pointer" },
@@ -1,7 +1,7 @@
1
1
  interface DisputeSectionProps {
2
2
  dispute: any;
3
- onUpdateDispute: (variables: any) => Promise<any>;
4
- onRefetch: () => Promise<void>;
3
+ documentUploadUrl: string;
4
+ updateClientInvoiceDisputeMutation: (variables: any) => Promise<any>;
5
5
  }
6
- export declare const DisputeSection: ({ dispute, onUpdateDispute, onRefetch, }: DisputeSectionProps) => JSX.Element;
6
+ export declare const DisputeSection: ({ dispute, documentUploadUrl, updateClientInvoiceDisputeMutation, }: DisputeSectionProps) => JSX.Element;
7
7
  export {};
@@ -22,11 +22,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
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
+ };
25
34
  Object.defineProperty(exports, "__esModule", { value: true });
26
35
  exports.DisputeSection = void 0;
27
36
  const react_1 = __importStar(require("react"));
28
37
  const base_ui_1 = require("@paro.io/base-ui");
29
38
  const base_icons_1 = require("@paro.io/base-icons");
39
+ const FileUploader_1 = require("../FileUploader");
40
+ const core_1 = require("@material-ui/core");
30
41
  const ACCEPTED_FILE_TYPES = [
31
42
  'application/pdf',
32
43
  'application/msword',
@@ -35,31 +46,50 @@ const ACCEPTED_FILE_TYPES = [
35
46
  'image/png',
36
47
  'text/csv',
37
48
  ];
38
- const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, }) => {
49
+ const DisputeSection = ({ dispute, documentUploadUrl, updateClientInvoiceDisputeMutation, }) => {
39
50
  var _a, _b, _c;
40
- const [files, setFiles] = (0, react_1.useState)((dispute === null || dispute === void 0 ? void 0 : dispute.clientDocumentLinks) || []);
41
51
  const fileInputRef = (0, react_1.useRef)(null);
52
+ const disputeProject = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a[0];
53
+ const clientDocumentLinks = (_b = disputeProject === null || disputeProject === void 0 ? void 0 : disputeProject.clientDocumentLinks) === null || _b === void 0 ? void 0 : _b.split(',');
54
+ const expertDocumentLinks = (_c = disputeProject === null || disputeProject === void 0 ? void 0 : disputeProject.expertDocumentLinks) === null || _c === void 0 ? void 0 : _c.split(',');
42
55
  const validateFileUpload = (file) => {
43
56
  return ACCEPTED_FILE_TYPES.includes(file.type);
44
57
  };
45
- const handleUpload = (event) => {
58
+ const handleUpload = (event, isExpert) => {
46
59
  const selectedFiles = event.target.files;
47
60
  if (!selectedFiles)
48
61
  return;
49
- const validFiles = Array.from(selectedFiles)
50
- .filter(file => validateFileUpload(file))
51
- .map(file => file.name);
52
- if (validFiles.length === 0)
53
- return;
54
- setFiles(prev => [...prev, ...validFiles]);
62
+ const getFileNames = selectedFiles && Array.from(selectedFiles).map((file) => {
63
+ if (!validateFileUpload(file)) {
64
+ return null;
65
+ }
66
+ if (file) {
67
+ return file.name;
68
+ }
69
+ }).filter((name) => name !== null);
70
+ if (getFileNames && getFileNames.length > 0) {
71
+ Array.from(selectedFiles).forEach((selectedFile) => {
72
+ const reader = new FileReader();
73
+ reader.onloadend = () => __awaiter(void 0, void 0, void 0, function* () {
74
+ var _a, _b;
75
+ yield (0, FileUploader_1.fileUploader)({
76
+ file: selectedFile,
77
+ documentName: selectedFile.name,
78
+ 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),
79
+ documentUploadUrl: documentUploadUrl,
80
+ updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation,
81
+ disputeId: dispute === null || dispute === void 0 ? void 0 : dispute.disputeId,
82
+ previousFiles: isExpert ? expertDocumentLinks : clientDocumentLinks,
83
+ isExpert: isExpert,
84
+ });
85
+ });
86
+ reader.readAsDataURL(selectedFile);
87
+ });
88
+ }
55
89
  if (fileInputRef.current) {
56
90
  fileInputRef.current.value = '';
57
91
  }
58
92
  };
59
- const handleRemoveFile = (fileName) => {
60
- setFiles(prev => prev.filter(f => f !== fileName));
61
- };
62
- const disputeProject = (_a = dispute === null || dispute === void 0 ? void 0 : dispute.disputeProjects) === null || _a === void 0 ? void 0 : _a[0];
63
93
  return (react_1.default.createElement("div", { className: "grid grid-cols-2 gap-6" },
64
94
  react_1.default.createElement("div", { className: "space-y-4" },
65
95
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
@@ -74,9 +104,17 @@ const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, }) => {
74
104
  react_1.default.createElement("div", null,
75
105
  react_1.default.createElement("div", { className: "text-sm font-bold text-[#333333] mb-2" }, "Supporting Documents:"),
76
106
  react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
77
- react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ACCEPTED_FILE_TYPES.join(','), className: "hidden", onChange: handleUpload }),
78
- react_1.default.createElement(base_ui_1.Button, { label: "Add File", iconLeft: react_1.default.createElement(base_icons_1.IconPlus, { size: "sm" }), onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, size: "sm", color: "info", className: "bg-white border border-[#248384] text-[#248384]" }), (_b = disputeProject === null || disputeProject === void 0 ? void 0 : disputeProject.clientDocumentLinks) === null || _b === void 0 ? void 0 :
79
- _b.map((file, index) => (react_1.default.createElement(base_ui_1.Tag, { key: index, label: file, variant: "subtle", color: "success", iconRight: react_1.default.createElement(base_icons_1.IconXCircle, null), onClick: () => handleRemoveFile(file) }))))))),
107
+ react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ACCEPTED_FILE_TYPES.join(','), className: "hidden", onChange: (e) => handleUpload(e, false) }),
108
+ react_1.default.createElement("div", { className: "flex flex-wrap gap-2" }, expertDocumentLinks === null || expertDocumentLinks === void 0 ? void 0 : expertDocumentLinks.map((file, index) => (
109
+ // @ts-ignore
110
+ react_1.default.createElement(core_1.Chip, { key: index, label: file.split('%2F').pop(), variant: "outlined", onClick: () => { window.open(file, '_blank'); }, sx: {
111
+ '&:hover': {
112
+ cursor: 'pointer',
113
+ backgroundColor: 'rgba(76, 175, 80, 0.1)'
114
+ }
115
+ } })))),
116
+ react_1.default.createElement("div", { className: "w-full mt-2" },
117
+ react_1.default.createElement(base_ui_1.Button, { label: "Add File", iconLeft: react_1.default.createElement(base_icons_1.IconPlus, { size: "sm" }), onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, size: "sm", color: "info", className: "bg-white border border-[#248384] text-[#248384]" })))))),
80
118
  react_1.default.createElement("div", { className: "space-y-4" },
81
119
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
82
120
  react_1.default.createElement("div", { className: "text-lg font-bold text-[#333333]" }, "Expert Rebuttal")),
@@ -87,8 +125,16 @@ const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, }) => {
87
125
  react_1.default.createElement("div", null,
88
126
  react_1.default.createElement("div", { className: "text-sm font-bold text-[#333333] mb-2" }, "Supporting Documents:"),
89
127
  react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
90
- react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ACCEPTED_FILE_TYPES.join(','), className: "hidden", onChange: handleUpload }),
91
- react_1.default.createElement(base_ui_1.Button, { label: "Add File", iconLeft: react_1.default.createElement(base_icons_1.IconPlus, { size: "sm" }), onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, size: "sm", color: "info", className: "bg-white border border-[#248384] text-[#248384]" }), (_c = disputeProject === null || disputeProject === void 0 ? void 0 : disputeProject.expertDocumentLinks) === null || _c === void 0 ? void 0 :
92
- _c.map((file, index) => (react_1.default.createElement(base_ui_1.Tag, { key: index, label: file, variant: "subtle", color: "success", iconRight: react_1.default.createElement(base_icons_1.IconXCircle, null), onClick: () => handleRemoveFile(file) })))))))));
128
+ react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ACCEPTED_FILE_TYPES.join(','), className: "hidden", onChange: (e) => handleUpload(e, true) }),
129
+ react_1.default.createElement("div", { className: "flex flex-wrap gap-2" }, clientDocumentLinks === null || clientDocumentLinks === void 0 ? void 0 : clientDocumentLinks.map((file, index) => (
130
+ // @ts-ignore
131
+ react_1.default.createElement(core_1.Chip, { key: index, label: file.split('%2F').pop(), variant: "outlined", onClick: () => { window.open(file, '_blank'); }, sx: {
132
+ '&:hover': {
133
+ cursor: 'pointer',
134
+ backgroundColor: 'rgba(76, 175, 80, 0.1)'
135
+ }
136
+ } })))),
137
+ react_1.default.createElement("div", { className: "w-full mt-2" },
138
+ react_1.default.createElement(base_ui_1.Button, { label: "Add File", iconLeft: react_1.default.createElement(base_icons_1.IconPlus, { size: "sm" }), onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, size: "sm", color: "info", className: "bg-white border border-[#248384] text-[#248384]" }))))))));
93
139
  };
94
140
  exports.DisputeSection = DisputeSection;
@@ -3,8 +3,9 @@ interface InvoiceCardProps {
3
3
  createDisputeChatMessage: any;
4
4
  user: any;
5
5
  chatMessages: any[];
6
- updateClientInvoiceMutation: any;
7
- refetchInvoiceDisputes: any;
6
+ updateClientInvoiceDisputeMutation: any;
7
+ documentUploadUrl: string;
8
+ isInternal?: boolean;
8
9
  }
9
- export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceMutation, refetchInvoiceDisputes, }: InvoiceCardProps) => JSX.Element;
10
+ export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, documentUploadUrl, isInternal }: InvoiceCardProps) => JSX.Element;
10
11
  export {};
@@ -11,15 +11,15 @@ const InvoiceDetails_1 = require("./InvoiceDetails");
11
11
  const DisputeSection_1 = require("./DisputeSection");
12
12
  const DiscussionSection_1 = require("./DiscussionSection");
13
13
  const DecisionSection_1 = require("./DecisionSection");
14
- const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceMutation, refetchInvoiceDisputes, }) => {
15
- var _a, _b, _c;
14
+ const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceDisputeMutation, documentUploadUrl, isInternal }) => {
15
+ var _a, _b;
16
16
  return (react_1.default.createElement(base_ui_1.Card, { className: "w-full bg-white rounded-lg shadow-sm overflow-hidden" },
17
17
  react_1.default.createElement(InvoiceHeader_1.InvoiceHeader, { invoice: clientInvoice }),
18
18
  react_1.default.createElement("div", { className: "p-6 space-y-6" },
19
19
  react_1.default.createElement(InvoiceDetails_1.InvoiceDetails, { invoice: clientInvoice }),
20
- react_1.default.createElement(DisputeSection_1.DisputeSection, { dispute: clientInvoice, onUpdateDispute: updateClientInvoiceMutation, onRefetch: refetchInvoiceDisputes }),
21
- (clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.chatEnabled) && (react_1.default.createElement(DiscussionSection_1.DiscussionSection, { disputeId: (_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.id, currentUser: user, messages: chatMessages, onCreateMessage: createDisputeChatMessage })),
22
- ((_c = user === null || user === void 0 ? void 0 : user.app_metadata) === null || _c === void 0 ? void 0 : _c.userTypeId) === 2 &&
23
- react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: clientInvoice, onUpdateDispute: updateClientInvoiceMutation, onRefetch: refetchInvoiceDisputes }))));
20
+ react_1.default.createElement(DisputeSection_1.DisputeSection, { dispute: clientInvoice, documentUploadUrl: documentUploadUrl, updateClientInvoiceDisputeMutation: updateClientInvoiceDisputeMutation }),
21
+ (clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.chatEnabled) && (react_1.default.createElement(DiscussionSection_1.DiscussionSection, { disputeId: (_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.id, currentUser: user, messages: chatMessages, onCreateMessage: createDisputeChatMessage, isInternal: isInternal })),
22
+ isInternal &&
23
+ react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: clientInvoice, onUpdateDispute: updateClientInvoiceDisputeMutation }))));
24
24
  };
25
25
  exports.InvoiceCard = InvoiceCard;
@@ -5,29 +5,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.InvoiceDetails = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
- const base_ui_1 = require("@paro.io/base-ui");
9
8
  const dayjs_1 = __importDefault(require("dayjs"));
10
9
  const DisputeProjectCard_1 = require("./DisputeProjectCard");
10
+ const core_1 = require("@material-ui/core");
11
11
  const InvoiceDetails = ({ invoice }) => {
12
12
  var _a;
13
13
  const getStatusColor = (status) => {
14
14
  switch (status) {
15
15
  case 'InProgress':
16
- return 'warning';
16
+ return 'primary';
17
17
  case 'UnderReview':
18
- return 'info';
18
+ return 'primary';
19
19
  case 'Resolved':
20
20
  return 'success';
21
21
  default:
22
- return 'default';
22
+ return 'primary';
23
23
  }
24
24
  };
25
25
  return (react_1.default.createElement("div", { className: "space-y-6" },
26
26
  react_1.default.createElement("div", { className: "flex items-center space-x-4" },
27
- react_1.default.createElement(base_ui_1.Tag, { label: invoice === null || invoice === void 0 ? void 0 : invoice.status, variant: "subtle", color: getStatusColor(invoice === null || invoice === void 0 ? void 0 : invoice.status) }),
27
+ react_1.default.createElement(core_1.Chip, { label: invoice === null || invoice === void 0 ? void 0 : invoice.status, size: "small", variant: "outlined",
28
+ // @ts-ignore
29
+ color: getStatusColor(invoice === null || invoice === void 0 ? void 0 : invoice.status) }),
28
30
  react_1.default.createElement("span", { className: "text-xs text-[#666666]" },
29
31
  "Last updated: ",
30
- (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeUpdatedDate).format('YYYY-MM-DD'))),
32
+ (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeUpdatedDate).format('MMM D, YYYY'))),
31
33
  ((_a = invoice === null || invoice === void 0 ? void 0 : invoice.disputeProjects) === null || _a === void 0 ? void 0 : _a.length) > 0 && (react_1.default.createElement("div", { className: "space-y-4" },
32
34
  react_1.default.createElement("div", { className: "grid grid-cols-1 gap-4" }, invoice.disputeProjects.map((project) => (react_1.default.createElement(DisputeProjectCard_1.DisputeProjectCard, { key: project.id, project: project, client: invoice === null || invoice === void 0 ? void 0 : invoice.client, disputeDate: invoice === null || invoice === void 0 ? void 0 : invoice.disputeDate, disputeUpdatedDate: invoice === null || invoice === void 0 ? void 0 : invoice.disputeUpdatedDate }))))))));
33
35
  };
@@ -5,6 +5,7 @@ export default class UploadClient {
5
5
  fileName: string;
6
6
  documentUploadUrl: string;
7
7
  projectId: number;
8
+ bucketName: string;
8
9
  };
9
10
  constructor(props: any);
10
11
  generateS3Key(projectId: number, fileName: string): string;
@@ -17,6 +17,7 @@ class UploadClient {
17
17
  fileName: props.fileName,
18
18
  documentUploadUrl: props.documentUploadUrl,
19
19
  projectId: props.projectId,
20
+ bucketName: props.bucketName,
20
21
  };
21
22
  }
22
23
  generateS3Key(projectId, fileName) {
@@ -34,6 +35,7 @@ class UploadClient {
34
35
  const params = {
35
36
  fileName: this.state.fileName,
36
37
  fileType: this.state.fileSelected.type,
38
+ bucketName: this.state.bucketName,
37
39
  method: 'start-upload',
38
40
  };
39
41
  const response = yield fetch(`${this.state.documentUploadUrl}`, {
@@ -67,7 +69,7 @@ class UploadClient {
67
69
  // Get presigned URL for each part from backend lambda
68
70
  let presignedUrlResponse = yield fetch(`${this.state.documentUploadUrl}`, {
69
71
  method: 'POST',
70
- body: JSON.stringify({ fileName: this.state.fileName, uploadId: this.state.uploadId, partNumber: index, method: 'get-presigned-url' }),
72
+ body: JSON.stringify({ fileName: this.state.fileName, uploadId: this.state.uploadId, partNumber: index, method: 'get-presigned-url', bucketName: this.state.bucketName }),
71
73
  });
72
74
  const { responseData } = yield presignedUrlResponse.json();
73
75
  // Add each upload part to promise array using presigned URL
@@ -100,11 +102,11 @@ class UploadClient {
100
102
  headers: {
101
103
  'Content-Type': 'application/json',
102
104
  },
103
- body: JSON.stringify({ fileName: this.state.fileName, uploadId: this.state.uploadId, parts: partsArray, method: 'complete-upload' }),
105
+ body: JSON.stringify({ fileName: this.state.fileName, uploadId: this.state.uploadId, parts: partsArray, method: 'complete-upload', bucketName: this.state.bucketName }),
104
106
  });
105
107
  const { responseData } = yield response.json();
106
108
  console.log('Upload Complete', responseData);
107
- return `Upload Complete ${JSON.stringify(responseData)}`;
109
+ return `${JSON.stringify(responseData)}`;
108
110
  }
109
111
  catch (error) {
110
112
  console.log(`Error Completing Multipart Upload ${error}`);
package/lib/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export { sharedUtils } from './components/shared/utils';
12
12
  export { ActiveProjectCard } from './components/ProjectCard/ActiveProjectCard';
13
13
  export { InvoiceCard } from './components/Invoices/InvoiceCard';
14
14
  export { DiscussionThread } from './components/DiscussionThread';
15
+ export { fileUploader } from './components/FileUploader';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DiscussionThread = exports.InvoiceCard = exports.ActiveProjectCard = exports.sharedUtils = exports.ServiceLinesTemplate = exports.HeaderNavBar = exports.DocumentCenter = exports.ProfileCompletedPercentage = exports.ExpertProfileHeader = exports.OrganizationChart = exports.FirmEmployeeSection = exports.ClientReferenceSection = exports.Reviews = exports.ReviewsTab = void 0;
3
+ exports.fileUploader = exports.DiscussionThread = exports.InvoiceCard = exports.ActiveProjectCard = exports.sharedUtils = exports.ServiceLinesTemplate = exports.HeaderNavBar = exports.DocumentCenter = exports.ProfileCompletedPercentage = exports.ExpertProfileHeader = exports.OrganizationChart = exports.FirmEmployeeSection = exports.ClientReferenceSection = exports.Reviews = exports.ReviewsTab = void 0;
4
4
  var ReviewsTab_1 = require("./components/ReviewsTab");
5
5
  Object.defineProperty(exports, "ReviewsTab", { enumerable: true, get: function () { return ReviewsTab_1.ReviewsTab; } });
6
6
  var Reviews_1 = require("./components/Reviews");
@@ -29,3 +29,5 @@ var InvoiceCard_1 = require("./components/Invoices/InvoiceCard");
29
29
  Object.defineProperty(exports, "InvoiceCard", { enumerable: true, get: function () { return InvoiceCard_1.InvoiceCard; } });
30
30
  var DiscussionThread_1 = require("./components/DiscussionThread");
31
31
  Object.defineProperty(exports, "DiscussionThread", { enumerable: true, get: function () { return DiscussionThread_1.DiscussionThread; } });
32
+ var FileUploader_1 = require("./components/FileUploader");
33
+ Object.defineProperty(exports, "fileUploader", { enumerable: true, get: function () { return FileUploader_1.fileUploader; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.11.4",
3
+ "version": "1.11.6",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {