From 91a785dc801b0ee7611f0be054475f32f6dcb2fd Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Wed, 28 Dec 2022 17:07:05 +0100 Subject: [PATCH] Refactor course sessions store to use setup API --- client/src/components/MainNavigationBar.vue | 7 +- client/src/pages/DashboardPage.vue | 6 +- client/src/stores/courseSessions.ts | 73 ++++++++++++++++++--- client/src/stores/user.ts | 7 +- 4 files changed, 75 insertions(+), 18 deletions(-) diff --git a/client/src/components/MainNavigationBar.vue b/client/src/components/MainNavigationBar.vue index db318565..363a7e60 100644 --- a/client/src/components/MainNavigationBar.vue +++ b/client/src/components/MainNavigationBar.vue @@ -6,7 +6,7 @@ import IconSettings from "@/components/icons/IconSettings.vue"; import MobileMenu from "@/components/MobileMenu.vue"; import ItDropdown from "@/components/ui/ItDropdown.vue"; import { useAppStore } from "@/stores/app"; -import { useCourseSessionsStore } from "@/stores/courseSessions"; +import { useSetupCourseSessionsStore } from "@/stores/courseSessions"; import { useUserStore } from "@/stores/user"; import type { DropdownListItem } from "@/types"; import type { Component } from "vue"; @@ -26,7 +26,7 @@ const route = useRoute(); const router = useRouter(); const userStore = useUserStore(); const appStore = useAppStore(); -const courseSessionsStore = useCourseSessionsStore(); +const courseSessionsStore = useSetupCourseSessionsStore(); const { t } = useI18n(); const state = reactive({ showMenu: false }); @@ -78,7 +78,8 @@ function logout() { onMounted(() => { log.debug("MainNavigationBar mounted"); if (userStore.loggedIn) { - courseSessionsStore.loadCourseSessionsData(); + // fixme: only when i'm logged in? should this be handled in the store? + // courseSessionsStore.loadCourseSessionsData(); } }); diff --git a/client/src/pages/DashboardPage.vue b/client/src/pages/DashboardPage.vue index 46242edf..72cab46e 100644 --- a/client/src/pages/DashboardPage.vue +++ b/client/src/pages/DashboardPage.vue @@ -1,7 +1,6 @@ diff --git a/client/src/stores/courseSessions.ts b/client/src/stores/courseSessions.ts index e2126a41..a78a78c8 100644 --- a/client/src/stores/courseSessions.ts +++ b/client/src/stores/courseSessions.ts @@ -1,25 +1,82 @@ import { itGetCached } from "@/fetchHelpers"; -import type { CourseSession } from "@/types"; +import type { CircleExpert, Course, CourseSession } from "@/types"; import _ from "lodash"; import log from "loglevel"; import { defineStore } from "pinia"; +import { computed, ref } from "vue"; import { useRoute } from "vue-router"; import { useUserStore } from "./user"; -export type CourseSessionsStoreState = { - courseSessions: CourseSession[] | undefined; -}; +function loadCourseSessionsData(reload = false) { + log.debug("loadCourseSessionsData called"); + const courseSessions = ref([]); -export const useCourseSessionsStore = defineStore({ + async function loadAndUpdate() { + courseSessions.value = await itGetCached(`/api/course/sessions/`, { + reload: reload, + }); + if (!courseSessions.value) { + throw `No courseSessionData found for user`; + } + } + + loadAndUpdate(); // this will be called asynchronously, but does not block + + // returns the empty sessions array at first, then after loading populates the ref + return { courseSessions }; +} + +export const useSetupCourseSessionsStore = defineStore("courseSessionsSetup", () => { + // using setup function seems cleaner, see https://pinia.vuejs.org/core-concepts/#setup-stores + + // this will become a state variable (like each other `ref()` + + // store should do own setup, we don't want to have each component initialize it + // that's why we call the load function in here + const { courseSessions } = loadCourseSessionsData(); + // these will become getters + const coursesFromCourseSessions = computed(() => + _.uniqBy(courseSessions.value, "course.id") + ); + const courseSessionForRoute = computed(() => { + const route = useRoute(); + const routePath = decodeURI(route.path); + + return courseSessions.value.find((cs) => { + return routePath.startsWith(cs.course_url); + }); + }); + const hasCockpit = computed(() => { + if (courseSessionForRoute.value) { + const userStore = useUserStore(); + return ( + courseSessionForRoute.value.experts.filter( + (expert) => expert.user_id === userStore.id + ).length > 0 + ); + } + + return false; + }); + + return { + courseSessions, + coursesFromCourseSessions, + courseSessionForRoute, + hasCockpit, + }; +}); + +export const useOptionsCourseSessionsStore = defineStore({ id: "courseSessions", state: () => { return { - courseSessions: undefined, - } as CourseSessionsStoreState; + courseSessions: [] as CourseSession[], + }; }, getters: { - courseSessionForRoute: (state) => { + courseSessionForRoute: (state): CourseSession | undefined => { const route = useRoute(); const routePath = decodeURI(route.path); return state.courseSessions?.find((cs) => { diff --git a/client/src/stores/user.ts b/client/src/stores/user.ts index 1067c136..6f5d2f6c 100644 --- a/client/src/stores/user.ts +++ b/client/src/stores/user.ts @@ -2,7 +2,7 @@ import * as log from "loglevel"; import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers"; import { useAppStore } from "@/stores/app"; -import { useCourseSessionsStore } from "@/stores/courseSessions"; +// import { useSetupCourseSessionsStore } from "@/stores/courseSessions"; import { defineStore } from "pinia"; const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT; @@ -77,8 +77,9 @@ export const useUserStore = defineStore({ this.$state = data; this.loggedIn = true; appStore.userLoaded = true; - const courseSessionsStore = useCourseSessionsStore(); - await courseSessionsStore.loadCourseSessionsData(); + // todo: why? + // const courseSessionsStore = useCourseSessionsStore(); + // await courseSessionsStore.loadCourseSessionsData(); }, }, });