1
0
peddlers-of-ketran/client/src/ConnectionStatus.tsx
2025-10-07 13:22:42 -07:00

95 lines
2.9 KiB
TypeScript

import React, { useState, useEffect } from "react";
import { Box, Typography, CircularProgress, Paper, LinearProgress } from "@mui/material";
import { ReadyState } from "react-use-websocket";
interface ConnectionStatusProps {
readyState: ReadyState;
reconnectAttempt?: number;
}
const ConnectionStatus: React.FC<ConnectionStatusProps> = ({ readyState, reconnectAttempt = 0 }) => {
const [countdown, setCountdown] = useState(0);
// Start countdown when connection is closed and we're attempting to reconnect
useEffect(() => {
if (readyState === ReadyState.CLOSED && reconnectAttempt > 0) {
setCountdown(5);
const interval = setInterval(() => {
setCountdown((prev) => {
if (prev <= 1) {
clearInterval(interval);
return 0;
}
return prev - 1;
});
}, 1000);
return () => clearInterval(interval);
}
}, [readyState, reconnectAttempt]);
const getConnectionStatusText = () => {
switch (readyState) {
case ReadyState.CONNECTING:
return reconnectAttempt > 0 ? `Reconnecting... (attempt ${reconnectAttempt})` : "Connecting to server...";
case ReadyState.OPEN:
return "Connected";
case ReadyState.CLOSING:
return "Disconnecting...";
case ReadyState.CLOSED:
if (reconnectAttempt > 0 && countdown > 0) {
return `Connection lost. Retrying in ${countdown}s... (attempt ${reconnectAttempt})`;
}
return reconnectAttempt > 0 ? "Reconnecting..." : "Disconnected";
case ReadyState.UNINSTANTIATED:
return "Initializing...";
default:
return "Unknown connection state";
}
};
const getConnectionColor = () => {
switch (readyState) {
case ReadyState.OPEN:
return "success.main";
case ReadyState.CONNECTING:
return "info.main";
case ReadyState.CLOSED:
return "error.main";
case ReadyState.CLOSING:
return "warning.main";
default:
return "text.secondary";
}
};
const shouldShowProgress =
readyState === ReadyState.CONNECTING || (readyState === ReadyState.CLOSED && reconnectAttempt > 0);
return (
<Paper
sx={{
p: 2,
m: 2,
width: "fit-content",
backgroundColor: readyState === ReadyState.CLOSED ? "#ffebee" : "background.paper",
}}
>
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
{shouldShowProgress && <CircularProgress size={20} />}
<Typography variant="h6" color={getConnectionColor()}>
{getConnectionStatusText()}
</Typography>
</Box>
{readyState === ReadyState.CLOSED && reconnectAttempt > 0 && countdown > 0 && (
<Box sx={{ mt: 2, width: "100%" }}>
<LinearProgress variant="determinate" value={((5 - countdown) / 5) * 100} sx={{ borderRadius: 1 }} />
</Box>
)}
</Paper>
);
};
export { ConnectionStatus };