diff --git a/maternal-web/app/globals.css b/maternal-web/app/globals.css index c2f9b27..4706cc8 100644 --- a/maternal-web/app/globals.css +++ b/maternal-web/app/globals.css @@ -165,3 +165,23 @@ body { outline: 2px solid #FF8B7D; outline-offset: 2px; } + +/* ============================================ + MUI Grid Custom Styling + ============================================ */ + +/* MUI Grid minimum width and centering */ +.mui-17fpwt7-MuiGrid-root { + min-width: 20% !important; +} + +/* Center MUI Grid containers and items */ +.MuiGrid-container { + justify-content: center !important; +} + +.MuiGrid-item { + display: flex !important; + justify-content: center !important; + align-items: center !important; +} diff --git a/maternal-web/components/features/analytics/InsightsDashboard.tsx b/maternal-web/components/features/analytics/InsightsDashboard.tsx index 1eac788..a25bdb0 100644 --- a/maternal-web/components/features/analytics/InsightsDashboard.tsx +++ b/maternal-web/components/features/analytics/InsightsDashboard.tsx @@ -7,10 +7,6 @@ import { Grid, Card, CardContent, - Select, - MenuItem, - FormControl, - InputLabel, CircularProgress, Alert, Paper, @@ -21,8 +17,6 @@ import { ListItemText, Avatar, Chip, - ToggleButtonGroup, - ToggleButton, Button, } from '@mui/material'; import { @@ -38,7 +32,6 @@ import { import { useRouter } from 'next/navigation'; import { motion } from 'framer-motion'; import { trackingApi, Activity, ActivityType } from '@/lib/api/tracking'; -import { childrenApi, Child } from '@/lib/api/children'; import { subDays, startOfDay, endOfDay, parseISO, differenceInMinutes } from 'date-fns'; import { useLocalizedDate } from '@/hooks/useLocalizedDate'; import { useTranslation } from '@/hooks/useTranslation'; @@ -46,7 +39,6 @@ import { useFormatting } from '@/hooks/useFormatting'; import { BarChart, Bar, LineChart, Line, PieChart, Pie, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; import { useAuth } from '@/lib/auth/AuthContext'; -type DateRange = '7days' | '30days' | '3months'; interface DayData { date: string; @@ -99,74 +91,37 @@ const getActivityColor = (type: ActivityType) => { return COLORS[type as keyof typeof COLORS] || '#CCCCCC'; }; -export const InsightsDashboard: React.FC = () => { +interface InsightsDashboardProps { + selectedChildId: string; + days: number; +} + +export const InsightsDashboard: React.FC = ({ selectedChildId, days }) => { const router = useRouter(); const { user } = useAuth(); const { format, formatDistanceToNow } = useLocalizedDate(); const { t } = useTranslation('insights'); const { formatNumber } = useFormatting(); - const [children, setChildren] = useState([]); - const [selectedChild, setSelectedChild] = useState(''); - const [dateRange, setDateRange] = useState('7days'); const [activities, setActivities] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const familyId = user?.families?.[0]?.familyId; - // Fetch children on mount + // Fetch activities when child or days changes useEffect(() => { - const fetchChildren = async () => { - if (!familyId) { - setError('No family found'); - return; - } - - try { - console.log('[InsightsDashboard] Loading children for familyId:', familyId); - const childrenData = await childrenApi.getChildren(familyId); - console.log('[InsightsDashboard] Loaded children:', childrenData); - setChildren(childrenData); - - if (childrenData.length > 0) { - // Validate selected child or pick first one - const validChild = childrenData.find(c => c.id === selectedChild); - if (!validChild) { - setSelectedChild(childrenData[0].id); - } - } - } catch (err: any) { - console.error('[InsightsDashboard] Failed to load children:', err); - setError(err.response?.data?.message || t('errors.loadChildren')); - } - }; - fetchChildren(); - }, [familyId]); - - // Fetch activities when child or date range changes - useEffect(() => { - if (!selectedChild || children.length === 0) return; - - // Validate that selectedChild belongs to current user's children - const childExists = children.some(child => child.id === selectedChild); - if (!childExists) { - console.warn('[InsightsDashboard] Selected child not found in user\'s children, resetting'); - setSelectedChild(children[0].id); - setError('Selected child not found. Showing data for your first child.'); - return; - } + if (!selectedChildId) return; const fetchActivities = async () => { setLoading(true); setError(null); try { - console.log('[InsightsDashboard] Fetching activities for child:', selectedChild); - const days = dateRange === '7days' ? 7 : dateRange === '30days' ? 30 : 90; + console.log('[InsightsDashboard] Fetching activities for child:', selectedChildId); const endDate = endOfDay(new Date()); const startDate = startOfDay(subDays(new Date(), days - 1)); const activitiesData = await trackingApi.getActivities( - selectedChild, + selectedChildId, undefined, startDate.toISOString(), endDate.toISOString() @@ -182,7 +137,7 @@ export const InsightsDashboard: React.FC = () => { }; fetchActivities(); - }, [selectedChild, dateRange, children]); + }, [selectedChildId, days]); // Calculate statistics const calculateStats = () => { @@ -198,7 +153,6 @@ export const InsightsDashboard: React.FC = () => { } return acc; }, 0); - const days = dateRange === '7days' ? 7 : dateRange === '30days' ? 30 : 90; const avgSleepHours = days > 0 ? (totalSleepMinutes / 60 / days).toFixed(1) : '0.0'; const typeCounts: Record = {}; @@ -217,7 +171,6 @@ export const InsightsDashboard: React.FC = () => { // Prepare chart data const prepareDailyData = (): DayData[] => { - const days = dateRange === '7days' ? 7 : dateRange === '30days' ? 30 : 90; const dailyMap = new Map(); for (let i = days - 1; i >= 0; i--) { @@ -291,7 +244,7 @@ export const InsightsDashboard: React.FC = () => { .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()) .slice(0, 20); - const noChildren = children.length === 0; + const noChildren = !selectedChildId; const noActivities = activities.length === 0 && !loading; return ( @@ -308,41 +261,6 @@ export const InsightsDashboard: React.FC = () => { {t('subtitle')} - {/* Time period selector */} - - {children.length > 1 && ( - - {t('filters.child')} - - - )} - newValue && setDateRange(newValue)} - sx={{ - '& .MuiToggleButton-root': { - textTransform: 'none', - fontWeight: 500, - minWidth: { xs: 80, sm: 120 } - } - }} - > - {t('filters.dateRange.7days')} - {t('filters.dateRange.30days')} - {t('filters.dateRange.3months')} - - {error && ( diff --git a/maternal-web/components/features/analytics/UnifiedInsightsDashboard.tsx b/maternal-web/components/features/analytics/UnifiedInsightsDashboard.tsx index f9be7a9..2edfd99 100644 --- a/maternal-web/components/features/analytics/UnifiedInsightsDashboard.tsx +++ b/maternal-web/components/features/analytics/UnifiedInsightsDashboard.tsx @@ -187,9 +187,9 @@ export function UnifiedInsightsDashboard() { )} - {/* Child Selector */} - {children.length > 1 && ( - + {/* Shared Filters */} + + {children.length > 1 && ( Child setDays(Number(e.target.value))} + > + Last 7 days + Last 30 days + Last 3 months + + + {/* Growth Spurt Alert */} {insights?.growthSpurt && } @@ -221,7 +233,7 @@ export function UnifiedInsightsDashboard() { {/* Tab Panels */} {/* Insights tab shows the existing InsightsDashboard */} - + diff --git a/maternal-web/store/slices/authSlice.ts b/maternal-web/store/slices/authSlice.ts index dc7b44b..056406c 100644 --- a/maternal-web/store/slices/authSlice.ts +++ b/maternal-web/store/slices/authSlice.ts @@ -15,27 +15,10 @@ export interface AuthState { loading: boolean; } -// Mock user and token for development (TODO: Remove in production and implement real auth) -const MOCK_USER: User = { - id: 'user_test123', - email: 'test@maternal.app', - name: 'Test User', - familyId: 'fam_test123', -}; - -// Mock JWT token for development - this is just for testing, real auth needed in production -const MOCK_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2VyX3Rlc3QxMjMiLCJmYW1pbHlJZCI6ImZhbV90ZXN0MTIzIiwiaWF0IjoxNjAwMDAwMDAwfQ.mock_signature_for_development'; - -// Set mock token in localStorage for development -if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') { - localStorage.setItem('accessToken', MOCK_TOKEN); -} - const initialState: AuthState = { - // Use mock user in development if no real user is stored - user: process.env.NODE_ENV === 'development' ? MOCK_USER : null, - token: process.env.NODE_ENV === 'development' ? MOCK_TOKEN : null, - isAuthenticated: process.env.NODE_ENV === 'development', + user: null, + token: null, + isAuthenticated: false, loading: false, };