- Add comprehensive API client methods for all advanced analytics endpoints - Create CircadianRhythmCard component for sleep pattern visualization - Create AnomalyAlertsPanel for anomaly detection and alerts - Create GrowthPercentileChart with WHO/CDC percentiles - Create CorrelationInsights for activity correlations - Create TrendAnalysisChart with predictions - Add advanced analytics page with all new components - Add UI component library (shadcn/ui) setup - Add navigation link to advanced analytics from insights page All advanced analytics features are now accessible from the frontend UI.
121 lines
3.8 KiB
TypeScript
121 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import { usePathname, useRouter } from 'next/navigation';
|
|
import { useState } from 'react';
|
|
import { BottomNavigation, BottomNavigationAction, Paper, Fab, Box, IconButton } from '@mui/material';
|
|
import {
|
|
Home,
|
|
Timeline,
|
|
Insights,
|
|
Chat,
|
|
Mic,
|
|
} from '@mui/icons-material';
|
|
import { useTranslation } from '@/hooks/useTranslation';
|
|
|
|
export const TabBar = () => {
|
|
const { t } = useTranslation('common');
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const [voiceOpen, setVoiceOpen] = useState(false);
|
|
|
|
const tabs = [
|
|
{ label: t('navigation.home'), icon: <Home />, value: '/' },
|
|
{ label: t('navigation.track'), icon: <Timeline />, value: '/track' },
|
|
{ label: '', icon: null, value: 'voice' }, // Placeholder for center button
|
|
{ label: t('navigation.insights'), icon: <Insights />, value: pathname.startsWith('/analytics') ? pathname : '/insights' },
|
|
{ label: t('navigation.aiChat'), icon: <Chat />, value: '/ai-assistant' },
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<Paper
|
|
component="nav"
|
|
aria-label="Primary navigation"
|
|
sx={{
|
|
position: 'fixed',
|
|
bottom: { xs: 0, md: 20 },
|
|
left: { xs: 0, md: '50%' },
|
|
right: { xs: 0, md: 'auto' },
|
|
transform: { xs: 'none', md: 'translateX(-50%)' },
|
|
width: { xs: '100%', md: '30%' },
|
|
zIndex: 1000,
|
|
borderRadius: { xs: 0, md: 2 },
|
|
}}
|
|
elevation={3}
|
|
>
|
|
<BottomNavigation
|
|
value={pathname}
|
|
onChange={(event, newValue) => {
|
|
if (newValue !== 'voice') {
|
|
router.push(newValue);
|
|
}
|
|
}}
|
|
showLabels
|
|
sx={{
|
|
height: 64,
|
|
borderRadius: { xs: 0, md: 2 },
|
|
'& .MuiBottomNavigationAction-root': {
|
|
minWidth: 60,
|
|
'&.Mui-selected': {
|
|
color: 'primary.main',
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
{tabs.map((tab) => {
|
|
if (tab.value === 'voice') {
|
|
// Center voice button - using BottomNavigationAction as wrapper to avoid prop warnings
|
|
return (
|
|
<BottomNavigationAction
|
|
key="voice-placeholder"
|
|
label=""
|
|
value="voice"
|
|
showLabel={false}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
const voiceButton = document.querySelector('[aria-label="voice input"]') as HTMLButtonElement;
|
|
if (voiceButton) {
|
|
voiceButton.click();
|
|
}
|
|
}}
|
|
icon={(
|
|
<Box
|
|
aria-label="voice command"
|
|
sx={{
|
|
bgcolor: '#FF69B4',
|
|
color: 'white',
|
|
width: 48,
|
|
height: 48,
|
|
'&:hover': {
|
|
bgcolor: '#FF1493',
|
|
},
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
borderRadius: '50%',
|
|
}}
|
|
>
|
|
<Mic />
|
|
</Box>
|
|
)}
|
|
sx={{ minWidth: 80 }}
|
|
/>
|
|
);
|
|
}
|
|
return (
|
|
<BottomNavigationAction
|
|
key={tab.value}
|
|
label={tab.label}
|
|
icon={tab.icon}
|
|
value={tab.value}
|
|
/>
|
|
);
|
|
})}
|
|
</BottomNavigation>
|
|
</Paper>
|
|
|
|
{/* Voice Command Floating Button is now centralized in layout.tsx - removed duplicate */}
|
|
</>
|
|
);
|
|
};
|