Add Phase 2 & 3: Web frontend with authentication and tracking features

- Initialize Next.js 14 web application with Material UI and TypeScript
- Implement authentication (login/register) with device fingerprint
- Create mobile-first responsive layout with app shell pattern
- Add tracking pages for feeding, sleep, and diaper changes
- Implement activity history with filtering
- Configure backend CORS for web frontend (port 3030)
- Update backend port to 3020, frontend to 3030
- Fix API response handling for auth endpoints

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
andupetcu
2025-09-30 21:21:22 +03:00
parent 1de21044d6
commit 37227369d3
32 changed files with 11584 additions and 0 deletions

View File

@@ -0,0 +1,248 @@
'use client';
import { useState } from 'react';
import {
Box,
Stepper,
Step,
StepLabel,
Button,
Typography,
Paper,
TextField,
Avatar,
IconButton,
Alert,
} from '@mui/material';
import { ArrowBack, ArrowForward, Check } from '@mui/icons-material';
import { motion, AnimatePresence } from 'framer-motion';
import { useRouter } from 'next/navigation';
const steps = ['Welcome', 'Add Child', 'Invite Family', 'Notifications'];
export default function OnboardingPage() {
const [activeStep, setActiveStep] = useState(0);
const [childName, setChildName] = useState('');
const [childBirthDate, setChildBirthDate] = useState('');
const router = useRouter();
const handleNext = () => {
if (activeStep === steps.length - 1) {
// Complete onboarding
router.push('/');
} else {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
}
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleSkip = () => {
router.push('/');
};
return (
<Box
sx={{
minHeight: '100vh',
display: 'flex',
flexDirection: 'column',
px: 3,
py: 4,
background: 'linear-gradient(135deg, #FFE4E1 0%, #FFDAB9 100%)',
}}
>
<Paper
elevation={0}
sx={{
maxWidth: 600,
mx: 'auto',
width: '100%',
p: 4,
borderRadius: 4,
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
}}
>
<Stepper activeStep={activeStep} sx={{ mb: 4 }}>
{steps.map((label) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
</Step>
))}
</Stepper>
<AnimatePresence mode="wait">
<motion.div
key={activeStep}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
>
{activeStep === 0 && (
<Box sx={{ textAlign: 'center', py: 4 }}>
<Typography variant="h4" gutterBottom fontWeight="600" color="primary.main">
Welcome to Maternal! 🎉
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mt: 2, mb: 4 }}>
We're excited to help you track and understand your child's development, sleep patterns, feeding schedules, and more.
</Typography>
<Box sx={{ display: 'flex', gap: 2, justifyContent: 'center', flexWrap: 'wrap' }}>
<Paper sx={{ p: 2, flex: 1, minWidth: 150 }}>
<Typography variant="h6" fontWeight="600">📊</Typography>
<Typography variant="body2">Track Activities</Typography>
</Paper>
<Paper sx={{ p: 2, flex: 1, minWidth: 150 }}>
<Typography variant="h6" fontWeight="600">🤖</Typography>
<Typography variant="body2">AI Insights</Typography>
</Paper>
<Paper sx={{ p: 2, flex: 1, minWidth: 150 }}>
<Typography variant="h6" fontWeight="600">👨👩👧</Typography>
<Typography variant="body2">Family Sharing</Typography>
</Paper>
</Box>
</Box>
)}
{activeStep === 1 && (
<Box sx={{ py: 4 }}>
<Typography variant="h5" gutterBottom fontWeight="600">
Add Your First Child
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
Let's start by adding some basic information about your child.
</Typography>
<TextField
fullWidth
label="Child's Name"
value={childName}
onChange={(e) => setChildName(e.target.value)}
margin="normal"
InputProps={{
sx: { borderRadius: 3 },
}}
/>
<TextField
fullWidth
label="Birth Date"
type="date"
value={childBirthDate}
onChange={(e) => setChildBirthDate(e.target.value)}
margin="normal"
InputLabelProps={{
shrink: true,
}}
InputProps={{
sx: { borderRadius: 3 },
}}
/>
<Alert severity="info" sx={{ mt: 3, borderRadius: 2 }}>
You can add more children and details later from settings.
</Alert>
</Box>
)}
{activeStep === 2 && (
<Box sx={{ py: 4 }}>
<Typography variant="h5" gutterBottom fontWeight="600">
Invite Family Members
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
Share your child's progress with family members. They can view activities and add their own entries.
</Typography>
<TextField
fullWidth
label="Email Address"
type="email"
margin="normal"
placeholder="partner@example.com"
InputProps={{
sx: { borderRadius: 3 },
}}
/>
<Button
variant="outlined"
fullWidth
sx={{ mt: 2 }}
>
Send Invitation
</Button>
<Alert severity="info" sx={{ mt: 3, borderRadius: 2 }}>
You can skip this step and invite family members later.
</Alert>
</Box>
)}
{activeStep === 3 && (
<Box sx={{ textAlign: 'center', py: 4 }}>
<Avatar
sx={{
width: 80,
height: 80,
bgcolor: 'primary.main',
mx: 'auto',
mb: 3,
}}
>
<Check sx={{ fontSize: 48 }} />
</Avatar>
<Typography variant="h5" gutterBottom fontWeight="600">
You're All Set! 🎉
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 4 }}>
Start tracking your child's activities and get personalized insights.
</Typography>
<Paper sx={{ p: 3, bgcolor: 'primary.light', mb: 3 }}>
<Typography variant="body2" fontWeight="600" gutterBottom>
Next Steps:
</Typography>
<Typography variant="body2" align="left" component="div">
• Track your first feeding, sleep, or diaper change<br />
• Chat with our AI assistant for parenting tips<br />
• Explore insights and predictions based on your data
</Typography>
</Paper>
</Box>
)}
</motion.div>
</AnimatePresence>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 4 }}>
<Button
onClick={handleBack}
disabled={activeStep === 0}
startIcon={<ArrowBack />}
>
Back
</Button>
<Box sx={{ flex: 1 }} />
{activeStep < steps.length - 1 && activeStep > 0 && (
<Button onClick={handleSkip} sx={{ mr: 2 }}>
Skip
</Button>
)}
<Button
variant="contained"
onClick={handleNext}
endIcon={activeStep === steps.length - 1 ? <Check /> : <ArrowForward />}
>
{activeStep === steps.length - 1 ? 'Get Started' : 'Next'}
</Button>
</Box>
</Paper>
</Box>
);
}