@@ -5,7 +5,28 @@ import ProtectedRoute from '../components/ProtectedRoute';
55import * as XLSX from 'xlsx' ;
66import { BarChart , Bar , XAxis , YAxis , Tooltip , ResponsiveContainer , CartesianGrid , LabelList , ReferenceLine , Legend , Cell } from 'recharts' ;
77
8- const API_BASE = import . meta. env . VITE_API_BASE || 'http://127.0.0.1:8000' ;
8+ // API Base URL configuration
9+ const getApiBase = ( ) => {
10+ // Check for environment variable first
11+ const envApiBase = import . meta. env . VITE_API_BASE ;
12+
13+ // If environment variable is set and doesn't look like a frontend URL, use it
14+ if ( envApiBase && ! envApiBase . includes ( 'azurestaticapps.net' ) ) {
15+ return envApiBase ;
16+ }
17+
18+ // Default to the Azure backend API
19+ return 'https://hospital-readmission-backend-api-e5fsevbxggfhdxbr.southindia-01.azurewebsites.net' ;
20+ } ;
21+
22+ const API_BASE = getApiBase ( ) ;
23+
24+ // Fallback API URLs in case the primary one fails
25+ const FALLBACK_APIS = [
26+ 'https://hospital-readmission-backend-api-e5fsevbxggfhdxbr.southindia-01.azurewebsites.net' ,
27+ 'http://127.0.0.1:8000' ,
28+ 'http://localhost:8000'
29+ ] ;
930
1031const DIAG_OPTIONS = [
1132 { value : '' , label : 'Select diagnosis' } ,
@@ -80,9 +101,35 @@ const DashboardPage = () => {
80101 readmitted : ''
81102 } ) ;
82103 const [ manualError , setManualError ] = useState ( '' ) ;
104+ const [ apiStatus , setApiStatus ] = useState ( { connected : false , endpoint : '' , checking : true } ) ;
83105
84106 const acceptedExtensions = useMemo ( ( ) => [ '.xls' , '.xlsx' ] , [ ] ) ;
85107
108+ // Check API status on component mount
109+ React . useEffect ( ( ) => {
110+ const checkApiStatus = async ( ) => {
111+ setApiStatus ( { connected : false , endpoint : '' , checking : true } ) ;
112+
113+ const apiUrls = [ API_BASE , ...FALLBACK_APIS . filter ( url => url !== API_BASE ) ] ;
114+
115+ for ( const baseUrl of apiUrls ) {
116+ try {
117+ const isHealthy = await checkApiHealth ( baseUrl ) ;
118+ if ( isHealthy ) {
119+ setApiStatus ( { connected : true , endpoint : baseUrl , checking : false } ) ;
120+ return ;
121+ }
122+ } catch ( error ) {
123+ console . error ( `API status check failed for ${ baseUrl } :` , error ) ;
124+ }
125+ }
126+
127+ setApiStatus ( { connected : false , endpoint : '' , checking : false } ) ;
128+ } ;
129+
130+ checkApiStatus ( ) ;
131+ } , [ ] ) ;
132+
86133 const handleBrowseClick = ( ) => {
87134 fileInputRef . current ?. click ( ) ;
88135 } ;
@@ -161,17 +208,54 @@ const DashboardPage = () => {
161208 } ;
162209 } ;
163210
211+ const checkApiHealth = async ( baseUrl ) => {
212+ try {
213+ const res = await fetch ( `${ baseUrl } /health` ) ;
214+ return res . ok ;
215+ } catch ( error ) {
216+ console . error ( `API health check failed for ${ baseUrl } :` , error ) ;
217+ return false ;
218+ }
219+ } ;
220+
164221 const callExplain = async ( patient ) => {
165- const res = await fetch ( `${ API_BASE } /explain` , {
166- method : 'POST' ,
167- headers : { 'Content-Type' : 'application/json' } ,
168- body : JSON . stringify ( patient )
169- } ) ;
170- if ( ! res . ok ) {
171- const err = await res . json ( ) . catch ( ( ) => ( { } ) ) ;
172- throw new Error ( err . detail || `HTTP ${ res . status } ` ) ;
222+ // Try multiple API endpoints
223+ const apiUrls = [ API_BASE , ...FALLBACK_APIS . filter ( url => url !== API_BASE ) ] ;
224+
225+ for ( const baseUrl of apiUrls ) {
226+ try {
227+ console . log ( 'Trying API with URL:' , `${ baseUrl } /explain` ) ;
228+
229+ // First check if API is accessible
230+ const isHealthy = await checkApiHealth ( baseUrl ) ;
231+ if ( ! isHealthy ) {
232+ console . log ( `API at ${ baseUrl } is not healthy, trying next...` ) ;
233+ continue ;
234+ }
235+
236+ const res = await fetch ( `${ baseUrl } /explain` , {
237+ method : 'POST' ,
238+ headers : { 'Content-Type' : 'application/json' } ,
239+ body : JSON . stringify ( patient )
240+ } ) ;
241+
242+ if ( ! res . ok ) {
243+ const err = await res . json ( ) . catch ( ( ) => ( { } ) ) ;
244+ console . error ( 'API Error:' , res . status , res . statusText , err ) ;
245+ throw new Error ( err . detail || `HTTP ${ res . status } : ${ res . statusText } ` ) ;
246+ }
247+
248+ console . log ( `Successfully called API at ${ baseUrl } ` ) ;
249+ return res . json ( ) ;
250+ } catch ( error ) {
251+ console . error ( `Failed to call API at ${ baseUrl } :` , error ) ;
252+ // Continue to next API if this one fails
253+ continue ;
254+ }
173255 }
174- return res . json ( ) ;
256+
257+ // If all APIs fail, throw an error
258+ throw new Error ( 'All API endpoints are unreachable. Please check your network connection and backend service status.' ) ;
175259 } ;
176260
177261 const processFile = useCallback ( async ( file ) => {
@@ -334,10 +418,57 @@ const DashboardPage = () => {
334418 < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" >
335419 { /* Header */ }
336420 < div className = "mb-8" >
337- < h1 className = "text-3xl font-bold text-gray-900 mb-2" > Dashboard</ h1 >
338- < p className = "text-gray-600" > Welcome back, { user ?. email || 'User' } !</ p >
421+ < div className = "flex items-center justify-between" >
422+ < div >
423+ < h1 className = "text-3xl font-bold text-gray-900 mb-2" > Dashboard</ h1 >
424+ < p className = "text-gray-600" > Welcome back, { user ?. email || 'User' } !</ p >
425+ </ div >
426+ < div className = "flex items-center gap-2" >
427+ { apiStatus . checking ? (
428+ < div className = "flex items-center gap-2 text-yellow-600" >
429+ < div className = "w-2 h-2 bg-yellow-500 rounded-full animate-pulse" > </ div >
430+ < span className = "text-sm" > Checking API...</ span >
431+ </ div >
432+ ) : apiStatus . connected ? (
433+ < div className = "flex items-center gap-2 text-green-600" >
434+ < div className = "w-2 h-2 bg-green-500 rounded-full" > </ div >
435+ < span className = "text-sm" > API Connected</ span >
436+ </ div >
437+ ) : (
438+ < div className = "flex items-center gap-2 text-red-600" >
439+ < div className = "w-2 h-2 bg-red-500 rounded-full" > </ div >
440+ < span className = "text-sm" > API Disconnected</ span >
441+ </ div >
442+ ) }
443+ </ div >
444+ </ div >
339445 </ div >
340446
447+ { /* API Status Warning */ }
448+ { ! apiStatus . checking && ! apiStatus . connected && (
449+ < div className = "bg-red-50 border border-red-200 rounded-lg p-4 mb-6" >
450+ < div className = "flex items-center" >
451+ < div className = "flex-shrink-0" >
452+ < svg className = "h-5 w-5 text-red-400" viewBox = "0 0 20 20" fill = "currentColor" >
453+ < path fillRule = "evenodd" d = "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule = "evenodd" />
454+ </ svg >
455+ </ div >
456+ < div className = "ml-3" >
457+ < h3 className = "text-sm font-medium text-red-800" > API Connection Issue</ h3 >
458+ < div className = "mt-2 text-sm text-red-700" >
459+ < p > The backend API is currently unreachable. This may be due to:</ p >
460+ < ul className = "list-disc list-inside mt-1 space-y-1" >
461+ < li > Backend service is down or restarting</ li >
462+ < li > Network connectivity issues</ li >
463+ < li > Incorrect API endpoint configuration</ li >
464+ </ ul >
465+ < p className = "mt-2" > Please try again later or contact support if the issue persists.</ p >
466+ </ div >
467+ </ div >
468+ </ div >
469+ </ div >
470+ ) }
471+
341472 { /* Uploader */ }
342473 < div className = "bg-white rounded-xl shadow-sm p-6 border border-gray-200 mb-8" >
343474 < div className = "flex items-center justify-between mb-4" >
0 commit comments