Skip to content

Commit

Permalink
feat: create multiple lists of ingredients (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-gustafsson authored Sep 6, 2023
1 parent 1faf1af commit e374345
Show file tree
Hide file tree
Showing 28 changed files with 466 additions and 52 deletions.
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,4 @@ node_modules
.env
/coverage

/android/keystore.jks
/android/release.jks.base64
/fastlane/service-account-key.base64
/fastlane/service-account-key.json
/fastlane/report.xml
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.moimob.drinkable"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 13602
versionName "1.36.2"
versionCode 13700
versionName "1.37.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
Expand Down
50 changes: 50 additions & 0 deletions cypress/e2e/ingredients.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ describe('Ingredients', () => {
window.localStorage.setItem('CapacitorStorage.messuarement-system', 'Metric');
cy.visit('#/ingredients');

cy.dataCy('selected-bar-component').should('not.exist');
cy.dataCy('ingredient-list').find('div').should('have.length', 0);
cy.dataCy('add-ingredients-search').type('Vodka');
cy.dataCy('tag-vodka').click();
Expand Down Expand Up @@ -49,6 +50,55 @@ describe('Ingredients', () => {
.first()
.should('contain', 'All ingredients selected');
});

it('My inventory - Navigate to selected bar', () => {
window.localStorage.setItem('CapacitorStorage.messuarement-system', 'Metric');
window.localStorage.setItem(
'CapacitorStorage.ingredient-lists',
JSON.stringify([
{ name: 'My Bar', ingredients: [] },
{ name: 'Test', ingredients: [] }
])
);

cy.visit('#/ingredients');

cy.dataCy('selected-bar-component').should('exist');
cy.dataCy('selected-bar-name').should('include.text', 'My Bar');

cy.get('header').should('contain.text', 'Ingredients');
cy.url().should('include', `ingredients`);

cy.dataCy('selected-bar-name').first().click();

cy.get('header').should('contain.text', 'Profile');
cy.url().should('include', `user`);
});

it('All ingredients - Navigate to selected bar', () => {
window.localStorage.setItem('CapacitorStorage.messuarement-system', 'Metric');
window.localStorage.setItem(
'CapacitorStorage.ingredient-lists',
JSON.stringify([
{ name: 'My Bar', ingredients: [] },
{ name: 'Test', ingredients: [] }
])
);

cy.visit('#/ingredients');
navigateToAllIngredients();

cy.dataCy('selected-bar-component').should('exist');
cy.dataCy('selected-bar-name').should('include.text', 'My Bar');

cy.get('header').should('contain.text', 'Ingredients');
cy.url().should('include', `ingredients`);

cy.dataCy('selected-bar-name').last().click();

cy.get('header').should('contain.text', 'Profile');
cy.url().should('include', `user`);
});
});

function navigateToInventory() {
Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/13700.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
• Added support for multiple lists of ingredients
2 changes: 1 addition & 1 deletion src/components/dialogs/welcome-dialog.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<ux-dialog class="small-dialog">
<div>
<div class="bg-base-200 modal-box relative p-4">
<div class="bg-base-200 modal-box relative m-auto p-4">
<h4 class="text-lg p4" t="welcome"></h4>
<p t="select-messuarement-system"></p>

Expand Down
11 changes: 11 additions & 0 deletions src/components/icons/icon-arrow-forward.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" stroke="currentColor" viewBox="0 0 512 512">
<title>Arrow Forward</title>
<path
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="48"
d="M268 112l144 144-144 144M392 256H100" />
</svg>
</template>
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function configure(config: FrameworkConfiguration) {
PLATFORM.moduleName('./icons/icon-refresh-outline.html'),
PLATFORM.moduleName('./icons/icon-reader.html'),
PLATFORM.moduleName('./tag-component.html'),
PLATFORM.moduleName('./add-ingredient-component/add-ingredient-component')
PLATFORM.moduleName('./add-ingredient-component/add-ingredient-component'),
PLATFORM.moduleName('./icons/icon-arrow-forward.html')
]);
}
5 changes: 5 additions & 0 deletions src/domain/entities/ingredient-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type IngredientList = {
id: number;
name: string;
ingredients: string[];
};
6 changes: 5 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@
"tags-title": "My Tags",
"tags-subtitle": "Manage your Cocktail Tags",
"create-cocktail-tag": "Create Tag",
"edit-cocktail-tag": "Edit Tag"
"edit-cocktail-tag": "Edit Tag",
"selected-ingredient-list": "Selected Bar",
"ingredient-lists-title": "My Bars",
"create-ingredient-list": "Create Bar",
"edit-ingredient-list": "Edit Bar"
},
"alcohol-level": {
"title": "Alcohol Level",
Expand Down
10 changes: 5 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import { HotjarConfig } from 'aurelia-hotjar';
import { getLanguages } from 'data/languages';

export async function configure(aurelia: Aurelia): Promise<void> {
const localStorageService = aurelia.container.get(LocalStorageService);
await localStorageService.initialize();

const language = await getLanguage(localStorageService);

aurelia.use
.standardConfiguration()
.developmentLogging(PRODUCTION ? 'none' : 'debug')
Expand Down Expand Up @@ -50,6 +45,11 @@ export async function configure(aurelia: Aurelia): Promise<void> {
});
});

const localStorageService = aurelia.container.get(LocalStorageService);
await localStorageService.initialize();

const language = await getLanguage(localStorageService);

await aurelia.start();
await aurelia.setRoot(PLATFORM.moduleName('app'));
}
Expand Down
2 changes: 2 additions & 0 deletions src/modules/ingredients/all-ingredients/all-ingredients.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<template>
<require from="./../selected-ingredients-list-component"></require>
<div class="absolute h-full w-full overflow-y-scroll">
<div class="selected-ingredients-wrapper">
<selected-ingredients-list-component></selected-ingredients-list-component>
<div repeat.for="group of ingredients" style="position: relative">
<div class="ingredient-group-header bg-base-100">
<p>${group.letter.toUpperCase()}</p>
Expand Down
4 changes: 2 additions & 2 deletions src/modules/ingredients/ingredients.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<require from="./all-ingredients/all-ingredients"></require>
<require from="./search-ingredients/search-ingredients"></require>

<div class="bg-base-300">
<header class="bg-base-300">
<h4 class="px-2 mb-1 pt-2" t="routes.ingredients"></h4>
<div class="tabs overflow-x-scroll hide-scrollbar flex-nowrap">
<a
Expand All @@ -13,7 +13,7 @@ <h4 class="px-2 mb-1 pt-2" t="routes.ingredients"></h4>
<span t.bind="navigation.translation"></span>
</a>
</div>
</div>
</header>

<div class="${navbarHidden ? 'full-page-height-navbar-hidden' : 'full-page-height'}">
<div ref="sliderElement" class="swipe">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<template>
<require from="./../selected-ingredients-list-component"></require>
<div class="absolute h-full w-full overflow-y-scroll pb-20">
<div class="selected-ingredients-wrapper" data-cy="ingredient-list">
<selected-ingredients-list-component></selected-ingredients-list-component>

<div
repeat.for="ingredient of selectedIngredients"
class="au-animate animate-fade-in animate-fade-out ingredient-group-item">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { EventAggregator } from 'aurelia-event-aggregator';
import { inject } from 'aurelia-framework';
import { autoinject } from 'aurelia-framework';
import { Ingredient } from 'domain/entities/ingredient';
import { IngredientService } from 'services/ingredient-service';
import { LocalStorageService } from 'services/local-storage-service';

@inject(EventAggregator, LocalStorageService, IngredientService)
@autoinject
export class SearchIngredients {
public selectedIngredients: Ingredient[] = [];
public ingredients: Ingredient[] = [];

private _activeIngredientIds: string[] = [];

constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<div if.bind="showSelectedIngredientList" class="my-4 mx-2 flex" data-cy="selected-bar-component">
<p class="text-sm"><span t="user.selected-ingredient-list"></span><span>:</span></p>

<p click.delegate="navigateToUserPage()" class="ml-2 text-sm link link-info" data-cy="selected-bar-name">
${ingredientListName}
</p>
</div>
</template>
20 changes: 20 additions & 0 deletions src/modules/ingredients/selected-ingredients-list-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { autoinject } from 'aurelia-framework';
import { Router } from 'aurelia-router';
import { LocalStorageService } from 'services/local-storage-service';

@autoinject
export class SelectedIngredientsListComponent {
public ingredientListName: string;
public showSelectedIngredientList = false;

constructor(private _localStorageService: LocalStorageService, private _router: Router) {}

bind() {
this.ingredientListName = this._localStorageService.getIngredientList().name;
this.showSelectedIngredientList = this._localStorageService.getIngredientLists().length > 1;
}

navigateToUserPage() {
this._router.navigateToRoute('user');
}
}
40 changes: 40 additions & 0 deletions src/modules/user/ingredient-lists/ingredient-list-drawer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<ux-dialog class="au-animate cocktail-dialog" data-cy="user-ingredient-lists-drawer">
<div class="grid full-dynamic-height overflow-y-scroll">
<div class="min-h-8" click.trigger="cancel()"></div>
<div class="menu p-3 bg-base-100 text-base-content w-full relative overflow-y-scroll">
<label class="btn btn-sm btn-circle absolute right-2 top-2" click.trigger="cancel()"></label>
<h3
class="text-lg font-bold"
t="${isNew ? 'user.create-ingredient-list' : 'user.edit-ingredient-list'}"></h3>

<div class="form-control w-full" validation-errors.bind="nameErrors">
<label class="label">
<span class="label-text" t="name"></span>
</label>
<input
type="text"
value.bind="name & validate"
class="input input-bordered w-full input-sm"
class.bind="nameErrors.length ? 'input-error' : ''"
data-cy="name-input" />
<ul style="list-style-position: inside">
<li repeat.for="errorInfo of nameErrors" class="text-xs">${errorInfo.error.message}</li>
</ul>
</div>
</div>
<div class="absolute bottom-4 flex w-full justify-between px-3 items-end">
<button
if.bind="!isNew && canDelete"
click.trigger="delete()"
class="btn btn-square"
data-cy="ingredient-list-delete">
<icon-trash class="h-6 w-6"></icon-trash>
</button>
<div else></div>

<label class="btn btn-primary" click.trigger="ok()" t="save" data-cy="drawer-ok"></label>
</div>
</div>
</ux-dialog>
</template>
70 changes: 70 additions & 0 deletions src/modules/user/ingredient-lists/ingredient-list-drawer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { inject, NewInstance } from 'aurelia-framework';
import { DialogController } from 'aurelia-dialog';
import { ValidationController, ValidationRules } from 'aurelia-validation';
import { LocalStorageService } from 'services/local-storage-service';
import { IngredientList } from 'domain/entities/ingredient-list';

@inject(DialogController, NewInstance.of(ValidationController), LocalStorageService)
export class IngredientListDrawer {
public name: string;
public isNew: boolean = true;
public canDelete: boolean = false;

private ingredientList: IngredientList;

constructor(
private _dialogController: DialogController,
private _validationController: ValidationController,
private localStorageService: LocalStorageService
) {
ValidationRules.ensure('name').required().withMessage('Name is required').on(this);
}

activate(ingredientList: IngredientList) {
if (ingredientList !== null) {
this.ingredientList = ingredientList;
this.name = ingredientList.name;
this.isNew = false;
if (this.ingredientList.id !== 0) {
this.canDelete = true;
}
}
}

cancel() {
this._dialogController.cancel();
}

async ok() {
const result = await this._validationController.validate();

if (!result.valid) {
return;
}

if (this.isNew === true) {
await this.localStorageService.createIngredientList(this.name);
this._dialogController.ok();
return;
}

const ingredientListToUpdate: IngredientList = {
id: this.ingredientList.id,
name: this.name,
ingredients: this.ingredientList.ingredients
};

await this.localStorageService.updateIngredientList(ingredientListToUpdate);

this._dialogController.ok();
}

async delete() {
if (this.isNew === true) {
return;
}

await this.localStorageService.deleteIngredientList(this.ingredientList.id);
this._dialogController.ok();
}
}
25 changes: 25 additions & 0 deletions src/modules/user/ingredient-lists/ingredient-lists.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<div class="p-4 pt-0">
<div class="flex justify-end items-center mb-3">
<button
click.delegate="openDialog(null)"
class="btn btn-secondary"
t="add"
data-cy="add-ingredient-list"></button>
</div>
<div data-cy="created-ingredient-lists-container">
<div
repeat.for="item of ingredientLists"
click.delegate="openDialog(item)"
class="flex justify-between items-center p-4 border-b border-base-content border-opacity-20">
<div>
<p>${item.name}</p>
<p class="text-xs font-light">
<span>${item.ingredients.length} </span> <span t="ingredients"></span>
</p>
</div>
<icon-arrow-forward class="h-6 w-6"></icon-arrow-forward>
</div>
</div>
</div>
</template>
Loading

0 comments on commit e374345

Please sign in to comment.