aboutsummaryrefslogtreecommitdiff
path: root/src/client/react/store/actions.js
blob: 131bcaae33e70acc55e98832a725d8957a5196c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { push } from 'connected-react-router';
import queryString from 'query-string';
import users from '../users';
import { selectUser, selectWeek, selectCurrentWeek } from './selectors';
import purifyWeek from '../lib/purifyWeek';
import withinRange from '../lib/withinRange';
import extractSchedule from '../lib/extractSchedule';
import rejectIfBadStatus from '../lib/rejectIfBadStatus';

function updatePathname(pathname = '') {
  return (dispatch, getState) => {
    const query = getState().router.location.search;
    dispatch(push(`/${pathname}${query}`));
  };
}

function updateQuery(newQuery) {
  return (dispatch, getState) => {
    const { location } = getState().router;
    const query = queryString.stringify({
      ...queryString.parse(location.search),
      ...newQuery,
    });

    dispatch(push(`${location.pathname}?${query}`));
  };
}

export function setUser(newUser) {
  return (dispatch) => {
    dispatch({ type: 'SEARCH/RESET' });
    dispatch(updatePathname(newUser));
  };
}

export function shiftRoom(shift) {
  return (dispatch, getState) => {
    const state = getState();
    const user = selectUser(state);
    const { allRoomIds } = users;

    if (users.byId[user].type !== 'r') throw new Error('User must be a room');

    const currentRoom = user;
    const currentRoomIndex = allRoomIds.indexOf(currentRoom);
    const nextRoomIndex = withinRange(
      currentRoomIndex + shift,
      allRoomIds.length - 1,
    );
    const nextRoom = allRoomIds[nextRoomIndex];

    dispatch(setUser(nextRoom));
  };
}

export function setWeek(newWeek) {
  return (dispatch, getState) => {
    const state = getState();
    const isCurrentWeek = selectCurrentWeek(state) === newWeek;

    dispatch(updateQuery({
      week: isCurrentWeek ? undefined : newWeek,
    }));
  };
}

export function shiftWeek(shift) {
  return (dispatch, getState) => {
    const state = getState();
    const week = selectWeek(state);
    dispatch(setWeek(purifyWeek(week + shift)));
  };
}

export function showRoomFinder() {
  return (dispatch, getState) => {
    const state = getState();
    const user = selectUser(state);

    if (user == null || users.byId[user].type !== 'r') {
      // We are not currently viewing a room, correct the situation.
      dispatch(setUser(users.allRoomIds[0]));
    }

    dispatch({ type: 'ROOM_FINDER/SHOW' });
  };
}

const fetchScheduleStart = (user, week) => ({
  type: 'VIEW/FETCH_SCHEDULE_START', user, week,
});

const fetchScheduleSuccess = (user, week, htmlStr) => ({
  type: 'VIEW/FETCH_SCHEDULE_SUCCESS', user, week, htmlStr,
});

const fetchScheduleError = (user, week, statusCode) => ({
  type: 'VIEW/FETCH_SCHEDULE_ERROR', user, week, statusCode,
});


export function fetchScheduleIfNeeded(user, week) {
  return (dispatch, getState) => {
    const { schedules } = getState();
    const schedule = extractSchedule(schedules, user, week);

    if (schedule.state !== 'NOT_REQUESTED') {
      return;
    }

    dispatch(fetchScheduleStart(user, week));

    fetch(`/get/${user}?week=${week}`)
      .then(rejectIfBadStatus)
      .then(r => r.text())
      .then(
        // success
        (htmlStr) => {
          dispatch(fetchScheduleSuccess(user, week, htmlStr));
        },

        // error
        (statusCode) => {
          // TODO: Handle error status
          dispatch(fetchScheduleError(user, week, statusCode));
        },
      );
  };
}