Skip to content

Commit

Permalink
Merge pull request #61 from sparcs-kaist/migration@reducers/timetable
Browse files Browse the repository at this point in the history
Migrate redux reducers about timetable
  • Loading branch information
sboh1214 authored Apr 26, 2024
2 parents 7566d6d + 048b859 commit 316d614
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ const CombinedReducer = combineReducers({
lectureFocus: lectureFocus,
});

export type TimetableState = ReturnType<typeof CombinedReducer>;
export default CombinedReducer;
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import Review from '@/shapes/model/review/Review';
import {
RESET,
SET_LECTURE_FOCUS,
CLEAR_LECTURE_FOCUS,
SET_REVIEWS,
SET_MULTIPLE_FOCUS,
CLEAR_MULTIPLE_FOCUS,
LectureFocusAction,
} from '../../actions/timetable/lectureFocus';

import { LectureFocusFrom } from '@/shapes/enum';
import Lecture from '@/shapes/model/subject/Lecture';
import { Detail } from '@/shapes/state/timetable/LectureFocus';

const initialState = {
interface LectureFocusState {
from: LectureFocusFrom;
clicked: boolean;
lecture: Lecture | null;
reviews: Review[] | null;
multipleTitle: string;
multipleDetails: Detail[];
}

const initialState: LectureFocusState = {
from: LectureFocusFrom.NONE,
clicked: false,
lecture: null,
Expand All @@ -18,50 +31,43 @@ const initialState = {
multipleDetails: [],
};

const lectureFocus = (state = initialState, action) => {
const lectureFocus = (state = initialState, action: LectureFocusAction) => {
switch (action.type) {
case RESET: {
return initialState;
}
case SET_LECTURE_FOCUS: {
const lectureChanged = !state.lecture || state.lecture.id !== action.lecture.id;
return Object.assign(
{},
state,
{
from: action.from,
clicked: action.clicked,
lecture: action.lecture,
},
lectureChanged ? { reviews: null } : {},
);
return {
...state,
from: action.from,
clicked: action.clicked,
lecture: action.lecture,
reviews: lectureChanged ? null : state.reviews,
};
}
case CLEAR_LECTURE_FOCUS: {
return Object.assign({}, state, {
return {
...state,
from: LectureFocusFrom.NONE,
clicked: false,
lecture: null,
reviews: null,
});
};
}
case SET_REVIEWS: {
return Object.assign({}, state, {
reviews: action.reviews,
});
return { ...state, reviews: action.reviews };
}
case SET_MULTIPLE_FOCUS: {
return Object.assign({}, state, {
return {
...state,
from: LectureFocusFrom.MULTIPLE,
multipleTitle: action.multipleTitle,
multipleDetails: action.multipleDetails,
});
};
}
case CLEAR_MULTIPLE_FOCUS: {
return Object.assign({}, state, {
from: LectureFocusFrom.NONE,
multipleTitle: '',
multipleDetails: [],
});
return { ...state, from: LectureFocusFrom.NONE, multipleTitle: '', multipleDetails: [] };
}
default: {
return state;
Expand Down
80 changes: 44 additions & 36 deletions src/reducers/timetable/list.js → src/reducers/timetable/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,28 @@ import {
ADD_LECTURE_TO_CART,
DELETE_LECTURE_FROM_CART,
SET_MOBILE_IS_LECTURE_LIST_OPEN,
} from '../../actions/timetable/list';

import { unique } from '../../utils/commonUtils';
LectureListAction,
} from '@/actions/timetable/list';
import { unique } from '@/utils/commonUtils';

import { LectureListCode } from '@/shapes/enum';
import Lecture from '@/shapes/model/subject/Lecture';

interface ListState {
selectedListCode: LectureListCode;
lists: {
[key in LectureListCode]: {
lectureGroups: Lecture[][] | null; // null when not loaded, empty array when loaded but no lectures
};
};
isLectureListOpenOnMobile: boolean;
}

const initialState = {
const initialState: ListState = {
selectedListCode: LectureListCode.SEARCH,
lists: {
[LectureListCode.SEARCH]: {
lectureGroups: [],
lectureGroups: [], // show empty array by default for search, instead of null
},
[LectureListCode.BASIC]: {
lectureGroups: null,
Expand All @@ -32,62 +43,63 @@ const initialState = {
isLectureListOpenOnMobile: false,
};

const list = (state = initialState, action) => {
const groupLectures = (lectures) => {
if (lectures.length === 0) {
return [];
}

const list = (state = initialState, action: LectureListAction) => {
const groupLectures = (lectures: Lecture[]) => {
const sortedLectures = lectures.sort((a, b) => {
if (a.old_code !== b.old_code) {
return a.old_code > b.old_code ? 10 : -10;
}
return a.class_no > b.class_no ? 1 : -1;
});
const courseIds = unique(sortedLectures.map((l) => l.course));
const courseIds: number[] = unique(sortedLectures.map((l) => l.course));
const lectureGroups = courseIds
.map((c) => sortedLectures.filter((l) => l.course === c))
.filter((c) => c.length > 0);
.map((course) => sortedLectures.filter((l) => l.course === course))
.filter((lectureGroup) => lectureGroup.length > 0);
return lectureGroups;
};

const ungroupLectureGroups = (lectureGroups) => lectureGroups.flat(1);
const ungroupLectureGroups = (lectureGroups: Lecture[][] | null) =>
lectureGroups ? lectureGroups.flat(1) : [];

switch (action.type) {
case RESET: {
return initialState;
}
case SET_SELECTED_LIST_CODE: {
return Object.assign({}, state, {
selectedListCode: action.listCode,
});
return { ...state, selectedListCode: action.listCode };
}
case SET_LIST_LECTURES: {
const newState = { ...state };
newState.lists = { ...newState.lists };
newState.lists[action.code] = { ...newState.lists[action.code] };
newState.lists[action.code].lectureGroups = groupLectures(action.lectures);
return Object.assign({}, state, newState);
return newState;
}
/**
* This is used to clear all lectures in all lists.
* Only search list becomes empty array, others become null.
* @example { SEARCH: [Lecture1, Lecture2, ...], BASIC: [Lecture3, Lecture4, ...], ... } => { SEARCH: [], BASIC: null, ...
*/
case CLEAR_ALL_LISTS_LECTURES: {
const newState = { ...state };
newState.lists = { ...newState.lists };
Object.keys(newState.lists).forEach((k) => {
newState.lists[k] = { ...newState.lists[k] };
if (k === LectureListCode.SEARCH) {
newState.lists[k].lectureGroups = [];
} else {
newState.lists[k].lectureGroups = null;
}
// keys can be not only LectureListCode but also FavoriteDepartment which set in FavoriteDepartmentsSubSection.
const keys = Object.keys(newState.lists) as Array<LectureListCode | string>;
keys.forEach((k) => {
newState.lists[k as keyof typeof newState.lists].lectureGroups =
k === LectureListCode.SEARCH ? [] : null;
});
return Object.assign({}, state, newState);
return newState;
}
/**
* This is used to make search result null before getting new search result.
* @example { SEARCH: [Lecture1, Lecture2, ...], BASIC: [...], ... } => { SEARCH: null, BASIC: [...], ... }
*/
case CLEAR_SEARCH_LIST_LECTURES: {
const newState = { ...state };
newState.lists = { ...newState.lists };
newState.lists[LectureListCode.SEARCH] = { ...newState.lists[LectureListCode.SEARCH] };
newState.lists[LectureListCode.SEARCH].lectureGroups = null;
return Object.assign({}, state, newState);
return newState;
}
case ADD_LECTURE_TO_CART: {
const { lectureGroups } = state.lists[LectureListCode.CART];
Expand All @@ -96,9 +108,8 @@ const list = (state = initialState, action) => {
const newLectureGroups = groupLectures(newLectures);
const newState = { ...state };
newState.lists = { ...newState.lists };
newState.lists[LectureListCode.CART] = { ...newState.lists[LectureListCode.CART] };
newState.lists[LectureListCode.CART].lectureGroups = newLectureGroups;
return Object.assign({}, state, newState);
return newState;
}
case DELETE_LECTURE_FROM_CART: {
const { lectureGroups } = state.lists[LectureListCode.CART];
Expand All @@ -107,14 +118,11 @@ const list = (state = initialState, action) => {
const newLectureGroups = groupLectures(newLectures);
const newState = { ...state };
newState.lists = { ...newState.lists };
newState.lists[LectureListCode.CART] = { ...newState.lists[LectureListCode.CART] };
newState.lists[LectureListCode.CART].lectureGroups = newLectureGroups;
return Object.assign({}, state, newState);
return newState;
}
case SET_MOBILE_IS_LECTURE_LIST_OPEN: {
return Object.assign({}, state, {
isLectureListOpenOnMobile: action.isLectureListOpenOnMobile,
});
return { ...state, isLectureListOpenOnMobile: action.isLectureListOpenOnMobile };
}
default: {
return state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,58 @@ import {
SET_LAST_SEARCH_OPTION,
SET_CLASSTIME_OPTIONS,
CLEAR_CLASSTIME_OPTIONS,
} from '../../actions/timetable/search';
SearchAction,
} from '@/actions/timetable/search';
import { Day } from '@/shapes/enum';
import LectureLastSearchOption from '@/shapes/state/timetable/LectureLastSearchOption';
import { stat } from 'fs';

const initialState = {
interface SearchState {
open: boolean;
lastSearchOption: LectureLastSearchOption;
classtimeBegin: number | null;
classtimeEnd: number | null;
classtimeDay: Day | null;
}

const initialState: SearchState = {
open: true,
lastSearchOption: {},
classtimeBegin: null,
classtimeEnd: null,
classtimeDay: null,
};

const search = (state = initialState, action) => {
const search = (state = initialState, action: SearchAction) => {
switch (action.type) {
case RESET: {
return initialState;
}
case OPEN_SEARCH: {
return Object.assign({}, state, {
open: true,
});
return { ...state, open: true };
}
case CLOSE_SEARCH: {
return Object.assign({}, state, {
return {
...state,
open: false,
classtimeBegin: null,
classtimeEnd: null,
classtimeDay: null,
});
};
}
case SET_LAST_SEARCH_OPTION: {
return Object.assign({}, state, {
lastSearchOption: action.lastSearchOption,
});
return { ...state, lastSearchOption: action.lastSearchOption };
}
case SET_CLASSTIME_OPTIONS: {
return Object.assign({}, state, {
return {
...state,
classtimeBegin: action.classtimeBegin,
classtimeEnd: action.classtimeEnd,
classtimeDay: action.classtimeDay,
});
};
}
case CLEAR_CLASSTIME_OPTIONS: {
return Object.assign({}, state, {
classtimeBegin: null,
classtimeEnd: null,
classtimeDay: null,
});
return { ...state, classtimeBegin: null, classtimeEnd: null, classtimeDay: null };
}
default: {
return state;
Expand Down
25 changes: 0 additions & 25 deletions src/reducers/timetable/semester.js

This file was deleted.

31 changes: 31 additions & 0 deletions src/reducers/timetable/semester.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { RESET, SET_SEMESTER, SemesterAction } from '@/actions/timetable/semester';
import { SemesterType } from '@/shapes/enum';

interface SemesterState {
year: number | null;
semester: SemesterType | null;
}

const initialState: SemesterState = {
year: null,
semester: null,
};

const semester = (state = initialState, action: SemesterAction) => {
switch (action.type) {
case RESET: {
return initialState;
}
case SET_SEMESTER: {
return {
year: action.year,
semester: action.semester,
};
}
default: {
return state;
}
}
};

export default semester;
Loading

0 comments on commit 316d614

Please sign in to comment.