Parcourir la source

Fetch planner from DB

Tatiana Inama il y a 7 ans
Parent
commit
cc95e862f9

+ 92 - 39
recipes/src/containers/Planner/actions.ts

@@ -1,60 +1,113 @@
 import { DBRecipe } from 'types/recipes';
-import { Meal, RecipePlan, Weekday } from 'types/planner';
+import { Meal, RecipePlan, Weekday, DBPlanner } from 'types/planner';
+import { Dispatch, ActionCreator, Action } from 'redux';
+import { getPlanner } from './services'
+import { ThunkAction } from 'redux-thunk';
 
 export const ADD_TO_BACKLOG = 'ADD_TO_BACKLOG';
 export const REMOVE_FROM_BACKLOG = 'REMOVE_FROM_BACKLOG';
 export const ASSIGN_TO_DAY = 'ASSIGN_TO_DAY';
 export const REMOVE_MEAL = 'REMOVE_MEAL';
 
-const actions = {
-  addToBacklog: (recipe: DBRecipe) => ({
-    type: ADD_TO_BACKLOG,
-    recipe: {
-      _id: recipe._id,
-      name: recipe.name
-    },
-  }),
-  removeFromBacklog: (recipe: RecipePlan) => ({
-    type: REMOVE_FROM_BACKLOG,
-    recipe,
-  }),
-  assignToDay: (recipe: RecipePlan, day: Weekday, meal: Meal) => ({
-    type: ASSIGN_TO_DAY,
-    recipe,
-    day,
-    meal,
-  }),
-  removeMeal: (day: Weekday, meal: Meal) => ({
-    type: REMOVE_MEAL,
-    day,
-    meal
-  })
-}
-
-export type AddToBacklog = {
-  type: typeof ADD_TO_BACKLOG,
-  recipe: RecipePlan,
-};
+export const REQUEST_PLANNER = 'REQUEST_PLANNER';
+export const RECEIVE_PLANNER = 'RECEIVE_PLANNER';
+
+export interface AddToBacklogAction extends Action<'ADD_TO_BACKLOG'> {
+  recipe: {
+    _id: string,
+    name: string
+  }
+}
+const addToBacklog = (recipe: DBRecipe): AddToBacklogAction => ({
+  recipe: {
+    _id: recipe._id,
+    name: recipe.name
+  },
+  type: ADD_TO_BACKLOG,
+});
 
-export type RemoveFromBacklog = {
-  type: typeof REMOVE_FROM_BACKLOG,
+export interface RemoveFromBacklogAction extends Action<'REMOVE_FROM_BACKLOG'> {
   recipe: RecipePlan
 }
+const removeFromBacklog = (recipe: RecipePlan): RemoveFromBacklogAction => ({
+  type: REMOVE_FROM_BACKLOG,
+  recipe,
+});
 
-export type AssignToDay = {
-  type: typeof ASSIGN_TO_DAY,
+export interface AssignToDayAction extends Action<'ASSIGN_TO_DAY'> {
   recipe: RecipePlan,
   day: Weekday,
   meal: Meal
 }
+const assignToDay = (recipe: RecipePlan, day: Weekday, meal: Meal): AssignToDayAction => ({
+  type: ASSIGN_TO_DAY,
+  recipe,
+  day,
+  meal,
+});
 
-export type RemoveMeal = {
-  type: typeof REMOVE_MEAL,
+export interface RemoveMealAction extends Action<'REMOVE_MEAL'> {
   day: Weekday,
   meal: Meal
 }
+const removeMeal = (day: Weekday, meal: Meal): RemoveMealAction => ({
+  type: REMOVE_MEAL,
+  day,
+  meal
+});
+
+export interface RequestPlannerAction extends Action<'REQUEST_PLANNER'> {
+  week: number
+}
+const requestPlanner = (week: number): RequestPlannerAction => ({
+  type: REQUEST_PLANNER,
+  week
+})
+
+export interface ReceivePlannerAction extends Action<'RECEIVE_PLANNER'>{
+  payload: DBPlanner,
+}
+const receivePlanner = (json: DBPlanner): ReceivePlannerAction => ({
+  type: RECEIVE_PLANNER,
+  payload: json
+})
+
+export const fetchPlannerActionCreator: ActionCreator<
+  ThunkAction<
+    Promise<ReceivePlannerAction>,
+    DBPlanner,
+    number,
+    ReceivePlannerAction
+  >
+> = (week: number) => {
+  return async (dispatch: Dispatch) => {
+    dispatch(requestPlanner(week));
+    const planner = await getPlanner(week);
+    return dispatch(receivePlanner(planner))
+  }
+}
+export const fetchPlanner = (week: number) => async (dispatch: Dispatch) => {
+  dispatch(requestPlanner(week));
+  try {
+    const data = await getPlanner(week);
+    return dispatch(receivePlanner(data));
+  }
+  catch (error) {
+    return console.log('Error while receiving planner data:', error);
+  }
+}
 
-export type ActionTypes = AddToBacklog | RemoveFromBacklog | AssignToDay | RemoveMeal;
+export type PlannerActions =
+  AddToBacklogAction |
+  RemoveFromBacklogAction |
+  AssignToDayAction |
+  RemoveMealAction |
+  RequestPlannerAction |
+  ReceivePlannerAction;
 
-export type Actions = typeof actions;
-export default actions
+export default {
+  addToBacklog,
+  removeFromBacklog,
+  assignToDay,
+  removeMeal,
+}

+ 17 - 4
recipes/src/containers/Planner/index.tsx

@@ -6,15 +6,19 @@ import { connect } from 'react-redux';
 import { PlannerState, Weekday, Meal, DayPlan } from 'types/planner';
 import { Grid, Row, Cell } from "@material/react-layout-grid";
 import Card from 'components/Card';
-import PlannerActions, { Actions } from './actions';
+import PlannerActions, { fetchPlannerActionCreator, PlannerActions as PlannerActionsTypes } from './actions';
 import moment from 'moment';
 import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd';
 import './styles.scss';
 import { getWeekDay } from 'services/time';
 import Button from 'components/Button';
+import { ThunkDispatch } from 'redux-thunk';
+import { Action, AnyAction } from 'redux';
 
+type Actions = typeof PlannerActions
 
 interface PlannerContainerProps extends RouteComponentProps, PlannerState, Actions {
+  fetch: any
 }
 
 interface PlannerContainerState {
@@ -22,7 +26,7 @@ interface PlannerContainerState {
 }
 
 const DisplayMeal = (dayPlan: DayPlan, meal: Meal, onRemove: typeof PlannerActions.removeMeal) => {
-  const dish = dayPlan[meal];
+  const dish = dayPlan ? dayPlan[meal] : dayPlan;
   if (dish !== undefined) {
     return (
       <div className='meal-card'>
@@ -46,6 +50,10 @@ class PlannerContainer extends Component<PlannerContainerProps, PlannerContainer
     }
   }
 
+  componentDidMount() {
+    this.props.fetch(this.props.week);
+  }
+
   assignRecipe = (result: DropResult) => {
     const recipe = this.findRecipe(result.draggableId);
     if (result.destination && recipe) {
@@ -154,7 +162,12 @@ const mapStateToProps = (state: AppState) => {
   return state.planner
 }
 
+const mapDispatchToProps = (dispatch: ThunkDispatch<AppState, any, any>) => ({
+  fetch: (week: number) => dispatch(fetchPlannerActionCreator(week)),
+  ...PlannerActions
+})
+
 export default connect(
   mapStateToProps,
-  PlannerActions
-)(PlannerContainer);
+  mapDispatchToProps
+)(PlannerContainer);

+ 24 - 5
recipes/src/containers/Planner/reducers.ts

@@ -1,7 +1,8 @@
-import { ActionTypes } from './actions';
-import { PlannerState } from 'types/planner';
+import { PlannerActions } from './actions';
+import { PlannerState, DBPlanner, WeekPlan, Weekday } from 'types/planner';
 import { getWeekNumber, mkWeekDay } from 'services/time';
-
+import { Reducer } from 'redux';
+import { merge } from 'ramda';
 
 const initialState: PlannerState = {
   isFetching: false,
@@ -33,9 +34,13 @@ const initialState: PlannerState = {
   ]
 }
 
-const PlannerReducer = (
+const joinPlanner = (old: WeekPlan, updated: DBPlanner): WeekPlan => Object.keys(old).reduce((dayplan, day) => {
+  return merge(dayplan, updated[day as Weekday])
+}, {...old});
+
+const PlannerReducer: Reducer<PlannerState, PlannerActions> = (
   state = initialState,
-  action: ActionTypes
+  action
 ): PlannerState => {
   switch (action.type) {
     case 'ADD_TO_BACKLOG': 
@@ -72,6 +77,20 @@ const PlannerReducer = (
         },
         backlog: meal ? state.backlog.concat([meal]) : state.backlog
       }
+    case 'REQUEST_PLANNER':
+      return {
+        ...state,
+        week: action.week,
+        from: mkWeekDay(1, action.week),
+        to: mkWeekDay(7, action.week),
+        isFetching: true,
+      }
+    case 'RECEIVE_PLANNER':
+      return {
+        ...state,
+        isFetching: false,
+        planner: joinPlanner(state.planner, action.payload)
+      }
     default:
       return state
   }

+ 4 - 1
recipes/src/services/time.ts

@@ -3,7 +3,10 @@ import { Weekday } from 'types/planner';
 
 export const mkWeek = () => ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] as Weekday[];
 
-export const mkWeekDay = (day: string | number): Moment => moment().isoWeekday(day);
+export const mkWeekDay = (day: string | number, week?: number): Moment => {
+  const date = week ? moment().week(week) : moment();
+  return date.isoWeekday(day);
+};
 
 export const getWeekNumber = (): number => moment().isoWeek();