GithubHelp home page GithubHelp logo

mikeyhogarth / cocktails Goto Github PK

View Code? Open in Web Editor NEW
110.0 8.0 27.0 1.3 MB

UI for browsing IBA cocktails

Home Page: https://iba-cocktails.netlify.com/

License: GNU General Public License v3.0

HTML 1.83% JavaScript 98.17%
react material-ui redux front-end beverage ui

cocktails's Introduction

Cocktails Browser

Netlify Status Build Status Codacy Badge GitHub license

Screenshot

Deployed at https://iba-cocktails.netlify.com/

This provides a user interface for browsing and filtering the IBA cocktails list (and a couple of other popular drinks). Features include;

  • Browse all 77 IBA cocktails, plus a few non-IBA drinks.
  • Maintain your bar to describe what you have at home.
  • Filter by ingredient, category, glass, vegan or "makeable from your bar"
  • Ability to "favourite" cocktails
  • Integration with TheCocktailDB for enrichment/cocktail images
  • Persistence (local browser storage only)
  • Configurable color schemes
  • See measurements in either parts, ml, cl or oz
  • Pro-mode! Have measurements replaced with 'bartender lingo' such as 'Jigger' and 'Pony'
  • Installable on smart devices (via PWA/Add To Home Screen)

This is a small pet-project and a work in progress. It is built entirely using functional components and react hooks.

Credits

Cocktail list and ingredient data was originally seeded from https://github.com/teijo/iba-cocktails

Enrichment and images provided by the amazing CocktailDB

Application is hosted over at netlify - awesome service

Tech stuff / Local Usage

If you want to run this locally you'll need nodejs/npm installed. Clone the repo, then;

npm install
npm start

All the data is in JSON files (see src/data), so there's no server or database to worry about.

Contributing

If you have a comment about one of the recipes / a data related issue, feel free to raise an issue and label it 'data'. It's just an unfortunate fact of life that cocktail recipes will vary and what some people think is good, others will not, but we're happy to correct blatant mistakes.

Take the labels "Help Wanted" or "Good first issue" as an open invitation to pick tickets up if you want to, but if they don't have those labels then please get in touch to discuss any change before contributing.

  • Assign yourself to a ticket if you're working on it.
  • If there's not already an open ticket, but you have a suggestion, please raise as an issue and discuss prior to doing any work.
  • We're not doing versioning yet so don't worry about bumping versions/changelogs.
  • We've got Snapshot Testing going on in this app, remember to update them if you change the views.
  • Don't check in package-lock unless package.json has changed.
  • This is a function-component-only project.

cocktails's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cocktails's Issues

Remove the concept of "Special" ingredients

cocktails.json has two kinds of ingredient: special and ingredient. The special ones are causing a pain because it means you can filter for cocktails and then find you still can't make it - additionally some of the special ingredients aren't vegan (e.g. #85) and it means that filter isn't working.

So, let's ditch the concept of a "special" completely and promote all specials to ingreients.json.

This will initially mean that they will all appear in the bar / on the ingredient filter, but we can introduce a feature to get rid of them later.

Example

{ "special": "6 Mint sprigs" },
{ "special": "1 dash Lime juice" }

becomes

{ "amount": 3, "ingredient": "Mint sprigs" }
{ "amount": "1 dash", "ingredient": "Lime juice" }
// ...and add "Mint sprigs" and "Lime juice" to ingredients.json

There are 26 of them. There is one weird one;

{ "special": "Dash of Angostura bitters (optional)" }

As this is optional, it shouldn't be affected by any of the filters, so just leave it as special for now.

Glass-specific SVGs

At the moment we are using one SVG to represent the concept of a 'glass';

import CocktailIcon from "@material-ui/icons/LocalBar";

It would be really cool if this SVG was tailored for each glass type. There are silhouettes of them at the bottom of this wikipedia page;

https://en.wikipedia.org/wiki/List_of_glassware

My only reservation with this is that the current image of the cocktail glass we're using is very definitively representative of the concept "Glass" - some of the other glasses are just going to look like little rectangles and it might make it less obvious what they represent if they're viewed in isolation. All depends on how good the SVGs are I suppose.

Better Glass SVGs

The glass SVGs (currently sitting in the images/glasses folder) were done by me, very hastily and very poorly. If you think you can do better, by all means go for it :)

Before spending any time though, consult with @laurahogarth on design (the last thing we want is for someone to spend a long time on this and then get their PR rejected because we disagree on whether they're right or not). That said, it is unlikely that anyone will be worse than me so it's probably relatively safe!

The icons need to have the following properties in order to work with the application;

  • 24x24
  • Only consist of a single path element

Infinite Scrolling on browser page

Right now the browse cocktails page loads every single cocktail in the database and displays them all - there are only 75 of them so it's not too bad but there is a noticable jank when going to this page which would be aleviated if we only rendered say, 10 cocktails. We could introduce pagination to get around this but another option is to present an infinite scroll to users, maybe using this library;

https://www.npmjs.com/package/react-infinite-scroller

Glass guides

Add functionality to inform people about what the different types of glass are / the size and what they look like maybe. At the moment we just have 'hurricane', 'martini', 'collins' which is great if you know what they are, but not so much if you don't.

Search for cocktails by name

Using ctrl-F is indicative of a bad UI - and this app currently invites ctrl-Fing to search for specific cocktails. What about a text box in the header to find the cocktail and go straight to its page? Could we maybe even add some kind of intelligent autocomplete so it would search ingredients too?

Add hardware support

Is it possible to add a "ORDER" button to the selected drink menu? and have this button send the list of ingredients and measure to a serial port?

The idea it to make your program a front-end for a drink mixing machine, like: https://www.youtube.com/watch?v=49msONntdEQ
These machines typically have an Arduino or some sort of microcontroller connected via USB serial to the host PC.

A program on the Arduino will then control motor and pumps, LED's, etc.

Add abv% for cocktails on cocktail page

We have the abv% for each ingredient - from this it should be possible to calculated the overall abv% for the cocktail and display it. We would need;

  • A function that takes a set of ingredients and returns a decimal showing total percentage
  • A call to that function in the fetchCocktails function that adds it (in much the same way we're adding the slug there)
  • Display it on the views (maybe in the existing subheaders)

This might be a good resource for writing test cases:
https://www.artofdrink.com/blog/alcohol-percentages-of-cocktails?fbclid=IwAR0kWRiv5P8_Yv0iYIcqpM43mHXzzeJ1_fdn_rwqxGoTK9xbhxBe77UVomU

This needs to be calculated rather than hard-coded against each cocktail so that if we ever add new cocktails it'll just all automatically happen.

Redesign filter UI

It basically takes over the whole screen - we knew we'd have to sort it out at some point, that time has probably come.

Add infinite scroll

Time to get rid of the slow load time by not rendering all cocktails at first, instead only load them when the user scrolls down the list.

Introduce reselect

The filter functionality is mixed up with the component rendering logic; for example, there's a filtersFromUserOptions function that produces some stuff from state. There are some patterns out there that make this sort of logic much easier to manage, the main of which being reselect: Introduce this to abstract derived-state logic in a more idiomatic way.

This may be the reason that I am seeing animation janking when I swap out react-redux's HoCs for hooks.

See comments by @markerikson: reduxjs/react-redux#1318 (comment)

Better snapshot tests

We have some snapshot tests, but theyr'e not particularly good - specifically;

  • We don't have 100% coverage
  • Theyr'e only 'shallow' tests
  • Things like the cocktailList/cocktailItem should be really easy to test

We want snapshot tests, but cant' really get those on things like the cocktailItem without introducing enzyme to use its mount functionality, or introducing things like the react-router MemoryRouter functionaity into the tests.

Lets spend some time making this good :)

Units selection has no default when first viewed

Option setting "units" has no default, and so when viewing the app for the first time all measurements are given as "undefined" - ie;

4.5 undefined of vodka
2 undefined of gin
9 undefined of orange juice

Refactor filters

The pattern is now visible, so time to start banging the nails in on this one. Currently every time you want to add a new filter you need to change as many as 6 separate files;

  1. CocktailFilter.js to add it to the UI (noting down the key you give it)
  2. New entry in filter.utils.js to add the label for the filter, and optionally a Component if it's a configurable filter.
  3. New condition in filter.js#filtersFromUserOptions to convert what the user asked for into an actual filter.
  4. New entry in FilterChips to generate the chip presentation logic for the new filter.
  5. New condition in the filter.js#applyFilter method in `` to catch the filter and hand off to a filterRule.
  6. New method in filterRules to include the filter logic.

This is a bit whiffy. Some of it I'm okay with... lots of it I'm not. Initial thoughts are;

  • We could centralise the component, chip rendering logic and label into a centralised "Filter config" file.
  • We could split out the filters into their own reducer and generate the applied filters on the fly (so, applied filters goes in state rather than being accessed through a selector).

Styles in "pride" mode

"Pride" mode - the white text with a yellow background is a bit hard to read - what can be done about it?

Check necessary ingredients which aren’t included in filters

Some cocktails require ingredients to make which aren’t taken into account when filtering.
Examples:

  • Ramos Fizz requires egg white, orange flower water, vanilla extract and soda water but these aren't available to add to "my bar", so it shows up as available to make if you have the other ingredients.
  • Russian Spring Punch: preparation method says "top up with sparkling wine", but that's not listed as an ingredient.
  • Derby: the only listed ingredient is gin, but you can't really make it without the other items.

Fix and complete cocktail colours

Either remove entirely or swap for 1 colour on most cocktails (Exception being things like B52). Whatever is decided, finish it for all cocktails.

Vampiro aint vegan!

Vampiro has honey in, so not vegan, but none of its "ingredients" are marked as vegan - the honey is a "special" and we don't pick up any meta data for those (it's just meant to cover "weird stuff" that whilst technically an ingredient, isn't necessarily something you'd have in your "bar")

We have a number of approaches;

  1. We could promote honey to an ingredient. This would mean it showed up in the "bar", which might not be what we want.
  2. We could put in the ability to mark "special" things as vegan - I don't really like this idea though as this means we'd have two different places to mark things as vegan.
  3. We could deprecate the idea of "special" completely, promote all things to "ingredient" - at which point they'd all show up in the "bar"/"filter" - BUT we could mark them as "special" in ingredients.json to stop that happening.

I like the sound of (3) personally- these "special" types have been the cause of most of you data problems and most of them are gone now anyway - but need to run it past @laurahogarth

Add more cocktails

Add selected cocktails to the site. Several “classics” (Gimlet, White Russian) aren’t currently on there because they don’t appear on the IBA’s list.

Allergen warnings

This needs a bit of research and refinement - we could indicate on each ingredients if it is potentially an allergen and then show warnings / allow filtering based on this.

Properly design cocktail page

Cocktail page itself (the thing you click through to from the browser) is very much in "placeholder" form at the moment. Let's put something more solid in place.

Ingredients guides

Add in some kind of guide to describe what ingredients are / what goes into them. The cocktailDB API actually provides an endpoint to get this information, so probably what we need here is a set of "ingredients" pages, clickable from the cocktail page. OR maybe some kind of boxout on the cocktail page that describes each ingredient.

Remove string literals from action creators/reducers

Currently we have this kind of thing going on;

// actions
export function loadIngredients(payload) {
  return { type: "LOAD_INGREDIENTS", payload };
}

// reducers
      case "LOAD_INGREDIENTS":

Where the string "LOAD_INGREDIENTS" is declared twice (and in fact every time a reducer is run). Aside from being (albeit minimally) inefficient, it also adds an extra level of churn if you ever want to change them. There are a couple of ways we could do this;

  1. Introduce an actionTypes.js file, put the constants in there, and reference them from actions/index.js and reducers/index.js.

  2. Introduce a supporting library such as Redux Actions to help us with this.

I actually don't feel particularly strongly either way - (1) will be simpler and overall be less code in the bundle, but (2) will be neater and will result in less code for us to actually write and work with.

Pie charts on cocktails page

How awesome would this be? We have ingredients / quantities, we could render a pie chart showing the makeup of the cocktail :)

Should we support other types of persistence?

Our persistence layer (see persistence.js) currently defaults to using localStorage with no fallbacks if the browser doesn't support that functionality (it basically just won't save). It might be worth abstracting this persistence layer out to another library, e.g. store.js

https://github.com/marcuswestin/store.js/

That might also give us some more declarative code to boot.

Or... this might be over-engineering. Have a look and figure out if we think it's worth doing.

Add vegan filter

It would be nice to be able to filter on whether a cocktail is vegan or not (e.g. things like cream and eggs) - suggest doing this by adding a "vegan" flag next to each ingredient in ingredients.json and then it should be really easy to just filter them out using the existing filter code.

Ability to change measurement type

At the moment all cocktails are stored with their ingredients in cl. Let's add a setting that allows you to switch to other forms of measurement. This will involve;

  • Writing some conversion functions (or, finding a decent library that does them)
  • Adding a new setting
  • Hooking into that setting and doing a conversion

All the ingredient stuff is already in one place, the IngredientDetail component - the variants functionality doesn't use that component though so for now this just covers the "native" cocktails, not the variants (we can do variants as a seperate PR, but if you're feeling brave then by all means pick it up in this one -it'll involve a bit of extra parsing when the API response comes back from cocktailDB to split out measurement and value, and then the incorporation of the IngredientDetail component into the CocktailVariant component)

Fix codacy issues

Couple of really minor codacy warnings about the codebase (click the code quality badge on the README, then click "issues") - would be nice to get these cleared up.

No need to fix them all in one PR.

Alignment issues on some cocktails

The cocktailDB API sometimes sends back stray spaces and things in its responses and this makes the display go all squiffy in the "variants" section - in particular look at the 'negroni' page - there's a variant whos ingredients look like this;

1 ozGin
1 ozLillet
1 ozSweet Vermouth
1Orange Peel

It doesn't actually happen for all data, so what we'll probably need to do is just shave off all spaces and then add one (so it's not just a case of adding a ' ' space, because then some ingredients will get two spaces!).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.