Skip to content

Commit 1f52075

Browse files
committed
Refactor plan approval logic to PlanPage
Moved plan approval and rejection logic from PlanChat to PlanPage for better separation of concerns. Updated PlanChat props to receive approval handlers and state from PlanPage. Improved error handling and UI state management for plan approval workflow. Minor UI adjustment in StreamingPlanState.
1 parent f507dab commit 1f52075

File tree

4 files changed

+78
-96
lines changed

4 files changed

+78
-96
lines changed

src/frontend/src/components/content/PlanChat.tsx

Lines changed: 15 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ interface SimplifiedPlanChatProps extends PlanChatProps {
4343
streamingMessageBuffer: string;
4444
agentMessages: AgentMessageData[];
4545
showProcessingPlanSpinner: boolean;
46-
setShowProcessingPlanSpinner: (show: boolean) => void;
46+
showApprovalButtons: boolean;
47+
handleApprovePlan: () => Promise<void>;
48+
handleRejectPlan: () => Promise<void>;
49+
processingApproval: boolean;
50+
4751
}
4852

4953
const PlanChat: React.FC<SimplifiedPlanChatProps> = ({
@@ -61,79 +65,23 @@ const PlanChat: React.FC<SimplifiedPlanChatProps> = ({
6165
streamingMessageBuffer,
6266
agentMessages,
6367
showProcessingPlanSpinner,
64-
setShowProcessingPlanSpinner
68+
showApprovalButtons,
69+
handleApprovePlan,
70+
handleRejectPlan,
71+
processingApproval
72+
6573

6674
}) => {
6775
const navigate = useNavigate();
6876

6977
const { showToast, dismissToast } = useInlineToaster();
7078
// States
7179

72-
const [processingApproval, setProcessingApproval] = useState(false);
73-
74-
const [showApprovalButtons, setShowApprovalButtons] = useState(true);
75-
76-
77-
78-
79-
// Listen for m_plan streaming
80-
81-
82-
// Handle plan approval
83-
const handleApprovePlan = useCallback(async () => {
84-
if (!planApprovalRequest) return;
85-
86-
setProcessingApproval(true);
87-
let id = showToast("Submitting Approval", "progress");
88-
try {
89-
await apiService.approvePlan({
90-
m_plan_id: planApprovalRequest.id,
91-
plan_id: planData?.plan?.id,
92-
approved: true,
93-
feedback: 'Plan approved by user'
94-
});
95-
96-
dismissToast(id);
97-
onPlanApproval?.(true);
98-
setShowProcessingPlanSpinner?.(true);
99-
setShowApprovalButtons(false);
100-
101-
} catch (error) {
102-
dismissToast(id);
103-
showToast("Failed to submit approval", "error");
104-
console.error('❌ Failed to approve plan:', error);
105-
} finally {
106-
setProcessingApproval(false);
107-
}
108-
}, [planApprovalRequest, planData, onPlanApproval, setShowProcessingPlanSpinner]);
109-
110-
// Handle plan rejection
111-
const handleRejectPlan = useCallback(async () => {
112-
if (!planApprovalRequest) return;
113-
114-
setProcessingApproval(true);
115-
let id = showToast("Submitting cancellation", "progress");
116-
try {
117-
await apiService.approvePlan({
118-
m_plan_id: planApprovalRequest.id,
119-
plan_id: planData?.plan?.id,
120-
approved: false,
121-
feedback: 'Plan rejected by user'
122-
});
123-
124-
dismissToast(id);
125-
onPlanApproval?.(false);
126-
navigate('/');
127-
128-
} catch (error) {
129-
dismissToast(id);
130-
showToast("Failed to submit cancellation", "error");
131-
console.error('❌ Failed to reject plan:', error);
132-
navigate('/');
133-
} finally {
134-
setProcessingApproval(false);
135-
}
136-
}, [planApprovalRequest, planData, onPlanApproval, navigate]);
80+
81+
82+
83+
84+
13785

13886
if (!planData)
13987
return (

src/frontend/src/components/content/streaming/StreamingPlanState.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ const renderPlanExecutionMessage = () => {
6060
backgroundColor: tokens.colorNeutralBackground2,
6161
borderRadius: tokens.borderRadiusMedium,
6262
border: `1px solid ${tokens.colorNeutralStroke1}`,
63-
marginBottom: tokens.spacingVerticalXL
63+
marginBottom: tokens.spacingVerticalXL,
64+
marginTop: tokens.spacingVerticalXL
6465
}}>
6566
<Spinner size="small" />
6667
<span style={{

src/frontend/src/pages/HomePage.tsx

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -77,39 +77,14 @@ const HomePage: React.FC = () => {
7777
}
7878
}
7979

80-
} else {
81-
throw new Error('Invalid response from init_team endpoint');
8280
}
8381

8482
} catch (error) {
8583
console.error('Error initializing team from backend:', error);
86-
showToast("Team initialization failed, using fallback", "warning");
84+
showToast("Team initialization failed", "warning");
8785

8886
// Fallback to the old client-side method
89-
try {
90-
console.log('Using fallback: client-side team loading...');
91-
const teams = await TeamService.getUserTeams();
92-
if (teams.length > 0) {
93-
const hrTeam = teams.find(team => team.name === "Human Resources Team");
94-
const defaultTeam = hrTeam || teams[0];
95-
setSelectedTeam(defaultTeam);
96-
TeamService.storageTeam(defaultTeam);
9787

98-
showToast(
99-
`${defaultTeam.name} team loaded (fallback mode)`,
100-
"info"
101-
);
102-
} else {
103-
console.log('No teams found - user needs to upload a team configuration');
104-
showToast(
105-
"No teams found. Please upload a team configuration.",
106-
"warning"
107-
);
108-
}
109-
} catch (fallbackError) {
110-
console.error('Fallback team loading also failed:', fallbackError);
111-
showToast("Failed to load team configuration", "error");
112-
}
11388
} finally {
11489
setIsLoadingTeam(false);
11590
}

src/frontend/src/pages/PlanPage.tsx

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ const PlanPage: React.FC = () => {
4545
const [submittingChatDisableInput, setSubmittingChatDisableInput] = useState<boolean>(true);
4646
const [error, setError] = useState<Error | null>(null);
4747
const [clarificationMessage, setClarificationMessage] = useState<ParsedUserClarification | null>(null);
48-
48+
const [processingApproval, setProcessingApproval] = useState(false);
4949
const [planApprovalRequest, setPlanApprovalRequest] = useState<MPlanData | null>(null);
5050
const [reloadLeftList, setReloadLeftList] = useState(true);
5151
const [waitingForPlan, setWaitingForPlan] = useState(true);
5252
const [showProcessingPlanSpinner, setShowProcessingPlanSpinner] = useState<boolean>(false);
53+
const [showApprovalButtons, setShowApprovalButtons] = useState<boolean>(true);
5354
// WebSocket connection state
5455
const [wsConnected, setWsConnected] = useState(false);
5556
const [streamingMessages, setStreamingMessages] = useState<StreamingPlanUpdate[]>([]);
@@ -362,6 +363,60 @@ const PlanPage: React.FC = () => {
362363
loadPlanDataRef.current = loadPlanData;
363364
}, [loadPlanData]);
364365

366+
// Handle plan approval
367+
const handleApprovePlan = useCallback(async () => {
368+
if (!planApprovalRequest) return;
369+
370+
setProcessingApproval(true);
371+
let id = showToast("Submitting Approval", "progress");
372+
try {
373+
await apiService.approvePlan({
374+
m_plan_id: planApprovalRequest.id,
375+
plan_id: planData?.plan?.id,
376+
approved: true,
377+
feedback: 'Plan approved by user'
378+
});
379+
380+
dismissToast(id);
381+
setShowProcessingPlanSpinner(true);
382+
setShowApprovalButtons(false);
383+
384+
} catch (error) {
385+
dismissToast(id);
386+
showToast("Failed to submit approval", "error");
387+
console.error('❌ Failed to approve plan:', error);
388+
} finally {
389+
setProcessingApproval(false);
390+
}
391+
}, [planApprovalRequest, planData, setProcessingApproval]);
392+
393+
// Handle plan rejection
394+
const handleRejectPlan = useCallback(async () => {
395+
if (!planApprovalRequest) return;
396+
397+
setProcessingApproval(true);
398+
let id = showToast("Submitting cancellation", "progress");
399+
try {
400+
await apiService.approvePlan({
401+
m_plan_id: planApprovalRequest.id,
402+
plan_id: planData?.plan?.id,
403+
approved: false,
404+
feedback: 'Plan rejected by user'
405+
});
406+
407+
dismissToast(id);
408+
409+
navigate('/');
410+
411+
} catch (error) {
412+
dismissToast(id);
413+
showToast("Failed to submit cancellation", "error");
414+
console.error('❌ Failed to reject plan:', error);
415+
navigate('/');
416+
} finally {
417+
setProcessingApproval(false);
418+
}
419+
}, [planApprovalRequest, planData, navigate, setProcessingApproval]);
365420
// Chat submission handler - updated for v3 backend compatibility
366421
const handleOnchatSubmit = useCallback(
367422
async (chatInput: string) => {
@@ -518,13 +573,16 @@ const PlanPage: React.FC = () => {
518573
streamingMessages={streamingMessages}
519574
wsConnected={wsConnected}
520575
onPlanApproval={(approved) => setPlanApproved(approved)}
521-
setShowProcessingPlanSpinner={(showProcessingPlanSpinner) => setShowProcessingPlanSpinner(showProcessingPlanSpinner)}
522576
planApprovalRequest={planApprovalRequest}
523577
waitingForPlan={waitingForPlan}
524578
messagesContainerRef={messagesContainerRef}
525579
streamingMessageBuffer={streamingMessageBuffer}
526580
agentMessages={agentMessages}
527581
showProcessingPlanSpinner={showProcessingPlanSpinner}
582+
showApprovalButtons={showApprovalButtons}
583+
processingApproval={processingApproval}
584+
handleApprovePlan={handleApprovePlan}
585+
handleRejectPlan={handleRejectPlan}
528586

529587
/>
530588
</>

0 commit comments

Comments
 (0)