@paro.io/expert-shared-components 1.12.41 → 1.12.43

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 (26) hide show
  1. package/lib/components/Escalations/EscalationChat.d.ts +8 -1
  2. package/lib/components/Escalations/EscalationChat.js +80 -23
  3. package/lib/components/Escalations/EscalationIssueCard.d.ts +7 -3
  4. package/lib/components/Escalations/EscalationIssueCard.js +38 -20
  5. package/lib/components/Escalations/EscalationRespondForm.d.ts +9 -1
  6. package/lib/components/Escalations/EscalationRespondForm.js +128 -20
  7. package/lib/components/Escalations/EscalationSubmitForm.d.ts +7 -2
  8. package/lib/components/Escalations/EscalationSubmitForm.js +138 -39
  9. package/lib/components/Escalations/EscalationTabsContent.d.ts +5 -8
  10. package/lib/components/Escalations/EscalationTabsContent.js +4 -9
  11. package/lib/components/Escalations/Escalations.d.ts +11 -5
  12. package/lib/components/Escalations/Escalations.js +8 -5
  13. package/lib/components/FileUploader/index.d.ts +9 -5
  14. package/lib/components/FileUploader/index.js +55 -9
  15. package/lib/components/Invoices/ClientDisputeProjectCard.d.ts +1 -1
  16. package/lib/components/Invoices/ClientDisputeProjectCard.js +3 -3
  17. package/lib/components/Invoices/DiscussionSection.d.ts +2 -2
  18. package/lib/components/Invoices/DiscussionSection.js +2 -2
  19. package/lib/components/Invoices/DisputeSection.js +1 -1
  20. package/lib/components/shared/UploadClient.d.ts +2 -1
  21. package/lib/components/shared/UploadClient.js +7 -4
  22. package/lib/components/shared/utils.d.ts +1 -0
  23. package/lib/components/shared/utils.js +6 -1
  24. package/lib/index.d.ts +0 -1
  25. package/lib/index.js +1 -3
  26. package/package.json +8 -2
@@ -1,6 +1,13 @@
1
- declare const EscalationChat: ({ activeChatIssue, showEscalationChat, setShowEscalationChat }: {
1
+ declare const EscalationChat: ({ activeChatIssue, showEscalationChat, setShowEscalationChat, user, createEscalationChatMessage, documentUploadUrl, bucketName, uploadExpertClientFiles, createProjectEscalation, isExpert, }: {
2
2
  activeChatIssue: any;
3
3
  showEscalationChat: boolean;
4
4
  setShowEscalationChat: (showEscalationChat: boolean) => void;
5
+ user: any;
6
+ createEscalationChatMessage: any;
7
+ documentUploadUrl: string;
8
+ bucketName: string;
9
+ uploadExpertClientFiles: string;
10
+ createProjectEscalation: string;
11
+ isExpert: boolean;
5
12
  }) => JSX.Element;
6
13
  export default EscalationChat;
@@ -38,17 +38,81 @@ const base_ui_1 = require("@paro.io/base-ui");
38
38
  const core_1 = require("@material-ui/core");
39
39
  const DiscussionSection_1 = require("../Invoices/DiscussionSection");
40
40
  const EscalationIssueCard_1 = require("./EscalationIssueCard");
41
- const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalationChat }) => {
41
+ const FileUploader_1 = require("../FileUploader");
42
+ const EscalationRespondForm_1 = require("./EscalationRespondForm");
43
+ const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalationChat, user, createEscalationChatMessage, documentUploadUrl, bucketName, uploadExpertClientFiles, createProjectEscalation, isExpert, }) => {
44
+ var _a;
42
45
  const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
43
46
  const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
44
47
  const fileInputRef = (0, react_1.useRef)(null);
45
- const handleFileUpload = (event) => {
46
- const files = Array.from(event.target.files);
47
- setUploadFiles(prev => [...prev, ...files]);
48
- };
49
- const removeFile = (index) => {
50
- setUploadFiles(prev => prev.filter((_, i) => i !== index));
51
- };
48
+ const handleFileUpload = (event) => __awaiter(void 0, void 0, void 0, function* () {
49
+ const selectedFiles = event.target.files;
50
+ if (!selectedFiles)
51
+ return;
52
+ setUploadingFile(true);
53
+ const validFileNames = Array.from(selectedFiles)
54
+ .filter(file => (0, EscalationRespondForm_1.validateFileUpload)(file))
55
+ .map(file => file.name);
56
+ if (validFileNames.length === 0)
57
+ return;
58
+ if (validFileNames && validFileNames.length > 0) {
59
+ const uploadPromises = Array.from(selectedFiles).map((selectedFile) => {
60
+ return new Promise((resolve, reject) => {
61
+ const reader = new FileReader();
62
+ reader.onloadend = () => __awaiter(void 0, void 0, void 0, function* () {
63
+ var _a;
64
+ try {
65
+ const res = yield (0, FileUploader_1.fileUploader)({
66
+ file: selectedFile,
67
+ documentName: selectedFile.name,
68
+ escalationId: activeChatIssue.escalationId,
69
+ projectId: activeChatIssue.projectDetails.length > 0 ? activeChatIssue.projectDetails[0].projectId : '',
70
+ documentUploadUrl: documentUploadUrl,
71
+ bucketName: bucketName,
72
+ isExpert: false,
73
+ uploadExpertClientFiles: uploadExpertClientFiles,
74
+ createProjectEscalation: createProjectEscalation,
75
+ extraData: {
76
+ clientId: activeChatIssue.client.id,
77
+ clientName: activeChatIssue.client.name,
78
+ email: isExpert ? "client@gmail.com" : user === null || user === void 0 ? void 0 : user.email,
79
+ freelancerId: activeChatIssue.freelancer.id,
80
+ freelancerName: (_a = activeChatIssue.freelancer.name) !== null && _a !== void 0 ? _a : '',
81
+ projectName: activeChatIssue.projectDetails.length > 0 ? activeChatIssue.projectDetails[0].projectName : '',
82
+ }
83
+ });
84
+ if (res) {
85
+ setUploadFiles(prev => [...prev, ...res]);
86
+ }
87
+ }
88
+ catch (error) {
89
+ reject(error);
90
+ }
91
+ finally {
92
+ resolve();
93
+ }
94
+ });
95
+ reader.readAsDataURL(selectedFile);
96
+ });
97
+ });
98
+ try {
99
+ const res = yield Promise.all(uploadPromises);
100
+ }
101
+ catch (error) {
102
+ console.error('Error uploading files:', error);
103
+ }
104
+ finally {
105
+ setUploadingFile(false);
106
+ }
107
+ }
108
+ ;
109
+ });
110
+ const docs = [activeChatIssue.expertSupportingDocuments, activeChatIssue.clientSupportingDocuments, activeChatIssue.internalSupportingDocuments, ...uploadFiles];
111
+ const processedDocs = docs
112
+ .filter(doc => doc !== null && doc !== undefined && doc !== '')
113
+ .flatMap(doc => doc.split(','))
114
+ .map(doc => doc.trim())
115
+ .filter(doc => doc !== '');
52
116
  return (react_1.default.createElement(core_1.Dialog, { open: showEscalationChat, onClose: () => setShowEscalationChat(false), maxWidth: 'sm' },
53
117
  react_1.default.createElement(core_1.DialogTitle, null,
54
118
  react_1.default.createElement("div", { className: "text-black mb-1 p-2 pl-4 absolute top-0 left-0 w-full flex flex-row justify-between items-center z-50" },
@@ -56,10 +120,10 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalation
56
120
  react_1.default.createElement("div", { className: "flex flex-row items-center" },
57
121
  react_1.default.createElement("h1", { className: "text-md font-bold mr-2" },
58
122
  "Escalation Chat #",
59
- activeChatIssue.caseId),
123
+ activeChatIssue.escalationNumber),
60
124
  react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: activeChatIssue.status })),
61
125
  react_1.default.createElement("p", { className: "text-xs" },
62
- activeChatIssue.title,
126
+ activeChatIssue.probelm,
63
127
  " - ",
64
128
  activeChatIssue.project)),
65
129
  react_1.default.createElement("div", { className: "flex items-center space-x-4" },
@@ -67,24 +131,17 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalation
67
131
  react_1.default.createElement(base_icons_1.IconX, null))))),
68
132
  react_1.default.createElement(core_1.DialogContent, null,
69
133
  react_1.default.createElement("div", { className: "bg-white rounded-lg w-full overflow-hidden flex flex-col p-2 mt-12" },
70
- react_1.default.createElement(DiscussionSection_1.DiscussionSection //update required
71
- , { disputeId: '1', currentUser: {}, messages: [], onCreateMessage: (variables) => __awaiter(void 0, void 0, void 0, function* () {
72
- return Promise.resolve();
73
- }), isInternal: false }),
134
+ react_1.default.createElement(DiscussionSection_1.DiscussionSection, { escalationNumber: activeChatIssue.escalationNumber, currentUser: user, messages: (_a = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.chatMessages) !== null && _a !== void 0 ? _a : [], onCreateMessage: createEscalationChatMessage, isInternal: false }),
135
+ processedDocs && processedDocs.length > 0 && (react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
136
+ react_1.default.createElement("span", { className: "text-sm font-bold text-gray-500 items-center" }, "Supporting Documents: "),
137
+ processedDocs.map((d, idx) => (react_1.default.createElement(EscalationIssueCard_1.CustomTag, { key: idx, label: d.split('%2F')[1] }))))),
74
138
  react_1.default.createElement("div", { className: "bg-white mt-2" },
75
139
  react_1.default.createElement("div", { className: "space-y-3" },
76
140
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
77
141
  react_1.default.createElement("div", { className: "flex items-center space-x-2" },
78
142
  react_1.default.createElement("input", { id: "upload-file", type: "file", multiple: true, accept: ".pdf,.doc,.docx,.jpeg,.png,.gif,.csv", style: { display: 'none' }, ref: fileInputRef, onChange: handleFileUpload }),
79
- react_1.default.createElement(base_ui_1.Button, { label: "Attach Files", 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(); }, color: "info", className: "mx-2", isLoading: uploadingFile }),
80
- uploadFiles.length > 0 && (react_1.default.createElement("div", { className: "text-sm text-gray-600" },
81
- uploadFiles.length,
82
- " file(s) selected"))),
143
+ react_1.default.createElement(base_ui_1.Button, { label: "Attach Files", 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(); }, color: "info", className: "mx-2", isLoading: uploadingFile })),
83
144
  react_1.default.createElement("div", { className: "flex space-x-2" },
84
- react_1.default.createElement(base_ui_1.Button, { label: "cancel", onClick: () => setShowEscalationChat(false) }))),
85
- uploadFiles.length > 0 && (react_1.default.createElement("div", { className: "space-y-1" }, uploadFiles.map((file, index) => (react_1.default.createElement("div", { key: index, className: "flex items-center justify-between bg-gray-50 px-2 py-1 rounded text-sm" },
86
- react_1.default.createElement("span", null, file.name),
87
- react_1.default.createElement(core_1.IconButton, { onClick: () => removeFile(index) },
88
- react_1.default.createElement(base_icons_1.IconX, { size: "sm" })))))))))))));
145
+ react_1.default.createElement(base_ui_1.Button, { label: "cancel", onClick: () => setShowEscalationChat(false), disabled: uploadingFile })))))))));
89
146
  };
90
147
  exports.default = EscalationChat;
@@ -1,15 +1,19 @@
1
1
  import React from 'react';
2
- import { EscalationChatDetails } from "./EscalationTabsContent";
3
- export declare const CustomTag: ({ label }: {
2
+ export declare const CustomTag: ({ label, iconLeft, onClick, }: {
4
3
  label: any;
4
+ iconLeft?: React.ReactNode;
5
+ onClick?: () => void;
5
6
  }) => React.JSX.Element;
6
7
  type EscalationIssueCardProps = {
7
8
  issues: any[];
8
9
  isExpert: boolean;
9
- openEscalationChat: (details: EscalationChatDetails) => void;
10
+ openEscalationChat: (issue: any) => void;
10
11
  showRespondButton?: boolean;
11
12
  setSelectedIssueId?: (id: number) => void;
12
13
  showMarkResolvedButton?: boolean;
14
+ updateProjectEscalation: any;
15
+ downloadDocumentUrl: string;
16
+ bucketName: string;
13
17
  };
14
18
  declare const EscalationIssueCard: React.FC<EscalationIssueCardProps>;
15
19
  export default EscalationIssueCard;
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.CustomTag = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const base_ui_1 = require("@paro.io/base-ui");
9
+ const ClientDisputeProjectCard_1 = require("../Invoices/ClientDisputeProjectCard");
10
+ const base_icons_1 = require("@paro.io/base-icons");
9
11
  const getBackgroundColor = (type) => {
10
12
  switch (type) {
11
13
  case 'Critical':
@@ -20,19 +22,27 @@ const getBackgroundColor = (type) => {
20
22
  return 'success';
21
23
  }
22
24
  };
23
- const CustomTag = ({ label }) => {
25
+ const CustomTag = ({ label, iconLeft, onClick, }) => {
24
26
  const color = getBackgroundColor(label);
25
- return (react_1.default.createElement("div", { className: `border box-border text-center px-4 pb-0.5 pt-1 text-sm inline-block break-words text-white rounded-full bg-${color} border-${color} ml-2 font-bold` }, label.toUpperCase()));
27
+ return (react_1.default.createElement("div", { onClick: onClick, className: `flex flex-row gap-1 border box-border text-center px-4 pb-0.5 pt-1 text-sm inline-block break-words text-white rounded-full bg-${color} border-${color} ml-2 font-bold ${onClick ? 'cursor-pointer' : ''}` },
28
+ iconLeft && react_1.default.createElement("span", null, iconLeft), label === null || label === void 0 ? void 0 :
29
+ label.toUpperCase()));
26
30
  };
27
31
  exports.CustomTag = CustomTag;
28
- const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespondButton = false, setSelectedIssueId, showMarkResolvedButton = false, }) => {
32
+ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespondButton = false, setSelectedIssueId, showMarkResolvedButton = false, updateProjectEscalation, downloadDocumentUrl, bucketName, }) => {
29
33
  if (!issues.length)
30
34
  return react_1.default.createElement("div", null, "No issues.");
31
35
  return (react_1.default.createElement("div", { className: "space-y-4" }, issues.map((issue) => {
32
- const project = issue.projectName && Array.isArray(issue.projectName) && issue.projectName.length > 0
33
- ? `${issue.projectName[0]}${issue.projectName.length > 1 ? ` +${issue.projectName.length - 1} more` : ''} `
36
+ var _a;
37
+ const project = issue.projectDetails && Array.isArray(issue.projectDetails) && issue.projectDetails.length > 0
38
+ ? `${(_a = issue.projectDetails[0]) === null || _a === void 0 ? void 0 : _a.projectName}${issue.projectDetails.length > 1 ? ` +${issue.projectDetails.length - 1} more` : ''} `
34
39
  : '';
35
- const docs = [...issue.expertSupportingDocuments, ...issue.clientSupportingDocuments];
40
+ const docs = [issue.expertSupportingDocuments, issue.clientSupportingDocuments, issue.internalSupportingDocuments];
41
+ const processedDocs = docs
42
+ .filter(doc => doc !== null && doc !== undefined && doc !== '')
43
+ .flatMap(doc => doc.split(','))
44
+ .map(doc => doc.trim())
45
+ .filter(doc => doc !== '');
36
46
  return (react_1.default.createElement("div", { key: issue.id, className: "border border-gray-200 rounded-lg bg-white p-4" },
37
47
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-3" },
38
48
  react_1.default.createElement("div", { className: "flex-1 ml-2" },
@@ -42,29 +52,37 @@ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespond
42
52
  react_1.default.createElement("div", { className: "text-xs text-gray-500 font-bold" },
43
53
  project,
44
54
  " \u2022 Case #",
45
- issue.id)),
46
- react_1.default.createElement(exports.CustomTag, { label: issue.issueType })),
55
+ issue.escalationNumber)),
56
+ react_1.default.createElement(exports.CustomTag, { label: issue.escalationType })),
47
57
  react_1.default.createElement("div", { className: "bg-gray-50 rounded-md p-3 mb-4 border" },
48
58
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-2" },
49
59
  react_1.default.createElement("div", { className: "text-sm text-gray-500" },
50
60
  "Submitted by: ",
51
- react_1.default.createElement("span", { className: "font-bold" }, issue.submittedBy),
61
+ react_1.default.createElement("span", { className: "font-bold" }, issue.submittedByUser.firstName + " " + issue.submittedByUser.lastName),
52
62
  issue.createdAt && react_1.default.createElement(react_1.default.Fragment, null,
53
63
  " \u2022 Submitted on: ",
54
64
  react_1.default.createElement("span", { className: "font-bold" }, issue.createdAt)))),
55
- react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-3" }, issue.expectedOutcome),
56
- docs && docs.length > 0 && (react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
65
+ react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-3" }, issue.outcome),
66
+ processedDocs && processedDocs.length > 0 && (react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
57
67
  react_1.default.createElement("span", { className: "text-sm font-bold text-gray-500 items-center" }, "Supporting Documents: "),
58
- docs.map((d, idx) => (react_1.default.createElement(exports.CustomTag, { key: idx, label: d })))))),
68
+ processedDocs.map((d, idx) => (react_1.default.createElement(exports.CustomTag, { key: idx, label: d.split('%2F')[1], iconLeft: react_1.default.createElement(base_icons_1.IconDocumentDownload, { size: "xs" }), onClick: () => {
69
+ (0, ClientDisputeProjectCard_1.handleDownloadDocument)(issue.escalationId, d.split('%2F')[1], downloadDocumentUrl, bucketName);
70
+ } })))))),
59
71
  react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
60
- react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
61
- title: issue.problem,
62
- project: issue.projectName,
63
- id: issue.id,
64
- status: issue.status
65
- }), label: "Chat", color: "primary" }),
66
- showRespondButton && setSelectedIssueId && (react_1.default.createElement(base_ui_1.Button, { label: "Respond to Escalation", onClick: () => setSelectedIssueId(issue.id), color: 'primary' })),
67
- showMarkResolvedButton && !isExpert && (react_1.default.createElement(base_ui_1.Button, { onClick: issue.markResolved, label: "Mark as Resolved", color: "primary" })))));
72
+ react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat(issue), label: "Chat", color: "primary" }),
73
+ showRespondButton && setSelectedIssueId && (react_1.default.createElement(base_ui_1.Button, { label: "Respond to Escalation", onClick: () => setSelectedIssueId(issue.escalationNumber), color: 'primary' })),
74
+ showMarkResolvedButton && !isExpert && (react_1.default.createElement(base_ui_1.Button, { onClick: () => {
75
+ updateProjectEscalation({
76
+ variables: {
77
+ input: {
78
+ escalationNumber: issue.escalationNumber,
79
+ status: 'Resolved'
80
+ }
81
+ }
82
+ }).then(() => { console.log("its marked as resolved"); }).catch((error) => {
83
+ console.error("Error updating escalation status:", error);
84
+ });
85
+ }, label: "Mark as Resolved", color: "primary" })))));
68
86
  })));
69
87
  };
70
88
  exports.default = EscalationIssueCard;
@@ -1,6 +1,14 @@
1
- declare const EscalationRespondForm: ({ goBack, selectedIssue, goHome }: {
1
+ export declare const ACCEPTED_FILE_TYPES: string[];
2
+ export declare const validateFileUpload: (file: File | null) => boolean;
3
+ declare const EscalationRespondForm: ({ goBack, selectedIssue, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, updateProjectEscalation, bucketName, goHome, isExpert, }: {
2
4
  goBack: () => void;
3
5
  selectedIssue: any;
6
+ documentUploadUrl: string;
7
+ downloadDocumentUrl: string;
8
+ uploadExpertClientFiles: any;
9
+ updateProjectEscalation: any;
10
+ bucketName: string;
4
11
  goHome: () => void;
12
+ isExpert: boolean;
5
13
  }) => JSX.Element;
6
14
  export default EscalationRespondForm;
@@ -22,10 +22,40 @@ 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 });
35
+ exports.validateFileUpload = exports.ACCEPTED_FILE_TYPES = void 0;
26
36
  const react_1 = __importStar(require("react"));
27
37
  const base_icons_1 = require("@paro.io/base-icons");
28
38
  const base_ui_1 = require("@paro.io/base-ui");
39
+ const FileUploader_1 = require("../FileUploader");
40
+ const EscalationIssueCard_1 = require("./EscalationIssueCard");
41
+ exports.ACCEPTED_FILE_TYPES = [
42
+ 'application/pdf',
43
+ 'application/msword',
44
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
45
+ 'image/jpeg',
46
+ 'image/png',
47
+ 'text/csv',
48
+ ];
49
+ const validateFileUpload = (file) => {
50
+ if (!file) {
51
+ return false;
52
+ }
53
+ if (!exports.ACCEPTED_FILE_TYPES.includes(file.type)) {
54
+ return false;
55
+ }
56
+ return true;
57
+ };
58
+ exports.validateFileUpload = validateFileUpload;
29
59
  const responseTypes = [
30
60
  {
31
61
  label: "Acknowledge issue and provide resolution plan",
@@ -40,29 +70,106 @@ const responseTypes = [
40
70
  {
41
71
  label: "Request clarification",
42
72
  description: "Ask for more details about the issue",
43
- value: "Clarification",
73
+ value: "NoResponse",
44
74
  },
45
75
  ];
46
- const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
76
+ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, updateProjectEscalation, bucketName, goHome, isExpert, }) => {
47
77
  const [selectedType, setSelectedType] = (0, react_1.useState)(responseTypes[0].value);
48
78
  const [responseInput, setResponseInput] = (0, react_1.useState)('');
49
79
  const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
50
80
  const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
81
+ const [submitting, setSubmitting] = (0, react_1.useState)(false);
51
82
  const fileInputRef = (0, react_1.useRef)(null);
52
- const handleFileUpload = (event) => {
53
- const files = Array.from(event.target.files);
54
- setUploadFiles(prev => [...prev, ...files]);
55
- };
56
- const submitResponse = () => {
57
- const responseData = {
58
- responseType: selectedType,
59
- responseText: responseInput,
60
- uploadedFiles: uploadFiles.map(file => file.name),
61
- selectedIssue: selectedIssue
62
- };
63
- console.log("Collected Response Data:", responseData);
64
- goHome();
65
- };
83
+ const handleFileUpload = (event) => __awaiter(void 0, void 0, void 0, function* () {
84
+ const selectedFiles = event.target.files;
85
+ if (!selectedFiles)
86
+ return;
87
+ setUploadingFile(true);
88
+ const validFileNames = Array.from(selectedFiles)
89
+ .filter(file => (0, exports.validateFileUpload)(file))
90
+ .map(file => file.name);
91
+ if (validFileNames.length === 0)
92
+ return;
93
+ if (validFileNames && validFileNames.length > 0) {
94
+ const uploadPromises = Array.from(selectedFiles).map((selectedFile) => {
95
+ return new Promise((resolve, reject) => {
96
+ const reader = new FileReader();
97
+ reader.onloadend = () => __awaiter(void 0, void 0, void 0, function* () {
98
+ var _a, _b, _c, _d, _e, _f, _g, _h;
99
+ try {
100
+ const res = yield (0, FileUploader_1.fileUploader)({
101
+ file: selectedFile,
102
+ documentName: selectedFile.name,
103
+ escalationId: selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.escalationId,
104
+ projectId: selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.projectDetails[0].projectId,
105
+ documentUploadUrl: documentUploadUrl,
106
+ bucketName: bucketName,
107
+ previousFiles: (selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.isExpert) ? (_a = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.clientDocumentLinks) !== null && _a !== void 0 ? _a : [] : selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.expertDocumentlinks,
108
+ isExpert: false,
109
+ uploadExpertClientFiles: uploadExpertClientFiles,
110
+ updateProjectEscalation: updateProjectEscalation,
111
+ extraData: {
112
+ clientId: selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client.id,
113
+ clientName: (_b = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client.name) !== null && _b !== void 0 ? _b : '',
114
+ email: isExpert ? (_d = (_c = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer) === null || _c === void 0 ? void 0 : _c.email) !== null && _d !== void 0 ? _d : '' : (_g = (_f = (_e = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client) === null || _e === void 0 ? void 0 : _e.primaryContact) === null || _f === void 0 ? void 0 : _f.email) !== null && _g !== void 0 ? _g : '',
115
+ freelancerId: selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer.id,
116
+ freelancerName: (_h = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer.name) !== null && _h !== void 0 ? _h : '',
117
+ projectName: selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.projectDetails[0].projectName,
118
+ }
119
+ });
120
+ if (res) {
121
+ setUploadFiles(prev => [...prev, ...res]);
122
+ }
123
+ }
124
+ catch (error) {
125
+ reject(error);
126
+ }
127
+ finally {
128
+ resolve();
129
+ }
130
+ });
131
+ reader.readAsDataURL(selectedFile);
132
+ });
133
+ });
134
+ try {
135
+ yield Promise.all(uploadPromises);
136
+ }
137
+ catch (error) {
138
+ console.error('Error uploading files:', error);
139
+ }
140
+ finally {
141
+ setUploadingFile(false);
142
+ }
143
+ }
144
+ ;
145
+ });
146
+ const submitResponse = () => __awaiter(void 0, void 0, void 0, function* () {
147
+ setSubmitting(true);
148
+ try {
149
+ yield updateProjectEscalation({
150
+ variables: {
151
+ input: {
152
+ escalationId: selectedIssue.escalationId,
153
+ [isExpert ? 'expertResponse' : 'clientResponse']: responseInput,
154
+ [isExpert ? 'expertSupportingDocuments' : 'clientSupportingDocuments']: uploadFiles.join(", "),
155
+ }
156
+ }
157
+ });
158
+ }
159
+ catch (error) {
160
+ console.error("Failed to send response!", error);
161
+ }
162
+ finally {
163
+ setSubmitting(false);
164
+ goHome();
165
+ }
166
+ });
167
+ const docs = [selectedIssue.expertSupportingDocuments, selectedIssue.clientSupportingDocuments, selectedIssue.internalSupportingDocuments, ...uploadFiles];
168
+ const processedDocs = docs
169
+ .filter(doc => doc !== null && doc !== undefined && doc !== '')
170
+ .flatMap(doc => doc.split(','))
171
+ .map(doc => doc.trim())
172
+ .filter(doc => doc !== '');
66
173
  return (react_1.default.createElement("div", null,
67
174
  react_1.default.createElement("button", { onClick: goBack, className: "flex items-center text-blue-600 mb-6" },
68
175
  react_1.default.createElement(base_icons_1.IconChevronLeft, { size: "xs" }),
@@ -96,8 +203,9 @@ const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
96
203
  react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-2" }, "Upload any supporting documentation"),
97
204
  react_1.default.createElement("input", { id: "upload-file", type: "file", multiple: true, accept: ".pdf,.doc,.docx,.jpeg,.png,.gif,.csv", style: { display: 'none' }, ref: fileInputRef, onChange: handleFileUpload }),
98
205
  react_1.default.createElement(base_ui_1.Button, { label: "Attach Files", 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(); }, color: "info", className: "mx-2", isLoading: uploadingFile, size: "sm" }),
99
- uploadFiles.length > 0 && (react_1.default.createElement("div", { className: "text-sm text-gray-600 mt-2" },
100
- react_1.default.createElement("ul", { className: "list-disc list-inside" }, uploadFiles.map((f) => (react_1.default.createElement("li", { key: f.name }, f.name)))))))),
206
+ processedDocs && processedDocs.length > 0 && (react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
207
+ react_1.default.createElement("span", { className: "text-sm font-bold text-gray-500 items-center" }, "Supporting Documents: "),
208
+ processedDocs.map((d, idx) => (react_1.default.createElement(EscalationIssueCard_1.CustomTag, { key: idx, label: d.split('%2F')[1] }))))))),
101
209
  react_1.default.createElement("div", { className: "bg-blue-50 border border-blue-200 rounded-md p-3" },
102
210
  react_1.default.createElement("div", { className: "flex items-center" },
103
211
  react_1.default.createElement(base_icons_1.IconInfoCircle, { size: "md" }),
@@ -105,7 +213,7 @@ const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
105
213
  react_1.default.createElement("p", { className: "font-medium" }, "Response Guidelines"),
106
214
  react_1.default.createElement("p", { className: "mt-1" }, "Your response will be visible to the client and Paro support team. Be professional and focus on resolution.")))),
107
215
  react_1.default.createElement("div", { className: "flex justify-end space-x-3" },
108
- react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack }),
109
- react_1.default.createElement(base_ui_1.Button, { label: "Submit Response", color: "primary", onClick: submitResponse })))))));
216
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack, disabled: uploadingFile || submitting }),
217
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit Response", color: "primary", onClick: submitResponse, isLoading: submitting, disabled: uploadingFile })))))));
110
218
  };
111
219
  exports.default = EscalationRespondForm;
@@ -1,9 +1,14 @@
1
1
  interface EscalationSubmitProps {
2
2
  goBack: () => void;
3
3
  goHome: () => void;
4
- experts: any[];
4
+ expertsOrClients: any[];
5
5
  projects: any[];
6
6
  isExpert: boolean;
7
+ documentUploadUrl: string;
8
+ bucketName: string;
9
+ uploadExpertClientFiles: any;
10
+ createProjectEscalation: any;
11
+ user: any;
7
12
  }
8
- declare const EscalationSubmitForm: ({ goBack, goHome, experts, projects, isExpert }: EscalationSubmitProps) => JSX.Element;
13
+ declare const EscalationSubmitForm: ({ goBack, goHome, expertsOrClients, projects, documentUploadUrl, bucketName, uploadExpertClientFiles, createProjectEscalation, isExpert, user }: EscalationSubmitProps) => JSX.Element;
9
14
  export default EscalationSubmitForm;