diff options
Diffstat (limited to 'public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar')
4 files changed, 175 insertions, 0 deletions
diff --git a/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.html b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.html new file mode 100644 index 0000000..3da30ae --- /dev/null +++ b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.html @@ -0,0 +1,18 @@ +<div class="toolbar" toolbar> + <div class="toggle-edition"> + <input + type="checkbox" + name="edition-mode" + id="edition-mode" + class="toggle-edition__checkbox" + [checked]="isEditionEnabled" + (click)="toggleEdition()" + /> + <label for="edition-mode" class="toggle-edition__label">{{ + toggleLabel + }}</label> + </div> + <button *ngIf="shouldDisplaySave()" class="btn" (click)="saveRecipe()"> + Save + </button> +</div> diff --git a/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.scss b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.scss new file mode 100644 index 0000000..2a954af --- /dev/null +++ b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.scss @@ -0,0 +1,68 @@ +.toolbar { + display: flex; + flex-flow: row wrap; + justify-content: flex-end; + gap: 1rem; + padding: 1rem; + position: absolute; + top: 0; + right: 0; +} + +.toggle-edition { + --gap: 0.5rem; + --toggle-width: 3.5rem; + + display: flex; + align-items: center; + + &__label { + display: inline-flex; + gap: var(--gap); + position: relative; + cursor: pointer; + color: hsl(0, 0%, 30%); + font-size: 0.9rem; + font-weight: 600; + letter-spacing: 1px; + text-transform: uppercase; + + &::before { + order: 2; + content: ""; + display: block; + background: hsl(0, 0%, 80%); + border-radius: 2rem; + box-shadow: inset 0 0 2px 0 hsla(0, 0%, 0%, 0.5), + 0 0 0 2px hsla(0, 0%, 0%, 0.5); + width: var(--toggle-width); + padding: 0 0.6rem; + } + + &::after { + content: ""; + display: block; + width: calc(var(--toggle-width) / 2); + background: hsl(0, 85%, 41%); + border: 1px solid hsl(0, 0%, 31%); + border-radius: 50%; + box-shadow: 0 0 0 1px hsla(0, 0%, 36%, 0.5); + position: absolute; + right: calc((var(--toggle-width) + var(--gap)) / 2); + top: -1px; + bottom: -1px; + transition: all 0.3s ease-in-out 0s; + } + } + + &__checkbox { + opacity: 0; + + &:checked ~ { + .toggle-edition__label::after { + background: hsl(120, 76%, 31%); + right: -1px; + } + } + } +} diff --git a/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.spec.ts b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.spec.ts new file mode 100644 index 0000000..31ca834 --- /dev/null +++ b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ToolbarComponent } from './toolbar.component'; + +describe('ToolbarComponent', () => { + let component: ToolbarComponent; + let fixture: ComponentFixture<ToolbarComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ToolbarComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ToolbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.ts b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.ts new file mode 100644 index 0000000..710b967 --- /dev/null +++ b/public/projects/angular-small-apps/apps/recipes/src/app/components/toolbar/toolbar.component.ts @@ -0,0 +1,65 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Router } from '@angular/router'; +import { LocalStorageService } from 'src/app/shared/services/local-storage.service'; +import { RecipesService } from 'src/app/shared/services/recipes.service'; +import { slugify } from 'src/app/shared/utilities/slugify'; + +@Component({ + selector: 'toolbar', + templateUrl: './toolbar.component.html', + styleUrls: ['./toolbar.component.scss'], +}) +export class ToolbarComponent { + @Output() isEditionMode = new EventEmitter<boolean>(); + isEditionEnabled: boolean = false; + recipeId = history.state?.id; + savedRecipes: object[] = this.storage.get('recipes'); + toggleLabel: string = 'Edition disabled'; + + constructor( + private storage: LocalStorageService, + private recipes: RecipesService, + private router: Router + ) {} + + isSavedRecipe(): boolean { + let recipeIndex; + + if (this.recipeId) { + recipeIndex = this.savedRecipes.findIndex( + (recipe: any) => recipe.idMeal === this.recipeId + ); + } else { + const slug = this.router.url.replace('/recipe/', ''); + recipeIndex = this.savedRecipes.findIndex( + (recipe: any) => recipe.slug === slug + ); + } + + return recipeIndex === -1 ? false : true; + } + + shouldDisplaySave(): boolean { + return !this.isSavedRecipe(); + } + + saveRecipe(): void { + this.recipes.getRecipeById(this.recipeId).subscribe((recipe: any) => { + const currentRecipe = recipe.meals[0]; + const newRecipe = { + ...currentRecipe, + slug: slugify(currentRecipe.strMeal), + }; + this.savedRecipes.push(newRecipe); + this.storage.set('recipes', this.savedRecipes); + }); + } + + toggleEdition() { + this.isEditionEnabled = !this.isEditionEnabled; + this.toggleLabel = this.isEditionEnabled + ? 'Edition enabled' + : 'Edition disabled'; + this.isEditionMode.emit(this.isEditionEnabled); + } +} |
