feat: Integrate ChildSelector in diaper tracking form
- Replace local child state with Redux state management - Use ChildSelector component instead of custom select - Sync selectedChildIds with Redux store - Update API calls to use selectedChild.id - Remove loadChildren function
This commit is contained in:
@@ -48,6 +48,10 @@ import { childrenApi, Child } from '@/lib/api/children';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useLocalizedDate } from '@/hooks/useLocalizedDate';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { fetchChildren, selectChild, selectSelectedChild, childrenSelectors } from '@/store/slices/childrenSlice';
|
||||
import { AppDispatch, RootState } from '@/store/store';
|
||||
import ChildSelector from '@/components/common/ChildSelector';
|
||||
|
||||
interface DiaperData {
|
||||
diaperType: 'wet' | 'dirty' | 'both' | 'dry';
|
||||
@@ -62,8 +66,15 @@ export default function DiaperTrackPage() {
|
||||
const { user } = useAuth();
|
||||
const { t } = useTranslation('tracking');
|
||||
const { formatDistanceToNow, format } = useLocalizedDate();
|
||||
const [children, setChildren] = useState<Child[]>([]);
|
||||
const [selectedChild, setSelectedChild] = useState<string>('');
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
|
||||
// Redux state
|
||||
const children = useSelector((state: RootState) => childrenSelectors.selectAll(state));
|
||||
const selectedChild = useSelector(selectSelectedChild);
|
||||
const familyId = useSelector((state: RootState) => state.auth.user?.familyId);
|
||||
|
||||
// Local state
|
||||
const [selectedChildIds, setSelectedChildIds] = useState<string[]>([]);
|
||||
|
||||
// Diaper state
|
||||
const [timestamp, setTimestamp] = useState<string>(
|
||||
@@ -78,7 +89,6 @@ export default function DiaperTrackPage() {
|
||||
const [notes, setNotes] = useState<string>('');
|
||||
const [recentDiapers, setRecentDiapers] = useState<Activity[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [childrenLoading, setChildrenLoading] = useState(true);
|
||||
const [diapersLoading, setDiapersLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||
@@ -87,8 +97,6 @@ export default function DiaperTrackPage() {
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [activityToDelete, setActivityToDelete] = useState<string | null>(null);
|
||||
|
||||
const familyId = user?.families?.[0]?.familyId;
|
||||
|
||||
const availableConditions = [
|
||||
'normal',
|
||||
'soft',
|
||||
@@ -98,19 +106,26 @@ export default function DiaperTrackPage() {
|
||||
'blood',
|
||||
];
|
||||
|
||||
// Load children
|
||||
// Load children from Redux
|
||||
useEffect(() => {
|
||||
if (familyId) {
|
||||
loadChildren();
|
||||
if (familyId && children.length === 0) {
|
||||
dispatch(fetchChildren(familyId));
|
||||
}
|
||||
}, [familyId]);
|
||||
}, [familyId, dispatch, children.length]);
|
||||
|
||||
// Sync selectedChildIds with Redux selectedChild
|
||||
useEffect(() => {
|
||||
if (selectedChild?.id) {
|
||||
setSelectedChildIds([selectedChild.id]);
|
||||
}
|
||||
}, [selectedChild]);
|
||||
|
||||
// Load recent diapers when child is selected
|
||||
useEffect(() => {
|
||||
if (selectedChild) {
|
||||
if (selectedChild?.id) {
|
||||
loadRecentDiapers();
|
||||
}
|
||||
}, [selectedChild]);
|
||||
}, [selectedChild?.id]);
|
||||
|
||||
// Pre-fill form from URL parameters (voice command)
|
||||
useEffect(() => {
|
||||
@@ -164,30 +179,12 @@ export default function DiaperTrackPage() {
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
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 loadRecentDiapers = async () => {
|
||||
if (!selectedChild) return;
|
||||
if (!selectedChild?.id) return;
|
||||
|
||||
try {
|
||||
setDiapersLoading(true);
|
||||
const activities = await trackingApi.getActivities(selectedChild, 'diaper');
|
||||
const activities = await trackingApi.getActivities(selectedChild.id, 'diaper');
|
||||
// Sort by timestamp descending and take last 10
|
||||
const sorted = activities.sort((a, b) =>
|
||||
new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
||||
@@ -217,7 +214,7 @@ export default function DiaperTrackPage() {
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!selectedChild) {
|
||||
if (!selectedChild?.id) {
|
||||
setError('Please select a child');
|
||||
return;
|
||||
}
|
||||
@@ -247,7 +244,7 @@ export default function DiaperTrackPage() {
|
||||
data.rashSeverity = rashSeverity;
|
||||
}
|
||||
|
||||
await trackingApi.createActivity(selectedChild, {
|
||||
await trackingApi.createActivity(selectedChild.id, {
|
||||
type: 'diaper',
|
||||
timestamp,
|
||||
data,
|
||||
@@ -361,7 +358,9 @@ export default function DiaperTrackPage() {
|
||||
}
|
||||
};
|
||||
|
||||
if (childrenLoading) {
|
||||
const childrenLoading = useSelector((state: RootState) => state.children.loading);
|
||||
|
||||
if (childrenLoading && children.length === 0) {
|
||||
return (
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
@@ -434,22 +433,21 @@ export default function DiaperTrackPage() {
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
{/* Child Selector */}
|
||||
{children.length > 1 && (
|
||||
{children.length > 0 && (
|
||||
<Paper sx={{ p: 2, mb: 3 }}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>{t('common.selectChild')}</InputLabel>
|
||||
<Select
|
||||
value={selectedChild}
|
||||
onChange={(e) => setSelectedChild(e.target.value)}
|
||||
label={t('common.selectChild')}
|
||||
>
|
||||
{children.map((child) => (
|
||||
<MenuItem key={child.id} value={child.id}>
|
||||
{child.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<ChildSelector
|
||||
children={children}
|
||||
selectedChildIds={selectedChildIds}
|
||||
onChange={(childIds) => {
|
||||
setSelectedChildIds(childIds);
|
||||
if (childIds.length > 0) {
|
||||
dispatch(selectChild(childIds[0]));
|
||||
}
|
||||
}}
|
||||
mode="single"
|
||||
label={t('common.selectChild')}
|
||||
required
|
||||
/>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user