@paro.io/expert-shared-components 1.12.37 → 1.12.39

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.
@@ -37,7 +37,7 @@ const AccountSuspensionModal = ({ showSuspensionModal, onClose }) => {
37
37
  " Forgot to log time, personal emergency, availability changes, minor communication delays"))),
38
38
  react_1.default.createElement("div", { className: "flex items-start" },
39
39
  react_1.default.createElement("div", { className: "bg-orange-500 rounded-full p-2 mr-4 relative z-10" },
40
- react_1.default.createElement(base_icons_1.IconExclamation, { className: "h-5 w-5 text-white" })),
40
+ react_1.default.createElement(base_icons_1.IconExclamationCircle, { className: "h-5 w-5 text-white" })),
41
41
  react_1.default.createElement("div", { className: "flex-1 pb-8" },
42
42
  react_1.default.createElement("div", { className: "flex justify-between items-start mb-2" },
43
43
  react_1.default.createElement("h4", { className: "font-semibold text-orange-800" }, "Level 2: Medium Severity"),
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const CustomTag: (label: any) => React.JSX.Element;
3
+ export default CustomTag;
@@ -0,0 +1,25 @@
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
+ const getBackgroundColor = (type) => {
8
+ switch (type) {
9
+ case 'Critical':
10
+ return 'danger';
11
+ case 'High':
12
+ return 'warning';
13
+ case 'Medium':
14
+ return 'info';
15
+ case 'Low':
16
+ return 'default';
17
+ default:
18
+ return 'default';
19
+ }
20
+ };
21
+ const CustomTag = (label) => {
22
+ const color = getBackgroundColor(label);
23
+ return (react_1.default.createElement("div", { className: `border box-border text-center px-4 pb-0.5 pt-1 text-sm inline-block break-words text-white cursor-pointer rounded-full bg-${color} border-${color}` }, label));
24
+ };
25
+ exports.default = CustomTag;
@@ -37,6 +37,7 @@ const base_icons_1 = require("@paro.io/base-icons");
37
37
  const base_ui_1 = require("@paro.io/base-ui");
38
38
  const core_1 = require("@material-ui/core");
39
39
  const DiscussionSection_1 = require("../Invoices/DiscussionSection");
40
+ const EscalationIssueCard_1 = require("./EscalationIssueCard");
40
41
  const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalationChat }) => {
41
42
  const [uploadFiles, setUploadFiles] = (0, react_1.useState)([]);
42
43
  const [uploadingFile, setUploadingFile] = (0, react_1.useState)(false);
@@ -56,7 +57,7 @@ const EscalationChat = ({ activeChatIssue, showEscalationChat, setShowEscalation
56
57
  react_1.default.createElement("h1", { className: "text-md font-bold mr-2" },
57
58
  "Escalation Chat #",
58
59
  activeChatIssue.caseId),
59
- react_1.default.createElement(base_ui_1.Tag, { label: activeChatIssue.status, color: "info" })),
60
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: activeChatIssue.status })),
60
61
  react_1.default.createElement("p", { className: "text-xs" },
61
62
  activeChatIssue.title,
62
63
  " - ",
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { EscalationChatDetails } from "./EscalationTabsContent";
3
+ export declare const CustomTag: ({ label }: {
4
+ label: any;
5
+ }) => React.JSX.Element;
6
+ type EscalationIssueCardProps = {
7
+ issues: any[];
8
+ isExpert: boolean;
9
+ openEscalationChat: (details: EscalationChatDetails) => void;
10
+ showRespondButton?: boolean;
11
+ setSelectedIssueId?: (id: number) => void;
12
+ showMarkResolvedButton?: boolean;
13
+ };
14
+ declare const EscalationIssueCard: React.FC<EscalationIssueCardProps>;
15
+ export default EscalationIssueCard;
@@ -0,0 +1,72 @@
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
+ exports.CustomTag = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const base_ui_1 = require("@paro.io/base-ui");
9
+ const getBackgroundColor = (type) => {
10
+ switch (type) {
11
+ case 'Critical':
12
+ return 'danger';
13
+ case 'High':
14
+ return 'warning';
15
+ case 'Medium':
16
+ return 'info';
17
+ case 'Low':
18
+ return 'default';
19
+ default:
20
+ return 'default';
21
+ }
22
+ };
23
+ const CustomTag = ({ label }) => {
24
+ const color = getBackgroundColor(label);
25
+ return (react_1.default.createElement("div", { className: `border box-border text-center px-4 pb-0.5 pt-1 text-sm inline-block break-words ${color === 'default' ? 'text-black' : 'text-white'} rounded-full bg-${color} border-${color} ml-2` }, label.toUpperCase()));
26
+ };
27
+ exports.CustomTag = CustomTag;
28
+ const EscalationIssueCard = ({ issues, isExpert, openEscalationChat, showRespondButton = false, setSelectedIssueId, showMarkResolvedButton = false, }) => {
29
+ if (!issues.length)
30
+ return react_1.default.createElement("div", null, "No issues.");
31
+ return (react_1.default.createElement("div", { className: "space-y-4" }, issues.map((issue) => {
32
+ const project = issue.projectName && Array.isArray(issue.projectName) && issue.projectName.length > 0
33
+ ? `${issue.projectName[0]}${issue.projectName.length > 1 ? ` +${issue.projectName.length - 1} more` : ''} `
34
+ : '';
35
+ const docs = [...issue.expertSupportingDocuments, ...issue.clientSupportingDocuments];
36
+ return (react_1.default.createElement("div", { key: issue.id, className: "border border-gray-200 rounded-lg bg-white p-4" },
37
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-3" },
38
+ react_1.default.createElement("div", { className: "flex-1 ml-2" },
39
+ react_1.default.createElement("div", { className: "font-bold" }, issue.problem),
40
+ react_1.default.createElement("div", { className: "text-xs text-gray-500 font-bold" },
41
+ project,
42
+ " \u2022 Case #",
43
+ issue.id)),
44
+ react_1.default.createElement("div", { className: "flex flex-row gap-2" },
45
+ react_1.default.createElement(exports.CustomTag, { label: issue.severityLevel }),
46
+ react_1.default.createElement(exports.CustomTag, { label: issue.issueType }))),
47
+ react_1.default.createElement("div", { className: "bg-gray-50 rounded-md p-3 mb-4 border" },
48
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-2" }, issue.updateLabel ? (react_1.default.createElement("div", { className: "text-sm text-gray-500" },
49
+ "Updated By: ",
50
+ react_1.default.createElement("span", { className: "font-bold" }, issue.updateLabel),
51
+ " \u2022 Updated on: ",
52
+ react_1.default.createElement("span", { className: "font-bold" }, issue.updateTime))) : (react_1.default.createElement("div", { className: "text-sm text-gray-500" },
53
+ "Submitted by: ",
54
+ react_1.default.createElement("span", { className: "font-bold" }, issue.submittedBy),
55
+ " \u2022 Submitted on: ",
56
+ react_1.default.createElement("span", { className: "font-bold" }, issue.createdAt)))),
57
+ react_1.default.createElement("div", { className: "text-sm text-gray-600 mb-3" }, issue.expectedOutcome)),
58
+ docs && docs.length > 0 && (react_1.default.createElement("div", { className: "flex flex-wrap gap-2 m-1 mb-3" },
59
+ react_1.default.createElement("span", { className: "font-bold" }, "Supporting Documents: "),
60
+ docs.map((d, idx) => (react_1.default.createElement(exports.CustomTag, { key: idx, label: d }))))),
61
+ react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
62
+ react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
63
+ title: issue.problem,
64
+ project: issue.projectName,
65
+ id: issue.id,
66
+ status: issue.status
67
+ }), label: "Chat", color: "primary" }),
68
+ showRespondButton && setSelectedIssueId && (react_1.default.createElement(base_ui_1.Button, { label: "Respond to Escalation", onClick: () => setSelectedIssueId(issue.id), color: 'primary' })),
69
+ showMarkResolvedButton && !isExpert && (react_1.default.createElement(base_ui_1.Button, { onClick: issue.markResolved, label: "Mark as Resolved", color: "primary" })))));
70
+ })));
71
+ };
72
+ exports.default = EscalationIssueCard;
@@ -11,7 +11,7 @@ const EscalationReportBanner = ({ onReport }) => {
11
11
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
12
12
  react_1.default.createElement("div", { className: "flex items-center" },
13
13
  react_1.default.createElement("div", { className: "bg-white bg-opacity-20 rounded-full p-2 mr-4" },
14
- react_1.default.createElement(base_icons_1.IconExclamation, null)),
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
17
  react_1.default.createElement("p", { className: "text-red-100 text-sm mt-1" }, "Report communication problems, quality concerns, or missed deadlines. We'll resolve it within 4-8 hours."))),
@@ -30,17 +30,17 @@ const responseTypes = [
30
30
  {
31
31
  label: "Acknowledge issue and provide resolution plan",
32
32
  description: "Explain circumstances and apologize",
33
- value: "acknowledge",
33
+ value: "Acknowledged",
34
34
  },
35
35
  {
36
36
  label: "Dispute issue and provide counter-evidence",
37
37
  description: "Challenge the client's concerns with documentation",
38
- value: "dispute",
38
+ value: "Disputed",
39
39
  },
40
40
  {
41
41
  label: "Request clarification",
42
42
  description: "Ask for more details about the issue",
43
- value: "clarification",
43
+ value: "Clarification",
44
44
  },
45
45
  ];
46
46
  const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
@@ -53,15 +53,23 @@ const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
53
53
  const files = Array.from(event.target.files);
54
54
  setUploadFiles(prev => [...prev, ...files]);
55
55
  };
56
+ const submitResponse = () => {
57
+ const responseData = {
58
+ responseType: selectedType,
59
+ responseText: responseInput,
60
+ uploadedFiles: uploadFiles.map(file => file.name),
61
+ selectedIssue: selectedIssue
62
+ };
63
+ console.log("Collected Response Data:", responseData);
64
+ goHome();
65
+ };
56
66
  return (react_1.default.createElement("div", null,
57
67
  react_1.default.createElement("button", { onClick: goBack, className: "flex items-center text-blue-600 mb-6" },
58
68
  react_1.default.createElement(base_icons_1.IconChevronLeft, { size: "xs" }),
59
69
  " Back"),
60
70
  react_1.default.createElement("div", { className: "mb-6" },
61
71
  react_1.default.createElement("h2", { className: "text-xl font-bold" }, "Respond to Issue"),
62
- react_1.default.createElement("p", { className: "text-gray-600 mt-1" }, selectedIssue === 'respond-to-issue-critical' ?
63
- "Ineo Systrans USA, Inc - Missing Deadlines - Poor Quality Work" :
64
- "Gene Baker CPA - Lack of Updates - Poor Communication")),
72
+ react_1.default.createElement("p", { className: "text-gray-600 mt-1" }, selectedIssue.problem)),
65
73
  react_1.default.createElement("div", { className: "border rounded-lg overflow-hidden mb-6" },
66
74
  react_1.default.createElement("div", { className: "bg-gray-50 p-3 border-b" },
67
75
  react_1.default.createElement("h3", { className: "font-medium" }, "Response Type")),
@@ -81,7 +89,7 @@ const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
81
89
  : "text-gray-500 text-xs mt-1" }, type.description))))))),
82
90
  react_1.default.createElement("div", null,
83
91
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Your Response"),
84
- react_1.default.createElement(base_ui_1.Input, { type: "text", value: responseInput, placeholder: "Address the client's concerns...", onChange: (e) => setResponseInput(e.target.value) })),
92
+ react_1.default.createElement(base_ui_1.Input, { type: "text", value: responseInput, placeholder: "Address the concern...", onChange: (e) => setResponseInput(e.target.value) })),
85
93
  react_1.default.createElement("div", null,
86
94
  react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Supporting Documents (Optional)"),
87
95
  react_1.default.createElement("div", { className: "border border-dashed border-gray-300 rounded-md p-6 text-center" },
@@ -98,6 +106,6 @@ const EscalationRespondForm = ({ goBack, selectedIssue, goHome }) => {
98
106
  react_1.default.createElement("p", { className: "mt-1" }, "Your response will be visible to the client and Paro support team. Be professional and focus on resolution.")))),
99
107
  react_1.default.createElement("div", { className: "flex justify-end space-x-3" },
100
108
  react_1.default.createElement(base_ui_1.Button, { label: "Cancel", onClick: goBack }),
101
- react_1.default.createElement(base_ui_1.Button, { label: "Submit Response", color: "primary", onClick: goHome })))))));
109
+ react_1.default.createElement(base_ui_1.Button, { label: "Submit Response", color: "primary", onClick: submitResponse })))))));
102
110
  };
103
111
  exports.default = EscalationRespondForm;
@@ -33,11 +33,12 @@ const core_1 = require("@material-ui/core");
33
33
  const LogTimeModalAuthenticated_1 = require("../ProjectCard/LogTimeModalAuthenticated");
34
34
  const dayjs_1 = __importDefault(require("dayjs"));
35
35
  const issueTypeOptions = [
36
- { value: 'Communication Issues', label: 'Communication Issues' },
36
+ { value: 'CommunicationIssues', label: 'Communication Issues' },
37
37
  { value: 'Professionalism', label: 'Professionalism' },
38
- { value: 'Project Abandonment', label: 'Project Abandonment' },
39
- { value: 'Delayed Deliverables or Deadlines due to Missing Information/Documentation', label: 'Delayed Deliverables or Deadlines due to Missing Information/Documentation' },
40
- { value: 'Billing Concern', label: 'Billing Concern' },
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' },
41
42
  { value: 'Other', label: 'Other' },
42
43
  ];
43
44
  const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = false }) => {
@@ -51,7 +52,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
51
52
  const [projectOptions, setProjectOptions] = (0, react_1.useState)([]);
52
53
  const [selectedProjects, setSelectedProjects] = (0, react_1.useState)([]);
53
54
  const [issueType, setIssueType] = (0, react_1.useState)('');
54
- const [priority, setPriority] = (0, react_1.useState)('');
55
+ const [severity, setSeverity] = (0, react_1.useState)('');
55
56
  const [startDate, setStartDate] = (0, react_1.useState)(undefined);
56
57
  const [isDateInvalid, setIsDateInvalid] = (0, react_1.useState)(false);
57
58
  const fileInputRef = (0, react_1.useRef)(null);
@@ -90,7 +91,7 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
90
91
  const requiredProjectSelection = isExpert || (!isExpert && selectedProjects.length > 0);
91
92
  return (selectedExpert !== null &&
92
93
  issueType !== '' &&
93
- priority !== '' &&
94
+ severity !== '' &&
94
95
  problemInput.trim() !== '' &&
95
96
  outcomeInput.trim() !== '' &&
96
97
  isChecked &&
@@ -104,9 +105,9 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
104
105
  selectedExpert,
105
106
  selectedProjects,
106
107
  issueType,
107
- priority,
108
+ severity,
108
109
  startDate,
109
- problemDescription: problemInput,
110
+ problem: problemInput,
110
111
  expectedOutcome: outcomeInput,
111
112
  supportingDocs: uploadFiles.map(f => f.name),
112
113
  };
@@ -172,12 +173,21 @@ const EscalationSubmitForm = ({ goBack, goHome, experts, projects, isExpert = fa
172
173
  react_1.default.createElement(core_1.Select, { fullWidth: true, value: issueType, onChange: e => setIssueType(e.target.value), displayEmpty: true, variant: "outlined" },
173
174
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
174
175
  react_1.default.createElement("em", null, "Select issue type...")),
175
- issueTypeOptions.map(option => (react_1.default.createElement(core_1.MenuItem, { key: option.value, value: option.value }, option.label))))),
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))))),
176
186
  react_1.default.createElement("div", null,
177
- react_1.default.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Priority Level"),
178
- react_1.default.createElement(core_1.Select, { fullWidth: true, value: priority, onChange: e => setPriority(e.target.value), displayEmpty: true, variant: "outlined" },
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" },
179
189
  react_1.default.createElement(core_1.MenuItem, { disabled: true, value: "" },
180
- react_1.default.createElement("em", null, "Select priority...")),
190
+ react_1.default.createElement("em", null, "Select severity...")),
181
191
  react_1.default.createElement(core_1.MenuItem, { value: "Critical" }, "Critical"),
182
192
  react_1.default.createElement(core_1.MenuItem, { value: "High" }, "High"),
183
193
  react_1.default.createElement(core_1.MenuItem, { value: "Medium" }, "Medium"),
@@ -9,22 +9,22 @@ const EscalationTabs = ({ activeTab, setActiveTab, activeIssues = 0, inProgressI
9
9
  return (react_1.default.createElement("div", { className: "border-b border-gray-200 mb-6" },
10
10
  react_1.default.createElement("nav", { className: "flex space-x-8" },
11
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-[#EF5360] text-[#EF5360]'
12
+ ? 'border-[#A73A43] text-[#A73A43]'
13
13
  : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
14
- react_1.default.createElement("div", { className: "bg-[#EF5360] w-2 h-2 rounded-full mr-2" }),
14
+ react_1.default.createElement("div", { className: "bg-[#A73A43] w-2 h-2 rounded-full mr-2" }),
15
15
  "Action Required",
16
- react_1.default.createElement("div", { className: "bg-red-100 text-[#EF5360] font-bold rounded-full px-2 py-1 text-xs ml-2" }, activeIssues)),
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
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-blue-500 text-blue-600'
18
+ ? 'border-[#115484] text-[#115484]'
19
19
  : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
20
- react_1.default.createElement("div", { className: "bg-blue-500 w-2 h-2 rounded-full mr-2" }),
20
+ react_1.default.createElement("div", { className: "bg-[#115484] w-2 h-2 rounded-full mr-2" }),
21
21
  "In Progress",
22
- react_1.default.createElement("div", { className: "bg-blue-100 text-blue-800 font-bold rounded-full px-2 py-1 text-xs ml-2" }, inProgressIssues)),
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
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-green-500 text-green-600'
24
+ ? 'border-[#12756F] text-[#12756F]'
25
25
  : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'}` },
26
- react_1.default.createElement("div", { className: "bg-green-500 w-2 h-2 rounded-full mr-2" }),
26
+ react_1.default.createElement("div", { className: "bg-[#12756F] w-2 h-2 rounded-full mr-2" }),
27
27
  "Resolved",
28
- react_1.default.createElement("div", { className: "bg-green-100 text-green-800 font-bold rounded-full px-2 py-1 text-xs ml-2" }, resolvedIssues)))));
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
29
  };
30
30
  exports.default = EscalationTabs;
@@ -1,17 +1,17 @@
1
- type EscalationChatDetails = {
1
+ export type EscalationChatDetails = {
2
2
  title: string;
3
3
  project: string;
4
- caseId: string;
4
+ id: string;
5
5
  status: string;
6
6
  };
7
7
  interface EscalationTabProps {
8
8
  activeTab: string;
9
9
  openEscalationChat: (details: EscalationChatDetails) => void;
10
- setSelectedIssue: (issue: string) => void;
10
+ setSelectedIssueId: (issue: number) => void;
11
11
  activeIssues: any[];
12
12
  inProgressIssues: any[];
13
13
  resolvedIssues: any[];
14
14
  isExpert: boolean;
15
15
  }
16
- declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssue, activeIssues, inProgressIssues, resolvedIssues, isExpert, }: EscalationTabProps) => JSX.Element;
16
+ declare const EscalationTabsContent: ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }: EscalationTabProps) => JSX.Element;
17
17
  export default EscalationTabsContent;
@@ -1,120 +1,89 @@
1
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
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const base_ui_1 = require("@paro.io/base-ui");
7
29
  const react_1 = __importDefault(require("react"));
30
+ const EscalationIssueCard_1 = __importStar(require("./EscalationIssueCard"));
31
+ const base_ui_1 = require("@paro.io/base-ui");
8
32
  ;
9
- const getBackgroundColor = (type) => {
10
- switch (type) {
11
- case 'Critical':
12
- return 'danger';
13
- case 'High':
14
- return 'warning';
15
- case 'Medium':
16
- return 'info';
17
- case 'Low':
18
- return 'default';
19
- default:
20
- return 'default';
21
- }
22
- };
23
- const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssue, activeIssues, inProgressIssues, resolvedIssues, isExpert, }) => {
33
+ const EscalationTabsContent = ({ activeTab, openEscalationChat, setSelectedIssueId, activeIssues, inProgressIssues, resolvedIssues, isExpert, }) => {
24
34
  if (activeTab === 'action-required') {
25
35
  return (react_1.default.createElement("div", null,
26
36
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
27
- react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues Requiring Your Response"),
28
- react_1.default.createElement("div", { className: "text-sm text-gray-500" }, "Ordered by urgency")),
29
- activeIssues.length > 0 ? react_1.default.createElement("div", { className: "space-y-4" }, activeIssues.map((issue) => (react_1.default.createElement("div", { key: issue.caseId, className: "border border-gray-200 rounded-lg bg-white p-4" },
30
- react_1.default.createElement("div", { className: "flex items-center" },
31
- react_1.default.createElement(base_ui_1.Tag, { label: issue.tag, color: getBackgroundColor(issue.tag) }),
32
- react_1.default.createElement("div", { className: "flex-1 ml-2" },
33
- react_1.default.createElement("div", { className: "font-bold" }, issue.title),
34
- react_1.default.createElement("div", { className: "text-xs text-gray-500" },
35
- issue.project,
36
- " \u2022 Case #",
37
- issue.caseId))),
38
- react_1.default.createElement("div", { className: "bg-gray-50 rounded-md p-3 mb-4 border" },
39
- react_1.default.createElement("div", { className: "flex items-center justify-between mb-2" },
40
- react_1.default.createElement("div", { className: "text-xs text-gray-500" }, issue.submitted)),
41
- react_1.default.createElement("div", { className: "text-sm text-gray-600 italic" }, issue.message)),
42
- react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
43
- react_1.default.createElement(base_ui_1.Button, { label: "Chat", onClick: () => openEscalationChat({
44
- title: issue.title,
45
- project: issue.project,
46
- caseId: issue.caseId,
47
- status: issue.status
48
- }), color: "primary" }),
49
- react_1.default.createElement(base_ui_1.Button, { label: "Respond to Escalation", onClick: () => setSelectedIssue(issue.respondKey), color: 'info', className: "bg-info hover:bg-white text-white hover:text-info-dark" }))))))
50
- :
51
- react_1.default.createElement("div", null, "No Active issues.")));
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 })));
52
39
  }
53
40
  if (activeTab === 'in-progress') {
54
41
  return (react_1.default.createElement("div", null,
55
42
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
56
- react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Issues In Progress"),
57
- react_1.default.createElement("div", { className: "text-sm text-gray-500" }, "Being handled by our team")),
58
- inProgressIssues.length > 0 ? react_1.default.createElement("div", { className: "space-y-4" }, inProgressIssues.map((issue) => (react_1.default.createElement("div", { key: issue.caseId, className: "border border-gray-200 rounded-lg bg-white p-4" },
59
- react_1.default.createElement("div", { className: "flex items-start justify-between mb-3" },
60
- react_1.default.createElement("div", { className: "flex items-center" },
61
- react_1.default.createElement(base_ui_1.Tag, { label: issue.tag, color: getBackgroundColor(issue.tag) }),
62
- react_1.default.createElement("div", { className: "flex-1 ml-2" },
63
- react_1.default.createElement("div", { className: "font-bold" }, issue.title),
64
- react_1.default.createElement("div", { className: "text-xs text-gray-500" },
65
- issue.project,
66
- " \u2022 Case #",
67
- issue.caseId),
68
- issue.extra))),
69
- react_1.default.createElement("div", { className: "bg-gray-50 rounded-md p-3 mb-4 border" },
70
- react_1.default.createElement("div", { className: "flex items-center justify-between mb-2" },
71
- react_1.default.createElement("span", { className: "text-sm font-medium" }, issue.updateLabel),
72
- react_1.default.createElement("div", { className: "text-xs text-gray-500" }, issue.updateTime)),
73
- react_1.default.createElement("div", { className: "text-sm text-gray-600 italic mb-3" }, issue.message)),
74
- react_1.default.createElement("div", { className: "flex flex-wrap gap-2" },
75
- react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
76
- title: issue.title,
77
- project: issue.project,
78
- caseId: issue.caseId,
79
- status: issue.status
80
- }), label: "Chat", color: "primary" }),
81
- !isExpert && react_1.default.createElement(base_ui_1.Button, { onClick: issue.markResolved, label: "Mark as Resolved", color: "info", className: "bg-info hover:bg-none text-white hover:text-info-dark" })))))) :
82
- react_1.default.createElement("div", null, "No inProgress issues.")));
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 })));
83
45
  }
84
46
  if (activeTab === 'resolved') {
85
47
  return (react_1.default.createElement("div", null,
86
48
  react_1.default.createElement("div", { className: "flex items-center justify-between mb-4" },
87
- react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, "Recently Resolved Issues"),
88
- react_1.default.createElement("button", { className: "text-sm text-gray-500 hover:text-gray-700 flex items-center" },
89
- react_1.default.createElement("span", null, "View All History"))),
90
- resolvedIssues.length > 0 ? react_1.default.createElement("div", { className: "space-y-3" }, resolvedIssues.map((issue) => (react_1.default.createElement("div", { key: issue.caseId, className: "border border-green-200 rounded-lg bg-green-50 p-4" },
91
- react_1.default.createElement("div", { className: "flex items-start justify-between" },
92
- react_1.default.createElement("div", { className: "flex items-start" },
93
- react_1.default.createElement("div", null,
94
- react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-1" }, issue.title),
95
- react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
96
- react_1.default.createElement("span", null, issue.person),
97
- react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
98
- react_1.default.createElement("span", null, issue.project),
99
- react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
100
- react_1.default.createElement("span", null,
101
- "Case #",
102
- issue.caseId)),
103
- react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-3" }, issue.description),
104
- react_1.default.createElement("div", { className: "flex items-center text-sm text-gray-600 mb-2" },
105
- react_1.default.createElement("span", { className: "text-xs text-gray-500" },
106
- "Resolved ",
107
- issue.resolvedDate),
108
- react_1.default.createElement("span", { className: "mx-2" }, "\u2022"),
109
- react_1.default.createElement("span", { className: "text-xs text-gray-500" },
110
- "Resolved By ",
111
- issue.resolvedBy)))),
112
- react_1.default.createElement(base_ui_1.Button, { onClick: () => openEscalationChat({
113
- title: issue.chatTitle,
114
- project: issue.project,
115
- caseId: issue.caseId,
116
- status: issue.chatStatus
117
- }), label: "Chat", color: "primary" }))))))
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
+ }))
118
87
  :
119
88
  react_1.default.createElement("div", null, "No resolved issues.")));
120
89
  }
@@ -38,17 +38,18 @@ const EscalationChat_1 = __importDefault(require("./EscalationChat"));
38
38
  const AccountSuspensionBanner_1 = __importDefault(require("./AccountSuspensionBanner"));
39
39
  const AccountSuspensionModal_1 = __importDefault(require("./AccountSuspensionModal"));
40
40
  const base_icons_1 = require("@paro.io/base-icons");
41
+ const EscalationIssueCard_1 = require("./EscalationIssueCard");
41
42
  const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProgressIssues, resolvedIssues, }) => {
42
43
  const [activeSection, setActiveSection] = (0, react_1.useState)('support');
43
44
  const [selectedProject, setSelectedProject] = (0, react_1.useState)(null);
44
- const [selectedIssue, setSelectedIssue] = (0, react_1.useState)(null);
45
+ const [selectedIssueId, setSelectedIssueId] = (0, react_1.useState)(null); // using selectedIssueId 0 for new escalation submission
45
46
  const [showEscalationChat, setShowEscalationChat] = (0, react_1.useState)(false);
46
47
  const [activeChatIssue, setActiveChatIssue] = (0, react_1.useState)(null); // update required
47
48
  const [activeEscalationTab, setActiveEscalationTab] = (0, react_1.useState)('action-required');
48
49
  const [showSuspensionModal, setShowSuspensionModal] = (0, react_1.useState)(false);
49
50
  const goBack = () => {
50
- if (selectedIssue) {
51
- setSelectedIssue(null);
51
+ if (selectedIssueId !== null) {
52
+ setSelectedIssueId(null);
52
53
  }
53
54
  else if (selectedProject) {
54
55
  setSelectedProject(null);
@@ -58,7 +59,7 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
58
59
  }
59
60
  };
60
61
  const goHome = () => {
61
- setSelectedIssue(null);
62
+ setSelectedIssueId(null);
62
63
  setSelectedProject(null);
63
64
  setActiveSection('support');
64
65
  };
@@ -68,11 +69,13 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
68
69
  };
69
70
  return (react_1.default.createElement("div", { className: "bg-white w-full" },
70
71
  react_1.default.createElement("div", { className: isExpert ? "p-6" : "mx-auto p-6 border-solid border-t-2" },
71
- activeSection === 'support' && !selectedIssue && react_1.default.createElement("div", null,
72
+ activeSection === 'support' && selectedIssueId === null && react_1.default.createElement("div", null,
72
73
  react_1.default.createElement("div", { className: "flex justify-between items-center mb-1 mt-2" },
73
74
  react_1.default.createElement("h2", { className: "text-xl font-bold" }, "Support & Escalation Management"),
74
75
  activeIssues.length && react_1.default.createElement("div", { className: "flex items-center space-x-2" },
75
- react_1.default.createElement(base_ui_1.Tag, { label: `${activeIssues.length} Active Issues`, color: "danger" }))),
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"))),
76
79
  react_1.default.createElement("div", { className: "border-b pb-4 mb-6" },
77
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.`)),
78
81
  react_1.default.createElement("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6" },
@@ -106,17 +109,17 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
106
109
  react_1.default.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Priority Levels & Response Times"),
107
110
  react_1.default.createElement("div", { className: "space-y-2 text-sm" },
108
111
  react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
109
- react_1.default.createElement(base_ui_1.Tag, { label: "Critical", color: "danger" }),
112
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Critical" }),
110
113
  react_1.default.createElement("span", null, "All work blocked")),
111
114
  react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
112
- react_1.default.createElement(base_ui_1.Tag, { label: "High", color: "warning" }),
115
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "High" }),
113
116
  react_1.default.createElement("span", null, "Progress blocked")),
114
117
  react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
115
- react_1.default.createElement(base_ui_1.Tag, { label: "Medium", color: "info" }),
118
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Medium" }),
116
119
  react_1.default.createElement("span", null, "Timeline impacted")),
117
120
  react_1.default.createElement("div", { className: "flex items-center gap-x-2" },
118
- react_1.default.createElement(base_ui_1.Tag, { label: "Low", color: "neutral" }),
119
- react_1.default.createElement("span", null, "Minor impact")))))),
121
+ react_1.default.createElement(EscalationIssueCard_1.CustomTag, { label: "Low" }),
122
+ react_1.default.createElement("span", null, "Minor issues")))))),
120
123
  isExpert &&
121
124
  react_1.default.createElement("div", { className: "rounded-lg p-2 mb-4 shadow-lg" },
122
125
  react_1.default.createElement("div", { className: "flex items-center justify-between" },
@@ -127,15 +130,15 @@ const Escalations = ({ experts, projects, isExpert = false, activeIssues, inProg
127
130
  react_1.default.createElement("div", { className: "mr-4" },
128
131
  react_1.default.createElement("h3", { className: "font-semibold text-sm mb-1" }, "Need Support with a Client?"),
129
132
  react_1.default.createElement("p", { className: "text-xs" }, "Report payment, scope, or communication activeIssues")))),
130
- react_1.default.createElement(base_ui_1.Button, { label: "Report issue", onClick: () => setSelectedIssue('submit-escalation'), iconLeft: react_1.default.createElement(base_icons_1.IconExclamation, { size: "sm", className: "text-white" }), color: "info", className: "bg-info hover:bg-white text-white hover:text-info-dark" }))),
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" }))),
131
134
  isExpert &&
132
135
  react_1.default.createElement(AccountSuspensionBanner_1.default, { setShowSuspensionModal: setShowSuspensionModal, suspended: false }),
133
136
  !isExpert &&
134
- react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssue('submit-escalation') }),
137
+ react_1.default.createElement(EscalationReportBanner_1.default, { onReport: () => setSelectedIssueId(0) }),
135
138
  react_1.default.createElement(EscalationTabs_1.default, { activeTab: activeEscalationTab, setActiveTab: setActiveEscalationTab, activeIssues: activeIssues.length, inProgressIssues: inProgressIssues.length, resolvedIssues: resolvedIssues.length }),
136
- react_1.default.createElement(EscalationTabsContent_1.default, { activeTab: activeEscalationTab, openEscalationChat: openEscalationChat, setSelectedIssue: setSelectedIssue, activeIssues: activeIssues, inProgressIssues: inProgressIssues, resolvedIssues: resolvedIssues, isExpert: isExpert })),
137
- activeSection === 'support' && (selectedIssue === 'respond-to-issue-critical' || selectedIssue === 'respond-to-issue-medium') && (react_1.default.createElement(EscalationRespondForm_1.default, { goBack: goBack, selectedIssue: selectedIssue, goHome: goHome })),
138
- activeSection === 'support' && selectedIssue === 'submit-escalation' && (react_1.default.createElement(EscalationSubmitForm_1.default, { goBack: goBack, goHome: goHome, experts: experts, projects: projects, isExpert: isExpert })),
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 })),
139
142
  showEscalationChat && activeChatIssue && (react_1.default.createElement(EscalationChat_1.default, { activeChatIssue: activeChatIssue, showEscalationChat: showEscalationChat, setShowEscalationChat: setShowEscalationChat })),
140
143
  showSuspensionModal &&
141
144
  react_1.default.createElement(AccountSuspensionModal_1.default, { showSuspensionModal: showSuspensionModal, onClose: () => setShowSuspensionModal(false) }))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.12.37",
3
+ "version": "1.12.39",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {