You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

96 lines
2.8 KiB

import {PastWorkout, WorkoutState} from "../models/Workouts";
import {createContext, useCallback, useContext, useEffect, useState} from "react";
import {unimplemented} from "../helpers/misc";
import {WithChildren} from "../primitives/Shared";
import workoutRepo from "../actions/workouts";
interface WorkoutContextValue {
workouts: PastWorkout[]
loadingWorkouts: boolean
expanded: boolean
getWorkout(workoutId: string): PastWorkout | null
fetchWorkout(workoutId: string): void
getStates(workoutId: string): WorkoutState[] | null
fetchStates(workoutId: string): void
refreshWorkouts(): void
showMoreWorkouts(): void
}
const WorkoutContext = createContext<WorkoutContextValue>({
workouts: [],
loadingWorkouts: false,
expanded: false,
getWorkout: unimplemented,
fetchWorkout: unimplemented,
getStates: unimplemented,
fetchStates: unimplemented,
refreshWorkouts: unimplemented,
showMoreWorkouts: unimplemented,
});
export function WorkoutContextProvider({children}: WithChildren) {
const [workouts, setWorkouts] = useState<PastWorkout[]>([]);
const [cache, setCache] = useState<Record<string, PastWorkout>>({});
const [loadingWorkouts, setLoadingWorkouts] = useState<boolean>(false);
const [expanded, setExpanded] = useState<boolean>(false);
const [ver, setVer] = useState(0);
const [stateMap, setStateMap] = useState<Record<string, WorkoutState[]>>({});
const getWorkout = useCallback((workoutId: string) => {
return cache[workoutId] || workouts.find(w => w.id === workoutId);
}, [cache, workouts]);
const fetchWorkout = useCallback((workoutId: string) => {
workoutRepo().findById(workoutId)
.then(result => {
if (result) {
setCache(prev => ({...prev, [workoutId]: result}));
}
});
}, []);
const getStates = useCallback((workoutId: string) => {
return stateMap[workoutId] || null;
}, [stateMap]);
const fetchStates = useCallback((workoutId: string) => {
workoutRepo().fetchStates(workoutId)
.then(result => setStateMap(prev => ({...prev, [workoutId]: result})));
}, []);
const refreshWorkouts = useCallback(() => {
setVer(prev => prev + 1);
}, []);
const showMoreWorkouts = useCallback(() => {
setExpanded(true);
}, []);
useEffect(() => {
if (ver === 0) {
return;
}
setLoadingWorkouts(true);
workoutRepo().fetchByFilter({daysBack: expanded ? undefined : 6, includeTest: false})
.then(setWorkouts)
.finally(() => setLoadingWorkouts(false));
}, [expanded, ver]);
return (
<WorkoutContext.Provider value={{
workouts, loadingWorkouts, expanded,
getWorkout, fetchWorkout,
getStates, fetchStates,
refreshWorkouts, showMoreWorkouts,
}}>
{children}
</WorkoutContext.Provider>
);
}
export default WorkoutContext;