@paro.io/expert-shared-components 1.12.36 → 1.12.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +2 -2
  3. package/lib/components/ClientReferencesSection/DeleteButton.js +11 -11
  4. package/lib/components/ClientReferencesSection/ParoError.js +10 -10
  5. package/lib/components/ClientReferencesSection/TagsSection.js +2 -2
  6. package/lib/components/ClientReferencesSection/styles/BrandedTypography.js +2 -2
  7. package/lib/components/ClientReferencesSection/styles/Buttons.js +15 -15
  8. package/lib/components/ClientReferencesSection/styles/Name.js +5 -5
  9. package/lib/components/ClientReferencesSection/styles/NullContentConditionalColor.js +4 -4
  10. package/lib/components/ClientReferencesSection/styles/SectionBody.js +11 -11
  11. package/lib/components/ClientReferencesSection/styles/SectionTitle.js +6 -6
  12. package/lib/components/ClientReferencesSection/styles/Tags.js +2 -2
  13. package/lib/components/DiscussionThread/chat.d.ts +22 -22
  14. package/lib/components/DiscussionThread/chat.js +106 -106
  15. package/lib/components/DocumentCenter/DocumentTable.d.ts +15 -15
  16. package/lib/components/DocumentCenter/DocumentTable.js +350 -350
  17. package/lib/components/DocumentCenter/UploadFilesButton.d.ts +6 -6
  18. package/lib/components/DocumentCenter/UploadFilesButton.js +29 -29
  19. package/lib/components/EarningsTracker/ActiveProjectCard.d.ts +52 -52
  20. package/lib/components/EarningsTracker/ActiveProjectCard.js +161 -161
  21. package/lib/components/EarningsTracker/CenterCardUI.d.ts +13 -13
  22. package/lib/components/EarningsTracker/CenterCardUI.js +134 -134
  23. package/lib/components/EarningsTracker/EarningsTracker.d.ts +52 -52
  24. package/lib/components/EarningsTracker/EarningsTracker.js +508 -508
  25. package/lib/components/EarningsTracker/EditDateModal.d.ts +22 -22
  26. package/lib/components/EarningsTracker/EditDateModal.js +149 -149
  27. package/lib/components/EarningsTracker/EmailModal.d.ts +14 -14
  28. package/lib/components/EarningsTracker/EmailModal.js +79 -79
  29. package/lib/components/EarningsTracker/EndProjectModal.d.ts +56 -56
  30. package/lib/components/EarningsTracker/EndProjectModal.js +221 -221
  31. package/lib/components/EarningsTracker/LeftCardUI.d.ts +18 -18
  32. package/lib/components/EarningsTracker/LeftCardUI.js +189 -189
  33. package/lib/components/EarningsTracker/LogTimeModalAuthenticated.d.ts +52 -52
  34. package/lib/components/EarningsTracker/LogTimeModalAuthenticated.js +358 -358
  35. package/lib/components/EarningsTracker/ProgressBar.d.ts +4 -4
  36. package/lib/components/EarningsTracker/ProgressBar.js +66 -66
  37. package/lib/components/EarningsTracker/ReviewRequestModal.d.ts +17 -17
  38. package/lib/components/EarningsTracker/ReviewRequestModal.js +135 -135
  39. package/lib/components/EarningsTracker/RightCardUI.d.ts +46 -46
  40. package/lib/components/EarningsTracker/RightCardUI.js +231 -231
  41. package/lib/components/EarningsTracker/index.d.ts +1 -1
  42. package/lib/components/EarningsTracker/index.js +5 -5
  43. package/lib/components/Escalations/AccountSuspensionBanner.d.ts +5 -0
  44. package/lib/components/Escalations/AccountSuspensionBanner.js +37 -0
  45. package/lib/components/Escalations/AccountSuspensionModal.d.ts +5 -0
  46. package/lib/components/Escalations/AccountSuspensionModal.js +112 -0
  47. package/lib/components/Escalations/CustomTag.d.ts +3 -0
  48. package/lib/components/Escalations/CustomTag.js +25 -0
  49. package/lib/components/Escalations/EscalationChat.d.ts +6 -0
  50. package/lib/components/Escalations/EscalationChat.js +90 -0
  51. package/lib/components/Escalations/EscalationIssueCard.d.ts +15 -0
  52. package/lib/components/Escalations/EscalationIssueCard.js +72 -0
  53. package/lib/components/Escalations/EscalationReportBanner.d.ts +4 -0
  54. package/lib/components/Escalations/EscalationReportBanner.js +20 -0
  55. package/lib/components/Escalations/EscalationRespondForm.d.ts +6 -0
  56. package/lib/components/Escalations/EscalationRespondForm.js +111 -0
  57. package/lib/components/Escalations/EscalationSubmitForm.d.ts +9 -0
  58. package/lib/components/Escalations/EscalationSubmitForm.js +217 -0
  59. package/lib/components/Escalations/EscalationTabs.d.ts +9 -0
  60. package/lib/components/Escalations/EscalationTabs.js +30 -0
  61. package/lib/components/Escalations/EscalationTabsContent.d.ts +17 -0
  62. package/lib/components/Escalations/EscalationTabsContent.js +92 -0
  63. package/lib/components/Escalations/Escalations.d.ts +10 -0
  64. package/lib/components/Escalations/Escalations.js +146 -0
  65. package/lib/components/Escalations/index.d.ts +1 -0
  66. package/lib/components/Escalations/index.js +5 -0
  67. package/lib/components/ExpertProfileHeader/ActionButtonSection.js +6 -6
  68. package/lib/components/ExpertProfileHeader/ProfileSection.js +7 -7
  69. package/lib/components/Invoices/TestDecisionSection.d.ts +1 -1
  70. package/lib/components/Invoices/TestDecisionSection.js +126 -126
  71. package/lib/components/OrganizationChart/OrganizationChart.d.ts +15 -15
  72. package/lib/components/OrganizationChart/OrganizationChart.js +312 -312
  73. package/lib/components/OrganizationChart/PersonCard.js +5 -5
  74. package/lib/components/OrganizationChart/utils.js +79 -79
  75. package/lib/components/ProjectCard/ProgressBar.js +4 -4
  76. package/lib/components/ProjectCard/ReviewRequestModal.js +5 -5
  77. package/lib/components/Reviews/Pagination.js +6 -6
  78. package/lib/components/ReviewsTab/RatingHeader.js +6 -6
  79. package/lib/components/ReviewsTab/expert-shared-components.code-workspace +20 -20
  80. package/lib/components/ReviewsTab/reviewRequestModal.js +5 -5
  81. package/lib/components/shared/Image.js +13 -13
  82. package/lib/components/shared/ProfileTextField.d.ts +18 -18
  83. package/lib/components/shared/ProfileTextField.js +16 -16
  84. package/lib/components/shared/StyledActionButtons.d.ts +7 -7
  85. package/lib/components/shared/StyledActionButtons.js +15 -15
  86. package/lib/components/shared/ToastNotification.d.ts +10 -10
  87. package/lib/components/shared/ToastNotification.js +63 -63
  88. package/lib/index.d.ts +1 -0
  89. package/lib/index.js +3 -1
  90. package/package.json +61 -61
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importStar(require("react"));
30
+ const base_icons_1 = require("@paro.io/base-icons");
31
+ const base_ui_1 = require("@paro.io/base-ui");
32
+ const core_1 = require("@material-ui/core");
33
+ const LogTimeModalAuthenticated_1 = require("../ProjectCard/LogTimeModalAuthenticated");
34
+ const dayjs_1 = __importDefault(require("dayjs"));
35
+ const issueTypeOptions = [
36
+ { value: 'CommunicationIssues', label: 'Communication Issues' },
37
+ { value: 'Professionalism', label: 'Professionalism' },
38
+ { value: 'ProjectAbandonment', label: 'Project Abandonment' },
39
+ { value: 'DelayedDeliverables', label: 'Delayed Deliverables or Deadlines due to Missing Information/Documentation' },
40
+ { value: 'BillingConcern', label: 'Billing Concern' },
41
+ { value: 'ScopeCreep', label: 'Scope Creep/Unauthorized Requests' },
42
+ { value: 'Other', label: 'Other' },
43
+ ];
44
+ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = false }) => {
45
+ const [isChecked, setIsChecked] = (0, react_1.useState)(false);
46
+ const [problemInput, setProblemInput] = (0, react_1.useState)('');
47
+ const [outcomeInput, setOutcomeInput] = (0, react_1.useState)('');
48
+ const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
49
+ const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
50
+ const [expertOptions, setExpertOptions] = (0, react_1.useState)([]);
51
+ const [selectedExpert, setSelectedExpert] = (0, react_1.useState)(null);
52
+ const [projectOptions, setProjectOptions] = (0, react_1.useState)([]);
53
+ const [selectedProjects, setSelectedProjects] = (0, react_1.useState)([]);
54
+ const [issueType, setIssueType] = (0, react_1.useState)('');
55
+ const [severity, setSeverity] = (0, react_1.useState)('');
56
+ const [startDate, setStartDate] = (0, react_1.useState)(undefined);
57
+ const [isDateInvalid, setIsDateInvalid] = (0, react_1.useState)(false);
58
+ const fileInputRef = (0, react_1.useRef)(null);
59
+ (0, react_1.useEffect)(() => {
60
+ if (experts && experts.length > 0) {
61
+ const options = experts.map((expert) => ({
62
+ label: isExpert ? expert.name : expert.freelancerName,
63
+ value: isExpert ? expert.id : expert.freelancerId,
64
+ }));
65
+ setExpertOptions(options);
66
+ }
67
+ }, [experts]);
68
+ (0, react_1.useEffect)(() => {
69
+ if (projects && projects.length > 0) {
70
+ const options = projects
71
+ .filter((p) => {
72
+ if (isExpert) {
73
+ return p.client.id === Number(selectedExpert);
74
+ }
75
+ else {
76
+ return p.freelancer.id === Number(selectedExpert);
77
+ }
78
+ })
79
+ .map((p) => ({
80
+ label: isExpert ? p.name : p.name,
81
+ value: isExpert ? p : p,
82
+ }));
83
+ setProjectOptions(options);
84
+ }
85
+ }, [projects, selectedExpert]);
86
+ const handleFileUpload = (event) => {
87
+ const files = Array.from(event.target.files);
88
+ setUploadFiles(prev => [...prev, ...files]);
89
+ };
90
+ const isFormValid = () => {
91
+ const requiredProjectSelection = isExpert || (!isExpert && selectedProjects.length > 0);
92
+ return (selectedExpert !== null &&
93
+ issueType !== '' &&
94
+ severity !== '' &&
95
+ problemInput.trim() !== '' &&
96
+ outcomeInput.trim() !== '' &&
97
+ isChecked &&
98
+ startDate !== undefined &&
99
+ requiredProjectSelection);
100
+ };
101
+ const handleSubmit = () => {
102
+ if (!isFormValid())
103
+ return;
104
+ const formData = {
105
+ selectedExpert,
106
+ selectedProjects,
107
+ issueType,
108
+ severity,
109
+ startDate,
110
+ problem: problemInput,
111
+ expectedOutcome: outcomeInput,
112
+ supportingDocs: uploadFiles.map(f => f.name),
113
+ };
114
+ console.log('Escalation Submitted:', formData);
115
+ // Redirect or perform additional logic
116
+ goHome();
117
+ };
118
+ const validateDate = (date) => {
119
+ const minDate = LogTimeModalAuthenticated_1.constants.MIN_DATE;
120
+ const maxDate = new Date();
121
+ const isValid = date ? date.setHours(0, 0, 0, 0) < minDate.setHours(0, 0, 0, 0) || date.setHours(0, 0, 0, 0) > maxDate.setHours(0, 0, 0, 0) : true;
122
+ setIsDateInvalid(isValid);
123
+ return !isValid;
124
+ };
125
+ return (react_1.default.createElement("div", { className: 'w-full max-w-full' },
126
+ react_1.default.createElement("button", { onClick: goBack, className: "flex items-center text-blue-600 mb-6" },
127
+ react_1.default.createElement(base_icons_1.IconChevronLeft, { size: "xs" }),
128
+ " Back"),
129
+ react_1.default.createElement("div", { className: "mb-6" },
130
+ react_1.default.createElement("h2", { className: "text-xl font-bold" }, "Report Issue with Your Expert"),
131
+ react_1.default.createElement("p", { className: "text-gray-600 mt-1" }, "Provide details about the issue you're experiencing and we'll resolve it within 4-8 hours")),
132
+ react_1.default.createElement("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 mb-6" },
133
+ react_1.default.createElement("div", { className: "flex items-start" },
134
+ react_1.default.createElement("span", { className: "mr-3" }, "!"),
135
+ react_1.default.createElement("div", null,
136
+ react_1.default.createElement("p", { className: "font-medium text-red-800" }, "Common Issues We Can Help With"),
137
+ react_1.default.createElement("ul", { className: "mt-1 text-sm text-red-700 list-disc list-inside space-y-1" },
138
+ react_1.default.createElement("li", null, `Communication delays (${isExpert ? 'client' : 'expert'} not responding)`),
139
+ !isExpert && react_1.default.createElement("li", null, "Missed deadlines or project delays"),
140
+ !isExpert && react_1.default.createElement("li", null, "Quality concerns with deliverables"),
141
+ react_1.default.createElement("li", null, "Scope changes or unexpected requests"),
142
+ react_1.default.createElement("li", null, "Billing or payment disputes"))))),
143
+ react_1.default.createElement("div", { className: "border rounded-lg overflow-hidden mb-6" },
144
+ react_1.default.createElement("div", { className: "bg-gray-50 p-3 border-b" },
145
+ react_1.default.createElement("h3", { className: "font-medium" }, "Issue Details")),
146
+ react_1.default.createElement("div", { className: "p-4 space-y-4" },
147
+ react_1.default.createElement("div", null,
148
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, `Which ${isExpert ? 'client' : 'expert'} are you experiencing the issue with?`),
149
+ react_1.default.createElement(core_1.Select, { fullWidth: true, value: selectedExpert !== null && selectedExpert !== void 0 ? selectedExpert : '', onChange: e => setSelectedExpert(e.target.value === '' ? null : Number(e.target.value)), displayEmpty: true, variant: "outlined", placeholder: `Select a ${isExpert ? 'Client' : 'Expert'}` },
150
+ react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
151
+ react_1.default.createElement("em", null, `Select a ${isExpert ? 'Client' : 'Expert'}`)),
152
+ expertOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
153
+ react_1.default.createElement("div", null,
154
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Which Project(s)?"),
155
+ react_1.default.createElement(core_1.Select, { multiple: true, fullWidth: true, value: selectedProjects, onChange: (e) => {
156
+ const value = e.target.value;
157
+ setSelectedProjects(Array.isArray(value) ? value : [value]);
158
+ }, variant: "outlined", displayEmpty: true, renderValue: (selected) => {
159
+ if (selected.length === 0) {
160
+ return react_1.default.createElement("span", { className: "text-gray-400" }, "Select project(s)");
161
+ }
162
+ return projectOptions
163
+ .filter(opt => selected.includes(opt.value))
164
+ .map(opt => opt.label)
165
+ .join(', ');
166
+ }, placeholder: `Select a Project(s)` },
167
+ react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
168
+ react_1.default.createElement("em", null, "Select a Project(s)...")),
169
+ projectOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
170
+ react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" },
171
+ react_1.default.createElement("div", null,
172
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Issue Type"),
173
+ react_1.default.createElement(core_1.Select, { fullWidth: true, value: issueType, onChange: e => setIssueType(e.target.value), displayEmpty: true, variant: "outlined" },
174
+ react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
175
+ react_1.default.createElement("em", null, "Select issue type...")),
176
+ issueTypeOptions
177
+ .filter(option => {
178
+ if (isExpert) {
179
+ return option.label !== 'Billing Concern';
180
+ }
181
+ else {
182
+ return option.label !== 'Scope Creep/Unauthorized Requests';
183
+ }
184
+ })
185
+ .map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
186
+ react_1.default.createElement("div", null,
187
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Severity Level"),
188
+ react_1.default.createElement(core_1.Select, { fullWidth: true, value: severity, onChange: e => setSeverity(e.target.value), displayEmpty: true, variant: "outlined" },
189
+ react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
190
+ react_1.default.createElement("em", null, "Select severity...")),
191
+ react_1.default.createElement(core_1.MenuItem, { value: "Critical" }, "Critical"),
192
+ react_1.default.createElement(core_1.MenuItem, { value: "High" }, "High"),
193
+ react_1.default.createElement(core_1.MenuItem, { value: "Medium" }, "Medium"),
194
+ react_1.default.createElement(core_1.MenuItem, { value: "Low" }, "Low")))),
195
+ react_1.default.createElement("div", null,
196
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "When did this issue start?"),
197
+ react_1.default.createElement(LogTimeModalAuthenticated_1.SelectDate, { timeLogDate: startDate, setTimeLogDate: setStartDate, isInvalid: false, setIsDateInvalid: setIsDateInvalid, validateDate: validateDate, maxDate: (0, dayjs_1.default)(new Date()).format("MM-DD-YYYY") })),
198
+ react_1.default.createElement("div", null,
199
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "What's the problem?"),
200
+ react_1.default.createElement(base_ui_1.Input, { type: "text", value: problemInput, placeholder: "Describe the issue...", onChange: (e) => setProblemInput(e.target.value) })),
201
+ react_1.default.createElement("div", null,
202
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "What outcome are you looking for?"),
203
+ react_1.default.createElement(base_ui_1.Input, { type: "text", value: outcomeInput, placeholder: "What would you like to see happen?", onChange: (e) => setOutcomeInput(e.target.value) })),
204
+ react_1.default.createElement("div", null,
205
+ react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Supporting Documents (Optional)"),
206
+ react_1.default.createElement("div", { className: "border border-dashed border-gray-300 rounded-md p-6 text-center" },
207
+ react_1.default.createElement("p", { className: "text-sm text-gray-600" }, "Upload screenshots, emails, or documents"),
208
+ react_1.default.createElement("input", { ref: fileInputRef, type: "file", multiple: true, accept: ".pdf,.doc,.docx,.jpeg,.png,.gif,.csv", hidden: true, onChange: handleFileUpload }),
209
+ react_1.default.createElement(base_ui_1.Button, { label: "Attach Files", iconLeft: react_1.default.createElement(base_icons_1.IconPlus, { size: "sm" }), onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, color: "info", isLoading: uploadingFile, size: "sm" }),
210
+ uploadFiles.length > 0 && (react_1.default.createElement("ul", { className: "mt-2 text-sm text-gray-600 list-disc list-inside" }, uploadFiles.map(f => react_1.default.createElement("li", { key: f.name }, f.name)))))),
211
+ react_1.default.createElement("div", { className: "bg-[#EFF6FF] p-3 rounded" },
212
+ react_1.default.createElement(base_ui_1.Checkbox, { id: "checkbox-1", label: `I understand this will notify my ${isExpert ? 'client' : 'expert'} and the Paro support team`, name: "acknowledge", isChecked: isChecked, onChange: () => setIsChecked(prev => !prev) })),
213
+ react_1.default.createElement("div", { className: "flex justify-end space-x-3 pt-4" },
214
+ react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack }),
215
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit issue", onClick: handleSubmit, color: "primary", disabled: !isFormValid() }))))));
216
+ };
217
+ exports.default = EscalationSubmitForm;
@@ -0,0 +1,9 @@
1
+ interface EscalationTabProps {
2
+ activeTab: string;
3
+ setActiveTab: (activeTab: string) => void;
4
+ activeIssues: number;
5
+ inProgressIssues: number;
6
+ resolvedIssues: number;
7
+ }
8
+ declare const EscalationTabs: ({ activeTab, setActiveTab, activeIssues, inProgressIssues, resolvedIssues, }: EscalationTabProps) => JSX.Element;
9
+ export default EscalationTabs;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ ;
8
+ const EscalationTabs = ({ activeTab, setActiveTab, activeIssues = 0, inProgressIssues = 0, resolvedIssues = 0, }) => {
9
+ return (react_1.default.createElement("div", { className: "border-b border-gray-200 mb-6" },
10
+ react_1.default.createElement("nav", { className: "flex space-x-8" },
11
+ react_1.default.createElement("button", { onClick: () => setActiveTab('action-required'), className: `py-2 px-1 border-b-2 font-medium text-sm flex items-center ${activeTab === 'action-required'
12
+ ? 'border-[#A73A43] text-[#A73A43]'
13
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
14
+ react_1.default.createElement("div", { className: "bg-[#A73A43] w-2 h-2 rounded-full mr-2" }),
15
+ "Action Required",
16
+ react_1.default.createElement("div", { className: "bg-[#F9BABF] text-[#A73A43] font-bold rounded-full px-2 py-1 text-xs ml-2" }, activeIssues)),
17
+ react_1.default.createElement("button", { onClick: () => setActiveTab('in-progress'), className: `py-2 px-1 border-b-2 font-medium text-sm flex items-center ${activeTab === 'in-progress'
18
+ ? 'border-[#115484] text-[#115484]'
19
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
20
+ react_1.default.createElement("div", { className: "bg-[#115484] w-2 h-2 rounded-full mr-2" }),
21
+ "In Progress",
22
+ react_1.default.createElement("div", { className: "bg-[#A3C9E5] text-[#115484] font-bold rounded-full px-2 py-1 text-xs ml-2" }, inProgressIssues)),
23
+ react_1.default.createElement("button", { onClick: () => setActiveTab('resolved'), className: `py-2 px-1 border-b-2 font-medium text-sm flex items-center ${activeTab === 'resolved'
24
+ ? 'border-[#12756F] text-[#12756F]'
25
+ : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
26
+ react_1.default.createElement("div", { className: "bg-[#12756F] w-2 h-2 rounded-full mr-2" }),
27
+ "Resolved",
28
+ react_1.default.createElement("div", { className: "bg-[#A3DCD8] text-[#12756F] font-bold rounded-full px-2 py-1 text-xs ml-2" }, resolvedIssues)))));
29
+ };
30
+ exports.default = EscalationTabs;
@@ -0,0 +1,17 @@
1
+ export type EscalationChatDetails = {
2
+ title: string;
3
+ project: string;
4
+ id: string;
5
+ status: string;
6
+ };
7
+ interface EscalationTabProps {
8
+ activeTab: string;
9
+ openEscalationChat: (details: EscalationChatDetails) => void;
10
+ setSelectedIssueId: (issue: number) => void;
11
+ activeIssues: any[];
12
+ inProgressIssues: any[];
13
+ resolvedIssues: any[];
14
+ isExpert: boolean;
15
+ }
16
+ declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }: EscalationTabProps) => JSX.Element;
17
+ export default EscalationTabsContent;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importDefault(require("react"));
30
+ const EscalationIssueCard_1 = __importStar(require("./EscalationIssueCard"));
31
+ const base_ui_1 = require("@paro.io/base-ui");
32
+ ;
33
+ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }) => {
34
+ if (activeTab === 'action-required') {
35
+ return (react_1.default.createElement("div", null,
36
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
37
+ react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues Requiring Your Response")),
38
+ react_1.default.createElement(EscalationIssueCard_1.default, { issues: activeIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showRespondButton: true, setSelectedIssueId: setSelectedIssueId })));
39
+ }
40
+ if (activeTab === 'in-progress') {
41
+ return (react_1.default.createElement("div", null,
42
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
43
+ react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues In Progress")),
44
+ react_1.default.createElement(EscalationIssueCard_1.default, { issues: inProgressIssues, isExpert: isExpert, openEscalationChat: openEscalationChat, showMarkResolvedButton: true })));
45
+ }
46
+ if (activeTab === 'resolved') {
47
+ return (react_1.default.createElement("div", null,
48
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
49
+ react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Recently Resolved Issues")),
50
+ resolvedIssues.length > 0 ? react_1.default.createElement("div", { className: "space-y-3" }, resolvedIssues.map((issue) => {
51
+ const project = issue.projectName && Array.isArray(issue.projectName) && issue.projectName.length > 0
52
+ ? `${issue.projectName[0]}${issue.projectName.length > 1 ? ` +${issue.projectName.length - 1} more` : ''} `
53
+ : '';
54
+ return (react_1.default.createElement("div", { key: issue.id, className: "border border-green-200 rounded-lg bg-green-50 p-4" },
55
+ react_1.default.createElement("div", { className: "flex items-start justify-between" },
56
+ react_1.default.createElement("div", { className: "flex items-start" },
57
+ react_1.default.createElement("div", null,
58
+ react_1.default.createElement("div", { className: "flex flex-row justify-between" },
59
+ react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-1" },
60
+ issue.problem,
61
+ " ",
62
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: issue.severityLevel }))),
63
+ react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
64
+ react_1.default.createElement("span", null, issue.person),
65
+ react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
66
+ react_1.default.createElement("span", null, project),
67
+ react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
68
+ react_1.default.createElement("span", null,
69
+ "Case #",
70
+ issue.id)),
71
+ react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-3" }, issue.description),
72
+ react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
73
+ react_1.default.createElement("span", { className: "text-xs text-gray-500" },
74
+ "Resolved ",
75
+ issue.resolvedDate),
76
+ react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
77
+ react_1.default.createElement("span", { className: "text-xs text-gray-500" },
78
+ "Resolved By ",
79
+ issue.resolvedBy)))),
80
+ react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
81
+ title: issue.chatTitle,
82
+ project: issue.projectName,
83
+ id: issue.id,
84
+ status: issue.chatStatus
85
+ }), label: "Chat", color: "primary" }))));
86
+ }))
87
+ :
88
+ react_1.default.createElement("div", null, "No resolved issues.")));
89
+ }
90
+ return react_1.default.createElement(react_1.default.Fragment, null);
91
+ };
92
+ exports.default = EscalationTabsContent;
@@ -0,0 +1,10 @@
1
+ interface EscalationsProps {
2
+ experts: any[];
3
+ projects: any[];
4
+ isExpert: boolean;
5
+ activeIssues: any[];
6
+ inProgressIssues: any[];
7
+ resolvedIssues: any[];
8
+ }
9
+ export declare const Escalations: ({ experts, projects, isExpert, activeIssues, inProgressIssues, resolvedIssues, }: EscalationsProps) => JSX.Element;
10
+ export {};
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Escalations = void 0;
30
+ const react_1 = __importStar(require("react"));
31
+ const EscalationReportBanner_1 = __importDefault(require("./EscalationReportBanner"));
32
+ const base_ui_1 = require("@paro.io/base-ui");
33
+ const EscalationTabs_1 = __importDefault(require("./EscalationTabs"));
34
+ const EscalationTabsContent_1 = __importDefault(require("./EscalationTabsContent"));
35
+ const EscalationRespondForm_1 = __importDefault(require("./EscalationRespondForm"));
36
+ const EscalationSubmitForm_1 = __importDefault(require("./EscalationSubmitForm"));
37
+ const EscalationChat_1 = __importDefault(require("./EscalationChat"));
38
+ const AccountSuspensionBanner_1 = __importDefault(require("./AccountSuspensionBanner"));
39
+ const AccountSuspensionModal_1 = __importDefault(require("./AccountSuspensionModal"));
40
+ const base_icons_1 = require("@paro.io/base-icons");
41
+ const EscalationIssueCard_1 = require("./EscalationIssueCard");
42
+ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProgressIssues, resolvedIssues, }) => {
43
+ const [activeSection, setActiveSection] = (0, react_1.useState)('support');
44
+ const [selectedProject, setSelectedProject] = (0, react_1.useState)(null);
45
+ const [selectedIssueId, setSelectedIssueId] = (0, react_1.useState)(null); // using selectedIssueId 0 for new escalation submission
46
+ const [showEscalationChat, setShowEscalationChat] = (0, react_1.useState)(false);
47
+ const [activeChatIssue, setActiveChatIssue] = (0, react_1.useState)(null); // update required
48
+ const [activeEscalationTab, setActiveEscalationTab] = (0, react_1.useState)('action-required');
49
+ const [showSuspensionModal, setShowSuspensionModal] = (0, react_1.useState)(false);
50
+ const goBack = () => {
51
+ if (selectedIssueId) {
52
+ setSelectedIssueId(null);
53
+ }
54
+ else if (selectedProject) {
55
+ setSelectedProject(null);
56
+ }
57
+ else {
58
+ setActiveSection('support');
59
+ }
60
+ };
61
+ const goHome = () => {
62
+ setSelectedIssueId(null);
63
+ setSelectedProject(null);
64
+ setActiveSection('support');
65
+ };
66
+ const openEscalationChat = (issue) => {
67
+ setActiveChatIssue(issue);
68
+ setShowEscalationChat(true);
69
+ };
70
+ return (react_1.default.createElement("div", { className: "bg-white w-full" },
71
+ react_1.default.createElement("div", { className: isExpert ? "p-6" : "mx-auto p-6 border-solid border-t-2" },
72
+ activeSection === 'support' && selectedIssueId === null && react_1.default.createElement("div", null,
73
+ react_1.default.createElement("div", { className: "flex justify-between items-center mb-1 mt-2" },
74
+ react_1.default.createElement("h2", { className: "text-xl font-bold" }, "Support & Escalation Management"),
75
+ activeIssues.length && react_1.default.createElement("div", { className: "flex items-center space-x-2" },
76
+ react_1.default.createElement("div", { className: `border box-border text-center px-4 pb-0.5 pt-1 text-sm inline-block break-words text-white rounded-full bg-danger border-danger` },
77
+ activeIssues.length,
78
+ " ACTIVE ISSUES"))),
79
+ react_1.default.createElement("div", { className: "border-b pb-4 mb-6" },
80
+ react_1.default.createElement("p", { className: "text-gray-600" }, `Manage escalations with integrated chat between you, your ${isExpert ? 'client' : 'expert'}, and Paro support. All conversations are organized by priority and status.`)),
81
+ react_1.default.createElement("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6" },
82
+ react_1.default.createElement("h3", { className: "font-medium text-blue-800 mb-3" }, "How Our Escalation System Works"),
83
+ react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6" },
84
+ react_1.default.createElement("div", null,
85
+ react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Standard Resolution Process"),
86
+ react_1.default.createElement("div", { className: "space-y-2 text-sm text-gray-600" },
87
+ react_1.default.createElement("div", { className: "flex items-center" },
88
+ react_1.default.createElement("div", { className: "bg-blue-500 w-2 h-2 rounded-full mr-2" }),
89
+ react_1.default.createElement("span", null,
90
+ react_1.default.createElement("strong", null, "Step 1:"),
91
+ " ",
92
+ `Issue escalated to ${isExpert ? 'client' : 'expert'} & Paro support`)),
93
+ react_1.default.createElement("div", { className: "flex items-center" },
94
+ react_1.default.createElement("div", { className: "bg-blue-500 w-2 h-2 rounded-full mr-2" }),
95
+ react_1.default.createElement("span", null,
96
+ react_1.default.createElement("strong", null, "Step 2:"),
97
+ " ",
98
+ `${isExpert ? 'Client' : 'Expert'} response with solution/timeline`)),
99
+ react_1.default.createElement("div", { className: "flex items-center" },
100
+ react_1.default.createElement("div", { className: "bg-blue-500 w-2 h-2 rounded-full mr-2" }),
101
+ react_1.default.createElement("span", null,
102
+ react_1.default.createElement("strong", null, "Step 3:"),
103
+ " Implementation & resolution confirmation"))),
104
+ react_1.default.createElement("div", { className: "mt-3 text-xs text-gray-600 bg-white p-2 rounded border" },
105
+ react_1.default.createElement("strong", null, "Chat integration:"),
106
+ " ",
107
+ `All escalations include real-time chat with ${isExpert ? 'client' : 'expert'} and support team for transparent communication.`)),
108
+ react_1.default.createElement("div", null,
109
+ react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Priority Levels & Response Times"),
110
+ react_1.default.createElement("div", { className: "space-y-2 text-sm" },
111
+ react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
112
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Critical" }),
113
+ react_1.default.createElement("span", null, "All work blocked")),
114
+ react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
115
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "High" }),
116
+ react_1.default.createElement("span", null, "Progress blocked")),
117
+ react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
118
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Medium" }),
119
+ react_1.default.createElement("span", null, "Timeline impacted")),
120
+ react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
121
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Low" }),
122
+ react_1.default.createElement("span", null, "Minor issues")))))),
123
+ isExpert &&
124
+ react_1.default.createElement("div", { className: "rounded-lg p-2 mb-4 shadow-lg" },
125
+ react_1.default.createElement("div", { className: "flex items-center justify-between" },
126
+ react_1.default.createElement("div", { className: "flex items-center" },
127
+ react_1.default.createElement("div", { className: "bg-white bg-opacity-20 rounded-full p-2 mr-3" },
128
+ react_1.default.createElement(base_icons_1.IconExclamationCircle, { className: "h-6 w-6 text-black" })),
129
+ react_1.default.createElement("div", null,
130
+ react_1.default.createElement("div", { className: "mr-4" },
131
+ react_1.default.createElement("h3", { className: "font-semibold text-sm mb-1" }, "Need Support with a Client?"),
132
+ react_1.default.createElement("p", { className: "text-xs" }, "Report payment, scope, or communication activeIssues")))),
133
+ 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" }))),
134
+ isExpert &&
135
+ react_1.default.createElement(AccountSuspensionBanner_1.default, { setShowSuspensionModal: setShowSuspensionModal, suspended: false }),
136
+ !isExpert &&
137
+ react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0) }),
138
+ react_1.default.createElement(EscalationTabs_1.default, { activeTab: activeEscalationTab, setActiveTab: setActiveEscalationTab, activeIssues: activeIssues.length, inProgressIssues: inProgressIssues.length, resolvedIssues: resolvedIssues.length }),
139
+ react_1.default.createElement(EscalationTabsContent_1.default, { activeTab: activeEscalationTab, openEscalationChat: openEscalationChat, setSelectedIssueId: setSelectedIssueId, activeIssues: activeIssues, inProgressIssues: inProgressIssues, resolvedIssues: resolvedIssues, isExpert: isExpert })),
140
+ activeSection === 'support' && activeIssues.filter((issue) => issue.id === selectedIssueId).length > 0 && (react_1.default.createElement(EscalationRespondForm_1.default, { goBack: goBack, selectedIssue: activeIssues.filter((issue) => issue.id === selectedIssueId), goHome: goHome })),
141
+ activeSection === 'support' && selectedIssueId === 0 && (react_1.default.createElement(EscalationSubmitForm_1.default, { goBack: goBack, goHome: goHome, experts: experts, projects: projects, isExpert: isExpert })),
142
+ showEscalationChat && activeChatIssue && (react_1.default.createElement(EscalationChat_1.default, { activeChatIssue: activeChatIssue, showEscalationChat: showEscalationChat, setShowEscalationChat: setShowEscalationChat })),
143
+ showSuspensionModal &&
144
+ react_1.default.createElement(AccountSuspensionModal_1.default, { showSuspensionModal: showSuspensionModal, onClose: () => setShowSuspensionModal(false) }))));
145
+ };
146
+ exports.Escalations = Escalations;
@@ -0,0 +1 @@
1
+ export { Escalations } from './Escalations';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Escalations = void 0;
4
+ var Escalations_1 = require("./Escalations");
5
+ Object.defineProperty(exports, "Escalations", { enumerable: true, get: function () { return Escalations_1.Escalations; } });
@@ -11,12 +11,12 @@ const CopyToClipboardAlert_1 = __importDefault(require("../shared/CopyToClipboar
11
11
  const colors_1 = __importDefault(require("../ClientReferencesSection/constants/colors"));
12
12
  const Banner_1 = __importDefault(require("./Banner"));
13
13
  const base_icons_1 = require("@paro.io/base-icons");
14
- const StyledButton = (0, styled_components_1.default)(core_1.Button) `
15
- margin: 0px !important;
16
- padding: 26px 0 18px 0 !important;
17
- span {
18
- color: ${colors_1.default.buttonText} !important
19
- }
14
+ const StyledButton = (0, styled_components_1.default)(core_1.Button) `
15
+ margin: 0px !important;
16
+ padding: 26px 0 18px 0 !important;
17
+ span {
18
+ color: ${colors_1.default.buttonText} !important
19
+ }
20
20
  `;
21
21
  const ActionButton = ({ title, ariaLabel, onClick, icon: Icon }) => (react_1.default.createElement(core_1.Tooltip, { arrow: true, placement: "top", interactive: true, className: "whitespace-nowrap", title: title },
22
22
  react_1.default.createElement(core_1.IconButton, { "aria-label": ariaLabel, onClick: onClick },
@@ -53,13 +53,13 @@ const formatPhoneNumber = (phone) => {
53
53
  return `(${numericPhone.slice(0, 3)}) ${numericPhone.slice(3, 6)} - ${numericPhone.slice(6)}`;
54
54
  };
55
55
  exports.formatPhoneNumber = formatPhoneNumber;
56
- exports.ProfilePhotoPreview = styled_components_1.default.img `
57
- height: 86px;
58
- width: 86px;
59
- border: 1px solid ${colors_1.default.lightGray};
60
- border-radius: 50%;
61
- object-fit: cover;
62
- object-position: top;
56
+ exports.ProfilePhotoPreview = styled_components_1.default.img `
57
+ height: 86px;
58
+ width: 86px;
59
+ border: 1px solid ${colors_1.default.lightGray};
60
+ border-radius: 50%;
61
+ object-fit: cover;
62
+ object-position: top;
63
63
  `;
64
64
  const ProfileSection = ({ legacyFreelancerId, imageUrl, shouldAllowEditProfile, firstName, lastName, primaryServiceLine, editServiceLine, city, stateAbbreviation, email, phone, setOpen, paroProjectsData, getUserDocument, uploadUserPhotoMutation, loadingNewImage, imageUpdateError, isInternal, getUserByEmail, updateUserEmail, updateUserMutation, getUserByEmailLazyQuery, updateUserPassword, verifyUserPassword, getExpertRates, paroTenure, hourlyRate, }) => {
65
65
  var _a;
@@ -1 +1 @@
1
- export declare const TestDecisionSection: () => JSX.Element;
1
+ export declare const TestDecisionSection: () => JSX.Element;