@paro.io/expert-shared-components 1.14.5 → 1.14.6

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.
@@ -9,10 +9,13 @@ interface EngagementHeaderProps {
9
9
  expertName: string;
10
10
  expertTitle: string;
11
11
  startDate: string;
12
- status: 'Discovery' | 'Kickoff_Complete' | 'In_Progress' | 'Completed' | 'Paused' | 'Cancelled';
12
+ status: 'PreKickoff' | 'Kickoff' | 'Setup' | 'Active' | 'Renewal';
13
13
  clientTabs: ClientTab[];
14
14
  selectedClientId: string | null;
15
15
  onClientChange: (opportunityId: string) => void;
16
+ allFocusAreasCompleted?: boolean;
17
+ onMoveToNextStage?: () => void;
18
+ isLoading?: boolean;
16
19
  }
17
20
  export declare const EngagementHeader: React.FC<EngagementHeaderProps>;
18
21
  export {};
@@ -7,22 +7,20 @@ exports.EngagementHeader = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const date_fns_1 = require("date-fns");
9
9
  const STATUS_COLORS = {
10
- Discovery: 'bg-orange-100 text-orange-800 border-orange-200',
11
- Kickoff_Complete: 'bg-green-100 text-green-800 border-green-200',
12
- In_Progress: 'bg-blue-100 text-blue-800 border-blue-200',
13
- Completed: 'bg-gray-100 text-gray-800 border-gray-200',
14
- Paused: 'bg-orange-100 text-orange-800 border-orange-200',
15
- Cancelled: 'bg-red-100 text-red-800 border-red-200',
10
+ 'PreKickoff': 'bg-orange-100 text-orange-800 border-orange-200',
11
+ Kickoff: 'bg-green-100 text-green-800 border-green-200',
12
+ Setup: 'bg-green-100 text-green-800 border-green-200',
13
+ Active: 'bg-green-100 text-green-800 border-green-200',
14
+ Renewal: 'bg-green-100 text-green-800 border-green-200',
16
15
  };
17
16
  const STATUS_LABELS = {
18
- Discovery: 'DISCOVERY',
19
- Kickoff_Complete: 'KICKOFF COMPLETE',
20
- In_Progress: 'IN PROGRESS',
21
- Completed: 'COMPLETED',
22
- Paused: 'PAUSED',
23
- Cancelled: 'CANCELLED',
17
+ 'PreKickoff': 'PRE KICKOFF',
18
+ Kickoff: 'KICKOFF',
19
+ Setup: 'SETUP',
20
+ Active: 'ACTIVE',
21
+ Renewal: 'RENEWAL',
24
22
  };
25
- const EngagementHeader = ({ clientName, expertName, expertTitle, startDate, status, clientTabs, selectedClientId, onClientChange }) => {
23
+ const EngagementHeader = ({ clientName, expertName, expertTitle, startDate, status, clientTabs, selectedClientId, onClientChange, allFocusAreasCompleted = false, onMoveToNextStage, isLoading = false }) => {
26
24
  const formattedDate = startDate ? (0, date_fns_1.format)(new Date(startDate), 'MMMM dd, yyyy') : (0, date_fns_1.format)(new Date(), 'MMMM dd, yyyy');
27
25
  return (react_1.default.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200" },
28
26
  react_1.default.createElement("div", { className: "px-6 pt-4" },
@@ -42,9 +40,14 @@ const EngagementHeader = ({ clientName, expertName, expertTitle, startDate, stat
42
40
  expertTitle,
43
41
  " \u2022 Started ",
44
42
  formattedDate)),
45
- react_1.default.createElement("div", { className: "flex items-center" },
43
+ react_1.default.createElement("div", { className: "flex items-center space-x-3" },
46
44
  react_1.default.createElement("span", { className: `inline-flex items-center px-3 py-1 rounded-full text-sm font-medium ${STATUS_COLORS[status]}` },
47
45
  react_1.default.createElement("div", { className: "w-2 h-2 bg-current rounded-full mr-1.5" }),
48
- STATUS_LABELS[status]))))));
46
+ STATUS_LABELS[status]),
47
+ allFocusAreasCompleted && status !== 'Active' && onMoveToNextStage && (react_1.default.createElement("button", { onClick: onMoveToNextStage, disabled: isLoading, className: `inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors ${isLoading ? 'opacity-50 cursor-not-allowed' : ''}` }, isLoading ? (react_1.default.createElement(react_1.default.Fragment, null,
48
+ react_1.default.createElement("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" },
49
+ react_1.default.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
50
+ react_1.default.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })),
51
+ "Processing...")) : ('Move to Next Stage'))))))));
49
52
  };
50
53
  exports.EngagementHeader = EngagementHeader;
@@ -28,9 +28,9 @@ const react_1 = __importStar(require("react"));
28
28
  const date_fns_1 = require("date-fns");
29
29
  const utils_1 = require("../../shared/utils");
30
30
  const STATUS_COLORS = {
31
- CONFIRMED: 'bg-green-100 text-green-800 border-green-200',
31
+ CONFIRMED: 'bg-blue-100 text-blue-800 border-blue-200',
32
32
  IN_PROGRESS: 'bg-blue-100 text-blue-800 border-blue-200',
33
- COMPLETED: 'bg-gray-100 text-gray-800 border-gray-200',
33
+ COMPLETED: 'bg-green-100 text-green-800 border-green-200',
34
34
  AT_RISK: 'bg-red-100 text-red-800 border-red-200',
35
35
  };
36
36
  const STATUS_ICONS = {
@@ -125,6 +125,32 @@ const FocusAreas = ({ focusAreas, updateOpportunityFocusArea, GetOpportunityInsi
125
125
  // Here you would typically call an API to update the focus area
126
126
  console.log('Saving focus area:', id, newTitle, newDescription);
127
127
  };
128
+ const handleStatusUpdate = (focusArea, newStatus) => {
129
+ try {
130
+ // Update in the backend
131
+ updateOpportunityFocusArea({
132
+ variables: {
133
+ opportunityId: selectedOpportunityId,
134
+ input: {
135
+ id: focusArea.id,
136
+ status: newStatus
137
+ }
138
+ },
139
+ refetchQueries: [
140
+ { query: GetOpportunityInsightsDocument, variables: { opportunityId: selectedOpportunityId } }
141
+ ]
142
+ });
143
+ // Update local state
144
+ setLocalFocusAreas(prev => prev.map(area => area.id === focusArea.id
145
+ ? Object.assign(Object.assign({}, area), { status: newStatus }) : area));
146
+ (0, utils_1.showToast)('success', `Focus area marked as ${newStatus.toLowerCase()}`);
147
+ onSaveFocusArea && onSaveFocusArea();
148
+ }
149
+ catch (error) {
150
+ console.error('Error updating focus area status:', error);
151
+ (0, utils_1.showToast)('warning', 'Error updating focus area status. Please try again.');
152
+ }
153
+ };
128
154
  return (react_1.default.createElement(react_1.default.Fragment, null,
129
155
  react_1.default.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200" },
130
156
  react_1.default.createElement("div", { className: "px-6 py-4 border-b border-gray-200" },
@@ -145,9 +171,13 @@ const FocusAreas = ({ focusAreas, updateOpportunityFocusArea, GetOpportunityInsi
145
171
  STATUS_ICONS[area.status],
146
172
  " ",
147
173
  area.status.replace('_', ' '))),
148
- react_1.default.createElement("button", { onClick: () => handleEditClick(area), className: "flex items-center space-x-1 px-2 py-1 text-xs font-medium text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors" },
149
- react_1.default.createElement("span", null, "\u270F\uFE0F"),
150
- react_1.default.createElement("span", null, "Edit Focus Area"))),
174
+ react_1.default.createElement("div", { className: "flex items-center space-x-2" },
175
+ area.status !== 'COMPLETED' && (react_1.default.createElement("button", { onClick: () => handleStatusUpdate(area, 'COMPLETED'), className: "flex items-center space-x-1 px-2 py-1 text-xs font-medium text-green-600 bg-green-50 hover:text-green-800 hover:bg-green-100 rounded transition-colors" },
176
+ react_1.default.createElement("span", null, "\u2713"),
177
+ react_1.default.createElement("span", null, "Mark as Complete"))),
178
+ react_1.default.createElement("button", { onClick: () => handleEditClick(area), className: "flex items-center space-x-1 px-2 py-1 text-xs font-medium text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors" },
179
+ react_1.default.createElement("span", null, "\u270F\uFE0F"),
180
+ react_1.default.createElement("span", null, "Edit Focus Area")))),
151
181
  react_1.default.createElement("p", { className: "text-sm text-gray-600 mb-2" }, area.description),
152
182
  react_1.default.createElement("div", { className: "flex items-center space-x-4 text-xs text-gray-500" },
153
183
  react_1.default.createElement("span", null, (0, date_fns_1.format)(new Date(area.dueDate), 'MMM dd, yyyy')),
@@ -77,48 +77,51 @@ const getPriorityLevel = (priority) => {
77
77
  return PRIORITY_LEVELS[0];
78
78
  }
79
79
  };
80
+ // Convert priority level string to priority value
81
+ const getPriorityNumber = (priorityLevel) => {
82
+ switch (priorityLevel) {
83
+ case 'Urgent - Blocks current work': return 'HIGH';
84
+ case 'High - Needed this week': return 'MEDIUM';
85
+ case 'Medium - Needed next week':
86
+ case 'Low - Needed eventually':
87
+ default: return 'LOW';
88
+ }
89
+ };
80
90
  // Request Information Modal Component
81
91
  const RequestInfoModal = ({ isOpen, missingInfoItem, onClose, onSubmit, documentCenterController, isInternal, handleRouteToDocuments, isParoIntelligenceRolePresent, }) => {
82
92
  const [submitting, setSubmitting] = (0, react_1.useState)(false);
83
- const [formData, setFormData] = (0, react_1.useState)({
84
- informationCategory: INFORMATION_CATEGORIES[0], // Default to first category
85
- priorityLevel: PRIORITY_LEVELS[0], // Default to first priority
86
- specificInformation: '',
87
- });
93
+ const [informationCategory, setInformationCategory] = (0, react_1.useState)(INFORMATION_CATEGORIES[0]);
94
+ const [priorityLevel, setPriorityLevel] = (0, react_1.useState)(PRIORITY_LEVELS[0]);
95
+ const [specificInformation, setSpecificInformation] = (0, react_1.useState)('');
88
96
  react_1.default.useEffect(() => {
89
97
  if (missingInfoItem) {
90
- setFormData({
91
- informationCategory: missingInfoItem.category || INFORMATION_CATEGORIES[0],
92
- priorityLevel: getPriorityLevel(missingInfoItem.priority),
93
- specificInformation: missingInfoItem.description || '',
94
- });
98
+ setInformationCategory(missingInfoItem.category || INFORMATION_CATEGORIES[0]);
99
+ setPriorityLevel(getPriorityLevel(missingInfoItem.priority));
100
+ setSpecificInformation(missingInfoItem.description || '');
95
101
  }
96
102
  }, [missingInfoItem]);
103
+ const handleCancel = () => {
104
+ setInformationCategory(INFORMATION_CATEGORIES[0]);
105
+ setPriorityLevel(PRIORITY_LEVELS[0]);
106
+ setSpecificInformation('');
107
+ setSubmitting(false);
108
+ onClose();
109
+ };
97
110
  const handleSubmit = () => {
98
111
  setSubmitting(true);
99
- try {
100
- onSubmit(Object.assign(Object.assign({}, formData), { itemId: missingInfoItem === null || missingInfoItem === void 0 ? void 0 : missingInfoItem.id, itemTitle: missingInfoItem === null || missingInfoItem === void 0 ? void 0 : missingInfoItem.title }));
101
- }
102
- catch (e) {
103
- console.error("Error while submitting request", e);
104
- }
105
- finally {
112
+ const data = {
113
+ informationCategory: informationCategory,
114
+ priority: getPriorityNumber(priorityLevel),
115
+ specificInformation: specificInformation,
116
+ };
117
+ if (onSubmit) {
118
+ onSubmit(data);
119
+ setInformationCategory(INFORMATION_CATEGORIES[0]);
120
+ setPriorityLevel(PRIORITY_LEVELS[0]);
121
+ setSpecificInformation('');
106
122
  setSubmitting(false);
123
+ onClose();
107
124
  }
108
- onClose();
109
- };
110
- const handleCancel = () => {
111
- // Reset form data when canceling
112
- if (missingInfoItem) {
113
- setFormData({
114
- informationCategory: missingInfoItem.category || '',
115
- priorityLevel: missingInfoItem.priority === 'HIGH' ? 'Urgent - Blocks current work' :
116
- missingInfoItem.priority === 'MEDIUM' ? 'High - Needed this week' :
117
- 'Medium - Needed next week',
118
- specificInformation: missingInfoItem.description || '',
119
- });
120
- }
121
- onClose();
122
125
  };
123
126
  const handleOpenDocumentCenter = () => {
124
127
  if (isInternal && handleRouteToDocuments) {
@@ -155,13 +158,13 @@ const RequestInfoModal = ({ isOpen, missingInfoItem, onClose, onSubmit, document
155
158
  "View Documents in Document Center"))))),
156
159
  react_1.default.createElement("div", null,
157
160
  react_1.default.createElement("label", { htmlFor: "informationCategory", className: "block text-sm font-medium text-gray-700 mb-1" }, "Information Category"),
158
- react_1.default.createElement("select", { id: "informationCategory", disabled: isInternal && !isParoIntelligenceRolePresent, value: formData.informationCategory, onChange: (e) => setFormData(prev => { var _a; return (Object.assign(Object.assign({}, prev), { informationCategory: (_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value })); }), className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" }, INFORMATION_CATEGORIES.map((category) => (react_1.default.createElement("option", { key: category, value: category }, category))))),
161
+ react_1.default.createElement("select", { id: "informationCategory", disabled: isInternal && !isParoIntelligenceRolePresent, value: informationCategory, onChange: (e) => { var _a; return setInformationCategory((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value); }, className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" }, INFORMATION_CATEGORIES.map((category) => (react_1.default.createElement("option", { key: category, value: category }, category))))),
159
162
  react_1.default.createElement("div", null,
160
163
  react_1.default.createElement("label", { htmlFor: "priorityLevel", className: "block text-sm font-medium text-gray-700 mb-1" }, "Priority Level"),
161
- react_1.default.createElement("select", { id: "priorityLevel", disabled: isInternal && !isParoIntelligenceRolePresent, value: formData.priorityLevel, onChange: (e) => setFormData(prev => { var _a; return (Object.assign(Object.assign({}, prev), { priorityLevel: (_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value })); }), className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" }, PRIORITY_LEVELS.map((level) => (react_1.default.createElement("option", { key: level, value: level }, level))))),
164
+ react_1.default.createElement("select", { id: "priorityLevel", disabled: isInternal && !isParoIntelligenceRolePresent, value: priorityLevel, onChange: (e) => { var _a; return setPriorityLevel((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value); }, className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm" }, PRIORITY_LEVELS.map((level) => (react_1.default.createElement("option", { key: level, value: level }, level))))),
162
165
  react_1.default.createElement("div", null,
163
166
  react_1.default.createElement("label", { htmlFor: "specificInformation", className: "block text-sm font-medium text-gray-700 mb-1" }, "Specific Information Needed"),
164
- react_1.default.createElement("textarea", { id: "specificInformation", disabled: isInternal && !isParoIntelligenceRolePresent, value: formData.specificInformation, onChange: (e) => setFormData(prev => { var _a; return (Object.assign(Object.assign({}, prev), { specificInformation: (_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value })); }), rows: 4, className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm", placeholder: "Need NetSuite configuration details:\n \n 1. US vs Colombian entity setup\n 2. Consolidation process and requirements" }))),
167
+ react_1.default.createElement("textarea", { id: "specificInformation", disabled: isInternal && !isParoIntelligenceRolePresent, value: specificInformation, onChange: (e) => { var _a; return setSpecificInformation((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.value); }, rows: 4, className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm", placeholder: "Need NetSuite configuration details:\n \n 1. US vs Colombian entity setup\n 2. Consolidation process and requirements" }))),
165
168
  react_1.default.createElement("div", { className: "px-6 py-4 border-t border-gray-200 flex justify-end space-x-3" },
166
169
  react_1.default.createElement("button", { onClick: handleCancel, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-500 transition-colors" }, "Cancel"),
167
170
  react_1.default.createElement("button", { onClick: handleSubmit, disabled: isInternal && !isParoIntelligenceRolePresent, className: `px-4 py-2 text-sm font-medium text-white bg-blue bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors cursor-${isInternal && !isParoIntelligenceRolePresent ? "not-allowed" : "pointer"}` }, buttonText)))));
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  interface ProgressTrackerProps {
3
3
  percentage: number;
4
4
  currentPhase: string;
5
- nextSteps: string;
6
5
  }
7
6
  export declare const ProgressTracker: React.FC<ProgressTrackerProps>;
8
7
  export {};
@@ -6,16 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ProgressTracker = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const PHASE_TABS = [
9
- { id: 'discovery', label: 'Discovery', active: true },
9
+ { id: 'prekickoff', label: 'Pre-Kickoff', active: true },
10
10
  { id: 'kickoff', label: 'Kickoff', active: false },
11
11
  { id: 'setup', label: 'Setup', active: false },
12
12
  { id: 'active', label: 'Active', active: false },
13
13
  { id: 'renewal', label: 'Renewal', active: false },
14
14
  ];
15
- const ProgressTracker = ({ percentage, currentPhase, nextSteps }) => {
15
+ const ProgressTracker = ({ percentage, currentPhase, }) => {
16
16
  return (react_1.default.createElement("div", { className: "bg-white rounded-lg shadow-sm border border-gray-200 mt-6" },
17
17
  react_1.default.createElement("div", { className: "px-6 py-4 border-b border-gray-200" },
18
- react_1.default.createElement("div", { className: "flex space-x-2" }, PHASE_TABS.map((phase) => (react_1.default.createElement("button", { key: phase.id, disabled: !phase.active, className: `px-4 py-2 text-sm font-medium rounded-md transition-colors ${phase.active
18
+ react_1.default.createElement("div", { className: "flex space-x-2" }, PHASE_TABS.map((phase) => (react_1.default.createElement("button", { key: phase.id, disabled: phase.id.toLowerCase() !== currentPhase.toLowerCase(), className: `px-4 py-2 text-sm font-medium rounded-md transition-colors ${phase.id.toLowerCase() === currentPhase.toLowerCase()
19
19
  ? 'bg-green-100 text-green-800 border border-green-200 hover:bg-green-200 cursor-pointer'
20
20
  : 'text-gray-400 bg-gray-50 border border-gray-200 cursor-not-allowed opacity-60'}` }, phase.label)))))));
21
21
  };
@@ -1,10 +1,30 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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;
4
24
  };
5
25
  Object.defineProperty(exports, "__esModule", { value: true });
6
26
  exports.ProjectIntelligence = void 0;
7
- const react_1 = __importDefault(require("react"));
27
+ const react_1 = __importStar(require("react"));
8
28
  const EngagementHeader_1 = require("./EngagementHeader");
9
29
  const ProgressTracker_1 = require("./ProgressTracker");
10
30
  const FocusAreas_1 = require("./FocusAreas");
@@ -14,7 +34,13 @@ const KeyMetrics_1 = require("./KeyMetrics");
14
34
  const MissingInformation_1 = require("./MissingInformation");
15
35
  const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityInsightsData, selectedOpportunityId, setSelectedOpportunityId, GetOpportunityInsightsDocument, updateOpportunityMissingInformation, documentCenterController = null, updateOpportunityFocusArea, isInternal = false, handleRouteToDocuments, onSaveFocusArea, onSaveMissingInformation, isParoIntelligenceRolePresent = false, }) => {
16
36
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10;
37
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
38
+ const [currentPhase, setCurrentPhase] = (0, react_1.useState)('Setup');
39
+ const [nextStageData, setNextStageData] = (0, react_1.useState)(null);
17
40
  const opportunityInsights = opportunityInsightsData === null || opportunityInsightsData === void 0 ? void 0 : opportunityInsightsData.getOpportunityInsights;
41
+ (0, react_1.useEffect)(() => {
42
+ setCurrentPhase((opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.phase) || 'In_Progress');
43
+ }, [opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.phase]);
18
44
  // Create client tabs from checkIfOpportunityInsightsExistData
19
45
  const clientTabs = ((_a = checkIfOpportunityInsightsExistData === null || checkIfOpportunityInsightsExistData === void 0 ? void 0 : checkIfOpportunityInsightsExistData.checkIfOpportunityInsightsExist) === null || _a === void 0 ? void 0 : _a.map((insight) => ({
20
46
  id: insight.opportunityId,
@@ -77,8 +103,12 @@ const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityI
77
103
  };
78
104
  // Convert API focus areas to component format
79
105
  const convertFocusAreas = () => {
80
- if (!(opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.focusAreas))
106
+ if (!(opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.focusAreas) && !nextStageData)
81
107
  return [];
108
+ // If we're showing the next stage data, return that instead
109
+ if (nextStageData && currentPhase === 'Active') {
110
+ return nextStageData.focusAreas;
111
+ }
82
112
  return opportunityInsights.focusAreas.map((area, index) => ({
83
113
  id: (area === null || area === void 0 ? void 0 : area.id) || `focus-${index}`,
84
114
  title: (area === null || area === void 0 ? void 0 : area.title) || 'N/A',
@@ -88,6 +118,87 @@ const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityI
88
118
  priority: mapPriority(area === null || area === void 0 ? void 0 : area.priority)
89
119
  }));
90
120
  };
121
+ // Check if all focus areas are completed
122
+ const areAllFocusAreasCompleted = () => {
123
+ if (!(opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.focusAreas) || opportunityInsights.focusAreas.length === 0) {
124
+ return false;
125
+ }
126
+ return opportunityInsights.focusAreas.every((area) => mapFocusAreaStatus(area === null || area === void 0 ? void 0 : area.status) === 'COMPLETED');
127
+ };
128
+ // Handle moving to the next stage
129
+ const handleMoveToNextStage = () => {
130
+ setIsLoading(true);
131
+ // Create next stage data with financial focus areas and carry over missing information
132
+ const nextStageFocusAreas = [
133
+ {
134
+ id: 'next-focus-1',
135
+ title: 'Clean up prior accounting periods',
136
+ description: 'Review and bring the company\'s books up-to-date for all prior accounting periods before the project start date. This includes entering invoices, applying payments, entering bills, categorizing transactions, and reconciling accounts test',
137
+ status: 'CONFIRMED',
138
+ dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), // 7 days from now
139
+ priority: 'HIGH'
140
+ },
141
+ {
142
+ id: 'next-focus-2',
143
+ title: 'Ongoing bookkeeping and accounting',
144
+ description: 'Provide monthly bookkeeping and accounting support including invoice entry, payment processing, bill entry, transaction categorization, account reconciliations, and reporting package delivery.',
145
+ status: 'CONFIRMED',
146
+ dueDate: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString(), // 14 days from now
147
+ priority: 'MEDIUM'
148
+ },
149
+ {
150
+ id: 'next-focus-3',
151
+ title: 'Transition to new accounting system',
152
+ description: 'Assist in preparing the books and migrating data to the company\'s new front-end accounting system once implemented.',
153
+ status: 'CONFIRMED',
154
+ dueDate: new Date(Date.now() + 10 * 24 * 60 * 60 * 1000).toISOString(), // 10 days from now
155
+ priority: 'HIGH'
156
+ }
157
+ ];
158
+ // Carry over missing information that doesn't have CLIENT_RESPONDED status
159
+ const carriedOverMissingInfo = (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.missingInformation)
160
+ ? opportunityInsights.missingInformation
161
+ .filter((item) => (item === null || item === void 0 ? void 0 : item.status) !== 'CLIENT_RESPONDED')
162
+ .map((item, index) => (Object.assign(Object.assign({}, item), { id: `carried-${item.id || index}` })))
163
+ : [];
164
+ // Add new missing information items
165
+ const newMissingInfo = [
166
+ {
167
+ id: 'new-missing-1',
168
+ title: 'Financial Transaction History',
169
+ description: 'Need access to the last 6 months of financial transaction history for the project',
170
+ priority: 'HIGH',
171
+ category: 'Financial',
172
+ status: 'PENDING'
173
+ },
174
+ {
175
+ id: 'new-missing-2',
176
+ title: 'Budget Approval Documentation',
177
+ description: 'Require documentation showing approval of the current budget allocation',
178
+ priority: 'MEDIUM',
179
+ category: 'Documentation',
180
+ status: 'PENDING'
181
+ },
182
+ {
183
+ id: 'new-missing-3',
184
+ title: 'Financial Stakeholder Contact Information',
185
+ description: 'Need contact details for all financial stakeholders involved in the project',
186
+ priority: 'LOW',
187
+ category: 'Contact',
188
+ status: 'PENDING'
189
+ }
190
+ ];
191
+ // Set the next stage data
192
+ setNextStageData({
193
+ focusAreas: nextStageFocusAreas,
194
+ missingInformation: [...carriedOverMissingInfo, ...newMissingInfo]
195
+ });
196
+ // Simulate loading and then update the UI
197
+ setTimeout(() => {
198
+ setCurrentPhase('Active');
199
+ setIsLoading(false);
200
+ }, 3000);
201
+ };
91
202
  const hasNoProjectIntelligence = !(checkIfOpportunityInsightsExistData === null || checkIfOpportunityInsightsExistData === void 0 ? void 0 : checkIfOpportunityInsightsExistData.checkIfOpportunityInsightsExist) ||
92
203
  checkIfOpportunityInsightsExistData.checkIfOpportunityInsightsExist.length === 0;
93
204
  // If there's no data, show a message
@@ -99,11 +210,54 @@ const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityI
99
210
  react_1.default.createElement("div", { className: "text-2xl font-bold text-gray-700 mb-2" }, "No project intelligence found"),
100
211
  react_1.default.createElement("p", { className: "text-gray-500 max-w-md" }, "No project intelligence found for your won projects. Please check back after you win your next Opportunity!")))));
101
212
  }
213
+ // Get missing information items based on current phase
214
+ const getMissingInformationItems = () => {
215
+ if (nextStageData && currentPhase === 'Active') {
216
+ return nextStageData.missingInformation.map((item, index) => ({
217
+ id: (item === null || item === void 0 ? void 0 : item.id) || `missing-${index}`,
218
+ title: (item === null || item === void 0 ? void 0 : item.title) || 'N/A',
219
+ description: (item === null || item === void 0 ? void 0 : item.description) || 'N/A',
220
+ priority: mapPriority(item === null || item === void 0 ? void 0 : item.priority),
221
+ category: (item === null || item === void 0 ? void 0 : item.category) || 'N/A',
222
+ status: (item === null || item === void 0 ? void 0 : item.status) || undefined,
223
+ clientResponse: (item === null || item === void 0 ? void 0 : item.clientResponse) || undefined
224
+ }));
225
+ }
226
+ return (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.missingInformation) ?
227
+ opportunityInsights.missingInformation.map((item, index) => ({
228
+ id: (item === null || item === void 0 ? void 0 : item.id) || `missing-${index}`,
229
+ title: (item === null || item === void 0 ? void 0 : item.title) || 'N/A',
230
+ description: (item === null || item === void 0 ? void 0 : item.description) || 'N/A',
231
+ priority: mapPriority(item === null || item === void 0 ? void 0 : item.priority),
232
+ category: (item === null || item === void 0 ? void 0 : item.category) || 'N/A',
233
+ status: (item === null || item === void 0 ? void 0 : item.status) || undefined,
234
+ clientResponse: (item === null || item === void 0 ? void 0 : item.clientResponse) || undefined
235
+ })) : [];
236
+ };
237
+ // Get the current phase and next steps text based on the current phase
238
+ const getPhaseInfo = () => {
239
+ if (currentPhase === 'Kickoff') {
240
+ return {
241
+ phaseDisplay: 'Kickoff Phase (Day 1 of 3)',
242
+ nextSteps: 'System access & team introductions'
243
+ };
244
+ }
245
+ else {
246
+ return {
247
+ phaseDisplay: 'Preparation Phase',
248
+ nextSteps: 'Complete initial focus areas'
249
+ };
250
+ }
251
+ };
252
+ const phaseInfo = getPhaseInfo();
102
253
  return (react_1.default.createElement(react_1.default.Fragment, null,
103
254
  react_1.default.createElement("div", { className: "mx-auto px-4 py-8" },
104
- react_1.default.createElement(EngagementHeader_1.EngagementHeader, { clientName: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.opportunityName) || '', expertName: ((_b = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.expertInfo) === null || _b === void 0 ? void 0 : _b.name) || '', expertTitle: ((_c = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.expertInfo) === null || _c === void 0 ? void 0 : _c.role) || '', startDate: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.startDate) || '', status: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.phase) || 'In_Progress', clientTabs: clientTabs, selectedClientId: selectedOpportunityId, onClientChange: handleClientChange }),
105
- react_1.default.createElement(ProgressTracker_1.ProgressTracker, { percentage: 0, currentPhase: "Kickoff Phase (Day 1 of 3)", nextSteps: "System access & team introductions" }),
106
- react_1.default.createElement("div", { className: "flex flex-row space-x-4 mt-8" },
255
+ react_1.default.createElement(EngagementHeader_1.EngagementHeader, { clientName: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.opportunityName) || '', expertName: ((_b = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.expertInfo) === null || _b === void 0 ? void 0 : _b.name) || '', expertTitle: ((_c = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.expertInfo) === null || _c === void 0 ? void 0 : _c.role) || '', startDate: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.startDate) || '', status: currentPhase || (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.phase) || 'In_Progress', clientTabs: clientTabs, selectedClientId: selectedOpportunityId, onClientChange: handleClientChange, allFocusAreasCompleted: areAllFocusAreasCompleted(), onMoveToNextStage: handleMoveToNextStage, isLoading: isLoading }),
256
+ react_1.default.createElement(ProgressTracker_1.ProgressTracker, { percentage: 0, currentPhase: currentPhase }),
257
+ isLoading ? (react_1.default.createElement("div", { className: "flex items-center justify-center h-64" },
258
+ react_1.default.createElement("div", { className: "text-center" },
259
+ react_1.default.createElement("div", { className: "animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mx-auto mb-4" }),
260
+ react_1.default.createElement("p", { className: "text-lg font-medium text-gray-700" }, "Calculating Intelligence for your next Stage")))) : (react_1.default.createElement("div", { className: "flex flex-row space-x-4 mt-8" },
107
261
  react_1.default.createElement("div", { className: "w-2/3 space-7-4" },
108
262
  react_1.default.createElement(FocusAreas_1.FocusAreas, { focusAreas: convertFocusAreas(), onEditFocusAreas: () => { }, updateOpportunityFocusArea: updateOpportunityFocusArea, GetOpportunityInsightsDocument: GetOpportunityInsightsDocument, selectedOpportunityId: selectedOpportunityId, onSaveFocusArea: onSaveFocusArea }),
109
263
  react_1.default.createElement(ProjectHealth_1.ProjectHealth, { healthData: {
@@ -124,16 +278,7 @@ const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityI
124
278
  description: ((_u = (_t = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.opportunityHealth) === null || _t === void 0 ? void 0 : _t.riskManagement) === null || _u === void 0 ? void 0 : _u.description) || 'N/A'
125
279
  }
126
280
  }, className: "mt-8" }),
127
- react_1.default.createElement(MissingInformation_1.MissingInformation, { items: (opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.missingInformation) ?
128
- opportunityInsights.missingInformation.map((item, index) => ({
129
- id: (item === null || item === void 0 ? void 0 : item.id) || `missing-${index}`,
130
- title: (item === null || item === void 0 ? void 0 : item.title) || 'N/A',
131
- description: (item === null || item === void 0 ? void 0 : item.description) || 'N/A',
132
- priority: mapPriority(item === null || item === void 0 ? void 0 : item.priority),
133
- category: (item === null || item === void 0 ? void 0 : item.category) || 'N/A',
134
- status: (item === null || item === void 0 ? void 0 : item.status) || undefined,
135
- clientResponse: (item === null || item === void 0 ? void 0 : item.clientResponse) || undefined
136
- })) : [], className: "mt-8", opportunityId: selectedOpportunityId, GetOpportunityInsightsDocument: GetOpportunityInsightsDocument, updateOpportunityMissingInformation: updateOpportunityMissingInformation, documentCenterController: documentCenterController, isInternal: isInternal, handleRouteToDocuments: handleRouteToDocuments, onSaveMissingInformation: onSaveMissingInformation, isParoIntelligenceRolePresent: isParoIntelligenceRolePresent })),
281
+ react_1.default.createElement(MissingInformation_1.MissingInformation, { items: getMissingInformationItems(), className: "mt-8", opportunityId: selectedOpportunityId, GetOpportunityInsightsDocument: GetOpportunityInsightsDocument, updateOpportunityMissingInformation: updateOpportunityMissingInformation, documentCenterController: documentCenterController, isInternal: isInternal, handleRouteToDocuments: handleRouteToDocuments, onSaveMissingInformation: onSaveMissingInformation, isParoIntelligenceRolePresent: isParoIntelligenceRolePresent })),
137
282
  react_1.default.createElement("div", { className: "w-1/3 space-y-4" },
138
283
  react_1.default.createElement(TeamSection_1.TeamSection, { clientTeam: opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.clientTeam, expert: {
139
284
  id: 'expert-1',
@@ -159,6 +304,6 @@ const ProjectIntelligence = ({ checkIfOpportunityInsightsExistData, opportunityI
159
304
  challenge: ((_8 = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.businessContext) === null || _8 === void 0 ? void 0 : _8.challenge) || 'N/A',
160
305
  opportunity: ((_9 = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.businessContext) === null || _9 === void 0 ? void 0 : _9.opportunity) || 'N/A',
161
306
  tags: ((_10 = opportunityInsights === null || opportunityInsights === void 0 ? void 0 : opportunityInsights.businessContext) === null || _10 === void 0 ? void 0 : _10.tags) || []
162
- }, GetOpportunityInsightsDocument: GetOpportunityInsightsDocument, selectedOpportunityId: selectedOpportunityId }))))));
307
+ }, GetOpportunityInsightsDocument: GetOpportunityInsightsDocument, selectedOpportunityId: selectedOpportunityId })))))));
163
308
  };
164
309
  exports.ProjectIntelligence = ProjectIntelligence;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.14.5",
3
+ "version": "1.14.6",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {