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

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.
Files changed (71) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +2 -2
  3. package/lib/components/ClientReferencesSection/DeleteButton.js +11 -11
  4. package/lib/components/ClientReferencesSection/ParoError.js +10 -10
  5. package/lib/components/ClientReferencesSection/TagsSection.js +2 -2
  6. package/lib/components/ClientReferencesSection/styles/BrandedTypography.js +2 -2
  7. package/lib/components/ClientReferencesSection/styles/Buttons.js +15 -15
  8. package/lib/components/ClientReferencesSection/styles/Name.js +5 -5
  9. package/lib/components/ClientReferencesSection/styles/NullContentConditionalColor.js +4 -4
  10. package/lib/components/ClientReferencesSection/styles/SectionBody.js +11 -11
  11. package/lib/components/ClientReferencesSection/styles/SectionTitle.js +6 -6
  12. package/lib/components/ClientReferencesSection/styles/Tags.js +2 -2
  13. package/lib/components/DocumentCenter/DocumentTable.d.ts +15 -15
  14. package/lib/components/DocumentCenter/DocumentTable.js +350 -350
  15. package/lib/components/DocumentCenter/UploadFilesButton.d.ts +6 -6
  16. package/lib/components/DocumentCenter/UploadFilesButton.js +29 -29
  17. package/lib/components/EarningsTracker/ActiveProjectCard.d.ts +52 -52
  18. package/lib/components/EarningsTracker/ActiveProjectCard.js +161 -161
  19. package/lib/components/EarningsTracker/CenterCardUI.d.ts +13 -13
  20. package/lib/components/EarningsTracker/CenterCardUI.js +134 -134
  21. package/lib/components/EarningsTracker/EarningsTracker.d.ts +52 -52
  22. package/lib/components/EarningsTracker/EarningsTracker.js +508 -508
  23. package/lib/components/EarningsTracker/EditDateModal.d.ts +22 -22
  24. package/lib/components/EarningsTracker/EditDateModal.js +149 -149
  25. package/lib/components/EarningsTracker/EmailModal.d.ts +14 -14
  26. package/lib/components/EarningsTracker/EmailModal.js +79 -79
  27. package/lib/components/EarningsTracker/EndProjectModal.d.ts +56 -56
  28. package/lib/components/EarningsTracker/EndProjectModal.js +221 -221
  29. package/lib/components/EarningsTracker/LeftCardUI.d.ts +18 -18
  30. package/lib/components/EarningsTracker/LeftCardUI.js +189 -189
  31. package/lib/components/EarningsTracker/LogTimeModalAuthenticated.d.ts +52 -52
  32. package/lib/components/EarningsTracker/LogTimeModalAuthenticated.js +358 -358
  33. package/lib/components/EarningsTracker/ProgressBar.d.ts +4 -4
  34. package/lib/components/EarningsTracker/ProgressBar.js +66 -66
  35. package/lib/components/EarningsTracker/ReviewRequestModal.d.ts +17 -17
  36. package/lib/components/EarningsTracker/ReviewRequestModal.js +135 -135
  37. package/lib/components/EarningsTracker/RightCardUI.d.ts +46 -46
  38. package/lib/components/EarningsTracker/RightCardUI.js +231 -231
  39. package/lib/components/EarningsTracker/index.d.ts +1 -1
  40. package/lib/components/EarningsTracker/index.js +5 -5
  41. package/lib/components/ExpertProfileHeader/ActionButtonSection.js +6 -6
  42. package/lib/components/ExpertProfileHeader/ProfileSection.js +7 -7
  43. package/lib/components/FileUploader/index.d.ts +10 -0
  44. package/lib/components/FileUploader/index.js +70 -0
  45. package/lib/components/Invoices/DiscussionSection.js +14 -0
  46. package/lib/components/Invoices/DisputeSection.d.ts +3 -1
  47. package/lib/components/Invoices/DisputeSection.js +36 -4
  48. package/lib/components/Invoices/InvoiceCard.d.ts +3 -1
  49. package/lib/components/Invoices/InvoiceCard.js +2 -2
  50. package/lib/components/Invoices/InvoiceDetails.js +1 -1
  51. package/lib/components/Invoices/InvoiceHeader.js +2 -2
  52. package/lib/components/OrganizationChart/OrganizationChart.d.ts +15 -15
  53. package/lib/components/OrganizationChart/OrganizationChart.js +312 -312
  54. package/lib/components/OrganizationChart/PersonCard.js +5 -5
  55. package/lib/components/OrganizationChart/utils.js +79 -79
  56. package/lib/components/ProjectCard/ProgressBar.js +4 -4
  57. package/lib/components/ProjectCard/ReviewRequestModal.js +5 -5
  58. package/lib/components/Reviews/Pagination.js +6 -6
  59. package/lib/components/ReviewsTab/RatingHeader.js +6 -6
  60. package/lib/components/ReviewsTab/expert-shared-components.code-workspace +20 -20
  61. package/lib/components/ReviewsTab/reviewRequestModal.js +5 -5
  62. package/lib/components/shared/Image.js +13 -13
  63. package/lib/components/shared/ProfileTextField.d.ts +18 -18
  64. package/lib/components/shared/ProfileTextField.js +16 -16
  65. package/lib/components/shared/StyledActionButtons.d.ts +7 -7
  66. package/lib/components/shared/StyledActionButtons.js +15 -15
  67. package/lib/components/shared/ToastNotification.d.ts +10 -10
  68. package/lib/components/shared/ToastNotification.js +63 -63
  69. package/lib/index.d.ts +1 -0
  70. package/lib/index.js +3 -1
  71. package/package.json +61 -61
@@ -0,0 +1,70 @@
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 CHUNK_SIZE = 5 * 1024 * 1024;
19
+ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, documentName, disputeId, projectId, documentUploadUrl, uploadExpertClientDisputeFilesData, }) {
20
+ var _b;
21
+ const fileExtension = file.name.split('.').pop() || '';
22
+ const fileNameWithExtension = `${documentName}.${fileExtension}`;
23
+ const isLargeFile = file.size >= CHUNK_SIZE;
24
+ try {
25
+ // Read file as base64
26
+ const fileForUpload = yield new Promise((resolve, reject) => {
27
+ const reader = new FileReader();
28
+ reader.onload = () => { var _a; return resolve(((_a = reader.result) === null || _a === void 0 ? void 0 : _a.toString()) || ''); };
29
+ reader.onerror = reject;
30
+ reader.readAsDataURL(file);
31
+ });
32
+ // Upload large file via multipart
33
+ if (isLargeFile) {
34
+ (0, utils_1.showToast)('warning', 'Uploading a large file — this may take longer than usual. Thank you for your patience!');
35
+ const uploadClient = new UploadClient_1.default({
36
+ fileSelected: file,
37
+ fileName: fileNameWithExtension,
38
+ projectId,
39
+ documentUploadUrl,
40
+ });
41
+ yield uploadClient.triggerMultipartUpload();
42
+ }
43
+ const inputData = {
44
+ disputeId: disputeId ? disputeId : projectId, // initially we don't have disputeId. clarify and update
45
+ fileName: documentName,
46
+ data: isLargeFile ? '' : fileForUpload,
47
+ fileSize: file.size,
48
+ };
49
+ console.log({ inputData, disputeId, projectId });
50
+ // Upload metadata to backend
51
+ const response = yield uploadExpertClientDisputeFilesData({
52
+ variables: {
53
+ input: inputData,
54
+ },
55
+ });
56
+ if ((_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.uploadExpertClientDisputeFilesData) {
57
+ (0, utils_1.showToast)('success', 'Supporting document uploaded successfully!');
58
+ return true;
59
+ }
60
+ else {
61
+ (0, utils_1.showToast)('warning', 'Failed to upload supporting document');
62
+ return false;
63
+ }
64
+ }
65
+ catch (error) {
66
+ (0, utils_1.showToast)('warning', 'Error uploading file. Please try again.');
67
+ return false;
68
+ }
69
+ });
70
+ exports.fileUploader = fileUploader;
@@ -44,6 +44,19 @@ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage,
44
44
  const [newMessage, setNewMessage] = (0, react_1.useState)('');
45
45
  const [visibility, setVisibility] = (0, react_1.useState)('ALL');
46
46
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
47
+ const threadsEndRef = (0, react_1.useRef)(null);
48
+ const didMountRef = (0, react_1.useRef)(false);
49
+ // Auto scroll to bottom when messages change
50
+ (0, react_1.useEffect)(() => {
51
+ if (didMountRef.current) {
52
+ if (threadsEndRef.current) {
53
+ threadsEndRef.current.scrollIntoView({ behavior: "smooth" });
54
+ }
55
+ }
56
+ else {
57
+ didMountRef.current = true;
58
+ }
59
+ }, [messages]);
47
60
  // Get the sequence of unique userTypeIds to determine alignment
48
61
  const userSequence = (0, react_1.useMemo)(() => {
49
62
  const uniqueUsers = Array.from(new Set(messages.map(m => m.sender.userTypeId)));
@@ -138,6 +151,7 @@ const DiscussionSection = ({ disputeId, currentUser, messages, onCreateMessage,
138
151
  react_1.default.createElement("span", { className: "text-xs text-[#666666]" }, (0, dayjs_1.default)(message.createdAt).format('MMM D, YYYY • h:mm A'))),
139
152
  react_1.default.createElement("div", { style: { backgroundColor: getSenderBackgroundColor(message.sender.userTypeId) }, className: "mt-1 p-3 rounded-lg" },
140
153
  react_1.default.createElement("p", { className: `text-sm ${getHeaderAlignment(message.sender.userTypeId)}`, style: { color: getSenderTextColor(message.sender.userTypeId) } }, message.messageText)))))))),
154
+ react_1.default.createElement("div", { ref: threadsEndRef }),
141
155
  react_1.default.createElement("div", { className: "space-y-4 p-6 space-y-6 rounded mt-4", style: { backgroundColor: '#F5F7F9' } },
142
156
  react_1.default.createElement("div", null,
143
157
  react_1.default.createElement("div", { className: "font-bold text-[#333333] mb-2" }, "Add Comment"),
@@ -2,6 +2,8 @@ interface DisputeSectionProps {
2
2
  dispute: any;
3
3
  onUpdateDispute: (variables: any) => Promise<any>;
4
4
  onRefetch: () => Promise<void>;
5
+ documentUploadUrl: string;
6
+ uploadExpertClientDisputeFiles: (variables: any) => Promise<any>;
5
7
  }
6
- export declare const DisputeSection: ({ dispute, onUpdateDispute, onRefetch, }: DisputeSectionProps) => JSX.Element;
8
+ export declare const DisputeSection: ({ dispute, onUpdateDispute, onRefetch, documentUploadUrl, uploadExpertClientDisputeFiles, }: DisputeSectionProps) => JSX.Element;
7
9
  export {};
@@ -22,11 +22,21 @@ 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");
30
40
  const ACCEPTED_FILE_TYPES = [
31
41
  'application/pdf',
32
42
  'application/msword',
@@ -35,7 +45,7 @@ const ACCEPTED_FILE_TYPES = [
35
45
  'image/png',
36
46
  'text/csv',
37
47
  ];
38
- const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, }) => {
48
+ const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, documentUploadUrl, uploadExpertClientDisputeFiles, }) => {
39
49
  var _a, _b, _c;
40
50
  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);
@@ -49,9 +59,31 @@ const DisputeSection = ({ dispute, onUpdateDispute, onRefetch, }) => {
49
59
  const validFiles = Array.from(selectedFiles)
50
60
  .filter(file => validateFileUpload(file))
51
61
  .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
+ uploadExpertClientDisputeFilesData: uploadExpertClientDisputeFiles,
81
+ });
82
+ });
83
+ reader.readAsDataURL(selectedFile);
84
+ });
85
+ setFiles(prev => [...prev, ...validFiles]);
86
+ }
55
87
  if (fileInputRef.current) {
56
88
  fileInputRef.current.value = '';
57
89
  }
@@ -5,6 +5,8 @@ interface InvoiceCardProps {
5
5
  chatMessages: any[];
6
6
  updateClientInvoiceMutation: any;
7
7
  refetchInvoiceDisputes: any;
8
+ documentUploadUrl: string;
9
+ uploadExpertClientDisputeFiles: any;
8
10
  }
9
- export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceMutation, refetchInvoiceDisputes, }: InvoiceCardProps) => JSX.Element;
11
+ export declare const InvoiceCard: ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceMutation, refetchInvoiceDisputes, documentUploadUrl, uploadExpertClientDisputeFiles, }: InvoiceCardProps) => JSX.Element;
10
12
  export {};
@@ -11,13 +11,13 @@ 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, }) => {
14
+ const InvoiceCard = ({ clientInvoice, createDisputeChatMessage, user, chatMessages, updateClientInvoiceMutation, refetchInvoiceDisputes, documentUploadUrl, uploadExpertClientDisputeFiles, }) => {
15
15
  var _a, _b, _c;
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 }),
20
+ react_1.default.createElement(DisputeSection_1.DisputeSection, { dispute: clientInvoice, onUpdateDispute: updateClientInvoiceMutation, onRefetch: refetchInvoiceDisputes, documentUploadUrl: documentUploadUrl, uploadExpertClientDisputeFiles: uploadExpertClientDisputeFiles }),
21
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
22
  ((_c = user === null || user === void 0 ? void 0 : user.app_metadata) === null || _c === void 0 ? void 0 : _c.userTypeId) === 2 &&
23
23
  react_1.default.createElement(DecisionSection_1.DecisionSection, { dispute: clientInvoice, onUpdateDispute: updateClientInvoiceMutation, onRefetch: refetchInvoiceDisputes }))));
@@ -27,7 +27,7 @@ const InvoiceDetails = ({ invoice }) => {
27
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) }),
28
28
  react_1.default.createElement("span", { className: "text-xs text-[#666666]" },
29
29
  "Last updated: ",
30
- (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeUpdatedDate).format('YYYY-MM-DD'))),
30
+ (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeUpdatedDate).format('MM-DD-YYYY'))),
31
31
  ((_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
32
  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
33
  };
@@ -15,10 +15,10 @@ const InvoiceHeader = ({ invoice }) => {
15
15
  react_1.default.createElement("span", { className: "ml-2" }, (_a = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _a === void 0 ? void 0 : _a.id)),
16
16
  react_1.default.createElement("div", null,
17
17
  react_1.default.createElement("span", { className: "text-sm font-bold" }, "Dispute Date: "),
18
- react_1.default.createElement("span", { className: "ml-2" }, (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeDate).format('MMM D, YYYY'))),
18
+ react_1.default.createElement("span", { className: "ml-2" }, (0, dayjs_1.default)(invoice === null || invoice === void 0 ? void 0 : invoice.disputeDate).format('MM-DD-YYYY'))),
19
19
  react_1.default.createElement("div", null,
20
20
  react_1.default.createElement("span", { className: "text-sm font-bold" }, "Invoice Date: "),
21
- react_1.default.createElement("span", { className: "ml-2" }, (0, dayjs_1.default)((_b = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _b === void 0 ? void 0 : _b.dateGenerated).format('MMM D, YYYY')))),
21
+ react_1.default.createElement("span", { className: "ml-2" }, (0, dayjs_1.default)((_b = invoice === null || invoice === void 0 ? void 0 : invoice.invoice) === null || _b === void 0 ? void 0 : _b.dateGenerated).format('MM-DD-YYYY')))),
22
22
  react_1.default.createElement("div", null,
23
23
  react_1.default.createElement("span", { className: "text-sm font-bold" }, "Expert Name: "),
24
24
  react_1.default.createElement("span", { className: "ml-2" }, (_c = invoice === null || invoice === void 0 ? void 0 : invoice.freelancer) === null || _c === void 0 ? void 0 :
@@ -1,15 +1,15 @@
1
- interface OrgChartProps {
2
- openModal: boolean;
3
- setOpenModal: (openModal: boolean) => void;
4
- expertFirms: any;
5
- firstName: string;
6
- lastName: string;
7
- imageUrl?: string;
8
- primaryServiceLine: string;
9
- city: string;
10
- stateAbbreviation: string;
11
- paroTenure?: string;
12
- isPublicProfile?: boolean;
13
- }
14
- export declare const OrganizationChart: ({ openModal, setOpenModal, expertFirms, firstName, lastName, imageUrl, primaryServiceLine, city, stateAbbreviation, paroTenure, isPublicProfile }: OrgChartProps) => JSX.Element;
15
- export {};
1
+ interface OrgChartProps {
2
+ openModal: boolean;
3
+ setOpenModal: (openModal: boolean) => void;
4
+ expertFirms: any;
5
+ firstName: string;
6
+ lastName: string;
7
+ imageUrl?: string;
8
+ primaryServiceLine: string;
9
+ city: string;
10
+ stateAbbreviation: string;
11
+ paroTenure?: string;
12
+ isPublicProfile?: boolean;
13
+ }
14
+ export declare const OrganizationChart: ({ openModal, setOpenModal, expertFirms, firstName, lastName, imageUrl, primaryServiceLine, city, stateAbbreviation, paroTenure, isPublicProfile }: OrgChartProps) => JSX.Element;
15
+ export {};