'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, Save, ChildCare, Delete, Refresh, Add, DirectionsWalk, Toys, MusicNote, } from '@mui/icons-material'; import { useRouter } from 'next/navigation'; import { AppShell } from '@/components/layouts/AppShell/AppShell'; import { ProtectedRoute } from '@/components/common/ProtectedRoute'; import { withErrorBoundary } from '@/components/common/ErrorFallbacks'; import { useAuth } from '@/lib/auth/AuthContext'; import { trackingApi, Activity } from '@/lib/api/tracking'; import { childrenApi, Child } from '@/lib/api/children'; import { VoiceInputButton } from '@/components/voice/VoiceInputButton'; import { FormSkeleton, ActivityListSkeleton } from '@/components/common/LoadingSkeletons'; import { motion } from 'framer-motion'; import { useLocalizedDate } from '@/hooks/useLocalizedDate'; import { useTranslation } from '@/hooks/useTranslation'; interface ActivityData { activityType: string; duration?: number; description?: string; } function ActivityTrackPage() { const router = useRouter(); const { user } = useAuth(); const { formatDistanceToNow } = useLocalizedDate(); const { t } = useTranslation('tracking'); const [children, setChildren] = useState([]); const [selectedChild, setSelectedChild] = useState(''); // Activity state const [activityType, setActivityType] = useState('play'); const [duration, setDuration] = useState(''); const [description, setDescription] = useState(''); // Common state const [notes, setNotes] = useState(''); const [recentActivities, setRecentActivities] = useState([]); const [loading, setLoading] = useState(false); const [childrenLoading, setChildrenLoading] = useState(true); const [activitiesLoading, setActivitiesLoading] = 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 activities when child is selected useEffect(() => { if (selectedChild) { loadRecentActivities(); } }, [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 loadRecentActivities = async () => { if (!selectedChild) return; try { setActivitiesLoading(true); const activities = await trackingApi.getActivities(selectedChild, 'activity'); // 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); setRecentActivities(sorted); } catch (err: any) { console.error('Failed to load recent activities:', err); } finally { setActivitiesLoading(false); } }; const handleSubmit = async () => { if (!selectedChild) { setError('Please select a child'); return; } // Validation if (!activityType) { setError('Please select activity type'); return; } try { setLoading(true); setError(null); const data: ActivityData = { activityType, duration: duration ? parseInt(duration) : undefined, description: description || undefined, }; await trackingApi.createActivity(selectedChild, { type: 'activity', timestamp: new Date().toISOString(), data, notes: notes || undefined, }); setSuccessMessage(t('activity.success')); // Reset form resetForm(); // Reload recent activities await loadRecentActivities(); } catch (err: any) { console.error('Failed to save activity:', err); setError(err.response?.data?.message || 'Failed to save activity'); } finally { setLoading(false); } }; const resetForm = () => { setActivityType('play'); setDuration(''); setDescription(''); setNotes(''); }; const handleDeleteClick = (activityId: string) => { setActivityToDelete(activityId); setDeleteDialogOpen(true); }; const handleDeleteConfirm = async () => { if (!activityToDelete) return; try { setLoading(true); await trackingApi.deleteActivity(activityToDelete); setSuccessMessage(t('activity.deleted')); setDeleteDialogOpen(false); setActivityToDelete(null); await loadRecentActivities(); } catch (err: any) { console.error('Failed to delete activity:', err); setError(err.response?.data?.message || 'Failed to delete activity'); } finally { setLoading(false); } }; const getActivityTypeIcon = (type: string) => { switch (type) { case 'play': return ; case 'walk': return ; case 'music': return ; default: return ; } }; const getActivityDetails = (activity: Activity) => { const data = activity.data as ActivityData; let details = data.activityType.charAt(0).toUpperCase() + data.activityType.slice(1); if (data.duration) { details += ` - ${data.duration} min`; } if (data.description) { details += ` - ${data.description}`; } return details; }; if (childrenLoading) { return ( {t('trackActivity')} {t('activity.recentActivities')} ); } if (!familyId || children.length === 0) { return ( {t('common.noChildrenAdded')} {t('common.noChildrenMessage')} ); } return ( router.back()} sx={{ mr: 2 }}> {t('trackActivity')} { console.log('[Activity] Voice transcript:', transcript); }} onClassifiedIntent={(result) => { if (result.intent === 'activity' && result.structuredData) { const data = result.structuredData; // Auto-fill form with voice data if (data.activityType) setActivityType(data.activityType); if (data.duration) setDuration(data.duration.toString()); if (data.description) setDescription(data.description); } }} size="medium" /> {error && ( setError(null)}> {error} )} {/* Child Selector */} {children.length > 1 && ( {t('common.selectChild')} )} {/* Main Form */} {t('activity.title')} {t('activity.type')} setDuration(e.target.value)} sx={{ mb: 3 }} placeholder={t('activity.placeholders.duration')} /> setDescription(e.target.value)} sx={{ mb: 3 }} placeholder={t('activity.placeholders.description')} /> setNotes(e.target.value)} sx={{ mb: 3 }} placeholder={t('activity.placeholders.notes')} /> {/* Recent Activities */} {t('activity.recentActivities')} {activitiesLoading ? ( ) : recentActivities.length === 0 ? ( {t('noEntries')} ) : ( {recentActivities.map((activity, index) => { const data = activity.data as ActivityData; if (!data || !data.activityType) { console.warn('[Activity] Activity missing activityType:', activity); return null; } return ( {getActivityTypeIcon(data.activityType)} {data.activityType.charAt(0).toUpperCase() + data.activityType.slice(1).replace('_', ' ')} {getActivityDetails(activity)} {activity.notes && ( {activity.notes} )} handleDeleteClick(activity.id)} disabled={loading} > ); })} )} {/* Delete Confirmation Dialog */} setDeleteDialogOpen(false)} > {t('common.delete')} {t('activity.title')}? {t('confirmDelete')} {/* Success Snackbar */} setSuccessMessage(null)} message={successMessage} /> ); } export default withErrorBoundary(ActivityTrackPage, 'form');