Skip to content
This repository has been archived by the owner on May 7, 2021. It is now read-only.

Commit

Permalink
Lock specific menu items (major)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jorge Cuadra committed Sep 5, 2018
1 parent a873adc commit 2b3ca89
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 61 deletions.
1 change: 0 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Roadmap

- [ ] snackbar is clipped by drawer
- [ ] lock specific menu items
- [ ] increase tolerance when stackoverflow
- [ ] add unit tests
- [ ] add unit tests snapshots for calculations
Expand Down
25 changes: 22 additions & 3 deletions src/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react';
import Link from 'next/link';
import moment from 'moment';
import getIn from 'lodash/get';
import { List } from 'immutable';
import { List, Set as iSet } from 'immutable';
import {
TopAppBar,
TopAppBarRow,
Expand All @@ -13,7 +13,7 @@ import {

import CoreContext from './CoreContext';
import MenuDrawer from './MenuDrawer';
import { calculateDayMenu, calculateSettings, randomSort } from './util';
import { calculateDayMenu, calculateSettings, prioritizeAndSort } from './util';
import { convertMacroGramToCalories } from './calculator/utils';
import demoRecipes from '../data/recipes';

Expand All @@ -25,12 +25,14 @@ function loadLocalValues() {
macrosWorkout: {},
menu: [],
recipes: List(),
recipesFavoriteKeys: iSet(),
settings: {},
tracker: { calories: 0, carbs: 0, protein: 0, fat: 0 },
};
}

const recipesJSON = getItem('recipes', '[]');
const recipesFavoriteKeysJSON = getItem('recipesFavoriteKeys', '[]');
const settings = getItem('settings', '{}');
const tracker = getItem('tracker', '{}');

Expand All @@ -40,6 +42,7 @@ function loadLocalValues() {
macrosWorkout: getItem('macrosWorkout', '{}'),
menu: getItem('menu', '[]'),
recipes: List(recipesJSON),
recipesFavoriteKeys: iSet(recipesFavoriteKeysJSON),
settings,
tracker: {
calories: 0,
Expand Down Expand Up @@ -82,6 +85,7 @@ class Layout extends Component {
macrosRest,
macrosWorkout,
recipes,
recipesFavoriteKeys,
settings,
tracker,
} = loadLocalValues();
Expand All @@ -95,6 +99,8 @@ class Layout extends Component {
menu,
handleMenuGenerate: this.handleMenuGenerate.bind(this),
recipes,
recipesFavoriteKeys,
handleRecipeFavoriteToggle: this.handleRecipeFavoriteToggle.bind(this),
handleRecipeAdd: this.handleRecipeAdd.bind(this),
handleRecipeRemove: this.handleRecipeRemove.bind(this),
handleRecipeEdit: this.handleRecipeEdit.bind(this),
Expand Down Expand Up @@ -202,7 +208,7 @@ class Layout extends Component {

try {
const { menu } = calculateDayMenu({
recipes: state.recipes.sort(randomSort),
recipes: prioritizeAndSort(state.recipes, state.recipesFavoriteKeys),
settings,
});

Expand All @@ -214,6 +220,19 @@ class Layout extends Component {
}
}

handleRecipeFavoriteToggle({ action = 'add', recipeKey }) {
this.setState(prevState => {
const recipesFavoriteKeys = prevState.recipesFavoriteKeys[action](
recipeKey,
);
localStorage.setItem(
'recipesFavoriteKeys',
JSON.stringify(recipesFavoriteKeys.toArray()),
);
return { recipesFavoriteKeys };
});
}

handleRecipeAdd(recipe) {
const recipes = this.state.recipes.unshift(recipe);

Expand Down
80 changes: 80 additions & 0 deletions src/plan/Food.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Link from 'next/link';

import { Button } from 'rmwc/Button';
import { Card } from 'rmwc/Card';
import { Fab } from 'rmwc/Fab';
import { GridCell } from 'rmwc/Grid';
import { List, SimpleListItem } from 'rmwc/List';
import { ListDivider } from 'rmwc/List';
import { Typography } from 'rmwc/Typography';

function Food({
menu,
handleMenuGenerate,
handleRecipeFavoriteToggle,
hasRecipesMinimum,
recipes,
recipesFavoriteKeys,
}) {
return (
<GridCell span="6" mobile="12">
<Card outlined>
<div className="flex justify-between p-4 items-center">
<Typography use="headline5">
{menu.length > 0 && `${menu.length} servings`}
</Typography>
<Fab onClick={handleMenuGenerate} icon="autorenew" label="shuffle" />
</div>

<ListDivider />

{hasRecipesMinimum && (
<Typography
use="headline5"
theme="text-secondary-on-background"
className="px-4 my-2"
>
Need {RECIPES_MINIMUM - recipes.size} more recipes to be able to
calculate.{' '}
<Link href="/recipes">
<Button>Add more recipes</Button>
</Link>
</Typography>
)}
<List twoLine dense>
{hasRecipesMinimum &&
!menu.length && (
<div className="text-center">
<Typography
use="headline6"
tag="div"
className="flex justify-center p-4"
>
Randomly generate a menu plan for the day
</Typography>
<Button onClick={handleMenuGenerate}>Generate</Button>
</div>
)}

{menu.map(({ _key, name, Calories, Protein, Carbs, Fat }, index) => {
const locked = recipesFavoriteKeys.has(_key);
const action = locked ? 'delete' : 'add';
return (
<SimpleListItem
key={_key + index}
text={name}
graphic={locked ? 'lock' : 'lock_open'}
secondaryText={`${Calories}cal | Protein ${Protein}g | Carbs ${Carbs}g | Fat ${Fat}g`}
onClick={() =>
handleRecipeFavoriteToggle({ action, recipeKey: _key })
}
/>
);
})}
</List>
</Card>
</GridCell>
);
}

export default Food;
70 changes: 13 additions & 57 deletions src/plan/Plan.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React from 'react';
import Link from 'next/link';
import numeral from 'numeral';
import { Button } from 'rmwc/Button';
import { Card } from 'rmwc/Card';
import { Grid, GridCell } from 'rmwc/Grid';
import { Fab } from 'rmwc/Fab';
import { ListDivider } from 'rmwc/List';
import { Typography } from 'rmwc/Typography';
import { List, SimpleListItem } from 'rmwc/List';
import { TabBar, Tab } from 'rmwc/Tabs';

import { RECIPES_MINIMUM } from '../recipes/constants';
import { withCoreContext } from '../CoreContext';

import Food from './Food';
import MacrosRings from './MacrosRings';
import Macro from './Macro';

Expand All @@ -24,8 +22,10 @@ class Plan extends React.Component {
isWorkoutDay = false,
menu = [],
handleMenuGenerate,
handleRecipeFavoriteToggle,
handleTracker,
recipes = [],
recipesFavoriteKeys = [],
macrosRest = {},
macrosWorkout = {},
tracker = {},
Expand Down Expand Up @@ -107,60 +107,16 @@ class Plan extends React.Component {
</GridCell>
)}
{showFood && (
<GridCell span="6" mobile="12">
<Card outlined>
<div className="flex justify-between p-4 items-center">
<Typography use="headline5">
{menu.length > 0 && `${menu.length} servings`}
</Typography>
<Fab
onClick={handleMenuGenerate}
icon="autorenew"
label="shuffle"
/>
</div>

<ListDivider />

{hasRecipesMinimum && (
<Typography
use="headline5"
theme="text-secondary-on-background"
className="px-4 my-2"
>
Need {RECIPES_MINIMUM - recipes.size} more recipes to be
able to calculate.{' '}
<Link href="/recipes">
<Button>Add more recipes</Button>
</Link>
</Typography>
)}
<List twoLine dense>
{hasRecipesMinimum &&
!menu.length && (
<div className="text-center">
<Typography
use="headline6"
tag="div"
className="flex justify-center p-4"
>
Randomly generate a menu plan for the day
</Typography>
<Button onClick={handleMenuGenerate}>Generate</Button>
</div>
)}
{menu.map(
({ _key, name, Calories, Protein, Carbs, Fat }, index) => (
<SimpleListItem
key={_key + index}
text={name}
secondaryText={`${Calories}cal | Protein ${Protein}g | Carbs ${Carbs}g | Fat ${Fat}g | 1 serving`}
/>
),
)}
</List>
</Card>
</GridCell>
<Food
{...{
menu,
handleMenuGenerate,
handleRecipeFavoriteToggle,
hasRecipesMinimum,
recipes,
recipesFavoriteKeys,
}}
/>
)}
</Grid>
<style jsx>{`
Expand Down
14 changes: 14 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ export function randomSort() {
return 0;
}

export function prioritizeAndSort(recipes, recipesFavoriteKeys) {
const favoriteKeys = recipes.filter(
filterFavoriteRecipes(recipesFavoriteKeys),
);
const nonFavorite = recipes
.filterNot(filterFavoriteRecipes(recipesFavoriteKeys))
.sort(randomSort);
return favoriteKeys.concat(nonFavorite);
}

function filterFavoriteRecipes(recipesFavoriteKeys) {
return recipe => recipesFavoriteKeys.has(recipe._key);
}

// Find the combinations of recipes that amount 2,800 cal
export function calculateDayMenu({
calories = 0,
Expand Down

0 comments on commit 2b3ca89

Please sign in to comment.