From c427006fea7e119491409e8aa9a09fdf8df53ea3 Mon Sep 17 00:00:00 2001
From: Santiago Gonzalez <santiago.gonzalez.pereyra@fing.edu.uy>
Date: Mon, 22 Jul 2019 22:13:29 -0300
Subject: [PATCH] Course api request refactor

---
 src/components/BreakpointManager.ts |  3 +-
 src/helper.ts                       |  2 +-
 src/screens/course/Course.tsx       | 98 +++++++++++++++++++++++++----
 src/style/Mixins.ts                 |  3 +-
 4 files changed, 92 insertions(+), 14 deletions(-)

diff --git a/src/components/BreakpointManager.ts b/src/components/BreakpointManager.ts
index e23038b..746c510 100644
--- a/src/components/BreakpointManager.ts
+++ b/src/components/BreakpointManager.ts
@@ -1,6 +1,7 @@
 import { useContext, useEffect } from "react";
-import { getBreakpointForWidth } from "src/helper";
+
 import { AppStoreContext } from "./AppStoreContext";
+import { getBreakpointForWidth } from "src/helper";
 
 export const BreakpointManager = () => {
 	const appStore = useContext(AppStoreContext);
diff --git a/src/helper.ts b/src/helper.ts
index 0378e0d..e1d6b76 100644
--- a/src/helper.ts
+++ b/src/helper.ts
@@ -4,7 +4,7 @@ export const getBreakpointForWidth = (width: number): number => {
 	const breakpoints = Object.keys(Breakpoint);
 
 	let result = breakpoints[0];
-	for (let i = 0; i < breakpoints.length && width > Breakpoint[breakpoints[i]]; i++) result = breakpoints[i];
+	for (let i = 0; i < breakpoints.length && width >= Breakpoint[breakpoints[i]]; i++) result = breakpoints[i];
 
 	return Breakpoint[result];
 };
diff --git a/src/screens/course/Course.tsx b/src/screens/course/Course.tsx
index b0722ed..87157bd 100644
--- a/src/screens/course/Course.tsx
+++ b/src/screens/course/Course.tsx
@@ -1,24 +1,87 @@
 import { CourseContext, CourseProvider } from "./useCourse";
+import React, { useContext, useEffect, useMemo } from "react";
 import { observer, useComputed } from "mobx-react-lite";
-import { useContext, useEffect, useMemo } from "react";
 
 import { AppStoreContext } from "src/components/AppStoreContext";
 import { Breakpoint } from "src/style";
 import { LayoutContext } from "../../layout/Layout";
 import { Loading } from "src/components/loading/Loading";
 import { NavigationComponentProps } from "../../navigation/Navigator";
-import React from "react";
+import { courseFromJSON } from "openfing-core/lib/factories";
+import gql from "graphql-tag";
 import queryString from "query-string";
 import { styles } from "./Course.styles";
-import { toJS } from "mobx";
 import { useDocumentTitle } from "../../components/useDocumentTitle";
-import { useFetchCourseByCode } from "openfing-core/lib/hooks/useFetchCourse";
 import { useHistory } from "src/hooks/useHistory";
+import { useQuery } from "react-apollo-hooks";
+import { useRootStore } from "openfing-core/lib/hooks/useRootStore";
+
+type CourseData = {
+	courseByCode: {
+		id: number;
+		code: string;
+		name?: string;
+		eva?: string;
+		iconURL?: string;
+	};
+};
+
+const COURSE_QUERY = gql`
+	query courseByCode($code: String!) {
+		courseByCode(code: $code) {
+			id
+			code
+			name
+			eva
+			semester
+			year
+			iconURL
+
+			classLists {
+				id
+				name
+
+				classes {
+					id
+					title
+					number
+
+					videos {
+						id
+						name
+						position
+
+						qualities {
+							id
+							height
+							width
+
+							formats {
+								id
+								name
+								url
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+`;
 
 // TODO: custom useQuery with parseData callback?
 
+const useForceUpdate = () => {
+	const [, setB] = React.useState(false);
+
+	return React.useCallback(() => {
+		setB(b => !b);
+	}, []);
+};
+
 export const Course: React.FunctionComponent<NavigationComponentProps<{ courseCode: string }>> = observer(props => {
 	const { courseCode } = props.match.params;
+	const forceUpdate = useForceUpdate();
 
 	const { history } = useHistory();
 	const queryParams = useMemo<{ t?: string; cci?: string; ccn?: string; ccl?: string }>(
@@ -26,9 +89,20 @@ export const Course: React.FunctionComponent<NavigationComponentProps<{ courseCo
 		[history.location.search]
 	);
 	const appStore = useContext(AppStoreContext);
-	const [fetchCourseByCodeState] = useFetchCourseByCode({ courseCode, autoFetch: true, forceFetch: false });
+	const { courseStore } = useRootStore();
+	const course = courseStore.coursesByCode.get(courseCode) || undefined;
+
+	const { loading, data, ...rest } = useQuery<CourseData>(COURSE_QUERY, {
+		skip: !!course && !!course.classLists,
+		variables: { code: courseCode },
+	});
+	React.useEffect(() => {
+		if (!data || !data.courseByCode) return;
+
+		courseStore.saveCourse(courseFromJSON(data.courseByCode));
+		forceUpdate();
+	}, [data]);
 
-	const course = fetchCourseByCodeState.success ? fetchCourseByCodeState.course : undefined;
 	const courseName = course ? course.name : undefined;
 	const setLayoutOptions = useContext(LayoutContext);
 	const contextRef = React.useRef<CourseContext>();
@@ -65,11 +139,15 @@ export const Course: React.FunctionComponent<NavigationComponentProps<{ courseCo
 
 		if (!current) return;
 
-		current.fetchCourseByCodeState = fetchCourseByCodeState;
+		current.fetchCourseByCodeState = loading
+			? { isLoading: loading }
+			: course
+			? { isLoading: false, success: true, course }
+			: { isLoading: false, success: undefined };
 		current.course = course;
 		current.courseClassList = courseClassList;
 		current.courseClass = courseClass;
-	}, [fetchCourseByCodeState, course, courseClassList, courseClass]);
+	}, [loading, course, courseClassList, courseClass]);
 
 	useEffect(() => {
 		if (!contextRef.current) return;
@@ -99,8 +177,6 @@ export const Course: React.FunctionComponent<NavigationComponentProps<{ courseCo
 	);
 
 	return (
-		<CourseProvider contextRef={contextRef}>
-			{fetchCourseByCodeState.isLoading ? <Loading /> : fetchCourseByCodeState.success ? content : null}
-		</CourseProvider>
+		<CourseProvider contextRef={contextRef}>{loading ? <Loading /> : course ? content : <div />}</CourseProvider>
 	);
 });
diff --git a/src/style/Mixins.ts b/src/style/Mixins.ts
index 869636b..0bbafeb 100644
--- a/src/style/Mixins.ts
+++ b/src/style/Mixins.ts
@@ -1,6 +1,7 @@
-import darken from "polished/lib/color/darken";
 import { FlattenSimpleInterpolation, css } from "styled-components";
+
 import { Breakpoint } from "./Breakpoint";
+import darken from "polished/lib/color/darken";
 
 export const EllipsisText = (maxHeight?: string) => css`
 	overflow: hidden;
-- 
GitLab