@paro.io/expert-shared-components 1.12.42 → 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.
@@ -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,158 @@ 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
+ try {
117
+ const res = yield (0, FileUploader_1.fileUploader)({
118
+ file: selectedFile,
119
+ documentName: selectedFile.name,
120
+ escalationId: escalationId,
121
+ projectId: selectedProjects.length > 0 ? selectedProjects[0].id : '',
122
+ documentUploadUrl: documentUploadUrl,
123
+ bucketName: bucketName,
124
+ isExpert: false,
125
+ uploadExpertClientFiles: uploadExpertClientFiles,
126
+ createProjectEscalation: createProjectEscalation,
127
+ extraData: {
128
+ clientId: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id : user === null || user === void 0 ? void 0 : user.userId,
129
+ clientName: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name : user === null || user === void 0 ? void 0 : user.name,
130
+ email: isExpert ? "client@gmail.com" : user === null || user === void 0 ? void 0 : user.email,
131
+ freelancerId: isExpert ? user === null || user === void 0 ? void 0 : user.userId : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id,
132
+ freelancerName: isExpert ? user === null || user === void 0 ? void 0 : user.name : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.name,
133
+ projectName: selectedProjects.length > 0 ? selectedProjects[0].name : '',
134
+ }
135
+ });
136
+ if (res) {
137
+ setUploadFiles(prev => [...prev, ...res]);
138
+ }
139
+ }
140
+ catch (error) {
141
+ reject(error);
142
+ }
143
+ finally {
144
+ resolve();
145
+ }
146
+ });
147
+ reader.readAsDataURL(selectedFile);
148
+ });
149
+ });
150
+ try {
151
+ const res = yield Promise.all(uploadPromises);
152
+ }
153
+ catch (error) {
154
+ console.error('Error uploading files:', error);
155
+ }
156
+ finally {
157
+ setUploadingFile(false);
158
+ }
159
+ }
160
+ ;
161
+ });
90
162
  const isFormValid = () => {
91
163
  const requiredProjectSelection = isExpert || (!isExpert && selectedProjects.length > 0);
92
- return (selectedExpert !== null &&
164
+ return (selectedUser !== null &&
93
165
  issueType !== '' &&
94
166
  severity !== '' &&
95
167
  problemInput.trim() !== '' &&
96
168
  outcomeInput.trim() !== '' &&
97
169
  isChecked &&
98
- startDate !== undefined &&
170
+ issueStartDate !== undefined &&
99
171
  requiredProjectSelection);
100
172
  };
101
- const handleSubmit = () => {
173
+ const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
174
+ var _a;
102
175
  if (!isFormValid())
103
176
  return;
177
+ setSubmitting(true);
104
178
  const formData = {
105
- selectedExpert,
106
- selectedProjects,
107
- issueType,
108
- severity,
109
- startDate,
179
+ escalationId: escalationId,
180
+ freelancerId: user.userId,
181
+ clientId: (_a = selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id) !== null && _a !== void 0 ? _a : 0,
182
+ projectDetails: selectedProjects.map((p) => { return { projectId: p.id, projectName: p.name }; }),
183
+ issueStartDate: issueStartDate,
184
+ escalationType: issueType,
185
+ severityLevel: severity,
110
186
  problem: problemInput,
111
- expectedOutcome: outcomeInput,
112
- supportingDocs: uploadFiles.map(f => f.name),
187
+ outcome: outcomeInput,
188
+ submittedByUserId: user.userId,
189
+ status: 'InProgress',
190
+ [isExpert ? 'expertSupportingDocuments' : 'clientSupportingDocuments']: uploadFiles.join(", "),
191
+ statusChangedBy: user.userId,
113
192
  };
114
- console.log('Escalation Submitted:', formData);
115
- // Redirect or perform additional logic
116
- goHome();
117
- };
193
+ try {
194
+ yield createProjectEscalation({
195
+ variables: {
196
+ input: formData
197
+ }
198
+ });
199
+ }
200
+ catch (error) {
201
+ console.error("Failed to create an escalation!", error);
202
+ }
203
+ finally {
204
+ setSubmitting(false);
205
+ goHome();
206
+ }
207
+ });
118
208
  const validateDate = (date) => {
119
209
  const minDate = LogTimeModalAuthenticated_1.constants.MIN_DATE;
120
210
  const maxDate = new Date();
@@ -146,10 +236,19 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
146
236
  react_1.default.createElement("div", { className: "p-4 space-y-4" },
147
237
  react_1.default.createElement("div", null,
148
238
  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'}` },
239
+ 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 => {
240
+ const selectedName = e.target.value;
241
+ if (selectedName === '') {
242
+ setSelectedUser(null);
243
+ }
244
+ else {
245
+ const selectedOption = expertOptions.find(opt => opt.value.name === selectedName);
246
+ setSelectedUser(selectedOption ? selectedOption.value : null);
247
+ }
248
+ }, displayEmpty: true, variant: "outlined", placeholder: `Select a ${isExpert ? 'Client' : 'Expert'}` },
150
249
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
151
250
  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))))),
251
+ expertOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value.id, value: option.value.name }, option.label))))),
153
252
  react_1.default.createElement("div", null,
154
253
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Which Project(s)?"),
155
254
  react_1.default.createElement(core_1.Select, { multiple: true, fullWidth: true, value: selectedProjects, onChange: (e) => {
@@ -166,7 +265,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
166
265
  }, placeholder: `Select a Project(s)` },
167
266
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
168
267
  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))))),
268
+ projectOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value.id, value: option.value }, option.label))))),
170
269
  react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" },
171
270
  react_1.default.createElement("div", null,
172
271
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Issue Type"),
@@ -194,7 +293,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
194
293
  react_1.default.createElement(core_1.MenuItem, { value: "Low" }, "Low")))),
195
294
  react_1.default.createElement("div", null,
196
295
  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") })),
296
+ 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
297
  react_1.default.createElement("div", null,
199
298
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "What's the problem?"),
200
299
  react_1.default.createElement(base_ui_1.Input, { type: "text", value: problemInput, placeholder: "Describe the issue...", onChange: (e) => setProblemInput(e.target.value) })),
@@ -206,12 +305,12 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
206
305
  react_1.default.createElement("div", { className: "border border-dashed border-gray-300 rounded-md p-6 text-center" },
207
306
  react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-2" }, "Upload screenshots, emails, or documents"),
208
307
  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)))))),
308
+ 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" }),
309
+ 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
310
  react_1.default.createElement("div", { className: "bg-[#EFF6FF] p-3 rounded" },
212
311
  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
312
  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() }))))));
313
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack, disabled: submitting || uploadingFile }),
314
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit issue", onClick: handleSubmit, color: "primary", isLoading: submitting, disabled: !isFormValid() || uploadingFile }))))));
216
315
  };
217
316
  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,7 +39,7 @@ 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
@@ -47,6 +47,9 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
47
47
  const [activeChatIssue, setActiveChatIssue] = (0, react_1.useState)(null); // update required
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 => { 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'; });
51
+ 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'; });
52
+ const resolvedIssues = escalations.filter(issue => (issue === null || issue === void 0 ? void 0 : issue.status) === 'Resolved');
50
53
  const goBack = () => {
51
54
  if (selectedIssueId !== null) {
52
55
  setSelectedIssueId(null);
@@ -136,10 +139,10 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
136
139
  !isExpert &&
137
140
  react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0) }),
138
141
  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 })),
142
+ 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 })),
143
+ 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 })),
144
+ 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 })),
145
+ 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
146
  showSuspensionModal &&
144
147
  react_1.default.createElement(AccountSuspensionModal_1.default, { showSuspensionModal: showSuspensionModal, onClose: () => setShowSuspensionModal(false) }))));
145
148
  };
@@ -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,27 @@ 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
+ console.log("input params here in file uploader is ", {
20
+ file,
21
+ disputeId,
22
+ escalationId,
23
+ projectId,
24
+ documentUploadUrl,
25
+ bucketName,
26
+ updateClientInvoiceDisputeMutation,
27
+ updateProjectEscalation,
28
+ uploadExpertClientFiles,
29
+ createProjectEscalation,
30
+ previousFiles,
31
+ isExpert,
32
+ extraData,
33
+ });
34
+ // Add these debug logs
35
+ console.log("escalationId exists?", !!escalationId);
36
+ console.log("escalationId value:", escalationId);
37
+ console.log("updateProjectEscalation exists?", !!updateProjectEscalation);
38
+ console.log("typeof updateProjectEscalation:", typeof updateProjectEscalation);
19
39
  const documentLinks = previousFiles ? (typeof previousFiles === 'string' ? previousFiles.split(',') : [...previousFiles]) : [];
20
40
  try {
21
41
  (0, utils_1.showToast)('success', 'Starting Document Upload');
@@ -23,6 +43,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
23
43
  fileSelected: file,
24
44
  fileName: file.name,
25
45
  projectId,
46
+ escalationId,
26
47
  documentUploadUrl,
27
48
  bucketName: bucketName,
28
49
  });
@@ -30,6 +51,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
30
51
  const resParsed = JSON.parse(res);
31
52
  const documentLink = resParsed === null || resParsed === void 0 ? void 0 : resParsed.Location;
32
53
  documentLinks.push(documentLink); // Add the new file to the documentLinks array
54
+ console.log("document links are ", documentLinks);
33
55
  const promises = [];
34
56
  if (disputeId) {
35
57
  promises.push(updateClientInvoiceDisputeMutation({
@@ -47,20 +69,43 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
47
69
  },
48
70
  }));
49
71
  }
50
- if (uploadExpertClientFiles && disputeData) {
72
+ console.log("Escalation id is ", escalationId);
73
+ console.log("About to check escalationId condition");
74
+ if (escalationNumber) {
75
+ console.log("escalationId condition is TRUE - adding updateProjectEscalation to promises");
76
+ console.log("updateProjectEscalation function:", updateProjectEscalation);
77
+ const escalationPromise = updateProjectEscalation({
78
+ variables: {
79
+ input: Object.assign({ escalationId }, (isExpert ? {
80
+ expertSupportingDocuments: documentLinks.join(',')
81
+ } : {
82
+ clientSupportingDocuments: documentLinks.join(',')
83
+ }))
84
+ },
85
+ });
86
+ console.log("Created escalation promise:", escalationPromise);
87
+ promises.push(escalationPromise);
88
+ console.log("Added escalation promise to promises array");
89
+ }
90
+ else {
91
+ console.log("escalationId condition is FALSE");
92
+ }
93
+ console.log("promises are ", promises.length, promises);
94
+ if (uploadExpertClientFiles && extraData) {
95
+ console.log("extra data is ", extraData);
51
96
  promises.push(uploadExpertClientFiles({
52
97
  variables: {
53
98
  input: {
54
- clientId: disputeData.clientId,
55
- clientName: disputeData.clientName,
56
- email: disputeData.email,
99
+ clientId: extraData.clientId,
100
+ clientName: extraData.clientName,
101
+ email: extraData.email,
57
102
  fileName: file.name,
58
103
  fileSize: file.size,
59
- fileType: 'DISPUTE_DOCUMENTS',
60
- freelancerId: disputeData.freelancerId,
61
- freelancerName: disputeData.freelancerName,
104
+ fileType: disputeId ? 'DISPUTE_DOCUMENTS' : 'ESCALATION_DOCUMENTS',
105
+ freelancerId: extraData.freelancerId,
106
+ freelancerName: extraData.freelancerName,
62
107
  projectId: projectId,
63
- projectName: disputeData.projectName,
108
+ projectName: extraData.projectName,
64
109
  uploadedBy: isExpert ? 'FREELANCER' : 'CLIENT',
65
110
  data: "",
66
111
  },
@@ -78,6 +123,7 @@ const fileUploader = (_a) => __awaiter(void 0, [_a], void 0, function* ({ file,
78
123
  return documentLinks;
79
124
  }
80
125
  catch (error) {
126
+ console.error("Error in fileUploader:", error);
81
127
  (0, utils_1.showToast)('warning', 'Error uploading file. Please try again.');
82
128
  return false;
83
129
  }
@@ -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,18 +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);
35
+ const fileName = this.generateS3Key(this.state.projectId, this.state.escalationId, this.state.fileName);
33
36
  console.log('File Name', fileName);
34
37
  this.state = Object.assign(Object.assign({}, this.state), { fileName: fileName });
35
38
  const params = {
@@ -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.43",
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
  },