fix: Comprehensive authentication and UI fixes
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

Authentication & Token Management:
- Add deviceId to token refresh flow (backend requires both refreshToken and deviceId)
- Fix React Strict Mode token clearing race condition with retry logic
- Improve AuthContext to handle all token state combinations properly
- Store deviceId in localStorage alongside tokens

UI/UX Improvements:
- Remove deprecated legacyBehavior from Next.js Link components
- Update primary theme color to WCAG AA compliant #7c3aed
- Fix nested button error in TabBar voice navigation
- Fix invalid Tabs value error in DynamicChildDashboard

Multi-Child Dashboard:
- Load all children into Redux store properly
- Fetch metrics for all children, not just selected one
- Remove mock data to prevent unauthorized API calls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-05 16:10:11 +00:00
parent ee6b5cddee
commit d0b78181a3
11 changed files with 272 additions and 124 deletions

View File

@@ -47,6 +47,7 @@ export default function HomePage() {
const [children, setChildren] = useState<Child[]>([]);
const [recentActivities, setRecentActivities] = useState<any[]>([]);
const [todaySummary, setTodaySummary] = useState<any>(null);
const [allChildMetrics, setAllChildMetrics] = useState<any>({});
const [loading, setLoading] = useState(true);
const [error, setError] = useState<any>(null);
@@ -58,10 +59,21 @@ export default function HomePage() {
}, [familyId, authLoading]);
const loadChildren = async () => {
if (!familyId) return;
if (!familyId) {
console.warn('[HomePage] No familyId available, cannot load children');
return;
}
try {
console.log('[HomePage] Loading children for familyId:', familyId);
// Dispatch to Redux to load children into store
await dispatch(fetchChildren(familyId)).unwrap();
// Also get children for local state
const data = await childrenApi.getChildren(familyId);
console.log('[HomePage] Loaded children:', data.map(c => ({ id: c.id, name: c.name, familyId: c.familyId })));
setChildren(data);
if (data.length > 0 && !selectedChildId) {
setSelectedChildId(data[0].id);
@@ -72,48 +84,68 @@ export default function HomePage() {
}
};
// Load dashboard data when child selected
// Load dashboard data when children are loaded
useEffect(() => {
if (selectedChildId) {
if (children.length > 0) {
loadDashboardData();
}
}, [selectedChildId]);
}, [children]);
const loadDashboardData = async () => {
if (!selectedChildId) return;
setLoading(true);
try {
// Load recent activities
const activities = await trackingApi.getActivities(selectedChildId);
setRecentActivities(activities.slice(0, 10));
// Load activities for ALL children to populate metrics
const allMetrics: any = {};
// Calculate today's summary from activities
const today = new Date();
today.setHours(0, 0, 0, 0);
const todayActivities = activities.filter((a: any) => {
const activityDate = new Date(a.timestamp || a.startedAt);
return activityDate >= today;
});
for (const child of children) {
try {
const activities = await trackingApi.getActivities(child.id);
const summary = {
feedingCount: todayActivities.filter((a: any) => a.type === 'feeding').length,
sleepCount: todayActivities.filter((a: any) => a.type === 'sleep').length,
diaperCount: todayActivities.filter((a: any) => a.type === 'diaper').length,
medicationCount: todayActivities.filter((a: any) => ['medication', 'medicine'].includes(a.type)).length,
totalFeedingAmount: todayActivities
.filter((a: any) => a.type === 'feeding')
.reduce((sum: number, a: any) => sum + (a.data?.amount || 0), 0),
totalSleepDuration: todayActivities
.filter((a: any) => a.type === 'sleep')
.reduce((sum: number, a: any) => {
const start = new Date(a.startedAt);
const end = a.endedAt ? new Date(a.endedAt) : new Date();
return sum + (end.getTime() - start.getTime()) / (1000 * 60);
}, 0),
};
// Calculate today's summary from activities
const today = new Date();
today.setHours(0, 0, 0, 0);
const todayActivities = activities.filter((a: any) => {
const activityDate = new Date(a.timestamp || a.startedAt);
return activityDate >= today;
});
setTodaySummary(summary);
allMetrics[child.id] = {
feedingCount: todayActivities.filter((a: any) => a.type === 'feeding').length,
sleepCount: todayActivities.filter((a: any) => a.type === 'sleep').length,
diaperCount: todayActivities.filter((a: any) => a.type === 'diaper').length,
medicationCount: todayActivities.filter((a: any) => ['medication', 'medicine'].includes(a.type)).length,
totalFeedingAmount: todayActivities
.filter((a: any) => a.type === 'feeding')
.reduce((sum: number, a: any) => sum + (a.data?.amount || a.metadata?.amount || 0), 0),
totalSleepDuration: todayActivities
.filter((a: any) => a.type === 'sleep')
.reduce((sum: number, a: any) => {
const start = new Date(a.startedAt);
const end = a.endedAt ? new Date(a.endedAt) : new Date();
return sum + (end.getTime() - start.getTime()) / (1000 * 60);
}, 0),
};
// If this is the selected child, also set recent activities
if (child.id === selectedChildId) {
setRecentActivities(activities.slice(0, 10));
setTodaySummary(allMetrics[child.id]);
}
} catch (err) {
console.error(`Failed to load activities for child ${child.id}:`, err);
allMetrics[child.id] = {
feedingCount: 0,
sleepCount: 0,
diaperCount: 0,
medicationCount: 0,
totalFeedingAmount: 0,
totalSleepDuration: 0,
};
}
}
// Store all metrics in state
setAllChildMetrics(allMetrics);
setError(null);
} catch (err) {
console.error('Failed to load dashboard data:', err);
@@ -188,15 +220,15 @@ export default function HomePage() {
const isLoading = authLoading || loading;
// Build child metrics object for DynamicChildDashboard
// Build child metrics object for DynamicChildDashboard from allChildMetrics
const childMetrics = children.reduce((acc: any, child: any) => {
// Use todaySummary for selected child, or zero for others
if (child.id === selectedChildId && todaySummary) {
const metrics = allChildMetrics[child.id];
if (metrics) {
acc[child.id] = {
feedingCount: todaySummary.feedingCount || 0,
sleepDuration: todaySummary.totalSleepDuration || 0,
diaperCount: todaySummary.diaperCount || 0,
medicationCount: todaySummary.medicationCount || 0,
feedingCount: metrics.feedingCount || 0,
sleepDuration: metrics.totalSleepDuration || 0,
diaperCount: metrics.diaperCount || 0,
medicationCount: metrics.medicationCount || 0,
};
} else {
acc[child.id] = {