Skip to content

Commit

Permalink
Abstract settings slice behind useSettings
Browse files Browse the repository at this point in the history
  • Loading branch information
lhvy committed Aug 17, 2024
1 parent cd736b4 commit 94c3629
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 53 deletions.
5 changes: 2 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { Suspense, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { NotificationOutlined } from '@ant-design/icons';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -12,8 +11,8 @@ import RequireToken from 'components/Auth/RequireToken';
import ErrorBoundary from 'components/ErrorBoundary';
import PageLoading from 'components/PageLoading';
import { inDev } from 'config/constants';
import type { RootState } from 'config/store';
import { darkTheme, GlobalStyles, lightTheme } from 'config/theme';
import useSettings from 'hooks/useSettings';
import Login from 'pages/Login';
import LoginSuccess from 'pages/LoginSuccess';
import Logout from 'pages/Logout';
Expand All @@ -31,7 +30,7 @@ const ProgressionChecker = React.lazy(() => import('./pages/ProgressionChecker')
const TermPlanner = React.lazy(() => import('./pages/TermPlanner'));

const App = () => {
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();

const [queryClient] = React.useState(
() => new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false } } })
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/components/FeedbackButton/FeedbackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { BugOutlined } from '@ant-design/icons';
import { Tooltip } from 'antd';
import { FEEDBACK_LINK } from 'config/constants';
import type { RootState } from 'config/store';
import useMediaQuery from 'hooks/useMediaQuery';
import useSettings from 'hooks/useSettings';
import S from './styles';

const FeedbackButton = () => {
Expand All @@ -13,7 +12,7 @@ const FeedbackButton = () => {
const openFeedbackLink = () => {
window.open(FEEDBACK_LINK, '_blank');
};
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();

// Move this to the drawer if the screen is too small
return isTablet ? null : (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { Suspense, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { Tooltip as ReactTooltip } from 'react-tooltip'; // TODO: investigate using antd tooltip?
import type { LiquidConfig } from '@ant-design/plots';
import Spinner from 'components/Spinner';
import { darkGrey, lightGrey, lightYellow, purple, yellow } from 'config/constants';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';

type Props = {
completedUOC: number;
Expand Down Expand Up @@ -32,7 +31,7 @@ const LiquidProgressChart = ({ completedUOC, totalUOC }: Props) => {
}

// dark mode always has white text
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
if (theme === 'dark') {
textColor = 'white';
}
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/components/ProgressBar/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React from 'react';
import { useSelector } from 'react-redux';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import S from './styles';

type Props = {
progress: number;
};

const ProgressBar = ({ progress }: Props) => {
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
const trailColor = theme === 'light' ? '#f5f5f5' : '#444249';

let bgColor = '#3cb371';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Tooltip } from 'antd';
import { addToUnplanned, removeCourse } from 'utils/api/plannerApi';
import { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import useToken from 'hooks/useToken';
import S from './styles';

Expand All @@ -21,7 +20,7 @@ const QuickAddCartButton = ({ courseCode, runMutate, planned }: Props) => {
? (code: string) => removeCourse(token, code)
: (code: string) => addToUnplanned(token, code);

const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
const iconStyles = {
color: theme === 'light' ? '#000' : '#fff'
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Link } from 'react-scroll';
import { Tooltip as ReactTooltip } from 'react-tooltip';
import { purple } from '@ant-design/colors';
import { Progress, Typography } from 'antd';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import S from './styles';

type Props = {
Expand All @@ -18,7 +17,7 @@ const SpecialisationCard = ({ type, totalUOC, currUOC, specTitle }: Props) => {
const { Title, Text } = Typography;
const progress = Math.min(Math.round((currUOC / totalUOC) * 100), 100);

const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
const trailColor = theme === 'light' ? '#fff' : '#444249';

return (
Expand Down
9 changes: 3 additions & 6 deletions frontend/src/components/ThemeToggle/ThemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import React from 'react';
import { IoIosSunny, IoMdMoon } from 'react-icons/io';
import { useDispatch, useSelector } from 'react-redux';
import { Switch } from 'antd';
import type { RootState } from 'config/store';
import { toggleTheme } from 'reducers/settingsSlice';
import useSettings from 'hooks/useSettings';

const ThemeToggle = () => {
const { theme } = useSelector((state: RootState) => state.settings);
const dispatch = useDispatch();
const { theme, mutateTheme } = useSettings();

const toggleStyle = {
backgroundColor: theme === 'light' ? '#b37feb' : '#722ed1'
Expand All @@ -18,7 +15,7 @@ const ThemeToggle = () => {
checkedChildren={<IoMdMoon />}
unCheckedChildren={<IoIosSunny />}
defaultChecked={theme === 'dark'}
onChange={() => dispatch(toggleTheme(theme === 'light' ? 'dark' : 'light'))}
onChange={() => mutateTheme(theme === 'light' ? 'dark' : 'light')}
style={toggleStyle}
/>
);
Expand Down
43 changes: 43 additions & 0 deletions frontend/src/hooks/useSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useCallback } from 'react';
import { useAppDispatch, useAppSelector } from 'hooks';
import {
toggleLockedCourses as toggleLocked,
toggleShowMarks as toggleMarks,
toggleShowPastWarnings as togglePastWarnings,
toggleTheme
} from 'reducers/settingsSlice';

interface Settings {
theme: string;
showMarks: boolean;
showLockedCourses: boolean;
showPastWarnings: boolean;
mutateTheme: (theme: 'light' | 'dark') => void;
toggleShowMarks: () => void;
toggleLockedCourses: () => void;
toggleShowPastWarnings: () => void;
}

function useSettings(): Settings {
const settings = useAppSelector((state) => state.settings);
const dispatch = useAppDispatch();

const mutateTheme = useCallback(
(theme: 'light' | 'dark') => dispatch(toggleTheme(theme)),
[dispatch]
);

const toggleShowMarks = useCallback(() => dispatch(toggleMarks()), [dispatch]);
const toggleLockedCourses = useCallback(() => dispatch(toggleLocked()), [dispatch]);
const toggleShowPastWarnings = useCallback(() => dispatch(togglePastWarnings()), [dispatch]);

return {
...settings,
mutateTheme,
toggleShowMarks,
toggleLockedCourses,
toggleShowPastWarnings
};
}

export default useSettings;
6 changes: 3 additions & 3 deletions frontend/src/pages/CourseSelector/CourseMenu/CourseMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type { MenuProps } from 'antd';
import { CourseUnitsStructure, MenuDataStructure, MenuDataSubgroup } from 'types/courseMenu';
Expand All @@ -11,7 +11,7 @@ import { addToUnplanned, removeCourse } from 'utils/api/plannerApi';
import { getProgramStructure } from 'utils/api/programsApi';
import { LoadingCourseMenu } from 'components/LoadingSkeleton';
import { MAX_COURSES_OVERFLOW } from 'config/constants';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import useToken from 'hooks/useToken';
import { addTab } from 'reducers/courseTabsSlice';
import CourseMenuTitle from '../CourseMenuTitle';
Expand Down Expand Up @@ -69,7 +69,7 @@ const CourseMenu = ({ planner, courses, degree }: CourseMenuProps) => {
const [menuData, setMenuData] = useState<MenuDataStructure>({});
const [coursesUnits, setCoursesUnits] = useState<CourseUnitsStructure | null>(null);

const { showLockedCourses } = useSelector((state: RootState) => state.settings);
const { showLockedCourses } = useSettings();

const [pageLoaded, setPageLoaded] = useState(false);

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/CourseSelector/CourseTabs/CourseTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Popconfirm, Switch, Tooltip } from 'antd';
import DraggableTab from 'components/DraggableTab';
import Spinner from 'components/Spinner';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import { reorderTabs, resetTabs, setActiveTab } from 'reducers/courseTabsSlice';
import { toggleLockedCourses } from 'reducers/settingsSlice';
import S from './styles';

const DragDropContext = React.lazy(() =>
Expand All @@ -20,7 +20,7 @@ const Droppable = React.lazy(() =>
const CourseTabs = () => {
const dispatch = useDispatch();
const { tabs } = useSelector((state: RootState) => state.courseTabs);
const { showLockedCourses } = useSelector((state: RootState) => state.settings);
const { showLockedCourses, toggleLockedCourses } = useSettings();

const handleOnDragStart: OnDragStartResponder = (result) => {
dispatch(setActiveTab(result.source.index));
Expand Down Expand Up @@ -49,7 +49,7 @@ const CourseTabs = () => {
size="small"
data-testid="show-all-courses"
defaultChecked={showLockedCourses}
onChange={() => dispatch(toggleLockedCourses())}
onChange={() => toggleLockedCourses()}
/>
</S.ShowAllCourses>
<Suspense fallback={<Spinner text="loading tabs..." size="small" />}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import {
ExpandAltOutlined,
ShrinkOutlined,
Expand All @@ -16,8 +15,8 @@ import { getProgramGraph } from 'utils/api/programsApi';
import { getUserCourses, getUserDegree, getUserPlanner } from 'utils/api/userApi';
import { unwrapQuery } from 'utils/queryUtils';
import Spinner from 'components/Spinner';
import { RootState } from 'config/store';
import { useAppWindowSize } from 'hooks';
import useSettings from 'hooks/useSettings';
import useToken from 'hooks/useToken';
import { ZOOM_IN_RATIO, ZOOM_OUT_RATIO } from '../constants';
import {
Expand Down Expand Up @@ -72,7 +71,7 @@ const CourseGraph = ({
queryFn: () => getUserCourses(token)
});
const windowSize = useAppWindowSize();
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
const previousTheme = useRef<typeof theme>(theme);

const graphRef = useRef<Graph | null>(null);
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/pages/GraphicalSelector/HowToUse/HowToUse.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Typography } from 'antd';
import { useTheme } from 'styled-components';
import step1Dark from 'assets/GraphicalSelectorHelp/step1-dark.jpg';
import step1Light from 'assets/GraphicalSelectorHelp/step1-light.jpg';
import step2Dark from 'assets/GraphicalSelectorHelp/step2-dark.jpg';
Expand All @@ -11,14 +11,13 @@ import step4Dark from 'assets/GraphicalSelectorHelp/step4-dark.jpg';
import step4Light from 'assets/GraphicalSelectorHelp/step4-light.jpg';
import step5Dark from 'assets/GraphicalSelectorHelp/step5-dark.jpg';
import step5Light from 'assets/GraphicalSelectorHelp/step5-light.jpg';
import type { RootState } from 'config/store';
import CS from '../common/styles';
import S from './styles';

const { Title } = Typography;

const HowToUse = () => {
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useTheme();

const step = (num: number) => {
const pics = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { Suspense } from 'react';
import { useContextMenu } from 'react-contexify';
import { useSelector } from 'react-redux';
import { Tooltip as ReactTooltip } from 'react-tooltip';
import { InfoCircleOutlined, PieChartOutlined, WarningOutlined } from '@ant-design/icons';
import { Typography } from 'antd';
Expand All @@ -11,8 +10,8 @@ import { CoursesResponse, PlannerResponse, ValidateResponse } from 'types/userRe
import { courseHasOffering } from 'utils/getAllCourseOfferings';
import getMostRecentPastTerm from 'utils/getMostRecentPastTerm';
import Spinner from 'components/Spinner';
import type { RootState } from 'config/store';
import useMediaQuery from 'hooks/useMediaQuery';
import useSettings from 'hooks/useSettings';
import ContextMenu from '../ContextMenu';
import S from './styles';

Expand All @@ -31,7 +30,7 @@ const Draggable = React.lazy(() =>

const DraggableCourse = ({ planner, validate, courses, courseInfo, index, time }: Props) => {
const { isSummerEnabled } = planner;
const { showMarks, showPastWarnings } = useSelector((state: RootState) => state.settings);
const { showMarks, showPastWarnings } = useSettings();
const theme = useTheme();
const { Text } = Typography;

Expand Down
5 changes: 2 additions & 3 deletions frontend/src/pages/TermPlanner/HelpMenu/HelpMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import additionalOptionsGifDark from 'assets/TermPlannerHelp/additional-options-dark.gif';
import additionalOptionsPicDark from 'assets/TermPlannerHelp/additional-options-dark.jpg';
import additionalOptionsGifLight from 'assets/TermPlannerHelp/additional-options-light.gif';
Expand All @@ -16,7 +15,7 @@ import unscheduleGifDark from 'assets/TermPlannerHelp/unschedule-dark.gif';
import unschedulePicDark from 'assets/TermPlannerHelp/unschedule-dark.jpg';
import unscheduleGifLight from 'assets/TermPlannerHelp/unschedule-light.gif';
import unschedulePicLight from 'assets/TermPlannerHelp/unschedule-light.jpg';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import CS from '../common/styles';
import S from './styles';

Expand Down Expand Up @@ -46,7 +45,7 @@ const HelpStep = ({ title, gif, pic, altText }: HelpStepProps) => {
};

const HelpMenu = () => {
const { theme } = useSelector((state: RootState) => state.settings);
const { theme } = useSettings();
const helpSteps = [
{
title: '1. Drag and Drop Courses',
Expand Down
13 changes: 5 additions & 8 deletions frontend/src/pages/TermPlanner/OptionsHeader/OptionsHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
/* eslint-disable import/no-extraneous-dependencies */
import React from 'react';
import { FaRegCalendarTimes } from 'react-icons/fa';
import { useDispatch, useSelector } from 'react-redux';
import { QuestionCircleOutlined, SettingFilled, WarningFilled } from '@ant-design/icons';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import Tippy from '@tippyjs/react';
import { Popconfirm, Switch, Tooltip } from 'antd';
import { unscheduleAll } from 'utils/api/plannerApi';
import { getUserPlanner } from 'utils/api/userApi';
import type { RootState } from 'config/store';
import useSettings from 'hooks/useSettings';
import useToken from 'hooks/useToken';
import { toggleShowMarks, toggleShowPastWarnings } from 'reducers/settingsSlice';
import HelpMenu from '../HelpMenu/HelpMenu';
import SettingsMenu from '../SettingsMenu';
import { isPlannerEmpty } from '../utils';
Expand All @@ -29,9 +27,8 @@ const OptionsHeader = () => {
});
const planner = plannerQuery.data;

const { theme } = useSelector((state: RootState) => state.settings);
const { showMarks, showPastWarnings } = useSelector((state: RootState) => state.settings);
const dispatch = useDispatch();
const { theme, showMarks, showPastWarnings, toggleShowMarks, toggleShowPastWarnings } =
useSettings();
const iconStyles = {
fontSize: '20px',
color: theme === 'light' ? '#323739' : '#f1f1f1'
Expand Down Expand Up @@ -128,7 +125,7 @@ const OptionsHeader = () => {
</Tooltip>
)}
<Tooltip title="Toggle warnings for previous terms">
<S.OptionButton onClick={() => dispatch(toggleShowPastWarnings())}>
<S.OptionButton onClick={() => toggleShowPastWarnings()}>
<WarningFilled
style={{
...iconStyles,
Expand All @@ -142,7 +139,7 @@ const OptionsHeader = () => {
<S.OptionSection>
<S.ShowMarks>
<S.TextShowMarks>Show Marks</S.TextShowMarks>
<Switch defaultChecked={showMarks} onChange={() => dispatch(toggleShowMarks())} />
<Switch defaultChecked={showMarks} onChange={() => toggleShowMarks()} />
</S.ShowMarks>
<Tippy
content={<HelpMenu />}
Expand Down
Loading

0 comments on commit 94c3629

Please sign in to comment.