From 008a3a4233eab6c59f7371326ddbf72c4e0fc4f4 Mon Sep 17 00:00:00 2001 From: "Wiktor A. Falkowski" Date: Tue, 20 Oct 2026 19:03:15 +0000 Subject: [PATCH] fix(dashboard): keep VPS creation progress reliable --- src/pages/DashboardPage.jsx | 155 +++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 36 deletions(-) diff --git a/src/pages/DashboardPage.jsx b/src/pages/DashboardPage.jsx index 95b00de..0ac7337 100644 --- a/src/pages/DashboardPage.jsx +++ b/src/pages/DashboardPage.jsx @@ -502,7 +502,9 @@ function DashboardPage({ setIsLoginOpen, setIsRegisterOpen, onCurrencyChange, pr visible: false, phase: '', progress: 0, - message: '' + message: '', + serverType: '', + state: 'active' }); const [personalInfo, setPersonalInfo] = useState({ firstName: user?.first_name || '', @@ -973,11 +975,21 @@ const handleWebSocketMessage = useCallback((data) => { break; case 'server_created': - // Hide progress notification when server creation completes - setServerCreationProgress(prev => ({ ...prev, visible: false })); + setServerCreationProgress({ + visible: true, + phase: 'Provisioned', + progress: 100, + message: data.server?.type === 'vps' + ? 'The VPS has been created. It may take a little longer to boot.' + : 'Your server has been created.', + serverType: data.server?.type || '', + state: 'complete' + }); if (data.server && data.server.id) { - setServers(prev => [...prev, data.server]); + setServers(prev => prev.some(server => server.id === data.server.id) + ? prev.map(server => server.id === data.server.id ? data.server : server) + : [...prev, data.server]); setIsCreatingServer(false); } else if (data.serverId) { sendMessageRef.current?.({ @@ -985,6 +997,7 @@ const handleWebSocketMessage = useCallback((data) => { }); setIsCreatingServer(false); } + setIsCreatingServer(false); if (data.credits !== undefined) { setUserCredits(data.credits); @@ -1124,24 +1137,49 @@ const handleWebSocketMessage = useCallback((data) => { break; case 'server_creation_progress': - // Hide progress if no active creation found (after reconnection check) - if (data.phase === 'Unknown' && data.progress === 0 && data.message === 'No active server creation found') { - setServerCreationProgress(prev => ({ ...prev, visible: false })); + if (data.state === 'unknown' || data.phase === 'Unknown') { + setServerCreationProgress(prev => prev.visible && prev.state === 'active' + ? { + ...prev, + phase: 'Status unavailable', + message: 'The connection lost the latest update. Check your server list for the current status.', + state: 'unknown' + } + : prev); break; } - setServerCreationProgress({ + setServerCreationProgress(prev => ({ + ...prev, visible: true, - phase: data.phase || '', - progress: data.progress || 0, - message: data.message || 'Creating server...' - }); - // Hide notification when progress reaches 100% - if (data.progress >= 100) { - setTimeout(() => { - setServerCreationProgress(prev => ({ ...prev, visible: false })); - }, 2000); - } + phase: data.phase || prev.phase, + progress: Math.max(prev.progress || 0, Math.min(100, Math.max(0, Number(data.progress) || 0))), + message: data.message || prev.message || 'Creating server…', + serverType: data.serverType || prev.serverType, + state: data.state || (Number(data.progress) >= 100 ? 'complete' : 'active') + })); + break; + + case 'server_creation_failed': + setIsCreatingServer(false); + setServerCreationProgress(prev => ({ + ...prev, + visible: true, + phase: 'Failed', + message: data.error || 'Server creation failed. Check the error details and try again.', + state: 'failed' + })); + break; + + case 'capacity_error': + setIsCreatingServer(false); + setServerCreationProgress(prev => ({ + ...prev, + visible: true, + phase: 'Capacity check', + message: data.error || 'There is not enough capacity for this server right now.', + state: 'failed' + })); break; case 'port_exposed': @@ -1247,6 +1285,14 @@ const handleWebSocketMessage = useCallback((data) => { } }, [dashboardStatus, serverCreationProgress.visible, sendDashboardMessage]); + useEffect(() => { + if (serverCreationProgress.state !== 'complete') return undefined; + const timeoutId = setTimeout(() => { + setServerCreationProgress(prev => ({ ...prev, visible: false })); + }, 4000); + return () => clearTimeout(timeoutId); + }, [serverCreationProgress.state]); + // Request metrics when server is selected and periodically update useEffect(() => { if (!selectedServer || !sendDashboardMessage || dashboardStatus !== 'connected') { @@ -1325,6 +1371,16 @@ const handleWebSocketMessage = useCallback((data) => { const handleCreateServer = async (serverConfig) => { setIsCreatingServer(true); + setServerCreationProgress({ + visible: true, + phase: 'Preparing', + progress: 1, + message: serverConfig.type === 'vps' + ? 'Checking capacity and preparing your VPS.' + : 'Checking capacity and preparing your server.', + serverType: serverConfig.type, + state: 'active' + }); sendDashboardMessage({ type: 'create_server', name: serverConfig.name, @@ -4458,7 +4514,7 @@ const handleWebSocketMessage = useCallback((data) => { borderColor: colors.brightBlack }} > -
+
@@ -4466,32 +4522,56 @@ const handleWebSocketMessage = useCallback((data) => {

- Server Creation in Progress + {serverCreationProgress.state === 'failed' + ? 'Server creation failed' + : serverCreationProgress.state === 'complete' + ? 'Server created' + : serverCreationProgress.state === 'unknown' + ? 'Creation status unavailable' + : serverCreationProgress.serverType === 'vps' + ? 'VPS creation' + : 'Server creation'}

{serverCreationProgress.message}

- + {serverCreationProgress.state !== 'active' && ( + + )}
{/* Progress Bar */} -
+
@@ -4501,8 +4581,11 @@ const handleWebSocketMessage = useCallback((data) => { {serverCreationProgress.phase} - - {serverCreationProgress.progress.toFixed(1)}% + + {Math.round(serverCreationProgress.progress)}%