'use client'; import { useState, useEffect } from 'react'; import { Box, Typography, Button, Paper, TextField, FormControl, InputLabel, Select, MenuItem, IconButton, Alert, CircularProgress, Card, CardContent, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Chip, Snackbar, } from '@mui/material'; import { ArrowBack, Refresh, Save, Delete, Bedtime, Hotel, DirectionsCar, Chair, Home, ChildCare, Add, } from '@mui/icons-material'; import { useRouter } from 'next/navigation'; import { AppShell } from '@/components/layouts/AppShell/AppShell'; import { ProtectedRoute } from '@/components/common/ProtectedRoute'; import { useAuth } from '@/lib/auth/AuthContext'; import { trackingApi, Activity } from '@/lib/api/tracking'; import { childrenApi, Child } from '@/lib/api/children'; import { motion } from 'framer-motion'; import { formatDistanceToNow, format } from 'date-fns'; interface SleepData { startTime: string; endTime?: string; quality: 'excellent' | 'good' | 'fair' | 'poor'; location: string; isOngoing?: boolean; } export default function SleepTrackPage() { const router = useRouter(); const { user } = useAuth(); const [children, setChildren] = useState([]); const [selectedChild, setSelectedChild] = useState(''); // Sleep state const [startTime, setStartTime] = useState( format(new Date(), "yyyy-MM-dd'T'HH:mm") ); const [endTime, setEndTime] = useState( format(new Date(), "yyyy-MM-dd'T'HH:mm") ); const [quality, setQuality] = useState<'excellent' | 'good' | 'fair' | 'poor'>('good'); const [location, setLocation] = useState('crib'); const [isOngoing, setIsOngoing] = useState(false); // Common state const [notes, setNotes] = useState(''); const [recentSleeps, setRecentSleeps] = useState([]); const [loading, setLoading] = useState(false); const [childrenLoading, setChildrenLoading] = useState(true); const [sleepsLoading, setSleepsLoading] = useState(false); const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); // Delete confirmation dialog const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [activityToDelete, setActivityToDelete] = useState(null); const familyId = user?.families?.[0]?.familyId; // Load children useEffect(() => { if (familyId) { loadChildren(); } }, [familyId]); // Load recent sleeps when child is selected useEffect(() => { if (selectedChild) { loadRecentSleeps(); } }, [selectedChild]); const loadChildren = async () => { if (!familyId) return; try { setChildrenLoading(true); const childrenData = await childrenApi.getChildren(familyId); setChildren(childrenData); if (childrenData.length > 0) { setSelectedChild(childrenData[0].id); } } catch (err: any) { console.error('Failed to load children:', err); setError(err.response?.data?.message || 'Failed to load children'); } finally { setChildrenLoading(false); } }; const loadRecentSleeps = async () => { if (!selectedChild) return; try { setSleepsLoading(true); const activities = await trackingApi.getActivities(selectedChild, 'sleep'); // Sort by timestamp descending and take last 10 const sorted = activities.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime() ).slice(0, 10); setRecentSleeps(sorted); } catch (err: any) { console.error('Failed to load recent sleeps:', err); } finally { setSleepsLoading(false); } }; const formatDuration = (start: string, end?: string) => { const startDate = new Date(start); const endDate = end ? new Date(end) : new Date(); const diffMs = endDate.getTime() - startDate.getTime(); if (diffMs < 0) return 'Invalid duration'; const hours = Math.floor(diffMs / (1000 * 60 * 60)); const minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); if (hours === 0) { return `${minutes} minute${minutes !== 1 ? 's' : ''}`; } else if (minutes === 0) { return `${hours} hour${hours !== 1 ? 's' : ''}`; } else { return `${hours} hour${hours !== 1 ? 's' : ''} ${minutes} minute${minutes !== 1 ? 's' : ''}`; } }; const calculateDuration = () => { if (!startTime) return null; if (isOngoing) { return formatDuration(startTime); } if (!endTime) return null; const start = new Date(startTime); const end = new Date(endTime); if (end <= start) return null; return formatDuration(startTime, endTime); }; const setStartNow = () => { setStartTime(format(new Date(), "yyyy-MM-dd'T'HH:mm")); }; const setEndNow = () => { setEndTime(format(new Date(), "yyyy-MM-dd'T'HH:mm")); }; const handleSubmit = async () => { if (!selectedChild) { setError('Please select a child'); return; } // Validation if (!startTime) { setError('Please enter start time'); return; } if (!isOngoing && !endTime) { setError('Please enter end time or mark as ongoing'); return; } if (!isOngoing && endTime) { const start = new Date(startTime); const end = new Date(endTime); if (end <= start) { setError('End time must be after start time'); return; } } try { setLoading(true); setError(null); const data: SleepData = { startTime, quality, location, isOngoing, }; if (!isOngoing && endTime) { data.endTime = endTime; } await trackingApi.createActivity(selectedChild, { type: 'sleep', timestamp: startTime, data, notes: notes || undefined, }); setSuccessMessage('Sleep logged successfully!'); // Reset form resetForm(); // Reload recent sleeps await loadRecentSleeps(); } catch (err: any) { console.error('Failed to save sleep:', err); setError(err.response?.data?.message || 'Failed to save sleep'); } finally { setLoading(false); } }; const resetForm = () => { setStartTime(format(new Date(), "yyyy-MM-dd'T'HH:mm")); setEndTime(format(new Date(), "yyyy-MM-dd'T'HH:mm")); setQuality('good'); setLocation('crib'); setIsOngoing(false); setNotes(''); }; const handleDeleteClick = (activityId: string) => { setActivityToDelete(activityId); setDeleteDialogOpen(true); }; const handleDeleteConfirm = async () => { if (!activityToDelete) return; try { setLoading(true); await trackingApi.deleteActivity(activityToDelete); setSuccessMessage('Sleep deleted successfully'); setDeleteDialogOpen(false); setActivityToDelete(null); await loadRecentSleeps(); } catch (err: any) { console.error('Failed to delete sleep:', err); setError(err.response?.data?.message || 'Failed to delete sleep'); } finally { setLoading(false); } }; const getLocationIcon = (loc: string) => { switch (loc) { case 'crib': return ; case 'bed': return ; case 'stroller': return ; case 'carrier': return ; case 'other': return ; default: return ; } }; const getQualityColor = (qual: string) => { switch (qual) { case 'excellent': return 'success'; case 'good': return 'primary'; case 'fair': return 'warning'; case 'poor': return 'error'; default: return 'default'; } }; const getSleepDetails = (activity: Activity) => { const data = activity.data as SleepData; const duration = data.endTime ? formatDuration(data.startTime, data.endTime) : data.isOngoing ? `Ongoing - ${formatDuration(data.startTime)}` : 'No end time'; return `${duration} - ${data.location.charAt(0).toUpperCase() + data.location.slice(1)}`; }; if (childrenLoading) { return ( ); } if (!familyId || children.length === 0) { return ( No Children Added You need to add a child before you can track sleep activities ); } return ( router.back()} sx={{ mr: 2 }}> Track Sleep {error && ( setError(null)}> {error} )} {/* Child Selector */} {children.length > 1 && ( Select Child )} {/* Main Form */} {/* Start Time */} Sleep Start Time setStartTime(e.target.value)} InputLabelProps={{ shrink: true }} /> {/* Ongoing Checkbox */} Sleep Status {/* End Time */} {!isOngoing && ( Wake Up Time setEndTime(e.target.value)} InputLabelProps={{ shrink: true }} /> )} {/* Duration Display */} {calculateDuration() && ( )} {/* Sleep Quality */} Sleep Quality {/* Location */} Location {/* Common Notes Field */} setNotes(e.target.value)} sx={{ mb: 3 }} placeholder="Any disruptions, dreams, or observations..." /> {/* Submit Button */} {/* Recent Sleeps */} Recent Sleep Activities {sleepsLoading ? ( ) : recentSleeps.length === 0 ? ( No sleep activities yet ) : ( {recentSleeps.map((activity, index) => { const data = activity.data as SleepData; return ( {getLocationIcon(data.location)} Sleep {getSleepDetails(activity)} {activity.notes && ( {activity.notes} )} handleDeleteClick(activity.id)} disabled={loading} > ); })} )} {/* Delete Confirmation Dialog */} setDeleteDialogOpen(false)} > Delete Sleep Activity? Are you sure you want to delete this sleep activity? This action cannot be undone. {/* Success Snackbar */} setSuccessMessage(null)} message={successMessage} /> ); }