feat: implement onboarding process and enrollment status tracking for users
This commit is contained in:
@@ -1,40 +1,50 @@
|
||||
import { createContext, useContext, useReducer, useEffect } from 'react';
|
||||
import * as db from '../lib/db';
|
||||
import { pb } from '../lib/pb';
|
||||
import { getPersonalWeekNumber } from '../lib/curriculumService';
|
||||
|
||||
const AppContext = createContext();
|
||||
|
||||
const initialState = {
|
||||
currentUser: null,
|
||||
users: [],
|
||||
weekNumber: getWeekNumber(new Date()),
|
||||
weekNumber: 0,
|
||||
isLoading: true
|
||||
};
|
||||
|
||||
function computeWeekNumber(user) {
|
||||
if (!user || !user.curriculum_started_at || user.enrollment_status !== 'active') return 0;
|
||||
return getPersonalWeekNumber(user.curriculum_started_at);
|
||||
}
|
||||
|
||||
function appReducer(state, action) {
|
||||
switch (action.type) {
|
||||
case 'INIT_APP':
|
||||
return {
|
||||
...state,
|
||||
users: action.payload.users,
|
||||
weekNumber: action.payload.weekNumber || state.weekNumber,
|
||||
isLoading: false
|
||||
};
|
||||
case 'LOGIN':
|
||||
return { ...state, currentUser: action.payload };
|
||||
return {
|
||||
...state,
|
||||
currentUser: action.payload,
|
||||
weekNumber: computeWeekNumber(action.payload),
|
||||
};
|
||||
case 'UPDATE_CURRENT_USER':
|
||||
return {
|
||||
...state,
|
||||
currentUser: action.payload,
|
||||
weekNumber: computeWeekNumber(action.payload),
|
||||
users: state.users.map(u => u.id === action.payload.id ? action.payload : u),
|
||||
};
|
||||
case 'LOGOUT':
|
||||
return { ...state, currentUser: null };
|
||||
return { ...state, currentUser: null, weekNumber: 0 };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function getWeekNumber(d) {
|
||||
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
||||
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
|
||||
const yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
|
||||
return Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
|
||||
}
|
||||
|
||||
export function AppProvider({ children }) {
|
||||
const [state, dispatch] = useReducer(appReducer, initialState);
|
||||
|
||||
@@ -52,8 +62,6 @@ export function AppProvider({ children }) {
|
||||
}
|
||||
}
|
||||
|
||||
const storedWeek = getWeekNumber(new Date());
|
||||
|
||||
const sessionUserId = sessionStorage.getItem('respellion_session');
|
||||
if (sessionUserId) {
|
||||
const user = members.find(u => u.id === sessionUserId);
|
||||
@@ -62,7 +70,7 @@ export function AppProvider({ children }) {
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({ type: 'INIT_APP', payload: { users: members, weekNumber: storedWeek } });
|
||||
dispatch({ type: 'INIT_APP', payload: { users: members } });
|
||||
};
|
||||
|
||||
loadState().catch(console.error);
|
||||
@@ -83,8 +91,23 @@ export function AppProvider({ children }) {
|
||||
dispatch({ type: 'LOGOUT' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Start the curriculum for the currently logged-in user.
|
||||
* Records the start timestamp and flips enrollment_status to 'active'.
|
||||
*/
|
||||
const enrollCurrentUser = async () => {
|
||||
if (!state.currentUser) throw new Error('No user is logged in.');
|
||||
const startedAt = new Date().toISOString();
|
||||
const updated = await pb.collection('team_members').update(state.currentUser.id, {
|
||||
curriculum_started_at: startedAt,
|
||||
enrollment_status: 'active',
|
||||
});
|
||||
dispatch({ type: 'UPDATE_CURRENT_USER', payload: updated });
|
||||
return updated;
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{ state, dispatch, login, logout }}>
|
||||
<AppContext.Provider value={{ state, dispatch, login, logout, enrollCurrentUser }}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user