@paro.io/expert-shared-components 1.13.8 → 1.13.10
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.d.ts +6 -2
- package/lib/components/Escalations/AccountSuspensionBanner.js +59 -5
- package/lib/components/Escalations/AccountSuspensionModal.js +1 -1
- package/lib/components/Escalations/EscalationReportBanner.d.ts +2 -1
- package/lib/components/Escalations/EscalationReportBanner.js +7 -2
- package/lib/components/Escalations/EscalationSubmitForm.js +6 -1
- package/lib/components/Escalations/EscalationTabsContent.js +18 -7
- package/lib/components/Escalations/Escalations.d.ts +2 -1
- package/lib/components/Escalations/Escalations.js +3 -3
- package/lib/components/Escalations/MarkResolvedModal.js +16 -1
- package/lib/components/ExpertProfileHeader/EarningsSection.d.ts +1 -0
- package/lib/components/ExpertProfileHeader/EarningsSection.js +6 -4
- package/lib/components/ExpertProfileHeader/ExpertProfileHeader.d.ts +3 -1
- package/lib/components/ExpertProfileHeader/ExpertProfileHeader.js +4 -4
- package/lib/components/ExpertProfileHeader/ExpertStatusCalculator.d.ts +1 -1
- package/lib/components/ExpertProfileHeader/ExpertStatusCalculator.js +14 -3
- package/lib/components/ExpertProfileHeader/NetworkSection.d.ts +3 -1
- package/lib/components/ExpertProfileHeader/NetworkSection.js +49 -3
- package/package.json +1 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
export declare const suspensionLevels: {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}[];
|
|
5
|
+
declare const AccountSuspensionBanner: ({ setShowSuspensionModal, escalationDisputeStatistics, }: {
|
|
2
6
|
setShowSuspensionModal: (showSuspensionModal: boolean) => void;
|
|
3
|
-
|
|
7
|
+
escalationDisputeStatistics: any;
|
|
4
8
|
}) => JSX.Element;
|
|
5
9
|
export default AccountSuspensionBanner;
|
|
@@ -3,17 +3,63 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.suspensionLevels = void 0;
|
|
6
7
|
const react_1 = __importDefault(require("react"));
|
|
7
8
|
const base_icons_1 = require("@paro.io/base-icons");
|
|
8
9
|
const base_ui_1 = require("@paro.io/base-ui");
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
11
|
+
exports.suspensionLevels = [
|
|
12
|
+
{ value: "LEVEL_1", label: "Low" },
|
|
13
|
+
{ value: "LEVEL_2", label: "Medium" },
|
|
14
|
+
{ value: "LEVEL_3", label: "High" },
|
|
15
|
+
{ value: "LEVEL_4", label: "Critical" },
|
|
16
|
+
];
|
|
17
|
+
const getSuspensionDuration = (label) => {
|
|
18
|
+
switch (label) {
|
|
19
|
+
case "Medium":
|
|
20
|
+
return "30 days";
|
|
21
|
+
case "High":
|
|
22
|
+
return "60 days";
|
|
23
|
+
case "Critical":
|
|
24
|
+
return "Permanent";
|
|
25
|
+
case "Low":
|
|
26
|
+
default:
|
|
27
|
+
return "No suspension";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const AccountSuspensionBanner = ({ setShowSuspensionModal, escalationDisputeStatistics, }) => {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
32
|
+
const suspensionLevel = (_b = (_a = exports.suspensionLevels.find((obj) => obj.value === escalationDisputeStatistics.suspensionLevel)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : "Low";
|
|
33
|
+
const suspensionStartDate = (_c = (0, dayjs_1.default)(escalationDisputeStatistics.suspensionStartDate).format("MM/DD/YYYY")) !== null && _c !== void 0 ? _c : "N/A";
|
|
34
|
+
const suspensionEndDate = (_d = (0, dayjs_1.default)(escalationDisputeStatistics.suspensionEndDate).format("MM/DD/YYYY")) !== null && _d !== void 0 ? _d : "N/A";
|
|
35
|
+
const mediumWarnings = (_e = escalationDisputeStatistics.mediumSeverityEscalationCount) !== null && _e !== void 0 ? _e : 0;
|
|
36
|
+
const highWarnings = (_f = escalationDisputeStatistics.highSeverityEscalationCount) !== null && _f !== void 0 ? _f : 0;
|
|
37
|
+
const criticalWarnings = (_g = escalationDisputeStatistics.criticalSeverityEscalationCount) !== null && _g !== void 0 ? _g : 0;
|
|
38
|
+
return (react_1.default.createElement("div", { className: "bg-[#EF5360] rounded-lg p-4 mb-6 shadow-lg" }, suspensionLevel !== "Low" ?
|
|
11
39
|
react_1.default.createElement("div", { className: "flex items-center" },
|
|
12
40
|
react_1.default.createElement("div", { className: "bg-white bg-opacity-20 rounded-full p-2 mr-3" },
|
|
13
41
|
react_1.default.createElement(base_icons_1.IconExclamation, { className: "h-6 w-6 text-white" })),
|
|
14
42
|
react_1.default.createElement("div", { className: "flex-1" },
|
|
15
|
-
react_1.default.createElement("h3", { className: "text-lg font-bold text-white" }, "\uD83D\uDEAB Account Suspended"),
|
|
16
|
-
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" },
|
|
43
|
+
react_1.default.createElement("h3", { className: "text-lg font-bold text-white" }, "\uD83D\uDEAB Account Suspended due to: Engagement Issues"),
|
|
44
|
+
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" },
|
|
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
|
+
' ',
|
|
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
|
+
"."),
|
|
49
|
+
react_1.default.createElement("div", { className: "mt-3 bg-white bg-opacity-10 rounded p-3" },
|
|
50
|
+
react_1.default.createElement("div", { className: "flex items-center justify-between text-sm" },
|
|
51
|
+
react_1.default.createElement("div", null,
|
|
52
|
+
react_1.default.createElement("span", { className: "text-red-100" }, "Suspension: "),
|
|
53
|
+
react_1.default.createElement("span", { className: "text-white font-medium" },
|
|
54
|
+
getSuspensionDuration(suspensionLevel),
|
|
55
|
+
' ',
|
|
56
|
+
suspensionLevel)),
|
|
57
|
+
react_1.default.createElement("div", null,
|
|
58
|
+
react_1.default.createElement("span", { className: "text-red-100" }, "Suspension Started Date: "),
|
|
59
|
+
react_1.default.createElement("span", { className: "text-white font-medium" }, suspensionStartDate)),
|
|
60
|
+
react_1.default.createElement("div", null,
|
|
61
|
+
react_1.default.createElement("span", { className: "text-red-100" }, "Suspension End Date: "),
|
|
62
|
+
react_1.default.createElement("span", { className: "text-white font-medium" }, suspensionEndDate))))))
|
|
17
63
|
:
|
|
18
64
|
react_1.default.createElement("div", { className: "flex items-center justify-between" },
|
|
19
65
|
react_1.default.createElement("div", { className: "flex items-center" },
|
|
@@ -21,7 +67,15 @@ const AccountSuspensionBanner = ({ setShowSuspensionModal, suspended = false })
|
|
|
21
67
|
react_1.default.createElement(base_icons_1.IconExclamation, { className: "h-6 w-6 text-white" })),
|
|
22
68
|
react_1.default.createElement("div", null,
|
|
23
69
|
react_1.default.createElement("h3", { className: "text-lg font-bold text-white" }, "Account Suspension Risk"),
|
|
24
|
-
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" }, "Unresolved escalations can lead to automatic suspension. Response times matter for client satisfaction.")
|
|
70
|
+
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" }, "Unresolved escalations can lead to automatic suspension. Response times matter for client satisfaction."),
|
|
71
|
+
react_1.default.createElement("div", { className: "flex items-center mt-2 text-red-100 text-xs" },
|
|
72
|
+
react_1.default.createElement("span", null,
|
|
73
|
+
mediumWarnings,
|
|
74
|
+
"/3 warnings: Medium = 30 days \u2022 ",
|
|
75
|
+
highWarnings,
|
|
76
|
+
"/2 warnings: High = 60 days \u2022 ",
|
|
77
|
+
criticalWarnings,
|
|
78
|
+
"/1 offense: Critical = Permanent")))),
|
|
25
79
|
react_1.default.createElement(base_ui_1.Button, { label: "view details", onClick: () => setShowSuspensionModal(true), iconLeft: react_1.default.createElement(base_icons_1.IconInfoCircle, { size: "sm" }), color: "danger", className: "bg-white hover:bg-danger text-danger-dark hover:text-white" }))));
|
|
26
80
|
};
|
|
27
81
|
exports.default = AccountSuspensionBanner;
|
|
@@ -29,7 +29,7 @@ const AccountSuspensionModal = ({ showSuspensionModal, onClose }) => {
|
|
|
29
29
|
react_1.default.createElement(base_icons_1.IconCheckCircle, { className: "h-5 w-5 text-white" })),
|
|
30
30
|
react_1.default.createElement("div", { className: "flex-1 pb-8" },
|
|
31
31
|
react_1.default.createElement("div", { className: "flex justify-between items-start mb-2" },
|
|
32
|
-
react_1.default.createElement("h4", { className: "font-semibold text-green-800" }, "Level 1:
|
|
32
|
+
react_1.default.createElement("h4", { className: "font-semibold text-green-800" }, "Level 1: Low Issues"),
|
|
33
33
|
react_1.default.createElement("div", { className: "text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full" }, "Coaching Only")),
|
|
34
34
|
react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-2" }, "Email coaching and guidance. No account restrictions."),
|
|
35
35
|
react_1.default.createElement("div", { className: "text-xs text-gray-500" },
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
const base_icons_1 = require("@paro.io/base-icons");
|
|
8
8
|
const base_ui_1 = require("@paro.io/base-ui");
|
|
9
|
-
const EscalationReportBanner = ({ onReport }) => {
|
|
9
|
+
const EscalationReportBanner = ({ onReport, isExpert }) => {
|
|
10
10
|
return (react_1.default.createElement("div", { className: "bg-[#EF5360] rounded-lg p-2 mb-4 shadow-lg" },
|
|
11
11
|
react_1.default.createElement("div", { className: "flex items-center justify-between" },
|
|
12
12
|
react_1.default.createElement("div", { className: "flex items-center" },
|
|
@@ -14,7 +14,12 @@ const EscalationReportBanner = ({ onReport }) => {
|
|
|
14
14
|
react_1.default.createElement(base_icons_1.IconExclamation, { className: "text-white" })),
|
|
15
15
|
react_1.default.createElement("div", null,
|
|
16
16
|
react_1.default.createElement("h3", { className: "text-xl font-bold text-white" }, "Having Issues with Your Expert?"),
|
|
17
|
-
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" },
|
|
17
|
+
react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" }, isExpert ? (`Report communication problems, quality concerns, or missed deadlines. We'll resolve it within 4-8 hours.`) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
18
|
+
"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",
|
|
19
|
+
' ',
|
|
20
|
+
react_1.default.createElement("a", { href: "mailto:clientsupport@paro.io", className: "underline text-white hover:text-red-200 cursor-pointer" }, "clientsupport@paro.io"),
|
|
21
|
+
' ',
|
|
22
|
+
"or your Account Executive."))))),
|
|
18
23
|
react_1.default.createElement(base_ui_1.Button, { label: "Report issue now", onClick: onReport, size: "sm", color: "danger", className: "bg-white hover:bg-danger text-danger-dark hover:text-white" }))));
|
|
19
24
|
};
|
|
20
25
|
exports.default = EscalationReportBanner;
|
|
@@ -220,7 +220,12 @@ const EscalationSubmitForm = ({ goBack, goHome, expertsOrClients, projects, docu
|
|
|
220
220
|
react_1.default.createElement("h2", { className: "text-xl font-bold" },
|
|
221
221
|
"Report Issue with Your ",
|
|
222
222
|
isExpert ? 'Client' : 'Expert'),
|
|
223
|
-
react_1.default.createElement("p", { className: "text-gray-600 mt-1" },
|
|
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`) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
224
|
+
"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
|
+
' ',
|
|
226
|
+
react_1.default.createElement("a", { href: "mailto:clientsupport@paro.io", className: "underline text-white hover:text-red-200 cursor-pointer" }, "clientsupport@paro.io"),
|
|
227
|
+
' ',
|
|
228
|
+
"or your Account Executive.")))),
|
|
224
229
|
react_1.default.createElement("div", null,
|
|
225
230
|
react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Priority Levels for Issues"),
|
|
226
231
|
react_1.default.createElement("div", { className: "space-y-2 text-sm" },
|
|
@@ -58,24 +58,35 @@ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssue
|
|
|
58
58
|
react_1.default.createElement("div", { className: "flex items-start" },
|
|
59
59
|
react_1.default.createElement("div", null,
|
|
60
60
|
react_1.default.createElement("div", { className: "flex flex-row justify-start items-center mb-3" },
|
|
61
|
-
react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-1 mr-4" },
|
|
61
|
+
react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-1 mr-4" }, project),
|
|
62
62
|
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: issue.severityLevel })),
|
|
63
63
|
react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
|
|
64
|
-
react_1.default.createElement("span", null,
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
react_1.default.createElement("span", null,
|
|
65
|
+
"Submitted By: ",
|
|
66
|
+
issue.submittedByUser.firstName + " " + issue.submittedByUser.lastName),
|
|
67
67
|
react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
|
|
68
68
|
react_1.default.createElement("span", null,
|
|
69
69
|
"Case #",
|
|
70
70
|
issue.escalationNumber)),
|
|
71
|
-
react_1.default.createElement("
|
|
71
|
+
react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-2" },
|
|
72
|
+
react_1.default.createElement("span", { className: "font-bold" }, "Problem:"),
|
|
73
|
+
" ",
|
|
74
|
+
issue.problem),
|
|
75
|
+
react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-2" },
|
|
76
|
+
react_1.default.createElement("span", { className: "font-bold" }, "Desired Outcome:"),
|
|
77
|
+
" ",
|
|
78
|
+
issue.outcome),
|
|
79
|
+
react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-2" },
|
|
80
|
+
react_1.default.createElement("span", { className: "font-bold" }, "Resolution:"),
|
|
81
|
+
" ",
|
|
82
|
+
issue.internalResolution ? issue.internalResolution : issue.clientResolution),
|
|
72
83
|
react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
|
|
73
84
|
react_1.default.createElement("span", { className: "text-xs text-gray-500" },
|
|
74
|
-
"Resolved ",
|
|
85
|
+
"Resolved: ",
|
|
75
86
|
(0, dayjs_1.default)(issue.updatedAt).format("MM-DD-YYYY")),
|
|
76
87
|
react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
|
|
77
88
|
react_1.default.createElement("span", { className: "text-xs text-gray-500" },
|
|
78
|
-
"Resolved By ",
|
|
89
|
+
"Resolved By: ",
|
|
79
90
|
issue.statusChangedByUser.firstName + " " + issue.statusChangedByUser.lastName,
|
|
80
91
|
" ",
|
|
81
92
|
issue.statusChangedByUser.userTypeId === 2 && '(Paro)')))),
|
|
@@ -12,6 +12,7 @@ interface EscalationsProps {
|
|
|
12
12
|
bucketName: string;
|
|
13
13
|
user: any;
|
|
14
14
|
clientId?: number;
|
|
15
|
+
escalationDisputeStatistics?: any;
|
|
15
16
|
}
|
|
16
|
-
export declare const Escalations: ({ expertsOrClients, projects, isExpert, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId, }: EscalationsProps) => JSX.Element;
|
|
17
|
+
export declare const Escalations: ({ expertsOrClients, projects, isExpert, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId, escalationDisputeStatistics, }: EscalationsProps) => JSX.Element;
|
|
17
18
|
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, }) => {
|
|
43
|
+
const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations, documentUploadUrl, downloadDocumentUrl, uploadExpertClientFiles, createProjectEscalation, updateProjectEscalation, createEscalationChatMessage, bucketName, user, clientId = 0, escalationDisputeStatistics, }) => {
|
|
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
|
|
@@ -156,9 +156,9 @@ const Escalations = ({ expertsOrClients, projects, isExpert = false, escalations
|
|
|
156
156
|
react_1.default.createElement("p", { className: "text-xs" }, "Report payment, scope, or communication activeIssues")))),
|
|
157
157
|
react_1.default.createElement(base_ui_1.Button, { label: "Report issue", onClick: () => setSelectedIssueId(0), iconLeft: react_1.default.createElement(base_icons_1.IconExclamation, { size: "sm", className: "text-white" }), color: "primary" }))),
|
|
158
158
|
isExpert &&
|
|
159
|
-
react_1.default.createElement(AccountSuspensionBanner_1.default, { setShowSuspensionModal: setShowSuspensionModal,
|
|
159
|
+
react_1.default.createElement(AccountSuspensionBanner_1.default, { setShowSuspensionModal: setShowSuspensionModal, escalationDisputeStatistics: escalationDisputeStatistics }),
|
|
160
160
|
!isExpert &&
|
|
161
|
-
react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0) }),
|
|
161
|
+
react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0), isExpert: isExpert }),
|
|
162
162
|
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
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 })),
|
|
164
164
|
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 })),
|
|
@@ -40,6 +40,7 @@ const utils_1 = require("../shared/utils");
|
|
|
40
40
|
const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProjectEscalation, userId, }) => {
|
|
41
41
|
const [resolutionText, setResolutionText] = (0, react_1.useState)(null);
|
|
42
42
|
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
43
|
+
const [expertResponsibility, setExpertResponsibility] = (0, react_1.useState)('');
|
|
43
44
|
const handleSubmit = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
45
|
setSubmitting(true);
|
|
45
46
|
try {
|
|
@@ -50,6 +51,7 @@ const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProj
|
|
|
50
51
|
clientResolution: resolutionText,
|
|
51
52
|
status: 'Resolved',
|
|
52
53
|
statusChangedBy: userId,
|
|
54
|
+
isExpertAtFault: expertResponsibility === 'atFault' ? true : false,
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
});
|
|
@@ -78,10 +80,23 @@ const MarkResolvedModal = ({ escalationId, expertName, open, onClose, updateProj
|
|
|
78
80
|
react_1.default.createElement("div", { className: "mt-6 mb-4" },
|
|
79
81
|
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."),
|
|
80
82
|
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
|
+
react_1.default.createElement("div", { style: { marginTop: '1em', marginBottom: '1em' } },
|
|
85
|
+
react_1.default.createElement("label", { className: "block text-sm font-normal mb-1" },
|
|
86
|
+
"Expert Responsibility ",
|
|
87
|
+
react_1.default.createElement("span", { className: "text-sm text-red-800" }, "*")),
|
|
88
|
+
react_1.default.createElement("div", null,
|
|
89
|
+
react_1.default.createElement("label", null,
|
|
90
|
+
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("div", null,
|
|
93
|
+
react_1.default.createElement("label", null,
|
|
94
|
+
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"))),
|
|
81
96
|
react_1.default.createElement("div", { className: "flex items-center justify-between" },
|
|
82
97
|
react_1.default.createElement("div", { className: "flex space-x-2" },
|
|
83
98
|
react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: onClose, disabled: submitting })),
|
|
84
99
|
react_1.default.createElement("div", { className: "flex space-x-2" },
|
|
85
|
-
react_1.default.createElement(base_ui_1.Button, { label: "Submit", color: "primary", onClick: handleSubmit, isLoading: submitting }))))));
|
|
100
|
+
react_1.default.createElement(base_ui_1.Button, { label: "Submit", color: "primary", onClick: handleSubmit, isLoading: submitting, disabled: expertResponsibility === '' }))))));
|
|
86
101
|
};
|
|
87
102
|
exports.default = MarkResolvedModal;
|
|
@@ -16,5 +16,6 @@ interface EarningsSectionProps {
|
|
|
16
16
|
hasCompletedProjects: boolean;
|
|
17
17
|
lifetimeFSV: any;
|
|
18
18
|
}
|
|
19
|
+
export declare const EarningsInfo: ({ label, value, textColor }: any) => JSX.Element;
|
|
19
20
|
declare const EarningsSection: ({ expertServiceLinesPlus, firmTags, haveATeamProp, expertLevels, currentMonthGoalHours, expertIRPRRatio, winRate, expertIRPRRatioPrev, winRatePrev, earnings, upsell, crossSell, lifetimeIRPR, lifetimeWinRate, hasCompletedProjects, lifetimeFSV }: EarningsSectionProps) => JSX.Element;
|
|
20
21
|
export default EarningsSection;
|
|
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.EarningsInfo = void 0;
|
|
17
18
|
const core_1 = require("@material-ui/core");
|
|
18
19
|
const styles_1 = require("@material-ui/core/styles");
|
|
19
20
|
const react_1 = __importDefault(require("react"));
|
|
@@ -64,6 +65,7 @@ const FirmTags = (_a) => {
|
|
|
64
65
|
const EarningsInfo = ({ label, value, textColor = 'black' }) => (react_1.default.createElement(core_1.Box, { mr: 2, display: "flex", justifyContent: "space-between", alignItems: "center" },
|
|
65
66
|
react_1.default.createElement(core_1.Typography, { variant: "body2" }, label),
|
|
66
67
|
react_1.default.createElement("b", { style: { color: textColor } }, value)));
|
|
68
|
+
exports.EarningsInfo = EarningsInfo;
|
|
67
69
|
const DataCell = ({ label, value }) => {
|
|
68
70
|
//@ts-ignore
|
|
69
71
|
const classes = useStyles();
|
|
@@ -129,16 +131,16 @@ const EarningsSection = ({ expertServiceLinesPlus, firmTags, haveATeamProp, expe
|
|
|
129
131
|
react_1.default.createElement(core_1.Box, { mb: 1 },
|
|
130
132
|
react_1.default.createElement("b", null, "Expert Earnings :")),
|
|
131
133
|
hasCompletedProjects ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
132
|
-
react_1.default.createElement(EarningsInfo, { label: "Monthly Goal", value: currentMonthGoalHours > 0 ? `$ ${ToLocalStringFn(currentMonthGoalHours)}` : 'N/A' }),
|
|
134
|
+
react_1.default.createElement(exports.EarningsInfo, { label: "Monthly Goal", value: currentMonthGoalHours > 0 ? `$ ${ToLocalStringFn(currentMonthGoalHours)}` : 'N/A' }),
|
|
133
135
|
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
134
136
|
react_1.default.createElement(core_1.Divider, null)),
|
|
135
|
-
react_1.default.createElement(EarningsInfo, { label: "Monthly Earnings", value: (earnings === null || earnings === void 0 ? void 0 : earnings.length) > 0 ? `$ ${ToLocalStringFn(earning)}` : 'N/A' }),
|
|
137
|
+
react_1.default.createElement(exports.EarningsInfo, { label: "Monthly Earnings", value: (earnings === null || earnings === void 0 ? void 0 : earnings.length) > 0 ? `$ ${ToLocalStringFn(earning)}` : 'N/A' }),
|
|
136
138
|
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
137
139
|
react_1.default.createElement(core_1.Divider, null)),
|
|
138
|
-
react_1.default.createElement(EarningsInfo, { label: "% to Goal", value: currentMonthGoalHours && earning ? `${ToLocalStringFn(((earning / currentMonthGoalHours) * 100).toFixed(2))} %` : 'N/A' }),
|
|
140
|
+
react_1.default.createElement(exports.EarningsInfo, { label: "% to Goal", value: currentMonthGoalHours && earning ? `${ToLocalStringFn(((earning / currentMonthGoalHours) * 100).toFixed(2))} %` : 'N/A' }),
|
|
139
141
|
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
140
142
|
react_1.default.createElement(core_1.Divider, null)),
|
|
141
|
-
react_1.default.createElement(EarningsInfo, { label: "Lifetime FSV", value: lifetimeFSV ? ToLocalStringFn(lifetimeFSV) : 'N/A', textColor: backgroundColor }),
|
|
143
|
+
react_1.default.createElement(exports.EarningsInfo, { label: "Lifetime FSV", value: lifetimeFSV ? ToLocalStringFn(lifetimeFSV) : 'N/A', textColor: backgroundColor }),
|
|
142
144
|
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
143
145
|
react_1.default.createElement(core_1.Divider, null)),
|
|
144
146
|
react_1.default.createElement(ExpertStatsTable, { expertIRPRRatioPrev: expertIRPRRatioPrev, expertIRPRRatio: expertIRPRRatio, winRatePrev: winRatePrev, winRate: winRate, lifetimeIRPR: lifetimeIRPR, lifetimeWinRate: lifetimeWinRate }))) : (react_1.default.createElement(core_1.Typography, { variant: "body1" }, "This Expert has not billed yet")))));
|
|
@@ -64,6 +64,8 @@ type QueryAndMutationProps = {
|
|
|
64
64
|
getExpertVanityTitles?: any;
|
|
65
65
|
getExpertRates?: any;
|
|
66
66
|
updateExpert?: any;
|
|
67
|
+
escalationDisputeStatistics?: any;
|
|
68
|
+
escalationDisputeStatisticsLoading?: any;
|
|
67
69
|
};
|
|
68
70
|
type ChangeEmailPasswordProps = {
|
|
69
71
|
getUserByEmail?: any;
|
|
@@ -79,5 +81,5 @@ type ProfileCompletedPercentageProps = {
|
|
|
79
81
|
handleScrollToBottom?: () => void;
|
|
80
82
|
clientReferencesSectionCompleted: boolean;
|
|
81
83
|
};
|
|
82
|
-
export declare const ExpertProfileHeader: ({ expertId, legacyFreelancerId, address: addressForReducer, companyName: companyNameForReducer, legacyMetadata: legacyMetadataForReducer, legacyMetadata: { primaryServiceLine, applicationStatus }, user: userForReducer, user: { id, imageUrl, email }, firmTags, detailsSectionCompleted, clientReferencesSectionCompleted, preferenceTasks, isWhiteLabel, handleScrollToBottom, haveATeamProp, expertFirms, paroAppUrl, isExpertOps, internalUserId, getExpertByLegacyFreelancerIdDocument, createExpertPublicProfileTrackingRecord, updateFreelancerServiceLine, serviceLineLoading, serviceLineData, serviceLineError, reviewData, profileReviewError, availabilityData, nextMonthAvailabilityData, expertStatusData, expertStatusLoading, expertLevelsData, projectsData, paroProjectsLoading, expertMetricsData, expertMetricsLoading, upSellCrossSellData, upSellCrossSellLoading, projectChangeLogData, projectChangeLogLoading, updateAddressMutation, addressUpdateLoading, updateUserMutation, userUpdateLoading, updateUserError, updateFreelancerMutation, updateFreelancerLoading, updateFreelancerError, getFreelancerEarnings, getQualityKPIs, expertLevelsTrainings, trainingsDataLoading, assignLetterTrainingToExpert, assignTrainingLoading, assignTrainingError, getUserDocument, getExpertStatusDocument, uploadUserPhotoMutation, loadingNewImage, imageUpdateError, getUserByEmail, updateUserEmail, getUserByEmailLazyQuery, updateUserPassword, verifyUserPassword, openServiceLinesTemplate, setOpenServiceLinesTemplate, getExpertVanityTitles, getExpertRates, updateExpert, vanityTitle, }: SectionContents & PersonalInformationType & ProfileCompletedPercentageProps & QueryAndMutationProps & ChangeEmailPasswordProps) => JSX.Element;
|
|
84
|
+
export declare const ExpertProfileHeader: ({ expertId, legacyFreelancerId, address: addressForReducer, companyName: companyNameForReducer, legacyMetadata: legacyMetadataForReducer, legacyMetadata: { primaryServiceLine, applicationStatus }, user: userForReducer, user: { id, imageUrl, email }, firmTags, detailsSectionCompleted, clientReferencesSectionCompleted, preferenceTasks, isWhiteLabel, handleScrollToBottom, haveATeamProp, expertFirms, paroAppUrl, isExpertOps, internalUserId, getExpertByLegacyFreelancerIdDocument, createExpertPublicProfileTrackingRecord, updateFreelancerServiceLine, serviceLineLoading, serviceLineData, serviceLineError, reviewData, profileReviewError, availabilityData, nextMonthAvailabilityData, expertStatusData, expertStatusLoading, expertLevelsData, projectsData, paroProjectsLoading, expertMetricsData, expertMetricsLoading, upSellCrossSellData, upSellCrossSellLoading, projectChangeLogData, projectChangeLogLoading, updateAddressMutation, addressUpdateLoading, updateUserMutation, userUpdateLoading, updateUserError, updateFreelancerMutation, updateFreelancerLoading, updateFreelancerError, getFreelancerEarnings, getQualityKPIs, expertLevelsTrainings, trainingsDataLoading, assignLetterTrainingToExpert, assignTrainingLoading, assignTrainingError, getUserDocument, getExpertStatusDocument, uploadUserPhotoMutation, loadingNewImage, imageUpdateError, getUserByEmail, updateUserEmail, getUserByEmailLazyQuery, updateUserPassword, verifyUserPassword, openServiceLinesTemplate, setOpenServiceLinesTemplate, getExpertVanityTitles, getExpertRates, updateExpert, vanityTitle, escalationDisputeStatistics, escalationDisputeStatisticsLoading, }: SectionContents & PersonalInformationType & ProfileCompletedPercentageProps & QueryAndMutationProps & ChangeEmailPasswordProps) => JSX.Element;
|
|
83
85
|
export {};
|
|
@@ -76,7 +76,7 @@ const convertRegionToStateAbbreviation = (region) => {
|
|
|
76
76
|
const personalInformationReducer = (state, updatedState) => {
|
|
77
77
|
return Object.assign(Object.assign({}, state), updatedState);
|
|
78
78
|
};
|
|
79
|
-
const ExpertProfileHeader = ({ expertId, legacyFreelancerId, address: addressForReducer, companyName: companyNameForReducer, legacyMetadata: legacyMetadataForReducer, legacyMetadata: { primaryServiceLine, applicationStatus }, user: userForReducer, user: { id, imageUrl, email }, firmTags, detailsSectionCompleted, clientReferencesSectionCompleted, preferenceTasks, isWhiteLabel, handleScrollToBottom, haveATeamProp, expertFirms, paroAppUrl, isExpertOps, internalUserId, getExpertByLegacyFreelancerIdDocument, createExpertPublicProfileTrackingRecord, updateFreelancerServiceLine, serviceLineLoading, serviceLineData, serviceLineError, reviewData, profileReviewError, availabilityData, nextMonthAvailabilityData, expertStatusData, expertStatusLoading, expertLevelsData, projectsData, paroProjectsLoading, expertMetricsData, expertMetricsLoading, upSellCrossSellData, upSellCrossSellLoading, projectChangeLogData, projectChangeLogLoading, updateAddressMutation, addressUpdateLoading, updateUserMutation, userUpdateLoading, updateUserError, updateFreelancerMutation, updateFreelancerLoading, updateFreelancerError, getFreelancerEarnings, getQualityKPIs, expertLevelsTrainings, trainingsDataLoading, assignLetterTrainingToExpert, assignTrainingLoading, assignTrainingError, getUserDocument, getExpertStatusDocument, uploadUserPhotoMutation, loadingNewImage, imageUpdateError, getUserByEmail, updateUserEmail, getUserByEmailLazyQuery, updateUserPassword, verifyUserPassword, openServiceLinesTemplate, setOpenServiceLinesTemplate, getExpertVanityTitles, getExpertRates, updateExpert, vanityTitle, }) => {
|
|
79
|
+
const ExpertProfileHeader = ({ expertId, legacyFreelancerId, address: addressForReducer, companyName: companyNameForReducer, legacyMetadata: legacyMetadataForReducer, legacyMetadata: { primaryServiceLine, applicationStatus }, user: userForReducer, user: { id, imageUrl, email }, firmTags, detailsSectionCompleted, clientReferencesSectionCompleted, preferenceTasks, isWhiteLabel, handleScrollToBottom, haveATeamProp, expertFirms, paroAppUrl, isExpertOps, internalUserId, getExpertByLegacyFreelancerIdDocument, createExpertPublicProfileTrackingRecord, updateFreelancerServiceLine, serviceLineLoading, serviceLineData, serviceLineError, reviewData, profileReviewError, availabilityData, nextMonthAvailabilityData, expertStatusData, expertStatusLoading, expertLevelsData, projectsData, paroProjectsLoading, expertMetricsData, expertMetricsLoading, upSellCrossSellData, upSellCrossSellLoading, projectChangeLogData, projectChangeLogLoading, updateAddressMutation, addressUpdateLoading, updateUserMutation, userUpdateLoading, updateUserError, updateFreelancerMutation, updateFreelancerLoading, updateFreelancerError, getFreelancerEarnings, getQualityKPIs, expertLevelsTrainings, trainingsDataLoading, assignLetterTrainingToExpert, assignTrainingLoading, assignTrainingError, getUserDocument, getExpertStatusDocument, uploadUserPhotoMutation, loadingNewImage, imageUpdateError, getUserByEmail, updateUserEmail, getUserByEmailLazyQuery, updateUserPassword, verifyUserPassword, openServiceLinesTemplate, setOpenServiceLinesTemplate, getExpertVanityTitles, getExpertRates, updateExpert, vanityTitle, escalationDisputeStatistics, escalationDisputeStatisticsLoading, }) => {
|
|
80
80
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
81
81
|
const [leftSideStatus, setLeftSideStatus] = react_1.default.useState("");
|
|
82
82
|
const [rightSideStatus, setRightSideStatus] = react_1.default.useState("");
|
|
@@ -142,7 +142,7 @@ const ExpertProfileHeader = ({ expertId, legacyFreelancerId, address: addressFor
|
|
|
142
142
|
const expertServiceLinesPlus = (serviceLineData === null || serviceLineData === void 0 ? void 0 : serviceLineData.getExpertByLegacyFreelancerId.serviceLinesPlus) || [];
|
|
143
143
|
const expertLevels = expertLevelsData === null || expertLevelsData === void 0 ? void 0 : expertLevelsData.getExpertLevelsData;
|
|
144
144
|
if ((expertStatuses && expertMetricsData && leftSideStatus === "" && rightSideStatus === "") || triggerNewStatus) {
|
|
145
|
-
(0, ExpertStatusCalculator_1.default)(expertStatuses, setLeftSideStatus, setRightSideStatus, setInfoColor, expertMetricsData, earnings, applicationStatus, setTriggerNewStatus);
|
|
145
|
+
(0, ExpertStatusCalculator_1.default)(expertStatuses, setLeftSideStatus, setRightSideStatus, setInfoColor, expertMetricsData, earnings, applicationStatus, setTriggerNewStatus, escalationDisputeStatistics);
|
|
146
146
|
}
|
|
147
147
|
const [open, setOpen] = react_1.default.useState(false);
|
|
148
148
|
const [reducedPersonalInformation, dispatchUpdatedPersonalInformationUpdate] = react_1.default.useReducer(personalInformationReducer, {
|
|
@@ -165,7 +165,7 @@ const ExpertProfileHeader = ({ expertId, legacyFreelancerId, address: addressFor
|
|
|
165
165
|
return react_1.default.createElement(ParoError_1.ParoError, null);
|
|
166
166
|
}
|
|
167
167
|
const publicProfileLink = `${paroAppUrl}/public/${id}`;
|
|
168
|
-
if (expertStatusLoading || expertMetricsLoading || serviceLineLoading || paroProjectsLoading || projectChangeLogLoading || upSellCrossSellLoading) {
|
|
168
|
+
if (expertStatusLoading || expertMetricsLoading || serviceLineLoading || paroProjectsLoading || projectChangeLogLoading || upSellCrossSellLoading || escalationDisputeStatisticsLoading) {
|
|
169
169
|
return react_1.default.createElement(Loader_1.default, { size: '30px', text: 'Loading Expert Stats...' });
|
|
170
170
|
}
|
|
171
171
|
const ServiceLines = [
|
|
@@ -219,7 +219,7 @@ const ExpertProfileHeader = ({ expertId, legacyFreelancerId, address: addressFor
|
|
|
219
219
|
react_1.default.createElement(ProfileSection_1.default, { legacyFreelancerId: Number(legacyFreelancerId), imageUrl: imageUrl, shouldAllowEditProfile: isExpertOps !== null && isExpertOps !== void 0 ? isExpertOps : false, firstName: firstName, lastName: lastName, primaryServiceLine: primaryServiceLine, editServiceLine: editServiceLine, city: city, stateAbbreviation: stateAbbreviation, email: email, phone: phone, setOpen: setOpen, paroTenure: paroTenure, hourlyRate: defaultHourlyRate, paroProjectsData: paroProjectsData, getUserDocument: getUserDocument, uploadUserPhotoMutation: uploadUserPhotoMutation, loadingNewImage: loadingNewImage, imageUpdateError: imageUpdateError, isInternal: isInternal, getUserByEmail: getUserByEmail, updateUserEmail: updateUserEmail, updateUserMutation: updateUserMutation, getUserByEmailLazyQuery: getUserByEmailLazyQuery, updateUserPassword: updateUserPassword, verifyUserPassword: verifyUserPassword, getExpertRates: getExpertRates }),
|
|
220
220
|
react_1.default.createElement(core_1.Divider, { orientation: isSmallScreen ? 'horizontal' : 'vertical', style: { marginLeft: '0px !important' } })),
|
|
221
221
|
react_1.default.createElement(core_1.Grid, { item: true, container: true, direction: 'column', justify: 'space-between', xs: 12, md: true, style: { flex: '1', width: 'auto' } },
|
|
222
|
-
react_1.default.createElement(NetworkSection_1.default, { handleScrollToBottom: isInternal && handleScrollToBottom ? handleScrollToBottom : () => { }, preferenceTasks: preferenceTasks, isWhiteLabel: isWhiteLabel, detailsSectionCompleted: detailsSectionCompleted, clientReferencesSectionCompleted: clientReferencesSectionCompleted, infoColor: infoColor, leftSideStatus: leftSideStatus, rightSideStatus: rightSideStatus, isInternal: isInternal, paroTenure: paroTenure, getExpertVanityTitles: getExpertVanityTitles, updateExpert: updateExpert, expertId: expertId, legacyFreelancerId: Number(legacyFreelancerId), vanityTitle: vanityTitle, getExpertByLegacyFreelancerIdDocument: getExpertByLegacyFreelancerIdDocument }),
|
|
222
|
+
react_1.default.createElement(NetworkSection_1.default, { handleScrollToBottom: isInternal && handleScrollToBottom ? handleScrollToBottom : () => { }, preferenceTasks: preferenceTasks, isWhiteLabel: isWhiteLabel, detailsSectionCompleted: detailsSectionCompleted, clientReferencesSectionCompleted: clientReferencesSectionCompleted, infoColor: infoColor, leftSideStatus: leftSideStatus, rightSideStatus: rightSideStatus, isInternal: isInternal, paroTenure: paroTenure, getExpertVanityTitles: getExpertVanityTitles, updateExpert: updateExpert, expertId: expertId, legacyFreelancerId: Number(legacyFreelancerId), vanityTitle: vanityTitle, getExpertByLegacyFreelancerIdDocument: getExpertByLegacyFreelancerIdDocument, escalationDisputeStatistics: escalationDisputeStatistics, paroAppUrl: paroAppUrl }),
|
|
223
223
|
react_1.default.createElement(core_1.Divider, { orientation: isSmallScreen ? 'horizontal' : 'vertical' })),
|
|
224
224
|
react_1.default.createElement(core_1.Grid, { item: true, container: true, direction: 'column', justify: 'space-between', xs: 12, md: true, style: { flex: '1', width: 'auto' } },
|
|
225
225
|
react_1.default.createElement(EarningsSection_1.default, { expertServiceLinesPlus: expertServiceLinesPlus, firmTags: firmTags, haveATeamProp: haveATeamProp, expertLevels: expertLevels, currentMonthGoalHours: currentMonthGoalHours, expertIRPRRatio: expertIRPRRatio, winRate: winRate, expertIRPRRatioPrev: expertIRPRRatioPrev, winRatePrev: winRatePrev, earnings: earnings, upsell: upsell, crossSell: crossSell, lifetimeIRPR: lifetimeIRPR, lifetimeWinRate: lifetimeWinRate, hasCompletedProjects: (_k = expertMetricsData === null || expertMetricsData === void 0 ? void 0 : expertMetricsData.getExpertMetrics) === null || _k === void 0 ? void 0 : _k.lastProjectCompleted, lifetimeFSV: lifetimeFSV }),
|
|
@@ -20,5 +20,5 @@ export type ExpertStatusData = {
|
|
|
20
20
|
hasValidInsurance: boolean;
|
|
21
21
|
insuranceExpiryDate: Date;
|
|
22
22
|
};
|
|
23
|
-
declare const ExpertStatusCalculator: (statusData: ExpertStatusData, setLeftSideStatus: (leftSideStatus: string) => void, setRightSideStatus: (rightSideStatus: string) => void, setInfoColor: ({ leftSideStatus, rightSideStatus, Matching, FaF, JobBoard, Available }: any) => void, expertMetricsData: any, earningsData: any, applicationStatus: any, setTriggerNewStatus: any) => void;
|
|
23
|
+
declare const ExpertStatusCalculator: (statusData: ExpertStatusData, setLeftSideStatus: (leftSideStatus: string) => void, setRightSideStatus: (rightSideStatus: string) => void, setInfoColor: ({ leftSideStatus, rightSideStatus, Matching, FaF, JobBoard, Available }: any) => void, expertMetricsData: any, earningsData: any, applicationStatus: any, setTriggerNewStatus: any, escalationDisputeStatistics: any) => void;
|
|
24
24
|
export default ExpertStatusCalculator;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../shared/utils");
|
|
4
|
+
const AccountSuspensionBanner_1 = require("../Escalations/AccountSuspensionBanner");
|
|
4
5
|
const isDespiseExpert = (earningsToShow, lastPitchDate, lastLoginDate, applicationStatus) => {
|
|
5
6
|
// Expert is in Despise Status IF:
|
|
6
7
|
// Active Expert who has no logins, no pitches, no earnings in the last 30 days
|
|
@@ -11,18 +12,28 @@ const isDespiseExpert = (earningsToShow, lastPitchDate, lastLoginDate, applicati
|
|
|
11
12
|
const earnedInLast2Months = earningsToShow.filter((earning) => earning.earnings_type === 'actual' && (earning.month === formattedPreviousMonthDate || earning.month === formattedCurrentMonthDate));
|
|
12
13
|
return (0, utils_1.isOlderThan30Days)(lastPitchDate) && (0, utils_1.isOlderThan30Days)(lastLoginDate) && earnedInLast2Months.length === 0 && applicationStatus === 'ACTIVE';
|
|
13
14
|
};
|
|
14
|
-
const ExpertStatusCalculator = (statusData, setLeftSideStatus, setRightSideStatus, setInfoColor, expertMetricsData, earningsData, applicationStatus, setTriggerNewStatus) => {
|
|
15
|
+
const ExpertStatusCalculator = (statusData, setLeftSideStatus, setRightSideStatus, setInfoColor, expertMetricsData, earningsData, applicationStatus, setTriggerNewStatus, escalationDisputeStatistics) => {
|
|
16
|
+
var _a, _b;
|
|
15
17
|
const suspensionStatus = (statusData.suspensionEndDate && statusData.suspensionEndDate !== "")
|
|
16
18
|
? `! Suspended till ${statusData.suspensionEndDate}, see notes.`
|
|
17
19
|
: '! Suspended, see notes.';
|
|
20
|
+
const suspensionLevel = (_b = (_a = AccountSuspensionBanner_1.suspensionLevels.find((obj) => obj.value === escalationDisputeStatistics.suspensionLevel)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : "Low";
|
|
21
|
+
const startDate = escalationDisputeStatistics.suspensionStartDate ? new Date(escalationDisputeStatistics.suspensionStartDate).toLocaleDateString() : '';
|
|
22
|
+
const endDate = escalationDisputeStatistics.suspensionEndDate ? new Date(escalationDisputeStatistics.suspensionEndDate).toLocaleDateString() : '';
|
|
18
23
|
if (statusData.churnedPermanently) {
|
|
19
24
|
const formattedDate = new Date(statusData.churnedDate).toLocaleDateString();
|
|
20
25
|
setLeftSideStatus('This Expert has been churned from the Network and cannot take on new projects.');
|
|
21
26
|
setRightSideStatus(`! Churned ${formattedDate} - Not eligible for rehire. See notes.`);
|
|
22
27
|
}
|
|
23
28
|
else if (statusData.suspended) {
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
if (suspensionLevel !== "Low" && startDate && endDate) { // suspension due to escalations
|
|
30
|
+
setLeftSideStatus(`The Expert is on ${suspensionLevel} severity level for Escalations.`);
|
|
31
|
+
setRightSideStatus(`This Expert has been suspended due to severity strikes on escalations and was suspended on ${startDate} and will come off suspension on ${endDate} due.`);
|
|
32
|
+
}
|
|
33
|
+
else { // suspension due to other reasons
|
|
34
|
+
setLeftSideStatus('This Expert is currently suspended and is unable to take on new projects.');
|
|
35
|
+
setRightSideStatus(`${suspensionStatus}`);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
38
|
else if (statusData.churned) {
|
|
28
39
|
const formattedDate = new Date(statusData.churnedDate).toLocaleDateString();
|
|
@@ -15,6 +15,8 @@ interface NetworkSectionProps {
|
|
|
15
15
|
expertId: string;
|
|
16
16
|
vanityTitle: string;
|
|
17
17
|
getExpertByLegacyFreelancerIdDocument: any;
|
|
18
|
+
escalationDisputeStatistics: any;
|
|
19
|
+
paroAppUrl: string;
|
|
18
20
|
}
|
|
19
|
-
declare const NetworkSection: ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, detailsSectionCompleted, clientReferencesSectionCompleted, infoColor, leftSideStatus, rightSideStatus, isInternal, paroTenure, getExpertVanityTitles, updateExpert, expertId, legacyFreelancerId, vanityTitle, getExpertByLegacyFreelancerIdDocument, }: NetworkSectionProps) => JSX.Element;
|
|
21
|
+
declare const NetworkSection: ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, detailsSectionCompleted, clientReferencesSectionCompleted, infoColor, leftSideStatus, rightSideStatus, isInternal, paroTenure, getExpertVanityTitles, updateExpert, expertId, legacyFreelancerId, vanityTitle, getExpertByLegacyFreelancerIdDocument, escalationDisputeStatistics, paroAppUrl, }: NetworkSectionProps) => JSX.Element;
|
|
20
22
|
export default NetworkSection;
|
|
@@ -39,6 +39,10 @@ const ProfileCompletedPercentange_1 = require("../ProfileCompletedPercentange");
|
|
|
39
39
|
const icons_1 = require("@material-ui/icons");
|
|
40
40
|
const ReviewsTab_1 = require("../ReviewsTab/ReviewsTab");
|
|
41
41
|
const base_ui_1 = require("@paro.io/base-ui");
|
|
42
|
+
const EarningsSection_1 = require("./EarningsSection");
|
|
43
|
+
const base_icons_1 = require("@paro.io/base-icons");
|
|
44
|
+
const EscalationIssueCard_1 = require("../Escalations/EscalationIssueCard");
|
|
45
|
+
const AccountSuspensionBanner_1 = require("../Escalations/AccountSuspensionBanner");
|
|
42
46
|
const useStyles = (0, styles_1.makeStyles)((theme) => ({
|
|
43
47
|
textSuccess: {
|
|
44
48
|
color: '#12756F',
|
|
@@ -75,11 +79,32 @@ const ExpertiseTitleModal = ({ openModal, updateTitle, titleOptions, selectedTit
|
|
|
75
79
|
react_1.default.createElement(base_ui_1.Button, { label: "UPDATE PROFILE", onClick: handleUpdateExpertTitle, type: "button", isLoading: updateTitle, disabled: selectedTitle === null || (selectedTitle === 'Other' && (customTitle === null || customTitle === '')), color: "primary" }),
|
|
76
80
|
react_1.default.createElement(base_ui_1.Button, { label: "CANCEL", onClick: handleOnClose, type: "button", disabled: updateTitle, isLoading: updateTitle })))));
|
|
77
81
|
};
|
|
78
|
-
const
|
|
82
|
+
const PriorityLevelModal = ({ openModal, onClose }) => {
|
|
83
|
+
return (react_1.default.createElement(base_ui_1.Modal, { open: openModal, size: "sm", onClose: onClose },
|
|
84
|
+
react_1.default.createElement("div", { className: "border border-1 border-gray-300 p-4 rounded-md gap-y-2" },
|
|
85
|
+
react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Severity Levels for Issues"),
|
|
86
|
+
react_1.default.createElement("div", { className: "space-y-2 text-sm" },
|
|
87
|
+
react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
|
|
88
|
+
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Critical" }),
|
|
89
|
+
react_1.default.createElement("span", null, "All deliverables are currently blocked; the project cannot move forward.")),
|
|
90
|
+
react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
|
|
91
|
+
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "High" }),
|
|
92
|
+
react_1.default.createElement("span", null, "Key deliverables are blocked, preventing meaningful progress.")),
|
|
93
|
+
react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
|
|
94
|
+
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Medium" }),
|
|
95
|
+
react_1.default.createElement("span", null, "Deliverables are still in progress, but timelines are at risk.")),
|
|
96
|
+
react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
|
|
97
|
+
react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Low" }),
|
|
98
|
+
react_1.default.createElement("span", null, "Minor issue or inconvenience that does not affect overall project flow."))))));
|
|
99
|
+
};
|
|
100
|
+
const NetworkSection = ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, detailsSectionCompleted, clientReferencesSectionCompleted, infoColor, leftSideStatus, rightSideStatus, isInternal, paroTenure, getExpertVanityTitles, updateExpert, expertId, legacyFreelancerId, vanityTitle, getExpertByLegacyFreelancerIdDocument, escalationDisputeStatistics, paroAppUrl, }) => {
|
|
101
|
+
var _a, _b, _c, _d, _e, _f;
|
|
79
102
|
const [openModal, setOpenModal] = (0, react_1.useState)(false);
|
|
80
103
|
const [selectedTitle, setSelectedTitle] = (0, react_1.useState)(vanityTitle);
|
|
81
104
|
const [customTitle, setCustomTitle] = (0, react_1.useState)(null);
|
|
82
105
|
const [updateTitle, setUpdateTitle] = (0, react_1.useState)(false);
|
|
106
|
+
const [showPriorityLevelModal, setShowPriorityLevelModal] = (0, react_1.useState)(false);
|
|
107
|
+
const suspensionLevel = (_b = (_a = AccountSuspensionBanner_1.suspensionLevels.find((obj) => obj.value === escalationDisputeStatistics.suspensionLevel)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : "Low";
|
|
83
108
|
const handleUpdateExpertTitle = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
84
109
|
setUpdateTitle(true);
|
|
85
110
|
updateExpert({
|
|
@@ -129,6 +154,21 @@ const NetworkSection = ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, d
|
|
|
129
154
|
react_1.default.createElement(icons_1.Cached, null))),
|
|
130
155
|
react_1.default.createElement(core_1.Box, { mt: 1, mb: 1, mr: 2 },
|
|
131
156
|
react_1.default.createElement(core_1.Divider, null))),
|
|
157
|
+
escalationDisputeStatistics &&
|
|
158
|
+
react_1.default.createElement(react_1.default.Fragment, null,
|
|
159
|
+
react_1.default.createElement(EarningsSection_1.EarningsInfo, { label: "# of Escalations in last 3 months", value: (_c = escalationDisputeStatistics.recentResolvedEscalations) !== null && _c !== void 0 ? _c : 0 }),
|
|
160
|
+
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
161
|
+
react_1.default.createElement(core_1.Divider, null)),
|
|
162
|
+
react_1.default.createElement(EarningsSection_1.EarningsInfo, { label: "Total # of Escalations", value: (_d = escalationDisputeStatistics.totalResolvedEscalations) !== null && _d !== void 0 ? _d : 0 }),
|
|
163
|
+
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
164
|
+
react_1.default.createElement(core_1.Divider, null)),
|
|
165
|
+
react_1.default.createElement(EarningsSection_1.EarningsInfo, { label: "# of Disputes in last 3 months", value: (_e = escalationDisputeStatistics.recentResolvedDisputes) !== null && _e !== void 0 ? _e : 0 }),
|
|
166
|
+
react_1.default.createElement(core_1.Box, { mb: 2 },
|
|
167
|
+
react_1.default.createElement(core_1.Divider, null)),
|
|
168
|
+
react_1.default.createElement(EarningsSection_1.EarningsInfo, { label: "Total # of Disputes", value: (_f = escalationDisputeStatistics.totalResolvedDisputes) !== null && _f !== void 0 ? _f : 0 }),
|
|
169
|
+
react_1.default.createElement(core_1.Box, { mb: 0.5 },
|
|
170
|
+
react_1.default.createElement(core_1.Divider, null)),
|
|
171
|
+
!isInternal && react_1.default.createElement("a", { href: `${paroAppUrl}/engagement-support`, className: "text-xs underline text-[#1878BD] cursor-pointer block text-right mb-2", target: "_blank", rel: "noopener noreferrer" }, "See more Disputes & Escalations")),
|
|
132
172
|
react_1.default.createElement(core_1.Grid, { style: { marginRight: '8px', marginLeft: '2px' } },
|
|
133
173
|
react_1.default.createElement(core_1.Box, { mb: 1 },
|
|
134
174
|
react_1.default.createElement("b", null, "Network Availability :")),
|
|
@@ -148,9 +188,15 @@ const NetworkSection = ({ handleScrollToBottom, preferenceTasks, isWhiteLabel, d
|
|
|
148
188
|
react_1.default.createElement(core_1.Box, null,
|
|
149
189
|
react_1.default.createElement("b", null, "Reason: "),
|
|
150
190
|
react_1.default.createElement("ul", null,
|
|
151
|
-
react_1.default.createElement("li", null,
|
|
191
|
+
react_1.default.createElement("li", null,
|
|
192
|
+
leftSideStatus,
|
|
193
|
+
" ",
|
|
194
|
+
suspensionLevel !== "Low" && react_1.default.createElement(core_1.IconButton, { "aria-label": "Show priority levels", onClick: () => { setShowPriorityLevelModal(true); } },
|
|
195
|
+
react_1.default.createElement(base_icons_1.IconInfoCircle, { size: "sm", className: "block text-right" }))),
|
|
152
196
|
react_1.default.createElement("li", null, rightSideStatus)))),
|
|
153
197
|
openModal &&
|
|
154
|
-
react_1.default.createElement(ExpertiseTitleModal, { openModal: openModal, updateTitle: updateTitle, titleOptions: [...getExpertVanityTitles], selectedTitle: selectedTitle, customTitle: customTitle, setCustomTitle: setCustomTitle, handleChangeTitle: (event) => { setSelectedTitle(event.target.value); }, handleOnClose: () => setOpenModal(false), handleUpdateExpertTitle: handleUpdateExpertTitle })
|
|
198
|
+
react_1.default.createElement(ExpertiseTitleModal, { openModal: openModal, updateTitle: updateTitle, titleOptions: [...getExpertVanityTitles], selectedTitle: selectedTitle, customTitle: customTitle, setCustomTitle: setCustomTitle, handleChangeTitle: (event) => { setSelectedTitle(event.target.value); }, handleOnClose: () => setOpenModal(false), handleUpdateExpertTitle: handleUpdateExpertTitle }),
|
|
199
|
+
showPriorityLevelModal &&
|
|
200
|
+
react_1.default.createElement(PriorityLevelModal, { openModal: showPriorityLevelModal, onClose: () => setShowPriorityLevelModal(false) })));
|
|
155
201
|
};
|
|
156
202
|
exports.default = NetworkSection;
|