Quellcode durchsuchen

Weekly navigation: Fetch and Save previous/future weeks

Tatiana Inama vor 7 Jahren
Ursprung
Commit
13e406bbea

+ 34 - 3
recipes/src/containers/Planner/actions.ts

@@ -1,5 +1,5 @@
 import { DBRecipe } from 'types/recipes';
-import { Meal, RecipePlan, Weekday, DBPlanner, PlannerMode, WeekPlan, DBDayPlan } from 'types/planner';
+import { Meal, RecipePlan, Weekday, DBPlanner, PlannerMode, WeekPlan, DBDayPlan, WeekShift } from 'types/planner';
 import { Dispatch, ActionCreator, Action } from 'redux';
 import { getPlanner, savePlanner } from './services'
 import { ThunkAction } from 'redux-thunk';
@@ -15,6 +15,7 @@ export const RECEIVE_PLANNER = 'RECEIVE_PLANNER';
 
 export const CHANGE_PLANNER_MODE = 'CHANGE_PLANNER_MODE';
 export const EDIT_PLANNER = 'EDIT_PLANNER';
+export const CHANGE_PLANNER_RANGE = 'CHANGE_PLANNER_RANGE';
 
 export const PENDING_SAVE_PLANNER = 'PENDING_SAVE_PLANNER';
 export const CONFIRM_SAVE_PLANNER = 'CONFIRM_SAVE_PLANNER';
@@ -113,6 +114,33 @@ export const editPlanner = (): EditPlannerAction => ({
   type: EDIT_PLANNER
 });
 
+export interface ChangePlannerRangeAction extends Action<'CHANGE_PLANNER_RANGE'> {
+  from: Moment,
+  to: Moment,
+  week: number
+}
+export const changePlannerRange = (from: Moment, to: Moment, week: number): ChangePlannerRangeAction => ({
+  type: CHANGE_PLANNER_RANGE,
+  from,
+  to,
+  week
+});
+export const changePlannerRangeActionCreator: ActionCreator<
+  ThunkAction<
+    Promise<ReceivePlannerAction>,
+    DBPlanner,
+    {from: Moment, to: Moment},
+    ReceivePlannerAction
+  >
+> = (from, to, week) => {
+  return async (dispatch: Dispatch) => {
+    dispatch(changePlannerRange(from, to, week));
+    dispatch(requestPlanner(from, to));
+    const planner = await getPlanner(from, to);
+    return dispatch(receivePlanner(planner))
+  }
+}
+
 export interface PendingSavePlannerAction extends Action<'PENDING_SAVE_PLANNER'> {
   planner: WeekPlan,
   from: Moment,
@@ -183,7 +211,9 @@ export type PlannerActions =
   PendingSavePlannerAction |
   ConfirmSavePlannerAction |
   RejectSavePlannerAction |
-  CancelSavePlannerAction;
+  CancelSavePlannerAction |
+  ChangePlannerRangeAction;
+
 
 export default {
   addToBacklog,
@@ -192,5 +222,6 @@ export default {
   removeMeal,
   changePlannerMode,
   editPlanner,
-  cancelSavePlanner
+  cancelSavePlanner,
+  changePlannerRange
 }

+ 22 - 7
recipes/src/containers/Planner/index.tsx

@@ -3,9 +3,9 @@ import { RouteComponentProps } from 'react-router';
 import Navbar from 'components/Navbar';
 import { AppState } from 'store/configureStore';
 import { connect } from 'react-redux';
-import { PlannerState, Weekday, Meal, PlannerMode, RecipePlan, WeekPlan, Meals } from 'types/planner';
+import { PlannerState, Weekday, Meal, PlannerMode, RecipePlan, WeekPlan, Meals, WeekShift } from 'types/planner';
 import Card from 'components/Card';
-import PlannerActions, { fetchPlannerActionCreator, savePlannerActionCreator } from './actions';
+import PlannerActions, { fetchPlannerActionCreator, savePlannerActionCreator, changePlannerRangeActionCreator } from './actions';
 import moment, { Moment } from 'moment';
 import { DragDropContext, Droppable, Draggable, DropResult, OnDragEndResponder } from 'react-beautiful-dnd';
 import './styles.scss';
@@ -13,12 +13,15 @@ import Button from 'components/Button';
 import { ThunkDispatch } from 'redux-thunk';
 import { bindActionCreators } from 'redux';
 import RecipeSearch from 'components/RecipeSearch';
-import { DBRecipe } from 'src/types/recipes';
+import { DBRecipe } from 'types/recipes';
+import { getWeekPeriod } from 'services/time';
+
 type Actions = typeof PlannerActions
 
 interface PlannerContainerProps extends RouteComponentProps, PlannerState, Actions {
   fetch: typeof fetchPlannerActionCreator,
   save: typeof savePlannerActionCreator
+  changeRange: typeof changePlannerRangeActionCreator
 }
 
 interface PlannerContainerState {
@@ -71,7 +74,12 @@ class PlannerContainer extends Component<PlannerContainerProps, PlannerContainer
 
   changeMode = (mode: PlannerMode) => this.props.changePlannerMode(mode);
 
-  cancel = () => this.props.cancelSavePlanner(this._prevState.planner, this._prevState.backlog)
+  cancel = () => this.props.cancelSavePlanner(this._prevState.planner, this._prevState.backlog);
+
+  changeWeek = (shift?: WeekShift) => {
+    const newPeriod = getWeekPeriod(this.props.from, this.props.to, shift);
+    this.props.changeRange(newPeriod.from, newPeriod.to, newPeriod.week);
+  }
 
   render () {
     return (
@@ -107,6 +115,7 @@ class PlannerContainer extends Component<PlannerContainerProps, PlannerContainer
           removeMeal={this.removeMeal}
           addToBacklog={this.props.addToBacklog}
           assignToDay={this.props.assignToDay}
+          changeWeek={this.changeWeek}
         />
       </div>
     );
@@ -122,8 +131,9 @@ const DisplayPlanner: React.SFC<{
   removeMeal: typeof PlannerActions.removeMeal,
   assignToDay: typeof PlannerActions.assignToDay,
   addToBacklog: (recipe: DBRecipe) => {},
+  changeWeek: (shift?: WeekShift) => void,
   mode?: PlannerMode,
-}> = ({ mode, onDragEnd, backlog, weekNumber, week, planner, removeMeal, addToBacklog, assignToDay }) => (
+}> = ({ mode, onDragEnd, backlog, weekNumber, week, planner, removeMeal, addToBacklog, assignToDay, changeWeek}) => (
   <section className='cbk-planner__body'>
     <DragDropContext onDragEnd={onDragEnd}>
       {
@@ -161,7 +171,11 @@ const DisplayPlanner: React.SFC<{
         ) : null
       }
       <div className='cbk-planner__body__calendar'>
-        <div>Week {weekNumber}</div>
+        <div>
+          Week {weekNumber}</div>
+          <Button onClick={() => changeWeek(WeekShift.Prev)}>Prev</Button>
+          <Button onClick={() => changeWeek()}>Current</Button>
+          <Button onClick={() => changeWeek(WeekShift.Next)}>Next</Button>
         <div className='container'>
           <div className='day-schedule day-schedule--meals'>
             <div className='day-schedule--date'></div>
@@ -177,7 +191,7 @@ const DisplayPlanner: React.SFC<{
             week.map(([weekday, day], dayNumber) => (
               <div key={dayNumber} className='day-schedule'>
                 <div className='day-schedule--date'>
-                  <h5>{weekday} {moment(day).format('DD')}</h5>
+                  <h5>{planner[weekday].date.format('ddd DD.MM') || weekday}</h5>
                 </div>
                 {
                   Meals.map((meal, key) => {
@@ -232,6 +246,7 @@ const mapStateToProps = (state: AppState) => {
 const mapDispatchToProps = (dispatch: ThunkDispatch<AppState, any, any>) => ({
   fetch: (from: Moment, to: Moment) => dispatch(fetchPlannerActionCreator(from, to)),
   save: (plan: WeekPlan, from: Moment, to: Moment) => dispatch(savePlannerActionCreator(plan, from, to)),
+  changeRange: (from: Moment, to: Moment, shift: WeekShift) => dispatch(changePlannerRangeActionCreator(from, to, shift)),
   ...bindActionCreators(PlannerActions, dispatch)
 })
 

+ 15 - 11
recipes/src/containers/Planner/reducers.ts

@@ -1,8 +1,9 @@
 import { PlannerActions } from './actions';
 import { PlannerState, DBPlanner, WeekPlan, Weekday, PlannerMode } from 'types/planner';
-import { getWeekNumber, mkWeekDay } from 'services/time';
+import { getWeekNumber, mkWeekDay, getWeekPeriod } from 'services/time';
 import { Reducer } from 'redux';
 import { merge, uniqBy } from 'ramda';
+import { mkPlanner } from './services';
 
 const initialState: PlannerState = {
   mode: PlannerMode.View,
@@ -12,21 +13,16 @@ const initialState: PlannerState = {
   from: mkWeekDay(1),
   to: mkWeekDay(7),
   week: getWeekNumber(),
-  planner: {
-    monday:     { date: mkWeekDay(1)},
-    tuesday:    { date: mkWeekDay(2)},
-    wednesday:  { date: mkWeekDay(3)},
-    thursday:   { date: mkWeekDay(4)},
-    friday:     { date: mkWeekDay(5)},
-    saturday:   { date: mkWeekDay(6)},
-    sunday:     { date: mkWeekDay(7)},
-  },
+  planner: mkPlanner(),
   backlog: []
 }
 
 const joinPlanner = (old: WeekPlan, updated: DBPlanner): WeekPlan => Object.keys(old).reduce((_oldPlanner, day) => ({
   ..._oldPlanner,
-  [day]: merge(_oldPlanner[day as Weekday], updated[day as Weekday])
+  [day]: {
+    ...merge(_oldPlanner[day as Weekday], updated[day as Weekday]),
+    date: _oldPlanner[day as Weekday].date
+  }
 }), {...old});
 
 const PlannerReducer: Reducer<PlannerState, PlannerActions> = (
@@ -91,6 +87,14 @@ const PlannerReducer: Reducer<PlannerState, PlannerActions> = (
         ...state,
         mode: action.mode
       }
+    case 'CHANGE_PLANNER_RANGE':
+      return {
+        ...state,
+        from: action.from,
+        to: action.to,
+        week: action.week,
+        planner: mkPlanner(action.from)
+      }
     case 'EDIT_PLANNER':
       return {
         ...state,

+ 8 - 1
recipes/src/containers/Planner/services.ts

@@ -1,4 +1,4 @@
-import { shortDate } from 'services/time';
+import { shortDate, mkWeekDay, mkWeek } from 'services/time';
 import axios from 'axios';
 import { DBPlanner, DBDayPlan, WeekPlan, Weekday, DayPlan, Meal } from 'types/planner';
 import moment, { Moment } from 'moment';
@@ -27,6 +27,13 @@ const toDBPlan = (weekplan: WeekPlan) => {
   }, [] as Array<DBDayPlan>)
 }
 
+export const mkPlanner = (from: Moment = moment()): WeekPlan => mkWeek().reduce((planner, weekday, index)=> {
+  return {
+    ...planner,
+    [weekday]: { date: mkWeekDay(index+1, from.isoWeek()) }
+  } 
+}, {} as WeekPlan);
+
 export const getPlanner = (from: Moment, to: Moment): Promise<DBPlanner> => 
   axios.get(`${PLANNER}/week/${shortDate(from)}/${shortDate(to)}`).then(response => response.data);
 

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

@@ -1,5 +1,5 @@
 import moment, { Moment } from 'moment';
-import { Weekday } from 'types/planner';
+import { Weekday, WeekShift } from 'types/planner';
 
 export const mkWeek = () => ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] as Weekday[];
 
@@ -16,6 +16,15 @@ export const mkWeekData = (weekNumber: number): [Weekday, string][] => mkWeek().
   [ day, moment().week(weekNumber).isoWeekday(day).format() ]
 ))
 
+export const getWeekPeriod = (from: Moment|Date|string, to: Moment|Date|string, shift?: WeekShift) => {
+  const anchor = shift ? moment(from).add(shift ? 7 : -7, 'days') : moment();
+  return {
+    from: moment(anchor).isoWeekday(1),
+    to: moment(anchor).isoWeekday(7),
+    week: anchor.isoWeek()
+  }
+}
+
 export const shortDate = (date: Moment): string => date.format('YYYY-MM-DD')
 
 export default {
@@ -24,4 +33,5 @@ export default {
   getWeekDay,
   mkWeekData,
   shortDate,
+  getWeekPeriod
 }

+ 6 - 1
recipes/src/types/planner.ts

@@ -59,4 +59,9 @@ export interface DBPlanner extends WeekPlan {
   week: number,
 }
 
-export const Meals = [Meal.Lunch, Meal.Dinner, Meal.Dessert]
+export const Meals = [Meal.Lunch, Meal.Dinner, Meal.Dessert]
+
+export enum WeekShift {
+  Prev,
+  Next
+}