@paro.io/expert-shared-components 1.12.42 → 1.12.44

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.
@@ -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;
@@ -22,6 +22,15 @@ 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
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
36
  };
@@ -32,6 +41,9 @@ const base_ui_1 = require("@paro.io/base-ui");
32
41
  const core_1 = require("@material-ui/core");
33
42
  const LogTimeModalAuthenticated_1 = require("../ProjectCard/LogTimeModalAuthenticated");
34
43
  const dayjs_1 = __importDefault(require("dayjs"));
44
+ const EscalationRespondForm_1 = require("./EscalationRespondForm");
45
+ const FileUploader_1 = require("../FileUploader");
46
+ const utils_1 = require("../shared/utils");
35
47
  const issueTypeOptions = [
36
48
  { value: 'CommunicationIssues', label: 'Communication Issues' },
37
49
  { value: 'Professionalism', label: 'Professionalism' },
@@ -41,80 +53,159 @@ const issueTypeOptions = [
41
53
  { value: 'ScopeCreep', label: 'Scope Creep/Unauthorized Requests' },
42
54
  { value: 'Other', label: 'Other' },
43
55
  ];
44
- const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = false }) => {
56
+ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, documentUploadUrl, bucketName, uploadExpertClientFiles, createProjectEscalation, isExpert = false, user }) => {
57
+ var _a;
45
58
  const [isChecked, setIsChecked] = (0, react_1.useState)(false);
46
59
  const [problemInput, setProblemInput] = (0, react_1.useState)('');
47
60
  const [outcomeInput, setOutcomeInput] = (0, react_1.useState)('');
48
61
  const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
49
62
  const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
50
63
  const [expertOptions, setExpertOptions] = (0, react_1.useState)([]);
51
- const [selectedExpert, setSelectedExpert] = (0, react_1.useState)(null);
64
+ const [selectedUser, setSelectedUser] = (0, react_1.useState)(null);
52
65
  const [projectOptions, setProjectOptions] = (0, react_1.useState)([]);
53
66
  const [selectedProjects, setSelectedProjects] = (0, react_1.useState)([]);
54
67
  const [issueType, setIssueType] = (0, react_1.useState)('');
55
68
  const [severity, setSeverity] = (0, react_1.useState)('');
56
- const [startDate, setStartDate] = (0, react_1.useState)(undefined);
69
+ const [issueStartDate, setIssueStartDate] = (0, react_1.useState)(undefined);
57
70
  const [isDateInvalid, setIsDateInvalid] = (0, react_1.useState)(false);
71
+ const [submitting, setSubmitting] = (0, react_1.useState)(false);
58
72
  const fileInputRef = (0, react_1.useRef)(null);
73
+ const escalationId = (0, utils_1.generateUUID)();
59
74
  (0, react_1.useEffect)(() => {
60
- if (experts && experts.length > 0) {
61
- const options = experts.map((expert) => ({
62
- label: isExpert ? expert.name : expert.freelancerName,
63
- value: isExpert ? expert.id : expert.freelancerId,
75
+ if (expertsOrClients && expertsOrClients.length > 0) {
76
+ const options = expertsOrClients.map((user) => ({
77
+ label: user.name,
78
+ value: { id: user.id, name: user.name },
64
79
  }));
65
80
  setExpertOptions(options);
66
81
  }
67
- }, [experts]);
82
+ }, [expertsOrClients]);
68
83
  (0, react_1.useEffect)(() => {
69
84
  if (projects && projects.length > 0) {
70
85
  const options = projects
71
86
  .filter((p) => {
72
87
  if (isExpert) {
73
- return p.client.id === Number(selectedExpert);
88
+ return p.client.id === Number(selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id);
74
89
  }
75
90
  else {
76
- return p.freelancer.id === Number(selectedExpert);
91
+ return p.freelancer.id === Number(selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id);
77
92
  }
78
93
  })
79
94
  .map((p) => ({
80
- label: isExpert ? p.name : p.name,
81
- value: isExpert ? p : p,
95
+ label: p.name,
96
+ value: p,
82
97
  }));
83
98
  setProjectOptions(options);
84
99
  }
85
- }, [projects, selectedExpert]);
86
- const handleFileUpload = (event) => {
87
- const files = Array.from(event.target.files);
88
- setUploadFiles(prev => [...prev, ...files]);
89
- };
100
+ }, [projects, selectedUser]);
101
+ const handleFileUpload = (event) => __awaiter(void 0, void 0, void 0, function* () {
102
+ const selectedFiles = event.target.files;
103
+ if (!selectedFiles)
104
+ return;
105
+ setUploadingFile(true);
106
+ const validFileNames = Array.from(selectedFiles)
107
+ .filter(file => (0, EscalationRespondForm_1.validateFileUpload)(file))
108
+ .map(file => file.name);
109
+ if (validFileNames.length === 0)
110
+ return;
111
+ if (validFileNames && validFileNames.length > 0) {
112
+ const uploadPromises = Array.from(selectedFiles).map((selectedFile) => {
113
+ return new Promise((resolve, reject) => {
114
+ const reader = new FileReader();
115
+ reader.onloadend = () => __awaiter(void 0, void 0, void 0, function* () {
116
+ var _a;
117
+ try {
118
+ const res = yield (0, FileUploader_1.fileUploader)({
119
+ file: selectedFile,
120
+ documentName: selectedFile.name,
121
+ escalationId: escalationId,
122
+ projectId: selectedProjects.length > 0 ? selectedProjects[0].id : '',
123
+ documentUploadUrl: documentUploadUrl,
124
+ bucketName: bucketName,
125
+ isExpert: false,
126
+ uploadExpertClientFiles: uploadExpertClientFiles,
127
+ createProjectEscalation: createProjectEscalation,
128
+ extraData: {
129
+ clientId: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id : user === null || user === void 0 ? void 0 : user.userId,
130
+ clientName: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name : user === null || user === void 0 ? void 0 : user.name,
131
+ email: isExpert ? (_a = selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.primaryContact) === null || _a === void 0 ? void 0 : _a.email : user === null || user === void 0 ? void 0 : user.email,
132
+ freelancerId: isExpert ? user === null || user === void 0 ? void 0 : user.userId : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id,
133
+ freelancerName: isExpert ? user === null || user === void 0 ? void 0 : user.name : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name,
134
+ projectName: selectedProjects.length > 0 ? selectedProjects[0].name : '',
135
+ }
136
+ });
137
+ if (res) {
138
+ setUploadFiles(prev => [...prev, ...res]);
139
+ }
140
+ }
141
+ catch (error) {
142
+ reject(error);
143
+ }
144
+ finally {
145
+ resolve();
146
+ }
147
+ });
148
+ reader.readAsDataURL(selectedFile);
149
+ });
150
+ });
151
+ try {
152
+ const res = yield Promise.all(uploadPromises);
153
+ }
154
+ catch (error) {
155
+ console.error('Error uploading files:', error);
156
+ }
157
+ finally {
158
+ setUploadingFile(false);
159
+ }
160
+ }
161
+ ;
162
+ });
90
163
  const isFormValid = () => {
91
164
  const requiredProjectSelection = isExpert || (!isExpert && selectedProjects.length > 0);
92
- return (selectedExpert !== null &&
165
+ return (selectedUser !== null &&
93
166
  issueType !== '' &&
94
167
  severity !== '' &&
95
168
  problemInput.trim() !== '' &&
96
169
  outcomeInput.trim() !== '' &&
97
170
  isChecked &&
98
- startDate !== undefined &&
171
+ issueStartDate !== undefined &&
99
172
  requiredProjectSelection);
100
173
  };
101
- const handleSubmit = () => {
174
+ const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
175
+ var _a;
102
176
  if (!isFormValid())
103
177
  return;
178
+ setSubmitting(true);
104
179
  const formData = {
105
- selectedExpert,
106
- selectedProjects,
107
- issueType,
108
- severity,
109
- startDate,
180
+ escalationId: escalationId,
181
+ freelancerId: user.userId,
182
+ clientId: (_a = selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id) !== null && _a !== void 0 ? _a : 0,
183
+ projectDetails: selectedProjects.map((p) => { return { projectId: p.id, projectName: p.name }; }),
184
+ issueStartDate: issueStartDate,
185
+ escalationType: issueType,
186
+ severityLevel: severity,
110
187
  problem: problemInput,
111
- expectedOutcome: outcomeInput,
112
- supportingDocs: uploadFiles.map(f => f.name),
188
+ outcome: outcomeInput,
189
+ submittedByUserId: user.userId,
190
+ status: 'InProgress',
191
+ [isExpert ? 'expertSupportingDocuments' : 'clientSupportingDocuments']: uploadFiles.join(", "),
192
+ statusChangedBy: user.userId,
113
193
  };
114
- console.log('Escalation Submitted:', formData);
115
- // Redirect or perform additional logic
116
- goHome();
117
- };
194
+ try {
195
+ yield createProjectEscalation({
196
+ variables: {
197
+ input: formData
198
+ }
199
+ });
200
+ }
201
+ catch (error) {
202
+ console.error("Failed to create an escalation!", error);
203
+ }
204
+ finally {
205
+ setSubmitting(false);
206
+ goHome();
207
+ }
208
+ });
118
209
  const validateDate = (date) => {
119
210
  const minDate = LogTimeModalAuthenticated_1.constants.MIN_DATE;
120
211
  const maxDate = new Date();
@@ -146,10 +237,19 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
146
237
  react_1.default.createElement("div", { className: "p-4 space-y-4" },
147
238
  react_1.default.createElement("div", null,
148
239
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, `Which ${isExpert ? 'client' : 'expert'} are you experiencing the issue with?`),
149
- react_1.default.createElement(core_1.Select, { fullWidth: true, value: selectedExpert !== null && selectedExpert !== void 0 ? selectedExpert : '', onChange: e => setSelectedExpert(e.target.value === '' ? null : Number(e.target.value)), displayEmpty: true, variant: "outlined", placeholder: `Select a ${isExpert ? 'Client' : 'Expert'}` },
240
+ react_1.default.createElement(core_1.Select, { fullWidth: true, value: (_a = selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name) !== null && _a !== void 0 ? _a : '', onChange: e => {
241
+ const selectedName = e.target.value;
242
+ if (selectedName === '') {
243
+ setSelectedUser(null);
244
+ }
245
+ else {
246
+ const selectedOption = expertOptions.find(opt => opt.value.name === selectedName);
247
+ setSelectedUser(selectedOption ? selectedOption.value : null);
248
+ }
249
+ }, displayEmpty: true, variant: "outlined", placeholder: `Select a ${isExpert ? 'Client' : 'Expert'}` },
150
250
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
151
251
  react_1.default.createElement("em", null, `Select a ${isExpert ? 'Client' : 'Expert'}`)),
152
- expertOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
252
+ expertOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value.id, value: option.value.name }, option.label))))),
153
253
  react_1.default.createElement("div", null,
154
254
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Which Project(s)?"),
155
255
  react_1.default.createElement(core_1.Select, { multiple: true, fullWidth: true, value: selectedProjects, onChange: (e) => {
@@ -166,7 +266,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
166
266
  }, placeholder: `Select a Project(s)` },
167
267
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
168
268
  react_1.default.createElement("em", null, "Select a Project(s)...")),
169
- projectOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
269
+ projectOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value.id, value: option.value }, option.label))))),
170
270
  react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" },
171
271
  react_1.default.createElement("div", null,
172
272
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Issue Type"),
@@ -194,7 +294,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
194
294
  react_1.default.createElement(core_1.MenuItem, { value: "Low" }, "Low")))),
195
295
  react_1.default.createElement("div", null,
196
296
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "When did this issue start?"),
197
- react_1.default.createElement(LogTimeModalAuthenticated_1.SelectDate, { timeLogDate: startDate, setTimeLogDate: setStartDate, isInvalid: false, setIsDateInvalid: setIsDateInvalid, validateDate: validateDate, maxDate: (0, dayjs_1.default)(new Date()).format("MM-DD-YYYY") })),
297
+ react_1.default.createElement(LogTimeModalAuthenticated_1.SelectDate, { timeLogDate: issueStartDate, setTimeLogDate: setIssueStartDate, isInvalid: false, setIsDateInvalid: setIsDateInvalid, validateDate: validateDate, maxDate: (0, dayjs_1.default)(new Date()).format("MM-DD-YYYY") })),
198
298
  react_1.default.createElement("div", null,
199
299
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "What's the problem?"),
200
300
  react_1.default.createElement(base_ui_1.Input, { type: "text", value: problemInput, placeholder: "Describe the issue...", onChange: (e) => setProblemInput(e.target.value) })),
@@ -206,12 +306,12 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
206
306
  react_1.default.createElement("div", { className: "border border-dashed border-gray-300 rounded-md p-6 text-center" },
207
307
  react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-2" }, "Upload screenshots, emails, or documents"),
208
308
  react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ".pdf,.doc,.docx,.jpeg,.png,.gif,.csv", hidden: true, onChange: handleFileUpload }),
209
- 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", isLoading: uploadingFile, size: "sm" }),
210
- uploadFiles.length > 0 && (react_1.default.createElement("ul", { className: "mt-2 text-sm text-gray-600 list-disc list-inside" }, uploadFiles.map(f => react_1.default.createElement("li", { key: f.name }, f.name)))))),
309
+ 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", isLoading: uploadingFile, disabled: selectedUser === null, size: "sm" }),
310
+ uploadFiles.length > 0 && (react_1.default.createElement("ul", { className: "mt-2 text-sm text-gray-600 list-disc list-inside" }, uploadFiles.map(f => react_1.default.createElement("li", { key: f.name }, f.split('%2F')[1])))))),
211
311
  react_1.default.createElement("div", { className: "bg-[#EFF6FF] p-3 rounded" },
212
312
  react_1.default.createElement(base_ui_1.Checkbox, { id: "checkbox-1", label: `I understand this will notify my ${isExpert ? 'client' : 'expert'} and the Paro support team`, name: "acknowledge", isChecked: isChecked, onChange: () => setIsChecked(prev => !prev) })),
213
313
  react_1.default.createElement("div", { className: "flex justify-end space-x-3 pt-4" },
214
- react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack }),
215
- react_1.default.createElement(base_ui_1.Button, { label: "Submit issue", onClick: handleSubmit, color: "primary", disabled: !isFormValid() }))))));
314
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack, disabled: submitting || uploadingFile }),
315
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit issue", onClick: handleSubmit, color: "primary", isLoading: submitting, disabled: !isFormValid() || uploadingFile }))))));
216
316
  };
217
317
  exports.default = EscalationSubmitForm;
@@ -1,17 +1,14 @@
1
- export type EscalationChatDetails = {
2
- title: string;
3
- project: string;
4
- id: string;
5
- status: string;
6
- };
7
1
  interface EscalationTabProps {
8
2
  activeTab: string;
9
- openEscalationChat: (details: EscalationChatDetails) => void;
3
+ openEscalationChat: (issue: any) => void;
10
4
  setSelectedIssueId: (issue: number) => void;
11
5
  activeIssues: any[];
12
6
  inProgressIssues: any[];
13
7
  resolvedIssues: any[];
14
8
  isExpert: boolean;
9
+ updateProjectEscalation: any;
10
+ downloadDocumentUrl: string;
11
+ bucketName: string;
15
12
  }
16
- declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }: EscalationTabProps) => JSX.Element;
13
+ declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, }: EscalationTabProps) => JSX.Element;
17
14
  export default EscalationTabsContent;
@@ -30,18 +30,18 @@ const react_1 = __importDefault(require("react"));
30
30
  const EscalationIssueCard_1 = __importStar(require("./EscalationIssueCard"));
31
31
  const base_ui_1 = require("@paro.io/base-ui");
32
32
  ;
33
- const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }) => {
33
+ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, }) => {
34
34
  if (activeTab === 'action-required') {
35
35
  return (react_1.default.createElement("div", null,
36
36
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
37
37
  react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues Requiring Your Response")),
38
- react_1.default.createElement(EscalationIssueCard_1.default, { issues: activeIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showRespondButton: true, setSelectedIssueId: setSelectedIssueId })));
38
+ react_1.default.createElement(EscalationIssueCard_1.default, { issues: activeIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showRespondButton: true, setSelectedIssueId: setSelectedIssueId, updateProjectEscalation: updateProjectEscalation, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName })));
39
39
  }
40
40
  if (activeTab === 'in-progress') {
41
41
  return (react_1.default.createElement("div", null,
42
42
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
43
43
  react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues In Progress")),
44
- react_1.default.createElement(EscalationIssueCard_1.default, { issues: inProgressIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showMarkResolvedButton: true })));
44
+ react_1.default.createElement(EscalationIssueCard_1.default, { issues: inProgressIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showMarkResolvedButton: true, updateProjectEscalation: updateProjectEscalation, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName })));
45
45
  }
46
46
  if (activeTab === 'resolved') {
47
47
  return (react_1.default.createElement("div", null,
@@ -77,12 +77,7 @@ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssue
77
77
  react_1.default.createElement("span", { className: "text-xs text-gray-500" },
78
78
  "Resolved By ",
79
79
  issue.resolvedBy)))),
80
- react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
81
- title: issue.chatTitle,
82
- project: issue.projectName,
83
- id: issue.id,
84
- status: issue.chatStatus
85
- }), label: "Chat", color: "primary" }))));
80
+ react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat(issue), label: "Chat", color: "primary" }))));
86
81
  }))
87
82
  :
88
83
  react_1.default.createElement("div", null, "No resolved issues.")));
@@ -1,10 +1,16 @@
1
1
  interface EscalationsProps {
2
- experts: any[];
2
+ expertsOrClients: any[];
3
3
  projects: any[];
4
4
  isExpert: boolean;
5
- activeIssues: any[];
6
- inProgressIssues: any[];
7
- resolvedIssues: any[];
5
+ escalations: any[];
6
+ documentUploadUrl: string;
7
+ downloadDocumentUrl: string;
8
+ uploadExpertClientFiles?: any;
9
+ createProjectEscalation: any;
10
+ updateProjectEscalation: any;
11
+ createEscalationChatMessage: any;
12
+ bucketName: string;
13
+ user: any;
8
14
  }
9
- export declare const Escalations: ({ experts, projects, isExpert, activeIssues, inProgressIssues, resolvedIssues, }: EscalationsProps) => JSX.Element;
15
+ export declare const Escalations: ({ expertsOrClients, projects, isExpert, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, }: EscalationsProps) => JSX.Element;
10
16
  export {};
@@ -39,14 +39,29 @@ const AccountSuspensionBanner_1 = __importDefault(require("./AccountSuspensionBa
39
39
  const AccountSuspensionModal_1 = __importDefault(require("./AccountSuspensionModal"));
40
40
  const base_icons_1 = require("@paro.io/base-icons");
41
41
  const EscalationIssueCard_1 = require("./EscalationIssueCard");
42
- const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProgressIssues, resolvedIssues, }) => {
42
+ const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, }) => {
43
43
  const [activeSection, setActiveSection] = (0, react_1.useState)('support');
44
44
  const [selectedProject, setSelectedProject] = (0, react_1.useState)(null);
45
45
  const [selectedIssueId, setSelectedIssueId] = (0, react_1.useState)(null); // using selectedIssueId 0 for new escalation submission
46
46
  const [showEscalationChat, setShowEscalationChat] = (0, react_1.useState)(false);
47
- const [activeChatIssue, setActiveChatIssue] = (0, react_1.useState)(null); // update required
47
+ const [activeChatIssue, setActiveChatIssue] = (0, react_1.useState)(null);
48
48
  const [activeEscalationTab, setActiveEscalationTab] = (0, react_1.useState)('action-required');
49
49
  const [showSuspensionModal, setShowSuspensionModal] = (0, react_1.useState)(false);
50
+ const activeIssues = escalations.filter(issue => {
51
+ var _a;
52
+ const userTypeId = (_a = issue === null || issue === void 0 ? void 0 : issue.submittedByUser) === null || _a === void 0 ? void 0 : _a.userTypeId;
53
+ const internalEscalationTo = issue === null || issue === void 0 ? void 0 : issue.internalEscalationTo;
54
+ const status = issue === null || issue === void 0 ? void 0 : issue.status;
55
+ // Determine if this issue should be shown to the current user
56
+ const isRelevantEscalation = (isExpert
57
+ ? (internalEscalationTo === 'expert' || internalEscalationTo === 'both')
58
+ : (internalEscalationTo === 'client' || internalEscalationTo === 'both'));
59
+ return ((userTypeId !== user.userTypeId ||
60
+ (userTypeId === 2 && isRelevantEscalation)) &&
61
+ status === 'InProgress');
62
+ });
63
+ const inProgressIssues = escalations.filter(issue => { var _a; return ((_a = issue === null || issue === void 0 ? void 0 : issue.submittedByUser) === null || _a === void 0 ? void 0 : _a.userTypeId) === user.userTypeId && (issue === null || issue === void 0 ? void 0 : issue.status) === 'InProgress'; });
64
+ const resolvedIssues = escalations.filter(issue => (issue === null || issue === void 0 ? void 0 : issue.status) === 'Resolved');
50
65
  const goBack = () => {
51
66
  if (selectedIssueId !== null) {
52
67
  setSelectedIssueId(null);
@@ -136,10 +151,10 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
136
151
  !isExpert &&
137
152
  react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0) }),
138
153
  react_1.default.createElement(EscalationTabs_1.default, { activeTab: activeEscalationTab, setActiveTab: setActiveEscalationTab, activeIssues: activeIssues.length, inProgressIssues: inProgressIssues.length, resolvedIssues: resolvedIssues.length }),
139
- react_1.default.createElement(EscalationTabsContent_1.default, { activeTab: activeEscalationTab, openEscalationChat: openEscalationChat, setSelectedIssueId: setSelectedIssueId, activeIssues: activeIssues, inProgressIssues: inProgressIssues, resolvedIssues: resolvedIssues, isExpert: isExpert })),
140
- activeSection === 'support' && activeIssues.filter((issue) => issue.id === selectedIssueId).length > 0 && (react_1.default.createElement(EscalationRespondForm_1.default, { goBack: goBack, selectedIssue: activeIssues.filter((issue) => issue.id === selectedIssueId), goHome: goHome })),
141
- activeSection === 'support' && selectedIssueId === 0 && (react_1.default.createElement(EscalationSubmitForm_1.default, { goBack: goBack, goHome: goHome, experts: experts, projects: projects, isExpert: isExpert })),
142
- showEscalationChat && activeChatIssue && (react_1.default.createElement(EscalationChat_1.default, { activeChatIssue: activeChatIssue, showEscalationChat: showEscalationChat, setShowEscalationChat: setShowEscalationChat })),
154
+ react_1.default.createElement(EscalationTabsContent_1.default, { activeTab: activeEscalationTab, openEscalationChat: openEscalationChat, setSelectedIssueId: setSelectedIssueId, activeIssues: activeIssues, inProgressIssues: inProgressIssues, resolvedIssues: resolvedIssues, updateProjectEscalation: updateProjectEscalation, isExpert: isExpert, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName })),
155
+ activeSection === 'support' && activeIssues.filter((issue) => issue.escalationNumber === selectedIssueId).length > 0 && (react_1.default.createElement(EscalationRespondForm_1.default, { goBack: goBack, selectedIssue: activeIssues.find((issue) => issue.escalationNumber === selectedIssueId), documentUploadUrl: documentUploadUrl, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName, uploadExpertClientFiles: uploadExpertClientFiles, updateProjectEscalation: updateProjectEscalation, goHome: goHome, isExpert: isExpert })),
156
+ activeSection === 'support' && selectedIssueId === 0 && (react_1.default.createElement(EscalationSubmitForm_1.default, { goBack: goBack, goHome: goHome, expertsOrClients: expertsOrClients, projects: projects, documentUploadUrl: documentUploadUrl, bucketName: bucketName, uploadExpertClientFiles: uploadExpertClientFiles, createProjectEscalation: createProjectEscalation, isExpert: isExpert, user: user })),
157
+ showEscalationChat && activeChatIssue && (react_1.default.createElement(EscalationChat_1.default, { activeChatIssue: activeChatIssue, showEscalationChat: showEscalationChat, setShowEscalationChat: setShowEscalationChat, user: user, createEscalationChatMessage: createEscalationChatMessage, documentUploadUrl: documentUploadUrl, bucketName: bucketName, uploadExpertClientFiles: uploadExpertClientFiles, createProjectEscalation: createProjectEscalation, isExpert: isExpert })),
143
158
  showSuspensionModal &&
144
159
  react_1.default.createElement(AccountSuspensionModal_1.default, { showSuspensionModal: showSuspensionModal, onClose: () => setShowSuspensionModal(false) }))));
145
160
  };
@@ -2,14 +2,18 @@ interface UploadFileParams {
2
2
  file: File;
3
3
  documentName: string;
4
4
  disputeId?: number;
5
- projectId: number;
5
+ escalationId?: string;
6
+ escalationNumber?: string;
7
+ projectId?: number;
6
8
  documentUploadUrl: string;
7
9
  bucketName: string;
8
- updateClientInvoiceDisputeMutation: any;
10
+ updateClientInvoiceDisputeMutation?: any;
11
+ updateProjectEscalation?: any;
9
12
  uploadExpertClientFiles?: any;
10
- previousFiles: string | string[];
13
+ createProjectEscalation?: any;
14
+ previousFiles?: string | string[];
11
15
  isExpert: boolean;
12
- disputeData?: {
16
+ extraData?: {
13
17
  clientId: number;
14
18
  clientName: string;
15
19
  email: string;
@@ -18,5 +22,5 @@ interface UploadFileParams {
18
22
  projectName: string;
19
23
  };
20
24
  }
21
- export declare const fileUploader: ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, uploadExpertClientFiles, bucketName, disputeId, previousFiles, isExpert, disputeData, }: UploadFileParams) => Promise<any>;
25
+ export declare const fileUploader: ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, updateProjectEscalation, uploadExpertClientFiles, createProjectEscalation, bucketName, disputeId, escalationId, escalationNumber, previousFiles, isExpert, extraData, }: UploadFileParams) => Promise<any>;
22
26
  export {};
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.fileUploader = void 0;
16
16
  const UploadClient_1 = __importDefault(require("../shared/UploadClient"));
17
17
  const utils_1 = require("../shared/utils");
18
- const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, uploadExpertClientFiles, bucketName, disputeId, previousFiles, isExpert, disputeData, }) {
18
+ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file, projectId, documentUploadUrl, updateClientInvoiceDisputeMutation, updateProjectEscalation, uploadExpertClientFiles, createProjectEscalation, bucketName, disputeId, escalationId, escalationNumber, previousFiles, isExpert, extraData, }) {
19
19
  const documentLinks = previousFiles ? (typeof previousFiles === 'string' ? previousFiles.split(',') : [...previousFiles]) : [];
20
20
  try {
21
21
  (0, utils_1.showToast)('success', 'Starting Document Upload');
@@ -23,6 +23,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
23
23
  fileSelected: file,
24
24
  fileName: file.name,
25
25
  projectId,
26
+ escalationId,
26
27
  documentUploadUrl,
27
28
  bucketName: bucketName,
28
29
  });
@@ -47,20 +48,35 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
47
48
  },
48
49
  }));
49
50
  }
50
- if (uploadExpertClientFiles && disputeData) {
51
+ if (escalationNumber) {
52
+ const escalationPromise = updateProjectEscalation({
53
+ variables: {
54
+ input: Object.assign({ escalationId }, (isExpert ? {
55
+ expertSupportingDocuments: documentLinks.join(',')
56
+ } : {
57
+ clientSupportingDocuments: documentLinks.join(',')
58
+ }))
59
+ },
60
+ });
61
+ promises.push(escalationPromise);
62
+ }
63
+ else {
64
+ console.log("escalationId condition is FALSE");
65
+ }
66
+ if (uploadExpertClientFiles && extraData) {
51
67
  promises.push(uploadExpertClientFiles({
52
68
  variables: {
53
69
  input: {
54
- clientId: disputeData.clientId,
55
- clientName: disputeData.clientName,
56
- email: disputeData.email,
70
+ clientId: extraData.clientId,
71
+ clientName: extraData.clientName,
72
+ email: extraData.email,
57
73
  fileName: file.name,
58
74
  fileSize: file.size,
59
- fileType: 'DISPUTE_DOCUMENTS',
60
- freelancerId: disputeData.freelancerId,
61
- freelancerName: disputeData.freelancerName,
75
+ fileType: disputeId ? 'DISPUTE_DOCUMENTS' : 'ESCALATION_DOCUMENTS',
76
+ freelancerId: extraData.freelancerId,
77
+ freelancerName: extraData.freelancerName,
62
78
  projectId: projectId,
63
- projectName: disputeData.projectName,
79
+ projectName: extraData.projectName,
64
80
  uploadedBy: isExpert ? 'FREELANCER' : 'CLIENT',
65
81
  data: "",
66
82
  },
@@ -78,6 +94,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
78
94
  return documentLinks;
79
95
  }
80
96
  catch (error) {
97
+ console.error("Error in fileUploader:", error);
81
98
  (0, utils_1.showToast)('warning', 'Error uploading file. Please try again.');
82
99
  return false;
83
100
  }
@@ -6,6 +6,6 @@ interface ClientDisputeProjectCardProps {
6
6
  bucketName?: string;
7
7
  uploadExpertClientFiles?: any;
8
8
  }
9
- export declare const handleDownloadDocument: (projectId: number, fileName: string, downloadDocumentUrl: string, bucketName: string | undefined) => Promise<void>;
9
+ export declare const handleDownloadDocument: (projectId: number, fileName: string, downloadDocumentUrl: string, bucketName: string | undefined, escalationId?: string | undefined) => Promise<void>;
10
10
  export declare const ClientDisputeProjectCard: ({ clientInvoice, updateClientInvoiceDisputeMutation, documentUploadUrl, downloadDocumentUrl, bucketName, uploadExpertClientFiles }: ClientDisputeProjectCardProps) => JSX.Element;
11
11
  export {};
@@ -131,11 +131,11 @@ const handleFileDownload = ({ fileData, downloadFilename, streamData, fileType =
131
131
  document.body.removeChild(downloadLink);
132
132
  URL.revokeObjectURL(blobUrl);
133
133
  };
134
- const handleDownloadDocument = (projectId, fileName, downloadDocumentUrl, bucketName) => __awaiter(void 0, void 0, void 0, function* () {
134
+ const handleDownloadDocument = (projectId, fileName, downloadDocumentUrl, bucketName, escalationId) => __awaiter(void 0, void 0, void 0, function* () {
135
135
  var _a;
136
136
  // Decode the filename from URL encoding if needed
137
137
  const decodedFileName = decodeURIComponent(fileName);
138
- const downloadFileName = `project-${projectId}/${decodedFileName}`;
138
+ const downloadFileName = escalationId ? `escalation-${escalationId}/${decodedFileName}` : `project-${projectId}/${decodedFileName}`;
139
139
  const downloadData = yield (0, FileDownloader_1.fileDownloader)({ downloadDocumentUrl: downloadDocumentUrl, fileKey: downloadFileName, bucketName: bucketName });
140
140
  handleFileDownload({
141
141
  fileData: downloadData,
@@ -205,7 +205,7 @@ const ClientDisputeProjectCard = ({ clientInvoice, updateClientInvoiceDisputeMut
205
205
  previousFiles: (_e = (_d = (_c = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.disputeProjects) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.clientDocumentLinks) !== null && _e !== void 0 ? _e : [],
206
206
  isExpert: false,
207
207
  uploadExpertClientFiles: uploadExpertClientFiles,
208
- disputeData: {
208
+ extraData: {
209
209
  clientId: (_f = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.invoice) === null || _f === void 0 ? void 0 : _f.clientId,
210
210
  clientName: (_g = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.client) === null || _g === void 0 ? void 0 : _g.name,
211
211
  email: (_h = clientInvoice === null || clientInvoice === void 0 ? void 0 : clientInvoice.freelancer) === null || _h === void 0 ? void 0 : _h.email,
@@ -86,7 +86,7 @@ const DisputeSection = ({ dispute, documentUploadUrl, downloadDocumentUrl, bucke
86
86
  disputeId: dispute === null || dispute === void 0 ? void 0 : dispute.disputeId,
87
87
  previousFiles: isExpert ? expertDocumentLinks : clientDocumentLinks,
88
88
  isExpert: isExpert,
89
- disputeData: {
89
+ extraData: {
90
90
  clientId: (_c = dispute === null || dispute === void 0 ? void 0 : dispute.invoice) === null || _c === void 0 ? void 0 : _c.clientId,
91
91
  clientName: (_d = dispute === null || dispute === void 0 ? void 0 : dispute.client) === null || _d === void 0 ? void 0 : _d.name,
92
92
  email: (_e = dispute === null || dispute === void 0 ? void 0 : dispute.freelancer) === null || _e === void 0 ? void 0 : _e.email,
@@ -6,9 +6,10 @@ export default class UploadClient {
6
6
  documentUploadUrl: string;
7
7
  projectId: number;
8
8
  bucketName: string;
9
+ escalationId: string;
9
10
  };
10
11
  constructor(props: any);
11
- generateS3Key(projectId: number, fileName: string): string;
12
+ generateS3Key(projectId: number, escalationId: string, fileName: string): string;
12
13
  triggerMultipartUpload(): Promise<string | undefined>;
13
14
  uploadMultiPartFile(): Promise<string | undefined>;
14
15
  completeUpload(partsArray: any): Promise<string | undefined>;
@@ -18,19 +18,21 @@ class UploadClient {
18
18
  documentUploadUrl: props.documentUploadUrl,
19
19
  projectId: props.projectId,
20
20
  bucketName: props.bucketName,
21
+ escalationId: props.escalationId,
21
22
  };
22
23
  }
23
- generateS3Key(projectId, fileName) {
24
+ generateS3Key(projectId, escalationId, fileName) {
24
25
  const sanitizedFileName = fileName.replace(/[^a-zA-Z0-9.-]/g, '_');
25
- let uniqueKey = `project-${projectId}/${sanitizedFileName}`;
26
- return uniqueKey;
26
+ if (escalationId) {
27
+ return `escalation-${escalationId}/${sanitizedFileName}`;
28
+ }
29
+ return `project-${projectId}/${sanitizedFileName}`;
27
30
  }
28
31
  ;
29
32
  triggerMultipartUpload() {
30
33
  return __awaiter(this, void 0, void 0, function* () {
31
34
  try {
32
- const fileName = this.generateS3Key(this.state.projectId, this.state.fileName);
33
- console.log('File Name', fileName);
35
+ const fileName = this.generateS3Key(this.state.projectId, this.state.escalationId, this.state.fileName);
34
36
  this.state = Object.assign(Object.assign({}, this.state), { fileName: fileName });
35
37
  const params = {
36
38
  fileName: this.state.fileName,
@@ -120,7 +122,6 @@ class UploadClient {
120
122
  throw new Error('Failed to complete multipart upload');
121
123
  }
122
124
  const { responseData } = yield response.json();
123
- console.log('Upload Complete', responseData);
124
125
  return `${JSON.stringify(responseData)}`;
125
126
  }
126
127
  catch (error) {
@@ -40,6 +40,7 @@ export declare const features: string[];
40
40
  export declare const titleFeatures: string[];
41
41
  export declare const serviceDescriptions: Record<string, string>;
42
42
  export declare const selectedServicesReducer: (selectedServices: any, action: any) => any;
43
+ export declare const generateUUID: () => string;
43
44
  export declare const sharedUtils: {
44
45
  selectedServicesReducer: (selectedServices: any, action: any) => any;
45
46
  };
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sharedUtils = exports.selectedServicesReducer = exports.serviceDescriptions = exports.titleFeatures = exports.features = exports.titleMappings = exports.DOCUMENT_TYPE_CONSTANTS = exports.validateFileUpload = exports.showToast = exports.MAX_FILE_SIZE = exports.ACCEPTED_FILE_TYPES = exports.formatDate = exports.CustomPaper = exports.handleDownloadPdf = exports.getFileMimeType = exports.stateAbbreviationMap = exports.getPreviousMonthStartDate = exports.isOlderThan30Days = exports.formatTenure = exports.isOnClickEvent = void 0;
3
+ exports.sharedUtils = exports.generateUUID = exports.selectedServicesReducer = exports.serviceDescriptions = exports.titleFeatures = exports.features = exports.titleMappings = exports.DOCUMENT_TYPE_CONSTANTS = exports.validateFileUpload = exports.showToast = exports.MAX_FILE_SIZE = exports.ACCEPTED_FILE_TYPES = exports.formatDate = exports.CustomPaper = exports.handleDownloadPdf = exports.getFileMimeType = exports.stateAbbreviationMap = exports.getPreviousMonthStartDate = exports.isOlderThan30Days = exports.formatTenure = exports.isOnClickEvent = void 0;
4
4
  exports.getComparator = getComparator;
5
5
  exports.stableSort = stableSort;
6
6
  exports.compareItems = compareItems;
7
7
  const core_1 = require("@material-ui/core");
8
8
  const ReviewsTab_1 = require("../ReviewsTab/ReviewsTab");
9
+ const uuid_1 = require("uuid");
9
10
  /* eslint-disable @typescript-eslint/no-explicit-any */
10
11
  const isOnClickEvent = (potentialEvent) => {
11
12
  return (potentialEvent === null || potentialEvent === void 0 ? void 0 : potentialEvent.type) === 'mouseup' || (potentialEvent === null || potentialEvent === void 0 ? void 0 : potentialEvent.type) === 'keydown' || (potentialEvent === null || potentialEvent === void 0 ? void 0 : potentialEvent.type) === 'click';
@@ -357,4 +358,8 @@ const selectedServicesReducer = (selectedServices, action) => {
357
358
  }
358
359
  };
359
360
  exports.selectedServicesReducer = selectedServicesReducer;
361
+ const generateUUID = () => {
362
+ return (0, uuid_1.v4)();
363
+ };
364
+ exports.generateUUID = generateUUID;
360
365
  exports.sharedUtils = { selectedServicesReducer: exports.selectedServicesReducer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.12.42",
3
+ "version": "1.12.44",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -14,7 +14,11 @@
14
14
  "unlink-local": "yarn unlink && cd node_modules/react && yarn unlink && cd ../react-dom && yarn unlink"
15
15
  },
16
16
  "repository": "https://github.com/paroadmin/expert-shared-components.git",
17
- "keywords": ["react", "components", "shared"],
17
+ "keywords": [
18
+ "react",
19
+ "components",
20
+ "shared"
21
+ ],
18
22
  "author": "apande@paro.io",
19
23
  "license": "MIT",
20
24
  "dependencies": {
@@ -40,6 +44,7 @@
40
44
  "react-hot-toast": "^2.4.1",
41
45
  "react-input-mask": "^3.0.0-alpha.2",
42
46
  "styled-components": "^5.3.3",
47
+ "uuid": "^11.1.0",
43
48
  "yup": "^0.32.11"
44
49
  },
45
50
  "devDependencies": {
@@ -49,6 +54,7 @@
49
54
  "@types/react-datepicker": "^4.19.6",
50
55
  "@types/react-dom": "^18.2.22",
51
56
  "@types/styled-components": "^5.1.22",
57
+ "@types/uuid": "^10.0.0",
52
58
  "@types/yup": "^0.29.13",
53
59
  "typescript": "^5.3.3"
54
60
  },