Spaces:
Sleeping
Sleeping
| import React, { useEffect, useState } from 'react'; | |
| import { AlertCircle, X, RefreshCw, WifiOff } from 'lucide-react'; | |
| import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; | |
| import { Button } from '@/components/ui/button'; | |
| import { checkApiConnection } from '@/lib/api'; | |
| import { API_BASE_URL } from '@/config'; | |
| import apiClient from '@/lib/api/axios-instance'; | |
| const ApiConnectionAlert = () => { | |
| const [isApiAvailable, setIsApiAvailable] = useState<boolean | null>(null); | |
| const [checking, setChecking] = useState(false); | |
| const [isVisible, setIsVisible] = useState(true); | |
| const [retryCount, setRetryCount] = useState(0); | |
| const [fadeOut, setFadeOut] = useState(false); | |
| const checkConnection = async () => { | |
| setChecking(true); | |
| try { | |
| console.log('Checking API connection...'); | |
| const isAvailable = await checkApiConnection(); | |
| console.log('API connection check result:', isAvailable); | |
| setIsApiAvailable(isAvailable); | |
| if (isAvailable) { | |
| // If connection is restored after previous failures, show success briefly then hide | |
| if (retryCount > 0) { | |
| setTimeout(() => { | |
| setFadeOut(true); | |
| setTimeout(() => setIsVisible(false), 300); | |
| }, 3000); | |
| } | |
| } else { | |
| setRetryCount(prev => prev + 1); | |
| } | |
| } catch (error) { | |
| console.error('Error checking API connection:', error); | |
| setIsApiAvailable(false); | |
| setRetryCount(prev => prev + 1); | |
| } finally { | |
| setChecking(false); | |
| } | |
| }; | |
| useEffect(() => { | |
| checkConnection(); | |
| // Set up automatic retry every 30 seconds if API is down | |
| const intervalId = setInterval(() => { | |
| if (isApiAvailable === false) { | |
| checkConnection(); | |
| } | |
| }, 30000); | |
| return () => clearInterval(intervalId); | |
| }, [isApiAvailable]); | |
| const closeAlert = () => { | |
| setFadeOut(true); | |
| setTimeout(() => setIsVisible(false), 300); | |
| }; | |
| if (isApiAvailable === true && !isVisible) { | |
| return null; | |
| } | |
| return ( | |
| <> | |
| {(isApiAvailable === false || (isApiAvailable === true && retryCount > 0)) && isVisible && ( | |
| <div | |
| className={`fixed bottom-4 right-4 z-50 max-w-md w-full transition-all duration-300 ${ | |
| fadeOut ? 'opacity-0 translate-y-5' : 'opacity-100 translate-y-0' | |
| }`} | |
| > | |
| <Alert | |
| variant={isApiAvailable === true ? "default" : "destructive"} | |
| className={` | |
| relative shadow-lg border-2 | |
| ${isApiAvailable === true | |
| ? "bg-green-50 border-green-200 dark:bg-green-900/20 dark:border-green-800" | |
| : "bg-red-50 border-red-200 dark:bg-red-900/20 dark:border-red-800"} | |
| `} | |
| > | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="absolute top-2 right-2 h-6 w-6 rounded-full p-0" | |
| onClick={closeAlert} | |
| > | |
| <X className="h-4 w-4" /> | |
| </Button> | |
| {isApiAvailable === true ? ( | |
| <div className="flex items-start"> | |
| <div className="rounded-full bg-green-100 dark:bg-green-800 p-2 mr-3"> | |
| <RefreshCw className="h-4 w-4 text-green-600 dark:text-green-200" /> | |
| </div> | |
| <div> | |
| <AlertTitle className="text-green-700 dark:text-green-300"> | |
| API Connection Restored | |
| </AlertTitle> | |
| <AlertDescription className="text-green-600 dark:text-green-400"> | |
| <p className="mb-2"> | |
| Successfully connected to the API server. You can continue using the application. | |
| </p> | |
| </AlertDescription> | |
| </div> | |
| </div> | |
| ) : ( | |
| <div className="flex items-start"> | |
| <div className="rounded-full bg-red-100 dark:bg-red-800 p-2 mr-3"> | |
| <WifiOff className="h-4 w-4 text-red-600 dark:text-red-200" /> | |
| </div> | |
| <div> | |
| <AlertTitle className="text-red-700 dark:text-red-300"> | |
| API Connection Error | |
| </AlertTitle> | |
| <AlertDescription className="text-red-600 dark:text-red-400"> | |
| <p className="mb-3"> | |
| Cannot connect to the API server at <code className="px-1 py-0.5 bg-red-100 dark:bg-red-900/30 rounded">{API_BASE_URL}</code>. | |
| Some features may not work correctly. | |
| </p> | |
| <div className="mb-3 space-y-1 pl-5"> | |
| <p className="font-medium text-sm">Troubleshooting steps:</p> | |
| <ul className="list-disc pl-4 text-sm space-y-1"> | |
| <li>Ensure the API server is running</li> | |
| <li>Check your network connection</li> | |
| <li>Verify that ports are not blocked by a firewall</li> | |
| <li>If you're a developer, check for CORS issues</li> | |
| </ul> | |
| </div> | |
| <div className="flex justify-end gap-2 mt-2"> | |
| <Button | |
| variant="outline" | |
| size="sm" | |
| onClick={closeAlert} | |
| className="border-red-200 hover:bg-red-100 hover:text-red-800" | |
| > | |
| Dismiss | |
| </Button> | |
| <Button | |
| size="sm" | |
| onClick={checkConnection} | |
| disabled={checking} | |
| className="bg-red-600 hover:bg-red-700 text-white" | |
| > | |
| {checking ? ( | |
| <> | |
| <RefreshCw className="h-3 w-3 mr-1 animate-spin" /> | |
| Checking... | |
| </> | |
| ) : ( | |
| <> | |
| <RefreshCw className="h-3 w-3 mr-1" /> | |
| Retry Connection | |
| </> | |
| )} | |
| </Button> | |
| </div> | |
| </AlertDescription> | |
| </div> | |
| </div> | |
| )} | |
| </Alert> | |
| </div> | |
| )} | |
| </> | |
| ); | |
| }; | |
| export default ApiConnectionAlert; |