Numan Saeed
feat: Add visual improvements and aesthetic enhancements
bedc7e7
import { useState, useEffect, useCallback } from 'react';
import { Scan, Calendar, HelpCircle } from 'lucide-react';
import { Header } from './components/Header';
import { Tabs } from './components/Tabs';
import { ClassificationPage } from './pages/ClassificationPage';
import { GestationalAgePage } from './pages/GestationalAgePage';
import { HelpPage } from './pages/HelpPage';
import { ImageProvider } from './lib/ImageContext';
import { checkHealth, getFeedbackStats } from './lib/api';
const tabs = [
{ id: 'classification', label: 'View Classification', icon: <Scan className="w-4 h-4" /> },
{ id: 'gestational-age', label: 'Gestational Age', icon: <Calendar className="w-4 h-4" /> },
{ id: 'help', label: 'Help', icon: <HelpCircle className="w-4 h-4" /> },
];
function App() {
const [activeTab, setActiveTab] = useState('classification');
const [isConnected, setIsConnected] = useState(false);
const [feedbackStats, setFeedbackStats] = useState<{
total: number;
correct: number;
incorrect: number;
} | null>(null);
useEffect(() => {
const checkConnection = async () => {
const healthy = await checkHealth();
setIsConnected(healthy);
};
checkConnection();
const interval = setInterval(checkConnection, 10000);
return () => clearInterval(interval);
}, []);
// Load feedback stats
const loadFeedbackStats = useCallback(async () => {
try {
const stats = await getFeedbackStats();
setFeedbackStats({
total: stats.total_feedback,
correct: stats.correct_count,
incorrect: stats.incorrect_count
});
} catch {
// Ignore errors - stats are optional
}
}, []);
useEffect(() => {
loadFeedbackStats();
}, [loadFeedbackStats]);
return (
<ImageProvider>
<div className="h-screen flex flex-col bg-dark-bg gradient-mesh overflow-hidden">
{/* Header - fixed height */}
<Header isConnected={isConnected} feedbackStats={feedbackStats} />
{/* Tabs - fixed height */}
<Tabs tabs={tabs} activeTab={activeTab} onChange={setActiveTab} />
{/* Main content - fills remaining space */}
<main className="flex-1 flex min-h-0 overflow-hidden">
{activeTab === 'classification' && <ClassificationPage onFeedbackUpdate={loadFeedbackStats} />}
{activeTab === 'gestational-age' && <GestationalAgePage />}
{activeTab === 'help' && <HelpPage />}
</main>
{/* Footer - fixed height, always visible */}
<footer className="flex-shrink-0 px-6 py-3 border-t border-dark-border bg-white">
<div className="flex items-center justify-between text-xs">
<span className="text-text-secondary">FetalCLIP • Foundation Model for Fetal Ultrasound Analysis</span>
<div className="flex items-center gap-4">
<a
href="https://huggingface.co/numansaeed/fetalclip-model"
target="_blank"
rel="noopener noreferrer"
className="text-accent-blue hover:text-accent-blue-hover transition-colors font-medium"
>
🤗 Model Hub
</a>
<a
href="https://arxiv.org/abs/2502.14807"
target="_blank"
rel="noopener noreferrer"
className="text-accent-blue hover:text-accent-blue-hover transition-colors font-medium"
>
📄 Paper
</a>
</div>
</div>
</footer>
</div>
</ImageProvider>
);
}
export default App;