docs: Add comprehensive multi-child implementation plan
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

Added detailed implementation plan covering:
- Frontend: Dynamic UI, child selector, bulk activity logging, comparison analytics
- Backend: Bulk operations, multi-child queries, family statistics
- AI/Voice: Child name detection, context building, clarification flows
- Database: Schema enhancements, user preferences, bulk operation tracking
- State management, API enhancements, real-time sync updates
- Testing strategy: Unit, integration, and E2E tests
- Migration plan with feature flags for phased rollout
- Performance optimizations: Caching, indexes, code splitting

Also includes:
- Security fixes for multi-family data leakage in analytics pages
- ParentFlow branding updates
- Activity tracking navigation improvements
- Backend DTO and error handling fixes

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 21:05:14 +00:00
parent f854fe6fcd
commit 95ef0e5e78
12 changed files with 2778 additions and 321 deletions

View File

@@ -40,6 +40,7 @@ import PredictionsCard from '@/components/features/analytics/PredictionsCard';
import GrowthSpurtAlert from '@/components/features/analytics/GrowthSpurtAlert';
import WeeklyReportCard from '@/components/features/analytics/WeeklyReportCard';
import MonthlyReportCard from '@/components/features/analytics/MonthlyReportCard';
import { useAuth } from '@/lib/auth/AuthContext';
interface TabPanelProps {
children?: React.ReactNode;
@@ -65,6 +66,7 @@ function TabPanel(props: TabPanelProps) {
export default function AnalyticsPage() {
const theme = useTheme();
const { user } = useAuth();
const [children, setChildren] = useState<Child[]>([]);
const [selectedChildId, setSelectedChildId] = useState<string>('');
const [tabValue, setTabValue] = useState(0);
@@ -74,27 +76,54 @@ export default function AnalyticsPage() {
const [insightsLoading, setInsightsLoading] = useState(false);
const [predictionsLoading, setPredictionsLoading] = useState(false);
const [days, setDays] = useState<number>(7);
const [error, setError] = useState<string>('');
const familyId = user?.families?.[0]?.familyId;
useEffect(() => {
loadChildren();
}, []);
useEffect(() => {
if (selectedChildId) {
loadInsights();
loadPredictions();
if (familyId) {
loadChildren();
}
}, [selectedChildId, days]);
}, [familyId]);
useEffect(() => {
if (selectedChildId && children.length > 0) {
// Validate that selectedChildId belongs to current user's children
const childExists = children.some(child => child.id === selectedChildId);
if (childExists) {
loadInsights();
loadPredictions();
} else {
console.warn('[AnalyticsPage] Selected child not found in user\'s children, resetting');
setSelectedChildId(children[0].id);
setError('Selected child not found. Showing data for your first child.');
}
}
}, [selectedChildId, days, children]);
const loadChildren = async () => {
if (!familyId) {
setLoading(false);
setError('No family found');
return;
}
try {
const data = await childrenApi.getChildren();
console.log('[AnalyticsPage] Loading children for familyId:', familyId);
const data = await childrenApi.getChildren(familyId);
console.log('[AnalyticsPage] Loaded children:', data);
setChildren(data);
if (data.length > 0 && !selectedChildId) {
setSelectedChildId(data[0].id);
if (data.length > 0) {
const existingChildStillValid = data.some(child => child.id === selectedChildId);
if (!selectedChildId || !existingChildStillValid) {
setSelectedChildId(data[0].id);
}
}
setError('');
} catch (error) {
console.error('Failed to load children:', error);
console.error('[AnalyticsPage] Failed to load children:', error);
setError('Failed to load children');
} finally {
setLoading(false);
}