feat: Update UI colors to use dynamic theme system and fix predictions
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

**Theme-Aware Colors Across App:**
- Updated track page cards to use theme.palette colors
- Updated analytics page icons to use theme colors
- Updated login/register gradient backgrounds to use theme colors
- All colors now respond to Standard/High Contrast theme toggle

**Fixed Next Predicted Activity Section:**
- Connected to real analytics API predictions endpoint
- Fetches sleep and feeding predictions based on actual data
- Shows "Nap time in X minutes" when prediction available
- Displays formatted time using formatDistanceToNow
- Falls back to "Not enough data available for now. Keep tracking :)" when no predictions

**Multi-Language Support:**
- Added "notEnoughData" translation key to all 7 languages:
  - English: "Not enough data available for now. Keep tracking :)"
  - Spanish: "No hay suficientes datos disponibles por ahora. ¡Sigue rastreando! :)"
  - French: "Pas assez de données disponibles pour le moment. Continuez à suivre :)"
  - Portuguese: "Dados insuficientes disponíveis no momento. Continue rastreando :)"
  - Chinese: "暂无足够数据。请继续记录 :)"
  - German: "Derzeit nicht genügend Daten verfügbar. Weiter verfolgen :)"
  - Italian: "Dati insufficienti al momento. Continua a monitorare :)"

**Color Mapping by Theme:**

*Purple Theme (Standard):*
- Feeding: Primary (#8b52ff)
- Sleep: Secondary (#ff7094)
- Diaper: Warning (amber)
- Medical: Error (red)
- Activity: Success (green)
- Growth: Primary Dark

*Peach Theme (High Contrast):*
- Feeding: Primary (#FFB6C1)
- Sleep: Secondary (#FFDAB9)
- Diaper: Warning (amber)
- Medical: Error (red)
- Activity: Success (green)
- Growth: Primary Dark

**Files Modified:**
- app/track/page.tsx - Dynamic theme colors
- app/analytics/page.tsx - Theme-aware icon colors
- app/(auth)/login/page.tsx - Gradient uses theme
- app/(auth)/register/page.tsx - Gradient uses theme
- app/page.tsx - Predictions integration
- locales/*/dashboard.json - All 7 languages

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 13:58:24 +00:00
parent 2a48dd24ff
commit f31addc471
13 changed files with 92 additions and 27 deletions

View File

@@ -23,15 +23,18 @@ import { useAuth } from '@/lib/auth/AuthContext';
import { useRouter } from 'next/navigation';
import { useQuery } from '@apollo/client/react';
import { GET_DASHBOARD } from '@/graphql/queries/dashboard';
import { format } from 'date-fns';
import { format, formatDistanceToNow } from 'date-fns';
import { useRealTimeActivities } from '@/hooks/useWebSocket';
import { useTranslation } from '@/hooks/useTranslation';
import { analyticsApi } from '@/lib/api/analytics';
export default function HomePage() {
const { t } = useTranslation('dashboard');
const { user, isLoading: authLoading } = useAuth();
const router = useRouter();
const [selectedChildId, setSelectedChildId] = useState<string | null>(null);
const [predictions, setPredictions] = useState<any>(null);
const [predictionsLoading, setPredictionsLoading] = useState(false);
// GraphQL query for dashboard data
const { data, loading, error, refetch } = useQuery(GET_DASHBOARD, {
@@ -94,6 +97,26 @@ export default function HomePage() {
}
}, [data, selectedChildId]);
// Fetch predictions when selectedChildId changes
useEffect(() => {
const fetchPredictions = async () => {
if (!selectedChildId) return;
setPredictionsLoading(true);
try {
const predictionData = await analyticsApi.getPredictions(selectedChildId);
setPredictions(predictionData);
} catch (err) {
console.error('Failed to fetch predictions:', err);
setPredictions(null);
} finally {
setPredictionsLoading(false);
}
};
fetchPredictions();
}, [selectedChildId]);
const quickActions = [
{ icon: <Restaurant />, label: t('quickActions.feeding'), color: '#E91E63', path: '/track/feeding' }, // Pink with 4.5:1 contrast
{ icon: <Hotel />, label: t('quickActions.sleep'), color: '#1976D2', path: '/track/sleep' }, // Blue with 4.5:1 contrast
@@ -322,12 +345,39 @@ export default function HomePage() {
<Typography variant="body2" sx={{ color: 'rgba(0, 0, 0, 0.7)' }} gutterBottom>
{t('predictions.title')}
</Typography>
<Typography variant="h6" fontWeight="600" gutterBottom>
{t('predictions.napTime', { minutes: 45 })}
</Typography>
<Typography variant="body2" sx={{ color: 'rgba(0, 0, 0, 0.7)' }}>
{t('predictions.basedOnPatterns')}
</Typography>
{predictionsLoading ? (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<CircularProgress size={20} />
<Typography variant="body2">Loading predictions...</Typography>
</Box>
) : predictions?.sleep?.nextNapTime || predictions?.feeding?.nextFeedingTime ? (
<>
{predictions.sleep?.nextNapTime && (
<>
<Typography variant="h6" fontWeight="600" gutterBottom>
Nap time {formatDistanceToNow(new Date(predictions.sleep.nextNapTime), { addSuffix: true })}
</Typography>
<Typography variant="body2" sx={{ color: 'rgba(0, 0, 0, 0.7)' }}>
{predictions.sleep.reasoning || t('predictions.basedOnPatterns')}
</Typography>
</>
)}
{!predictions.sleep?.nextNapTime && predictions.feeding?.nextFeedingTime && (
<>
<Typography variant="h6" fontWeight="600" gutterBottom>
Feeding time {formatDistanceToNow(new Date(predictions.feeding.nextFeedingTime), { addSuffix: true })}
</Typography>
<Typography variant="body2" sx={{ color: 'rgba(0, 0, 0, 0.7)' }}>
{predictions.feeding.reasoning || t('predictions.basedOnPatterns')}
</Typography>
</>
)}
</>
) : (
<Typography variant="body1" sx={{ color: 'rgba(0, 0, 0, 0.7)' }}>
{t('predictions.notEnoughData')}
</Typography>
)}
</Paper>
</Box>
</motion.div>