Skip to content

Commit

Permalink
feat(all): add ratings (#163)
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-gustafsson authored Nov 13, 2022
1 parent 26e1300 commit a5b300c
Show file tree
Hide file tree
Showing 22 changed files with 187 additions and 40 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ android {
applicationId "com.moimob.drinkable"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 11300
versionName "1.13.0"
versionCode 11400
versionName "1.14.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
55 changes: 55 additions & 0 deletions cypress/e2e/cocktails.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,59 @@ describe('Ingredients', () => {

cy.getByDataAttribute('cocktails-wrapper').should('contain', 'Test Cocktail');
});

it('Cocktails Search - Should display only result from search', () => {
cy.visit('#/cocktails');

cy.getByDataAttribute('cocktails-search').type('Gin & Tonic');
cy.getByDataAttribute('cocktails-wrapper').children().should('have.length', '1');
});

it('Rate Cocktail - Should display rating', () => {
cy.visit('#/cocktails');

cy.getByDataAttribute('cocktail-item-rating').should('not.exist');

cy.getByDataAttribute('cocktails-wrapper').children().first().click();

cy.getByDataAttribute('rating-input-3').click();

cy.getByDataAttribute('close-dialog').click();

cy.getByDataAttribute('cocktail-item-rating')
.should('exist')
.children()
.each((el, index) => {
if (index < 3) {
expect(el).to.not.have.class('bg-opacity-20');
} else {
expect(el).to.have.class('bg-opacity-20');
}
});
});

it('Rate Custom made Cocktail - Should display rating', () => {
cy.visit('#/cocktails');

cy.getByDataAttribute('create-cocktail').click();

cy.getByDataAttribute('cocktail-name').type('Test Cocktail').blur();
cy.getByDataAttribute('cocktail-image').selectFile('static/images/balmoral.jpg', { force: true });
cy.getByDataAttribute('textarea').type('Test Instructions');
cy.getByDataAttribute('save-cocktail').click();
cy.getByDataAttribute('rating-input-4').click();

cy.getByDataAttribute('close-dialog').click();

cy.getByDataAttribute('cocktail-item-rating')
.should('exist')
.children()
.each((el, index) => {
if (index < 4) {
expect(el).to.not.have.class('bg-opacity-20');
} else {
expect(el).to.have.class('bg-opacity-20');
}
});
});
});
2 changes: 2 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/11400.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
• Added Dutch translation
• Added Ability to Rate cocktails
13 changes: 13 additions & 0 deletions src/components/cocktail-list-item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template bindable="cocktail" class="cocktail-list-item">
<img if.bind="cocktail.imageSrc !== undefined" class="small-round-image" src.bind="cocktail.imageSrc"
loading="lazy">
<img else class="small-round-image" src="/static/images/no-image.png">
<div>
<p>${cocktail.name}</p>
<div if.bind="cocktail.rating" class="rating rating-xs" data-cy="cocktail-item-rating">
<div repeat.for="i of 5" type="radio"
class="${cocktail.rating > i ? '' : 'bg-opacity-20'} mask mask-star-2 bg-warning w-3 h-3">
</div>
</div>
</div>
</template>
26 changes: 23 additions & 3 deletions src/components/dialogs/cocktail-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ <h6 data-cy="ingredients-number"> ${extendedIngredientGroup.length}</h6>
<section>
<div if.bind="!isEditMode" class="multiplier-select">
<select value.bind="multiplier" class="select select-ghost w-full select-sm">
<option repeat.for="value of multiplierValues" model.bind="value">
${value}
<option repeat.for="i of 10" model.bind="i + 1">
${i + 1}
</option>
</select>
</div>
Expand Down Expand Up @@ -181,12 +181,14 @@ <h5 if.bind="!isEditMode">${ingredientGroup.ingredient.name}</h5>
</section>

<section>
<h6 t="instructions"></h6>
<h5 class="font-bold mb-2" t="instructions"></h5>
<p if.bind="!isEditMode" class="whitespace-pre-wrap">${cocktail.instructions}</p>
<textarea if.bind="isEditMode" rows="5" class="textarea textarea-bordered p-1 w-full"
value.bind="cocktail.instructions" data-cy="textarea"></textarea>
</section>

<div class="divider"></div>

<div if.bind="isEditMode && !isNewCocktail" style="display: flex; align-items: center; margin: 0.5em;">
<p click.delegate="deleteCocktail()"
style="margin-bottom: 0; padding-right: 0.25em; text-decoration: underline;" t="delete-cocktail">
Expand All @@ -203,6 +205,24 @@ <h6 t="instructions"></h6>
</svg>
</div>

<section if.bind="!isEditMode">
<h5 class="font-bold mb-2" t="rating"></h5>
<div class="rating rating-lg justify-center w-full">
<button click.delegate="clearRating()" if.bind="selectedRating !== 0"
class="btn btn-circle btn-sm self-center mr-2 absolute left-0">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<input if.bind="selectedRating === 0" type="radio" name="rating-9" class="rating-hidden"
style="width: 0px;" checked />
<input repeat.for="i of 5" type="radio" name="rating-5" class="mask mask-star-2 bg-warning"
model.bind="i + 1" checked.bind="selectedRating" data-cy="rating-input-${i + 1}" />
</div>
</section>

<section if.bind="isUserCreatedCocktail && !isEditMode && cocktail.isSubmitted !== true">
<div class="divider"></div>
<h4 t="submit-review-title"></h4>
Expand Down
20 changes: 19 additions & 1 deletion src/components/dialogs/cocktail-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ import { SupabaseService } from 'services/supabase-service';
)
export class CocktailDialog {
@observable public searchFilter: string;
@observable public selectedRating: number = 0;

public cocktail: Cocktail;
public extendedIngredientGroup: ExtendedIngredientGroup[];
public controller: DialogController;
public multiplier = 1;
public multiplierValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
public cocktailCategories: DrinkCategory[] = getDrinkCategories();
public ingredientUnits: Unit[] = [];
public isFavorite = false;
Expand Down Expand Up @@ -101,6 +102,7 @@ export class CocktailDialog {
}

this.isUserCreatedCocktail = this.cocktail.id === undefined || this.cocktail.id?.includes('x-');
this.selectedRating = this.cocktail.rating ?? 0;

ValidationRules.ensure('name').required().on(this.cocktail);

Expand Down Expand Up @@ -159,6 +161,22 @@ export class CocktailDialog {
}
}

async selectedRatingChanged(newValue: number, oldValue: number) {
if (oldValue === undefined) {
return;
}

this.cocktail.rating = newValue;

this.isUserCreatedCocktail
? await this._cocktailService.updateCocktail(this.cocktail)
: await this._cocktailService.updateCocktailInformation(this.cocktail);
}

clearRating() {
this.selectedRating = 0;
}

checkIngredient(ingredient: ExtendedIngredientGroup) {
if (this.isEditMode) {
return;
Expand Down
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export function configure(config: FrameworkConfiguration) {
PLATFORM.moduleName('./widgets/ingredients-widget/ingredients-widget'),
PLATFORM.moduleName('./widgets/add-ingredients/add-ingredients'),
PLATFORM.moduleName('./navbar/navbar'),
PLATFORM.moduleName('./../converters/amount-format'),
PLATFORM.moduleName('./cocktail-list-item.html'),
PLATFORM.moduleName('./../converters/amount-format')
]);
}
3 changes: 2 additions & 1 deletion src/data/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ const languages = [
{ value: 'sv', name: 'Svenska' },
{ value: 'it', name: 'Italiano' },
{ value: 'es', name: 'Español' },
{ value: 'ca', name: 'Català' }
{ value: 'ca', name: 'Català' },
{ value: 'nl', name: 'Nederlands' }
];
4 changes: 4 additions & 0 deletions src/domain/entities/cocktail-information.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class CocktailInformation {
public id: string;
public rating: number;
}
1 change: 1 addition & 0 deletions src/domain/entities/cocktail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export class Cocktail {
ingredientGroups: IngredientGroup[];
instructions: string;
isSubmitted?: boolean;
rating?: number;
}

export class IngredientGroup {
Expand Down
5 changes: 3 additions & 2 deletions src/locales/ca/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Quantitat",
"unit": "Unitat",
"basic-app-translations": "Traducció Bàsica de l'App",
"ingredient-translations": "Traducció d'Ingredients"
}
"ingredient-translations": "Traducció d'Ingredients",
"rating": "Valoració"
}
3 changes: 2 additions & 1 deletion src/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Menge",
"unit": "Einheit",
"basic-app-translations": "Grundlegende App-Übersetzungen",
"ingredient-translations": "Zutaten-Übersetzungen"
"ingredient-translations": "Zutaten-Übersetzungen",
"rating": "Bewertung"
}
3 changes: 2 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Amount",
"unit": "Unit",
"basic-app-translations": "Basic App Translations",
"ingredient-translations": "Ingredient Translations"
"ingredient-translations": "Ingredient Translations",
"rating": "Rating"
}
5 changes: 3 additions & 2 deletions src/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Cantidad",
"unit": "Unidad",
"basic-app-translations": "Traducción Basica de la App",
"ingredient-translations": "Traducción de Ingredientes"
}
"ingredient-translations": "Traducción de Ingredientes",
"rating": "Clasificación"
}
3 changes: 2 additions & 1 deletion src/locales/it/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Quantità",
"unit": "Unità",
"basic-app-translations": "Traduzioni di base per app",
"ingredient-translations": "Traduzioni degli ingredienti"
"ingredient-translations": "Traduzioni degli ingredienti",
"rating": "Valutazione"
}
5 changes: 3 additions & 2 deletions src/locales/nl/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Hoeveelheid",
"unit": "Eenheid",
"basic-app-translations": "Basisappvertralingen",
"ingredient-translations": "Ingrediëntvertalingen"
}
"ingredient-translations": "Ingrediëntvertalingen",
"rating": "Beoordeling"
}
3 changes: 2 additions & 1 deletion src/locales/sv/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@
"amount": "Mängd",
"unit": "Enhet",
"basic-app-translations": "Grundläggande appöversättningar",
"ingredient-translations": "Ingrediensöversättningar"
"ingredient-translations": "Ingrediensöversättningar",
"rating": "Betyg"
}
14 changes: 6 additions & 8 deletions src/modules/cocktails/all-cocktails/all-cocktails.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<template>
<div class="absolute h-full w-full overflow-y-scroll pb-12" data-cy="cocktails-wrapper">
<div click.delegate="openCocktailDialog(cocktail)" repeat.for="cocktail of filteredCocktails"
class="cocktail-list-item">
<img if.bind="cocktail.imageSrc !== undefined" class="small-round-image" src.bind="cocktail.imageSrc"
loading="lazy">
<img else class="small-round-image" src="/static/images/no-image.png">
<p>${cocktail.name}</p>
</div>

<cocktail-list-item cocktail.bind="cocktail" click.delegate="openCocktailDialog(cocktail)"
repeat.for="cocktail of filteredCocktails">
</cocktail-list-item>
</div>

<div class="fab">
<button click.delegate="openCocktailDialog(null)" class="btn btn-primary btn-circle" data-cy="create-cocktail">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 512 512" stroke="currentColor">
Expand All @@ -23,7 +21,7 @@
<div style="display: flex;">
<input type="text" class="input input-bordered input-sm w-full max-w-xs" autocomplete="off"
ref="searchElement" type="search" placeholder="${'search' | t}" id="searchInput"
value.bind="searchFilter" />
value.bind="searchFilter" data-cy="cocktails-search" />
<div>
<label for="searchInput" aria-label="Search"></label>
</div>
Expand Down
10 changes: 3 additions & 7 deletions src/modules/cocktails/favorites/favorites.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
<div class="absolute h-full w-full overflow-y-scroll">
<div style="margin-top: 0.25em;">
<div if.bind="cocktails.length > 0">
<div click.delegate="openCocktailDialog(cocktail)" repeat.for="cocktail of cocktails"
class="cocktail-list-item">
<img if.bind="cocktail.imageSrc !== undefined" class="small-round-image"
src.bind="cocktail.imageSrc" loading="lazy">
<img else class="small-round-image" src="/static/images/no-image.png">
<p>${cocktail.name}</p>
</div>
<cocktail-list-item cocktail.bind="cocktail" click.delegate="openCocktailDialog(cocktail)"
repeat.for="cocktail of cocktails">
</cocktail-list-item>
</div>
<div else>
<p style="padding: 0.5em" t="no-favorite-cocktails-found"></p>
Expand Down
11 changes: 4 additions & 7 deletions src/modules/cocktails/from-ingredients/from-ingredients.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<template>
<div class="absolute h-full w-full overflow-y-scroll">
<div if.bind="cocktails.length > 0 || cocktailsWithMissingIngredient.length > 0">
<div click.delegate="openCocktailDialog(cocktail)" repeat.for="cocktail of cocktails"
class="cocktail-list-item">
<img if.bind="cocktail.imageSrc !== undefined" class="small-round-image" src.bind="cocktail.imageSrc"
loading="lazy">
<img else class="small-round-image" src="/static/images/no-image.png">
<p>${cocktail.name}</p>
</div>

<cocktail-list-item cocktail.bind="cocktail" click.delegate="openCocktailDialog($event, cocktail)"
repeat.for="cocktail of cocktails">
</cocktail-list-item>

<div if.bind="cocktailsWithMissingIngredient.length > 0" class="question-wrapper"
click.delegate="toggleIsOpen()">
Expand Down
20 changes: 20 additions & 0 deletions src/services/cocktail-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ import { inject } from 'aurelia-framework';
import { Cocktail, CocktailWithMissingIngredient } from 'domain/entities/cocktail';
import { getStaticCocktails, toCocktailWithMissingIngredients } from 'data/cocktail-data';
import { IngredientService } from './ingredient-service';
import { CocktailInformation } from 'domain/entities/cocktail-information';

@inject(LocalStorageService, IngredientService)
export class CocktailService {
private _cocktails: Cocktail[] = getStaticCocktails();
private _createdCocktails: Cocktail[] = [];
private _cocktailInformation: CocktailInformation[] = [];
private _highestId = 0;
constructor(private _localStorageService: LocalStorageService, private _ingredientService: IngredientService) {
this._createdCocktails = this._localStorageService.getCocktails();
this._cocktailInformation = this._localStorageService.getCocktailInformation();

this._createdCocktails.forEach(x => {
const id = Number(x.id.split('-')[1]);
Expand All @@ -20,6 +23,13 @@ export class CocktailService {

this._cocktails.push(x);
});

this._cocktailInformation.forEach(element => {
let cocktail = this._cocktails.find(x => x.id === element.id);
if (cocktail !== undefined) {
cocktail.rating = element.rating ?? 0;
}
});
}

public getCocktails() {
Expand Down Expand Up @@ -105,6 +115,16 @@ export class CocktailService {
this._cocktails.push(cocktail);
}

public async updateCocktailInformation(cocktail: Cocktail) {
this._cocktailInformation = this._cocktailInformation.filter(x => x.id !== cocktail.id);
this._cocktailInformation.push({
id: cocktail.id,
rating: cocktail.rating
});

await this._localStorageService.updateCocktailInformation(this._cocktailInformation);
}

public async deleteCocktail(id: string) {
this._createdCocktails = this._createdCocktails.filter(x => x.id !== id);
await this._localStorageService.updateCocktails(this._createdCocktails);
Expand Down
Loading

0 comments on commit a5b300c

Please sign in to comment.