const React = require("react"); const { Box, Text } = require("ink"); const { useState, useEffect } = React; const useAppState = require("../hooks/useAppState.js"); const useNavigation = require("../hooks/useNavigation.js"); const { useServiceContext } = require("../providers/ServiceProvider.jsx"); /** * StatusBar Component * Displays global status information at the top of the application * Shows connection status, operation progress, and current screen * Requirements: 8.1, 8.2, 8.3 */ const StatusBar = () => { const { operationState, configuration } = useAppState(); const { currentScreen } = useNavigation(); const { testConnection, isInitialized, error: serviceError, } = useServiceContext(); const [connectionStatus, setConnectionStatus] = useState({ status: "disconnected", lastChecked: null, error: null, }); // Test connection status periodically using ShopifyService useEffect(() => { const performConnectionTest = async () => { try { // Only test connection if services are initialized and we have configuration if (!isInitialized) { setConnectionStatus({ status: "initializing", lastChecked: new Date(), error: "Services initializing...", }); return; } if (serviceError) { setConnectionStatus({ status: "error", lastChecked: new Date(), error: serviceError, }); return; } if (!configuration.shopDomain || !configuration.accessToken) { setConnectionStatus({ status: "not_configured", lastChecked: new Date(), error: "Missing configuration", }); return; } // Set connecting status setConnectionStatus((prev) => ({ ...prev, status: "connecting", })); // Use ShopifyService to test connection const isConnected = await testConnection(); setConnectionStatus({ status: isConnected ? "connected" : "disconnected", lastChecked: new Date(), error: isConnected ? null : "Connection failed", }); } catch (error) { setConnectionStatus({ status: "error", lastChecked: new Date(), error: error.message, }); } }; // Test connection immediately if services are ready if (isInitialized) { performConnectionTest(); } // Test connection every 30 seconds const interval = setInterval(() => { if (isInitialized) { performConnectionTest(); } }, 30000); return () => clearInterval(interval); }, [ configuration.shopDomain, configuration.accessToken, isInitialized, serviceError, testConnection, ]); // Get connection display info const getConnectionInfo = () => { switch (connectionStatus.status) { case "connected": return { text: "Connected", color: "green", indicator: "●", }; case "connecting": return { text: "Connecting...", color: "yellow", indicator: "◐", }; case "initializing": return { text: "Initializing...", color: "yellow", indicator: "◑", }; case "not_configured": return { text: "Not Configured", color: "gray", indicator: "○", }; case "error": return { text: "Connection Error", color: "red", indicator: "●", }; case "disconnected": default: return { text: "Disconnected", color: "red", indicator: "○", }; } }; // Get operation status info const getOperationInfo = () => { if (!operationState) { return null; } const { status, progress, type, currentProduct } = operationState; switch (status) { case "running": return { text: `${type === "rollback" ? "Rollback" : "Update"}: ${ progress || 0 }%`, color: "blue", indicator: "▶", details: currentProduct ? `Processing: ${currentProduct}` : null, }; case "completed": return { text: `${type === "rollback" ? "Rollback" : "Update"} Complete`, color: "green", indicator: "✓", }; case "error": return { text: `${type === "rollback" ? "Rollback" : "Update"} Failed`, color: "red", indicator: "✗", }; case "paused": return { text: `${type === "rollback" ? "Rollback" : "Update"} Paused`, color: "yellow", indicator: "⏸", }; default: return { text: "Ready", color: "gray", indicator: "○", }; } }; // Get current screen name for display const getScreenName = () => { const screenNames = { "main-menu": "Main Menu", configuration: "Configuration", operation: "Operation", scheduling: "Scheduling", logs: "Logs", "tag-analysis": "Tag Analysis", }; return screenNames[currentScreen] || "Unknown"; }; // Get system status indicator const getSystemStatus = () => { if (operationState?.status === "error") { return { color: "red", text: "ERROR" }; } if (operationState?.status === "running") { return { color: "blue", text: "ACTIVE" }; } if (connectionStatus.status === "error") { return { color: "red", text: "CONN_ERR" }; } if (connectionStatus.status === "connected") { return { color: "green", text: "READY" }; } return { color: "gray", text: "IDLE" }; }; const connectionInfo = getConnectionInfo(); const operationInfo = getOperationInfo(); const systemStatus = getSystemStatus(); return React.createElement( Box, { borderStyle: "single", paddingX: 1, justifyContent: "space-between", height: 3, }, // Left side: Connection and screen info React.createElement( Box, { flexDirection: "column" }, React.createElement( Box, null, React.createElement( Text, { color: connectionInfo.color }, `${connectionInfo.indicator} ` ), React.createElement(Text, null, connectionInfo.text), React.createElement(Text, { color: "gray" }, " | "), React.createElement(Text, null, `Screen: ${getScreenName()}`) ), connectionStatus.error && React.createElement( Text, { color: "red", dimColor: true }, `Error: ${connectionStatus.error.substring(0, 40)}${ connectionStatus.error.length > 40 ? "..." : "" }` ) ), // Right side: Operation status and system status React.createElement( Box, { flexDirection: "column", alignItems: "flex-end" }, React.createElement( Box, null, operationInfo && React.createElement( Text, { color: operationInfo.color }, `${operationInfo.indicator} ${operationInfo.text}` ), operationInfo && React.createElement(Text, { color: "gray" }, " | "), React.createElement( Text, { color: systemStatus.color, bold: true }, systemStatus.text ) ), operationInfo?.details && React.createElement( Text, { color: "gray", dimColor: true }, operationInfo.details.substring(0, 30) + (operationInfo.details.length > 30 ? "..." : "") ) ) ); }; module.exports = StatusBar;