diff --git a/maternal-web/store/slices/childrenSlice.ts b/maternal-web/store/slices/childrenSlice.ts index dde4484..5740ccb 100644 --- a/maternal-web/store/slices/childrenSlice.ts +++ b/maternal-web/store/slices/childrenSlice.ts @@ -7,10 +7,14 @@ export interface Child { name: string; birthDate: string; gender: 'male' | 'female' | 'other'; - profilePhoto?: string; - metadata?: Record; + photoUrl?: string; + photoAlt?: string; + displayColor: string; + sortOrder: number; + nickname?: string; + medicalInfo?: any; createdAt: string; - updatedAt: string; + updatedAt?: string; // Offline metadata _optimistic?: boolean; _localId?: string; @@ -20,7 +24,8 @@ export interface Child { // Create entity adapter const childrenAdapter = createEntityAdapter({ selectId: (child) => child.id, - sortComparer: (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), + // Sort by sortOrder (birth order) instead of createdAt + sortComparer: (a, b) => a.sortOrder - b.sortOrder, }); // Async thunks @@ -78,13 +83,28 @@ export const updateChild = createAsyncThunk( } ); +interface ChildrenState { + loading: boolean; + error: string | null; + selectedChildId: string | null; + selectedChildIds: string[]; + defaultChildId: string | null; + viewMode: 'auto' | 'tabs' | 'cards'; + lastSelectedPerScreen: Record; + lastSyncTime: string | null; +} + const childrenSlice = createSlice({ name: 'children', - initialState: childrenAdapter.getInitialState({ + initialState: childrenAdapter.getInitialState({ loading: false, - error: null as string | null, - selectedChildId: null as string | null, - lastSyncTime: null as string | null, + error: null, + selectedChildId: null, + selectedChildIds: [], + defaultChildId: null, + viewMode: 'auto', + lastSelectedPerScreen: {}, + lastSyncTime: null, }), reducers: { // Optimistic operations @@ -124,13 +144,59 @@ const childrenSlice = createSlice({ _optimistic: false, }); }, - // Select child + // Select child (single) selectChild: (state, action: PayloadAction) => { state.selectedChildId = action.payload; + state.selectedChildIds = [action.payload]; + // Save to localStorage + if (typeof window !== 'undefined') { + localStorage.setItem('selectedChildId', action.payload); + } + }, + // Select multiple children + selectChildren: (state, action: PayloadAction) => { + state.selectedChildIds = action.payload; + state.selectedChildId = action.payload[0] || null; + }, + // Toggle child selection (for multi-select) + toggleChildSelection: (state, action: PayloadAction) => { + const childId = action.payload; + const index = state.selectedChildIds.indexOf(childId); + + if (index >= 0) { + state.selectedChildIds.splice(index, 1); + } else { + state.selectedChildIds.push(childId); + } + + state.selectedChildId = state.selectedChildIds[0] || null; + }, + // Set default child for quick actions + setDefaultChild: (state, action: PayloadAction) => { + state.defaultChildId = action.payload; + if (typeof window !== 'undefined') { + localStorage.setItem('defaultChildId', action.payload); + } + }, + // Set view mode + setViewMode: (state, action: PayloadAction<'auto' | 'tabs' | 'cards'>) => { + state.viewMode = action.payload; + if (typeof window !== 'undefined') { + localStorage.setItem('childViewMode', action.payload); + } + }, + // Remember last selected child per screen + setLastSelectedForScreen: (state, action: PayloadAction<{ screen: string; childId: string }>) => { + state.lastSelectedPerScreen[action.payload.screen] = action.payload.childId; + if (typeof window !== 'undefined') { + localStorage.setItem('lastSelectedPerScreen', JSON.stringify(state.lastSelectedPerScreen)); + } }, clearChildren: (state) => { childrenAdapter.removeAll(state); state.selectedChildId = null; + state.selectedChildIds = []; + state.defaultChildId = null; state.error = null; }, }, @@ -202,6 +268,11 @@ export const { rollbackOptimistic, markSynced, selectChild, + selectChildren, + toggleChildSelection, + setDefaultChild, + setViewMode, + setLastSelectedForScreen, clearChildren, } = childrenSlice.actions; @@ -216,6 +287,18 @@ export const selectSelectedChild = (state: RootState) => { return id ? state.children.entities[id] : null; }; +export const selectSelectedChildren = (state: RootState) => { + const ids = state.children.selectedChildIds; + return ids + .map(id => state.children.entities[id]) + .filter((child): child is Child => child !== undefined); +}; + +export const selectDefaultChild = (state: RootState) => { + const id = state.children.defaultChildId; + return id ? state.children.entities[id] : null; +}; + export const selectChildrenByFamily = (state: RootState, familyId: string) => childrenSelectors .selectAll(state) @@ -226,4 +309,27 @@ export const selectPendingChildren = (state: RootState) => .selectAll(state) .filter((child) => child._optimistic); +export const selectChildrenCount = (state: RootState) => + childrenSelectors.selectTotal(state); + +export const selectViewMode = (state: RootState) => { + const { viewMode } = state.children; + const childrenCount = childrenSelectors.selectTotal(state); + + if (viewMode === 'auto') { + return childrenCount <= 3 ? 'tabs' : 'cards'; + } + + return viewMode; +}; + +export const selectChildColor = (childId: string) => (state: RootState) => { + const child = state.children.entities[childId]; + return child?.displayColor || '#FF6B9D'; +}; + +export const selectLastSelectedForScreen = (screen: string) => (state: RootState) => { + return state.children.lastSelectedPerScreen[screen]; +}; + export default childrenSlice.reducer;