@paro.io/expert-shared-components 1.13.9 → 1.13.11
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.
- package/lib/components/Escalations/AccountSuspensionBanner.js +2 -2
- package/lib/components/Escalations/AccountSuspensionModal.js +25 -49
- package/lib/components/Escalations/EscalationChat.js +10 -12
- package/lib/components/Escalations/EscalationIssueCard.d.ts +1 -0
- package/lib/components/Escalations/EscalationIssueCard.js +39 -4
- package/lib/components/Escalations/EscalationRespondForm.js +11 -13
- package/lib/components/Escalations/EscalationSubmitForm.js +17 -21
- package/lib/components/Escalations/EscalationTabsContent.d.ts +2 -1
- package/lib/components/Escalations/EscalationTabsContent.js +6 -2
- package/lib/components/Escalations/Escalations.d.ts +2 -1
- package/lib/components/Escalations/Escalations.js +22 -9
- package/lib/components/Escalations/MarkResolvedModal.d.ts +2 -1
- package/lib/components/Escalations/MarkResolvedModal.js +10 -9
- package/lib/components/ExpertProfileHeader/NetworkSection.js +1 -1
- package/lib/components/FileUploader/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ const getSuspensionDuration = (label) => {
|
|
|
24
24
|
return "Permanent";
|
|
25
25
|
case "Low":
|
|
26
26
|
default:
|
|
27
|
-
return "
|
|
27
|
+
return "No suspension";
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
const AccountSuspensionBanner = ({ setShowSuspensionModal, escalationDisputeStatistics, }) => {
|
|
@@ -42,7 +42,7 @@ const AccountSuspensionBanner = ({ setShowSuspensionModal, escalationDisputeStat
|
|
|
42
42
|
react_1.default.createElement("div", { className: "flex-1" },
|
|
43
43
|
react_1.default.createElement("h3", { className: "text-lg font-bold text-white" }, "\uD83D\uDEAB Account Suspended due to: Engagement Issues"),
|
|
44
44
|
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" },
|
|
45
|
-
"Your account has been suspended due to
|
|
45
|
+
"Your account has been suspended due to engagement issues. If you have any problems with the suspension, please go to the Engagement Support section to respond to your issues or reach out to",
|
|
46
46
|
' ',
|
|
47
47
|
react_1.default.createElement("a", { href: "mailto:expertsupport@paro.io", className: "underline text-white hover:text-red-200 cursor-pointer" }, "expertsupport@paro.io"),
|
|
48
48
|
"."),
|
|
@@ -42,12 +42,12 @@ const AccountSuspensionModal = ({ showSuspensionModal, onClose }) => {
|
|
|
42
42
|
react_1.default.createElement("div", { className: "flex justify-between items-start mb-2" },
|
|
43
43
|
react_1.default.createElement("h4", { className: "font-semibold text-orange-800" }, "Level 2: Medium Severity"),
|
|
44
44
|
react_1.default.createElement("div", { className: "text-xs bg-orange-100 text-orange-700 px-2 py-1 rounded-full" }, "3 Warnings System")),
|
|
45
|
-
react_1.default.createElement("p", { className: "text-sm
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
react_1.default.createElement("
|
|
50
|
-
"
|
|
45
|
+
react_1.default.createElement("p", { className: "text-sm mb-2 font-medium text-red-800" }, "After 3 warnings: 30-day suspension"),
|
|
46
|
+
react_1.default.createElement("div", null,
|
|
47
|
+
react_1.default.createElement("b", null, "Note: "),
|
|
48
|
+
"Warnings are counted within this level, not as a total. Suspension is triggered after 3 warnings at this severity. ",
|
|
49
|
+
react_1.default.createElement("b", null, "After 3 warnings in this level:"),
|
|
50
|
+
" 30-day suspension"))),
|
|
51
51
|
react_1.default.createElement("div", { className: "flex items-start" },
|
|
52
52
|
react_1.default.createElement("div", { className: "bg-red-500 rounded-full p-2 mr-4 relative z-10" },
|
|
53
53
|
react_1.default.createElement(base_icons_1.IconExclamation, { className: "h-5 w-5 text-white" })),
|
|
@@ -55,12 +55,12 @@ const AccountSuspensionModal = ({ showSuspensionModal, onClose }) => {
|
|
|
55
55
|
react_1.default.createElement("div", { className: "flex justify-between items-start mb-2" },
|
|
56
56
|
react_1.default.createElement("h4", { className: "font-semibold text-red-800" }, "Level 3: High Severity"),
|
|
57
57
|
react_1.default.createElement("div", { className: "text-xs bg-red-100 text-red-700 px-2 py-1 rounded-full" }, "2 Warnings System")),
|
|
58
|
-
react_1.default.createElement("p", { className: "text-sm
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
react_1.default.createElement("
|
|
63
|
-
"
|
|
58
|
+
react_1.default.createElement("p", { className: "text-sm mb-2 font-medium text-red-800" }, "After 2 warnings: 60-day suspension"),
|
|
59
|
+
react_1.default.createElement("div", null,
|
|
60
|
+
react_1.default.createElement("b", null, "Note: "),
|
|
61
|
+
"Warnings are counted within this level, not as a total. Suspension is triggered after 2 warnings at this severity. ",
|
|
62
|
+
react_1.default.createElement("b", null, "After 2 warnings in this level:"),
|
|
63
|
+
" 60-day suspension"))),
|
|
64
64
|
react_1.default.createElement("div", { className: "flex items-start" },
|
|
65
65
|
react_1.default.createElement("div", { className: "bg-black rounded-full p-2 mr-4 relative z-10" },
|
|
66
66
|
react_1.default.createElement(base_icons_1.IconX, { className: "h-5 w-5 text-white" })),
|
|
@@ -68,45 +68,21 @@ const AccountSuspensionModal = ({ showSuspensionModal, onClose }) => {
|
|
|
68
68
|
react_1.default.createElement("div", { className: "flex justify-between items-start mb-2" },
|
|
69
69
|
react_1.default.createElement("h4", { className: "font-semibold text-gray-900" }, "Level 4: Critical Severity"),
|
|
70
70
|
react_1.default.createElement("div", { className: "text-xs bg-gray-800 text-white px-2 py-1 rounded-full" }, "One Time Offense")),
|
|
71
|
-
react_1.default.createElement("p", { className: "text-sm
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
react_1.default.createElement("
|
|
78
|
-
|
|
79
|
-
react_1.default.createElement("div", { className: "flex items-center text-sm" },
|
|
80
|
-
react_1.default.createElement("div", { className: "w-3 h-3 bg-yellow-400 rounded-full mr-3" }),
|
|
81
|
-
react_1.default.createElement("span", null,
|
|
82
|
-
react_1.default.createElement("strong", null, "Medium (3 warnings):"),
|
|
83
|
-
" Expert coaching and performance improvement plan")),
|
|
84
|
-
react_1.default.createElement("div", { className: "flex items-center text-sm" },
|
|
85
|
-
react_1.default.createElement("div", { className: "w-3 h-3 bg-orange-500 rounded-full mr-3" }),
|
|
86
|
-
react_1.default.createElement("span", null,
|
|
87
|
-
react_1.default.createElement("strong", null, "High (2 warnings):"),
|
|
88
|
-
" Escalated coaching with enhanced monitoring")),
|
|
89
|
-
react_1.default.createElement("div", { className: "flex items-center text-sm" },
|
|
90
|
-
react_1.default.createElement("div", { className: "w-3 h-3 bg-red-500 rounded-full mr-3" }),
|
|
91
|
-
react_1.default.createElement("span", null,
|
|
92
|
-
react_1.default.createElement("strong", null, "Final warning:"),
|
|
93
|
-
" Automatic suspension with mandatory training")),
|
|
94
|
-
react_1.default.createElement("div", { className: "flex items-center text-sm" },
|
|
95
|
-
react_1.default.createElement("div", { className: "w-3 h-3 bg-black rounded-full mr-3" }),
|
|
96
|
-
react_1.default.createElement("span", null,
|
|
97
|
-
react_1.default.createElement("strong", null, "Critical offense:"),
|
|
98
|
-
" Immediate permanent account removal")),
|
|
99
|
-
react_1.default.createElement("div", { className: "flex items-center text-sm" },
|
|
100
|
-
react_1.default.createElement("div", { className: "w-3 h-3 bg-gray-400 rounded-full mr-3" }),
|
|
101
|
-
react_1.default.createElement("span", null,
|
|
102
|
-
react_1.default.createElement("strong", null, "Reset:"),
|
|
103
|
-
" Warnings reset after 6 months of good standing")))),
|
|
71
|
+
react_1.default.createElement("p", { className: "text-sm mb-2 font-medium text-red-800" }, "Permanent suspension"),
|
|
72
|
+
react_1.default.createElement("div", null,
|
|
73
|
+
react_1.default.createElement("b", null, "Note: "),
|
|
74
|
+
"Warnings are counted within this level, not as a total. Suspension is triggered after 1 warning at this severity. ",
|
|
75
|
+
react_1.default.createElement("b", null, "After 1 warning in this level"),
|
|
76
|
+
": Permentant suspension")))),
|
|
77
|
+
react_1.default.createElement("div", { className: "text-xs" },
|
|
78
|
+
react_1.default.createElement("b", null, "\u26A0\uFE0F Suspension thresholds are based on the number of warnings within each severity level, not total warnings across all levels"))),
|
|
104
79
|
react_1.default.createElement("div", { className: "mt-6 bg-gray-50 rounded-lg p-4" },
|
|
105
80
|
react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Important Reminders"),
|
|
106
81
|
react_1.default.createElement("ul", { className: "text-sm text-gray-600 space-y-1" },
|
|
107
|
-
react_1.default.createElement("li", null,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
82
|
+
react_1.default.createElement("li", null,
|
|
83
|
+
"\u2022 Warnings are tracked separately per severity level. Suspensions are triggered only when the threshold is met ",
|
|
84
|
+
react_1.default.createElement("b", null, "within a specific level"),
|
|
85
|
+
" (e.g., 3 Medium-level warnings = Medium suspension)"),
|
|
86
|
+
react_1.default.createElement("li", null, "\u2022 Warnings reset after 6 months of good standing (no new warnings)")))))));
|
|
111
87
|
};
|
|
112
88
|
exports.default = AccountSuspensionModal;
|
|
@@ -43,7 +43,7 @@ const EscalationRespondForm_1 = require("./EscalationRespondForm");
|
|
|
43
43
|
const utils_1 = require("../shared/utils");
|
|
44
44
|
const EscalationChat = ({ activeChatIssue, showEscalationChat, onClose, user, createEscalationChatMessage, documentUploadUrl, bucketName, uploadExpertClientFiles, updateProjectEscalation, isExpert, }) => {
|
|
45
45
|
var _a, _b;
|
|
46
|
-
const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
|
|
46
|
+
const [uploadFiles, setUploadFiles] = (0, react_1.useState)([activeChatIssue.expertSupportingDocuments, activeChatIssue.clientSupportingDocuments, activeChatIssue.internalSupportingDocuments]);
|
|
47
47
|
const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
|
|
48
48
|
const fileInputRef = (0, react_1.useRef)(null);
|
|
49
49
|
const handleFileUpload = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -63,7 +63,7 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, onClose, user, cr
|
|
|
63
63
|
}
|
|
64
64
|
const uploadPromises = validFiles.map((selectedFile) => {
|
|
65
65
|
return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
66
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
67
67
|
try {
|
|
68
68
|
const res = yield (0, FileUploader_1.fileUploader)({
|
|
69
69
|
file: selectedFile,
|
|
@@ -73,21 +73,21 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, onClose, user, cr
|
|
|
73
73
|
projectId: activeChatIssue.projectDetails.length > 0 ? activeChatIssue.projectDetails[0].projectId : '',
|
|
74
74
|
documentUploadUrl: documentUploadUrl,
|
|
75
75
|
bucketName: bucketName,
|
|
76
|
-
previousFiles: isExpert ? activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.
|
|
76
|
+
previousFiles: isExpert ? (_b = (_a = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.expertSupportingDocuments) === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [] : (_d = (_c = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.clientSupportingDocuments) === null || _c === void 0 ? void 0 : _c.split(',')) !== null && _d !== void 0 ? _d : [],
|
|
77
77
|
isExpert: isExpert,
|
|
78
78
|
uploadExpertClientFiles: uploadExpertClientFiles,
|
|
79
79
|
updateProjectEscalation: updateProjectEscalation,
|
|
80
80
|
extraData: {
|
|
81
|
-
clientId: (
|
|
82
|
-
clientName: (
|
|
83
|
-
email: isExpert ? (
|
|
84
|
-
freelancerId: (
|
|
85
|
-
freelancerName: (
|
|
81
|
+
clientId: (_f = (_e = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.client) === null || _e === void 0 ? void 0 : _e.id) !== null && _f !== void 0 ? _f : 0,
|
|
82
|
+
clientName: (_h = (_g = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.client) === null || _g === void 0 ? void 0 : _g.name) !== null && _h !== void 0 ? _h : '',
|
|
83
|
+
email: isExpert ? (_l = (_k = (_j = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.client) === null || _j === void 0 ? void 0 : _j.primaryContact) === null || _k === void 0 ? void 0 : _k.email) !== null && _l !== void 0 ? _l : '' : (_o = (_m = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.freelancer) === null || _m === void 0 ? void 0 : _m.email) !== null && _o !== void 0 ? _o : '',
|
|
84
|
+
freelancerId: (_q = (_p = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.freelancer) === null || _p === void 0 ? void 0 : _p.id) !== null && _q !== void 0 ? _q : 0,
|
|
85
|
+
freelancerName: (_s = (_r = activeChatIssue === null || activeChatIssue === void 0 ? void 0 : activeChatIssue.freelancer) === null || _r === void 0 ? void 0 : _r.name) !== null && _s !== void 0 ? _s : '',
|
|
86
86
|
projectName: activeChatIssue.projectDetails.length > 0 ? activeChatIssue.projectDetails[0].projectName : '',
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
89
|
if (res) {
|
|
90
|
-
setUploadFiles(
|
|
90
|
+
setUploadFiles([...res]);
|
|
91
91
|
}
|
|
92
92
|
resolve();
|
|
93
93
|
}
|
|
@@ -103,11 +103,9 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, onClose, user, cr
|
|
|
103
103
|
}
|
|
104
104
|
finally {
|
|
105
105
|
setUploadingFile(false);
|
|
106
|
-
setUploadFiles([]);
|
|
107
106
|
}
|
|
108
107
|
});
|
|
109
|
-
const
|
|
110
|
-
const processedDocs = (0, utils_1.processDocs)(docs);
|
|
108
|
+
const processedDocs = (0, utils_1.processDocs)(uploadFiles);
|
|
111
109
|
const project = activeChatIssue.projectDetails && Array.isArray(activeChatIssue.projectDetails) && activeChatIssue.projectDetails.length > 0
|
|
112
110
|
? `${(_a = activeChatIssue.projectDetails[0]) === null || _a === void 0 ? void 0 : _a.projectName}${activeChatIssue.projectDetails.length > 1 ? ` +${activeChatIssue.projectDetails.length - 1} more` : ''} `
|
|
113
111
|
: '';
|
|
@@ -16,6 +16,7 @@ type EscalationIssueCardProps = {
|
|
|
16
16
|
downloadDocumentUrl: string;
|
|
17
17
|
bucketName: string;
|
|
18
18
|
userId: number;
|
|
19
|
+
refetchEscalationDisputeStatistics?: any;
|
|
19
20
|
};
|
|
20
21
|
declare const EscalationIssueCard: React.FC<EscalationIssueCardProps>;
|
|
21
22
|
export default EscalationIssueCard;
|
|
@@ -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
|
};
|
|
@@ -35,6 +44,7 @@ const dayjs_1 = __importDefault(require("dayjs"));
|
|
|
35
44
|
const ViewResponseModal_1 = __importDefault(require("./ViewResponseModal"));
|
|
36
45
|
const MarkResolvedModal_1 = __importDefault(require("./MarkResolvedModal"));
|
|
37
46
|
const utils_1 = require("../shared/utils");
|
|
47
|
+
const utils_2 = require("../shared/utils");
|
|
38
48
|
const getBackgroundColor = (type) => {
|
|
39
49
|
switch (type) {
|
|
40
50
|
case 'Critical':
|
|
@@ -57,10 +67,11 @@ const CustomTag = ({ label, iconLeft, onClick, customColor, }) => {
|
|
|
57
67
|
label.toUpperCase()));
|
|
58
68
|
};
|
|
59
69
|
exports.CustomTag = CustomTag;
|
|
60
|
-
const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespondButton = false, setSelectedIssueId, showMarkResolvedButton = false, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, }) => {
|
|
70
|
+
const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespondButton = false, setSelectedIssueId, showMarkResolvedButton = false, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, refetchEscalationDisputeStatistics, }) => {
|
|
61
71
|
var _a, _b;
|
|
62
72
|
const [viewResponseModal, setViewResponseModal] = (0, react_1.useState)(null);
|
|
63
73
|
const [markAsResolved, setMarkAsResolved] = (0, react_1.useState)(null);
|
|
74
|
+
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
64
75
|
const getResponseButtonText = (issue) => {
|
|
65
76
|
var _a;
|
|
66
77
|
const userTypeId = (_a = issue === null || issue === void 0 ? void 0 : issue.submittedByUser) === null || _a === void 0 ? void 0 : _a.userTypeId;
|
|
@@ -85,6 +96,28 @@ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespond
|
|
|
85
96
|
}
|
|
86
97
|
return "Awaiting Response";
|
|
87
98
|
};
|
|
99
|
+
const handleMakeVisibleToExpert = (escalationId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
100
|
+
setSubmitting(true);
|
|
101
|
+
try {
|
|
102
|
+
yield updateProjectEscalation({
|
|
103
|
+
variables: {
|
|
104
|
+
input: {
|
|
105
|
+
escalationId: escalationId,
|
|
106
|
+
clientEscalationTo: 'both',
|
|
107
|
+
statusChangedBy: userId,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
(0, utils_2.showToast)("success", "Expert visibility updated Successfully!");
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error("Failed to update expert visibility for this escalation!", error);
|
|
115
|
+
(0, utils_2.showToast)("warning", "Failed to update expert visibility!");
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
setSubmitting(false);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
88
121
|
if (!issues.length)
|
|
89
122
|
return react_1.default.createElement("div", null, "No issues.");
|
|
90
123
|
return (react_1.default.createElement("div", { className: "space-y-4" },
|
|
@@ -95,7 +128,7 @@ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespond
|
|
|
95
128
|
: '';
|
|
96
129
|
const docs = [issue.expertSupportingDocuments, issue.clientSupportingDocuments, issue.internalSupportingDocuments];
|
|
97
130
|
const processedDocs = (0, utils_1.processDocs)(docs);
|
|
98
|
-
return (react_1.default.createElement("div", { key: issue.
|
|
131
|
+
return (react_1.default.createElement("div", { key: issue.escalationId, className: "border border-gray-200 rounded-lg bg-white p-4" },
|
|
99
132
|
react_1.default.createElement("div", { className: "flex items-center justify-between mb-3" },
|
|
100
133
|
react_1.default.createElement("div", { className: "flex-1 ml-2" },
|
|
101
134
|
react_1.default.createElement("div", { className: "flex flex-row justify-start gap-2" },
|
|
@@ -139,9 +172,11 @@ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespond
|
|
|
139
172
|
showRespondButton && setSelectedIssueId && (react_1.default.createElement(base_ui_1.Button, { label: "Respond to Escalation", onClick: () => setSelectedIssueId(issue.escalationNumber), color: 'primary' })),
|
|
140
173
|
showMarkResolvedButton && (react_1.default.createElement(base_ui_1.Button, { label: getResponseButtonText(issue), onClick: () => { setViewResponseModal(issue); }, color: 'primary', disabled: getResponseButtonText(issue) === 'Awaiting Response' })),
|
|
141
174
|
showMarkResolvedButton && !isExpert && issue.submittedByUser.userTypeId === 3 && ( // only client can resolve issue raised by client
|
|
142
|
-
react_1.default.createElement(base_ui_1.Button, { onClick: () => { setMarkAsResolved(issue); }, label: "Mark as Resolved", color: "primary" }))
|
|
175
|
+
react_1.default.createElement(base_ui_1.Button, { onClick: () => { setMarkAsResolved(issue); }, label: "Mark as Resolved", color: "primary" })),
|
|
176
|
+
showMarkResolvedButton && !isExpert && issue.submittedByUser.userTypeId === 3 && issue.clientEscalationTo === "paro" && ( // only client can update this, raised by client
|
|
177
|
+
react_1.default.createElement(base_ui_1.Button, { onClick: () => handleMakeVisibleToExpert(issue.escalationId), label: "Make visible to expert", color: "primary", isLoading: submitting })))));
|
|
143
178
|
}),
|
|
144
179
|
!!viewResponseModal && react_1.default.createElement(ViewResponseModal_1.default, { selectedIssue: viewResponseModal, isExpert: isExpert, open: !!viewResponseModal, onClose: () => setViewResponseModal(null) }),
|
|
145
|
-
!!markAsResolved && react_1.default.createElement(MarkResolvedModal_1.default, { escalationId: markAsResolved.escalationId, expertName: (_b = (_a = markAsResolved === null || markAsResolved === void 0 ? void 0 : markAsResolved.freelancer) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'Expert', open: !!markAsResolved, onClose: () => setMarkAsResolved(false), updateProjectEscalation: updateProjectEscalation, userId: userId })));
|
|
180
|
+
!!markAsResolved && react_1.default.createElement(MarkResolvedModal_1.default, { escalationId: markAsResolved.escalationId, expertName: (_b = (_a = markAsResolved === null || markAsResolved === void 0 ? void 0 : markAsResolved.freelancer) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'Expert', open: !!markAsResolved, onClose: () => setMarkAsResolved(false), updateProjectEscalation: updateProjectEscalation, userId: userId, refetchEscalationDisputeStatistics: refetchEscalationDisputeStatistics })));
|
|
146
181
|
};
|
|
147
182
|
exports.default = EscalationIssueCard;
|
|
@@ -96,7 +96,7 @@ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downl
|
|
|
96
96
|
const responseTypes = isExpert ? exports.expertResponseTypes : exports.clientResponseTypes;
|
|
97
97
|
const [selectedType, setSelectedType] = (0, react_1.useState)(responseTypes[0].value);
|
|
98
98
|
const [responseInput, setResponseInput] = (0, react_1.useState)('');
|
|
99
|
-
const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
|
|
99
|
+
const [uploadFiles, setUploadFiles] = (0, react_1.useState)([selectedIssue.expertSupportingDocuments, selectedIssue.clientSupportingDocuments, selectedIssue.internalSupportingDocuments]);
|
|
100
100
|
const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
|
|
101
101
|
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
102
102
|
const fileInputRef = (0, react_1.useRef)(null);
|
|
@@ -117,7 +117,7 @@ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downl
|
|
|
117
117
|
}
|
|
118
118
|
const uploadPromises = validFiles.map((selectedFile) => {
|
|
119
119
|
return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
120
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
121
121
|
try {
|
|
122
122
|
const res = yield (0, FileUploader_1.fileUploader)({
|
|
123
123
|
file: selectedFile,
|
|
@@ -127,21 +127,21 @@ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downl
|
|
|
127
127
|
projectId: (_b = (_a = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.projectDetails) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.projectId,
|
|
128
128
|
documentUploadUrl: documentUploadUrl,
|
|
129
129
|
bucketName: bucketName,
|
|
130
|
-
previousFiles: isExpert ? selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.
|
|
130
|
+
previousFiles: isExpert ? (_d = (_c = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.expertSupportingDocuments) === null || _c === void 0 ? void 0 : _c.split(',')) !== null && _d !== void 0 ? _d : [] : (_f = (_e = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.clientSupportingDocuments) === null || _e === void 0 ? void 0 : _e.split(',')) !== null && _f !== void 0 ? _f : [],
|
|
131
131
|
isExpert: isExpert,
|
|
132
132
|
uploadExpertClientFiles: uploadExpertClientFiles,
|
|
133
133
|
updateProjectEscalation: updateProjectEscalation,
|
|
134
134
|
extraData: {
|
|
135
|
-
clientId: (
|
|
136
|
-
clientName: (
|
|
137
|
-
email: isExpert ? (
|
|
138
|
-
freelancerId: (
|
|
139
|
-
freelancerName: (
|
|
140
|
-
projectName: (
|
|
135
|
+
clientId: (_g = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client) === null || _g === void 0 ? void 0 : _g.id,
|
|
136
|
+
clientName: (_j = (_h = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client) === null || _h === void 0 ? void 0 : _h.name) !== null && _j !== void 0 ? _j : '',
|
|
137
|
+
email: isExpert ? (_m = (_l = (_k = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.client) === null || _k === void 0 ? void 0 : _k.primaryContact) === null || _l === void 0 ? void 0 : _l.email) !== null && _m !== void 0 ? _m : '' : (_p = (_o = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer) === null || _o === void 0 ? void 0 : _o.email) !== null && _p !== void 0 ? _p : '',
|
|
138
|
+
freelancerId: (_q = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer) === null || _q === void 0 ? void 0 : _q.id,
|
|
139
|
+
freelancerName: (_s = (_r = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.freelancer) === null || _r === void 0 ? void 0 : _r.name) !== null && _s !== void 0 ? _s : '',
|
|
140
|
+
projectName: (_u = (_t = selectedIssue === null || selectedIssue === void 0 ? void 0 : selectedIssue.projectDetails) === null || _t === void 0 ? void 0 : _t[0]) === null || _u === void 0 ? void 0 : _u.projectName,
|
|
141
141
|
}
|
|
142
142
|
});
|
|
143
143
|
if (res) {
|
|
144
|
-
setUploadFiles(
|
|
144
|
+
setUploadFiles([...res]);
|
|
145
145
|
}
|
|
146
146
|
resolve();
|
|
147
147
|
}
|
|
@@ -157,7 +157,6 @@ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downl
|
|
|
157
157
|
}
|
|
158
158
|
finally {
|
|
159
159
|
setUploadingFile(false);
|
|
160
|
-
setUploadFiles([]);
|
|
161
160
|
}
|
|
162
161
|
});
|
|
163
162
|
const submitResponse = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -185,8 +184,7 @@ const EscalationRespondForm = ({ goBack, selectedIssue, documentUploadUrl, downl
|
|
|
185
184
|
goHome();
|
|
186
185
|
}
|
|
187
186
|
});
|
|
188
|
-
const
|
|
189
|
-
const processedDocs = (0, utils_1.processDocs)(docs);
|
|
187
|
+
const processedDocs = (0, utils_1.processDocs)(uploadFiles);
|
|
190
188
|
return (react_1.default.createElement("div", null,
|
|
191
189
|
react_1.default.createElement("button", { onClick: goBack, className: "flex items-center text-blue-600 mb-6" },
|
|
192
190
|
react_1.default.createElement(base_icons_1.IconChevronLeft, { size: "xs" }),
|
|
@@ -71,6 +71,7 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
71
71
|
const [issueStartDate, setIssueStartDate] = (0, react_1.useState)((0, dayjs_1.default)(new Date).format('MM-DD-YYYY'));
|
|
72
72
|
const [isDateInvalid, setIsDateInvalid] = (0, react_1.useState)(false);
|
|
73
73
|
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
74
|
+
const [clientEscalationTo, setClientEscalationTo] = (0, react_1.useState)('');
|
|
74
75
|
const fileInputRef = (0, react_1.useRef)(null);
|
|
75
76
|
const escalationId = (0, utils_1.generateUUID)();
|
|
76
77
|
(0, react_1.useEffect)(() => {
|
|
@@ -78,7 +79,7 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
78
79
|
const options = expertsOrClients.map((user) => ({
|
|
79
80
|
label: user.name,
|
|
80
81
|
value: { id: user.id, name: user.name },
|
|
81
|
-
}));
|
|
82
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
82
83
|
setExpertOptions(options);
|
|
83
84
|
}
|
|
84
85
|
}, [expertsOrClients]);
|
|
@@ -96,7 +97,7 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
96
97
|
.map((p) => ({
|
|
97
98
|
label: p.name,
|
|
98
99
|
value: p,
|
|
99
|
-
}));
|
|
100
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
100
101
|
setProjectOptions(options);
|
|
101
102
|
}
|
|
102
103
|
}, [projects, selectedUser]);
|
|
@@ -155,11 +156,12 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
155
156
|
}
|
|
156
157
|
finally {
|
|
157
158
|
setUploadingFile(false);
|
|
158
|
-
setUploadFiles([]);
|
|
159
159
|
}
|
|
160
160
|
});
|
|
161
161
|
const isFormValid = () => {
|
|
162
162
|
const requiredProjectSelection = isExpert || (!isExpert && selectedProjects.length > 0);
|
|
163
|
+
const requireEscalationTo = (isExpert || (!isExpert && clientEscalationTo !== ''));
|
|
164
|
+
console.log({ issueStartDate });
|
|
163
165
|
return (selectedUser !== null &&
|
|
164
166
|
issueType !== '' &&
|
|
165
167
|
severity !== '' &&
|
|
@@ -167,27 +169,14 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
167
169
|
outcomeInput.trim() !== '' &&
|
|
168
170
|
isChecked &&
|
|
169
171
|
issueStartDate !== undefined &&
|
|
170
|
-
requiredProjectSelection
|
|
172
|
+
requiredProjectSelection &&
|
|
173
|
+
requireEscalationTo);
|
|
171
174
|
};
|
|
172
175
|
const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
173
176
|
if (!isFormValid())
|
|
174
177
|
return;
|
|
175
178
|
setSubmitting(true);
|
|
176
|
-
const formData = {
|
|
177
|
-
escalationId: escalationId,
|
|
178
|
-
freelancerId: isExpert ? user.userId : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id,
|
|
179
|
-
clientId: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id : clientId,
|
|
180
|
-
projectDetails: selectedProjects.filter((p) => p !== undefined).map((p) => { return { projectId: p.id, projectName: p.name }; }),
|
|
181
|
-
issueStartDate: issueStartDate,
|
|
182
|
-
escalationType: issueType,
|
|
183
|
-
severityLevel: severity,
|
|
184
|
-
problem: problemInput,
|
|
185
|
-
outcome: outcomeInput,
|
|
186
|
-
submittedByUserId: user.userId,
|
|
187
|
-
status: 'InProgress',
|
|
188
|
-
[isExpert ? 'expertSupportingDocuments' : 'clientSupportingDocuments']: uploadFiles.length > 0 ? uploadFiles.join(", ") : '',
|
|
189
|
-
statusChangedBy: user.userId,
|
|
190
|
-
};
|
|
179
|
+
const formData = Object.assign({ escalationId: escalationId, freelancerId: isExpert ? user.userId : selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id, clientId: isExpert ? selectedUser === null || selectedUser === void 0 ? void 0 : selectedUser.id : clientId, projectDetails: selectedProjects.filter((p) => p !== undefined).map((p) => { return { projectId: p.id, projectName: p.name }; }), issueStartDate: issueStartDate, escalationType: issueType, severityLevel: severity, problem: problemInput, outcome: outcomeInput, submittedByUserId: user.userId, status: 'InProgress', [isExpert ? 'expertSupportingDocuments' : 'clientSupportingDocuments']: uploadFiles.length > 0 ? uploadFiles.join(", ") : '', statusChangedBy: user.userId }, (isExpert ? {} : { clientEscalationTo }));
|
|
191
180
|
try {
|
|
192
181
|
yield createProjectEscalation({
|
|
193
182
|
variables: {
|
|
@@ -220,7 +209,7 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
220
209
|
react_1.default.createElement("h2", { className: "text-xl font-bold" },
|
|
221
210
|
"Report Issue with Your ",
|
|
222
211
|
isExpert ? 'Client' : 'Expert'),
|
|
223
|
-
react_1.default.createElement("p", { className: "text-gray-600 mt-1" }, isExpert ? (`Provide details about the issue you're experiencing and we'll resolve it within 4-8 hours
|
|
212
|
+
react_1.default.createElement("p", { className: "text-gray-600 mt-1" }, isExpert ? (`Provide details about the issue you're experiencing and we'll resolve it within 4-8 hours`) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
224
213
|
"Report communication problems, quality concerns, or missed deadlines. All issues right now will be submitted to the Expert and Paro. If you want to submit issues directly to Paro please email",
|
|
225
214
|
' ',
|
|
226
215
|
react_1.default.createElement("a", { href: "mailto:clientsupport@paro.io", className: "underline text-white hover:text-red-200 cursor-pointer" }, "clientsupport@paro.io"),
|
|
@@ -241,7 +230,7 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
241
230
|
react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
|
|
242
231
|
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Low" }),
|
|
243
232
|
react_1.default.createElement("span", null, "Minor issue or inconvenience that does not affect overall project flow.")))),
|
|
244
|
-
react_1.default.createElement("div", { className: "border rounded-lg overflow-hidden mb-6" },
|
|
233
|
+
react_1.default.createElement("div", { className: "border rounded-lg overflow-hidden mb-6 mt-4" },
|
|
245
234
|
react_1.default.createElement("div", { className: "bg-gray-50 p-3 border-b" },
|
|
246
235
|
react_1.default.createElement("h3", { className: "font-medium" }, "Issue Details")),
|
|
247
236
|
react_1.default.createElement("div", { className: "p-4 space-y-4" },
|
|
@@ -332,6 +321,13 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
332
321
|
react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: false, accept: ".pdf,.doc,.docx,.jpeg,.png,.gif,.csv, .xslx", hidden: true, onChange: handleFileUpload }),
|
|
333
322
|
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" }),
|
|
334
323
|
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])))))),
|
|
324
|
+
!isExpert && react_1.default.createElement("div", null,
|
|
325
|
+
react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Initially Address To:"),
|
|
326
|
+
react_1.default.createElement(core_1.Select, { fullWidth: true, value: clientEscalationTo, onChange: e => setClientEscalationTo(e.target.value), displayEmpty: true, variant: "outlined", placeholder: "Select party" },
|
|
327
|
+
react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
|
|
328
|
+
react_1.default.createElement("em", null, "Select party")),
|
|
329
|
+
react_1.default.createElement(core_1.MenuItem, { value: "paro" }, "Paro only"),
|
|
330
|
+
react_1.default.createElement(core_1.MenuItem, { value: "both" }, "Both Expert And Paro"))),
|
|
335
331
|
react_1.default.createElement("div", { className: "bg-[#EFF6FF] p-3 rounded" },
|
|
336
332
|
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) })),
|
|
337
333
|
react_1.default.createElement("div", { className: "flex justify-end space-x-3 pt-4" },
|
|
@@ -10,6 +10,7 @@ interface EscalationTabProps {
|
|
|
10
10
|
downloadDocumentUrl: string;
|
|
11
11
|
bucketName: string;
|
|
12
12
|
userId: number;
|
|
13
|
+
refetchEscalationDisputeStatistics: any;
|
|
13
14
|
}
|
|
14
|
-
declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, }: EscalationTabProps) => JSX.Element;
|
|
15
|
+
declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, refetchEscalationDisputeStatistics, }: EscalationTabProps) => JSX.Element;
|
|
15
16
|
export default EscalationTabsContent;
|
|
@@ -31,7 +31,7 @@ const EscalationIssueCard_1 = __importStar(require("./EscalationIssueCard"));
|
|
|
31
31
|
const base_ui_1 = require("@paro.io/base-ui");
|
|
32
32
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
33
33
|
;
|
|
34
|
-
const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, }) => {
|
|
34
|
+
const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, updateProjectEscalation, downloadDocumentUrl, bucketName, userId, refetchEscalationDisputeStatistics, }) => {
|
|
35
35
|
if (activeTab === 'action-required') {
|
|
36
36
|
return (react_1.default.createElement("div", null,
|
|
37
37
|
react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
@@ -42,7 +42,7 @@ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssue
|
|
|
42
42
|
return (react_1.default.createElement("div", null,
|
|
43
43
|
react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
|
|
44
44
|
react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues In Progress")),
|
|
45
|
-
react_1.default.createElement(EscalationIssueCard_1.default, { issues: inProgressIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showMarkResolvedButton: true, updateProjectEscalation: updateProjectEscalation, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName, userId: userId })));
|
|
45
|
+
react_1.default.createElement(EscalationIssueCard_1.default, { issues: inProgressIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showMarkResolvedButton: true, updateProjectEscalation: updateProjectEscalation, downloadDocumentUrl: downloadDocumentUrl, bucketName: bucketName, userId: userId, refetchEscalationDisputeStatistics: refetchEscalationDisputeStatistics })));
|
|
46
46
|
}
|
|
47
47
|
if (activeTab === 'resolved') {
|
|
48
48
|
return (react_1.default.createElement("div", null,
|
|
@@ -80,6 +80,10 @@ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssue
|
|
|
80
80
|
react_1.default.createElement("span", { className: "font-bold" }, "Resolution:"),
|
|
81
81
|
" ",
|
|
82
82
|
issue.internalResolution ? issue.internalResolution : issue.clientResolution),
|
|
83
|
+
react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-2" },
|
|
84
|
+
react_1.default.createElement("span", { className: "font-bold" }, "Expert at Fault: "),
|
|
85
|
+
" ",
|
|
86
|
+
issue.isExpertAtFault ? "True" : "False"),
|
|
83
87
|
react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
|
|
84
88
|
react_1.default.createElement("span", { className: "text-xs text-gray-500" },
|
|
85
89
|
"Resolved: ",
|
|
@@ -13,6 +13,7 @@ interface EscalationsProps {
|
|
|
13
13
|
user: any;
|
|
14
14
|
clientId?: number;
|
|
15
15
|
escalationDisputeStatistics?: any;
|
|
16
|
+
refetchEscalationDisputeStatistics?: any;
|
|
16
17
|
}
|
|
17
|
-
export declare const Escalations: ({ expertsOrClients, projects, isExpert, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId, escalationDisputeStatistics, }: EscalationsProps) => JSX.Element;
|
|
18
|
+
export declare const Escalations: ({ expertsOrClients, projects, isExpert, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId, escalationDisputeStatistics, refetchEscalationDisputeStatistics, }: EscalationsProps) => JSX.Element;
|
|
18
19
|
export {};
|
|
@@ -40,7 +40,7 @@ const AccountSuspensionModal_1 = __importDefault(require("./AccountSuspensionMod
|
|
|
40
40
|
const base_icons_1 = require("@paro.io/base-icons");
|
|
41
41
|
const EscalationIssueCard_1 = require("./EscalationIssueCard");
|
|
42
42
|
const react_hot_toast_1 = require("react-hot-toast");
|
|
43
|
-
const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId = 0, escalationDisputeStatistics, }) => {
|
|
43
|
+
const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId = 0, escalationDisputeStatistics, refetchEscalationDisputeStatistics, }) => {
|
|
44
44
|
const [activeSection, setActiveSection] = (0, react_1.useState)('support');
|
|
45
45
|
const [selectedProject, setSelectedProject] = (0, react_1.useState)(null);
|
|
46
46
|
const [selectedIssueId, setSelectedIssueId] = (0, react_1.useState)(null); // using selectedIssueId 0 for new escalation submission
|
|
@@ -50,21 +50,34 @@ const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations
|
|
|
50
50
|
const [showSuspensionModal, setShowSuspensionModal] = (0, react_1.useState)(false);
|
|
51
51
|
const activeIssues = escalations.filter(issue => {
|
|
52
52
|
var _a;
|
|
53
|
-
const
|
|
53
|
+
const submittedUserTypeId = (_a = issue === null || issue === void 0 ? void 0 : issue.submittedByUser) === null || _a === void 0 ? void 0 : _a.userTypeId;
|
|
54
54
|
const internalEscalationTo = issue === null || issue === void 0 ? void 0 : issue.internalEscalationTo;
|
|
55
55
|
const status = issue === null || issue === void 0 ? void 0 : issue.status;
|
|
56
|
-
const isDifferentUserType =
|
|
56
|
+
const isDifferentUserType = submittedUserTypeId !== user.userTypeId;
|
|
57
57
|
const isPendingResponse = isExpert
|
|
58
58
|
? issue.expertResponse === null
|
|
59
59
|
: issue.clientResponse === null;
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
// Determine if the escalation is valid for the current user
|
|
61
|
+
let isValidEscalation = false;
|
|
62
|
+
if (submittedUserTypeId === 2) {
|
|
63
|
+
// Submitted by internal
|
|
64
|
+
isValidEscalation = isExpert
|
|
62
65
|
? internalEscalationTo !== "client" // expert should NOT see escalations to client
|
|
63
|
-
: internalEscalationTo !== "expert"
|
|
64
|
-
|
|
66
|
+
: internalEscalationTo !== "expert"; // client should NOT see escalations to expert
|
|
67
|
+
}
|
|
68
|
+
else if (submittedUserTypeId === 3) {
|
|
69
|
+
// Submitted by client
|
|
70
|
+
isValidEscalation = isExpert
|
|
71
|
+
? (issue === null || issue === void 0 ? void 0 : issue.clientEscalationTo) !== 'paro'
|
|
72
|
+
: submittedUserTypeId !== user.userTypeId;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Submitted by expert
|
|
76
|
+
isValidEscalation = submittedUserTypeId !== user.userTypeId;
|
|
77
|
+
}
|
|
65
78
|
const shouldInclude = isDifferentUserType &&
|
|
66
79
|
isPendingResponse &&
|
|
67
|
-
|
|
80
|
+
isValidEscalation &&
|
|
68
81
|
status === 'InProgress';
|
|
69
82
|
return shouldInclude;
|
|
70
83
|
});
|
|
@@ -160,7 +173,7 @@ const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations
|
|
|
160
173
|
!isExpert &&
|
|
161
174
|
react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0), isExpert: isExpert }),
|
|
162
175
|
escalations.length > 0 ? react_1.default.createElement(EscalationTabs_1.default, { activeTab: activeEscalationTab, setActiveTab: setActiveEscalationTab, activeIssues: activeIssues.length, inProgressIssues: inProgressIssues.length, resolvedIssues: resolvedIssues.length }) : null,
|
|
163
|
-
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, userId: user.userId })),
|
|
176
|
+
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, userId: user.userId, refetchEscalationDisputeStatistics: refetchEscalationDisputeStatistics })),
|
|
164
177
|
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, userId: user.userId })),
|
|
165
178
|
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, clientId: clientId })),
|
|
166
179
|
showEscalationChat && activeChatIssue && (react_1.default.createElement(EscalationChat_1.default, { activeChatIssue: activeChatIssue, showEscalationChat: showEscalationChat, onClose: () => {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
declare const MarkResolvedModal: ({ escalationId, expertName, open, onClose, updateProjectEscalation, userId, }: {
|
|
2
|
+
declare const MarkResolvedModal: ({ escalationId, expertName, open, onClose, updateProjectEscalation, userId, refetchEscalationDisputeStatistics, }: {
|
|
3
3
|
escalationId: string;
|
|
4
4
|
expertName: string;
|
|
5
5
|
open: boolean;
|
|
6
6
|
onClose: () => void;
|
|
7
7
|
updateProjectEscalation: any;
|
|
8
8
|
userId: number;
|
|
9
|
+
refetchEscalationDisputeStatistics?: any;
|
|
9
10
|
}) => React.JSX.Element;
|
|
10
11
|
export default MarkResolvedModal;
|
|
@@ -37,7 +37,7 @@ const base_icons_1 = require("@paro.io/base-icons");
|
|
|
37
37
|
const base_ui_1 = require("@paro.io/base-ui");
|
|
38
38
|
const core_1 = require("@material-ui/core");
|
|
39
39
|
const utils_1 = require("../shared/utils");
|
|
40
|
-
const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProjectEscalation, userId, }) => {
|
|
40
|
+
const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProjectEscalation, userId, refetchEscalationDisputeStatistics, }) => {
|
|
41
41
|
const [resolutionText, setResolutionText] = (0, react_1.useState)(null);
|
|
42
42
|
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
43
43
|
const [expertResponsibility, setExpertResponsibility] = (0, react_1.useState)('');
|
|
@@ -53,7 +53,9 @@ const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProj
|
|
|
53
53
|
statusChangedBy: userId,
|
|
54
54
|
isExpertAtFault: expertResponsibility === 'atFault' ? true : false,
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
},
|
|
57
|
+
}).then(() => {
|
|
58
|
+
refetchEscalationDisputeStatistics && refetchEscalationDisputeStatistics();
|
|
57
59
|
});
|
|
58
60
|
(0, utils_1.showToast)("success", "Issue marked as resolved. You can now find it in the `Resolved` section");
|
|
59
61
|
}
|
|
@@ -80,23 +82,22 @@ const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProj
|
|
|
80
82
|
react_1.default.createElement("div", { className: "mt-6 mb-4" },
|
|
81
83
|
react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Please provide additional details before marking this issue as resolved."),
|
|
82
84
|
react_1.default.createElement(base_ui_1.Input, { type: "text", value: resolutionText, placeholder: "Enter details here...", onChange: (e) => setResolutionText(e.target.value) })),
|
|
83
|
-
react_1.default.createElement("p", null, "Please provide additional details before marking this issue as resolved."),
|
|
84
85
|
react_1.default.createElement("div", { style: { marginTop: '1em', marginBottom: '1em' } },
|
|
85
|
-
react_1.default.createElement("label", { className: "block text-sm font-
|
|
86
|
+
react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" },
|
|
86
87
|
"Expert Responsibility ",
|
|
87
88
|
react_1.default.createElement("span", { className: "text-sm text-red-800" }, "*")),
|
|
88
89
|
react_1.default.createElement("div", null,
|
|
89
|
-
react_1.default.createElement("label",
|
|
90
|
+
react_1.default.createElement("label", { className: "flex items-center space-x-2" },
|
|
90
91
|
react_1.default.createElement("input", { type: "radio", name: "expertResponsibility", value: "atFault", checked: expertResponsibility === 'atFault', onChange: () => setExpertResponsibility('atFault'), required: true }),
|
|
91
|
-
"Expert is at fault for this issue")),
|
|
92
|
+
react_1.default.createElement("span", null, "Expert is at fault for this issue"))),
|
|
92
93
|
react_1.default.createElement("div", null,
|
|
93
|
-
react_1.default.createElement("label",
|
|
94
|
+
react_1.default.createElement("label", { className: "flex items-center space-x-2" },
|
|
94
95
|
react_1.default.createElement("input", { type: "radio", name: "expertResponsibility", value: "notAtFault", checked: expertResponsibility === 'notAtFault', onChange: () => setExpertResponsibility('notAtFault'), required: true }),
|
|
95
|
-
"Expert is NOT at fault"))),
|
|
96
|
+
react_1.default.createElement("span", null, "Expert is NOT at fault for this issue")))),
|
|
96
97
|
react_1.default.createElement("div", { className: "flex items-center justify-between" },
|
|
97
98
|
react_1.default.createElement("div", { className: "flex space-x-2" },
|
|
98
99
|
react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: onClose, disabled: submitting })),
|
|
99
100
|
react_1.default.createElement("div", { className: "flex space-x-2" },
|
|
100
|
-
react_1.default.createElement(base_ui_1.Button, { label: "Submit", color: "primary", onClick: handleSubmit, isLoading: submitting, disabled: expertResponsibility === '' }))))));
|
|
101
|
+
react_1.default.createElement(base_ui_1.Button, { label: "Submit", color: "primary", onClick: handleSubmit, isLoading: submitting, disabled: expertResponsibility === '' || resolutionText === '' }))))));
|
|
101
102
|
};
|
|
102
103
|
exports.default = MarkResolvedModal;
|
|
@@ -191,7 +191,7 @@ const NetworkSection = ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, d
|
|
|
191
191
|
react_1.default.createElement("li", null,
|
|
192
192
|
leftSideStatus,
|
|
193
193
|
" ",
|
|
194
|
-
suspensionLevel !== "Low" && react_1.default.createElement(core_1.IconButton, { onClick: () => { setShowPriorityLevelModal(true); } },
|
|
194
|
+
suspensionLevel !== "Low" && react_1.default.createElement(core_1.IconButton, { "aria-label": "Show priority levels", onClick: () => { setShowPriorityLevelModal(true); } },
|
|
195
195
|
react_1.default.createElement(base_icons_1.IconInfoCircle, { size: "sm", className: "block text-right" }))),
|
|
196
196
|
react_1.default.createElement("li", null, rightSideStatus)))),
|
|
197
197
|
openModal &&
|
|
@@ -11,7 +11,7 @@ interface UploadFileParams {
|
|
|
11
11
|
updateProjectEscalation?: any;
|
|
12
12
|
uploadExpertClientFiles?: any;
|
|
13
13
|
createProjectEscalation?: any;
|
|
14
|
-
previousFiles?: string | string[];
|
|
14
|
+
previousFiles?: string | string[] | [];
|
|
15
15
|
isExpert: boolean;
|
|
16
16
|
extraData?: {
|
|
17
17
|
clientId: number;
|