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
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;
|
|
|