Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { Component, OnInit } from '@angular/core';
- import { Recipe } from '../../../recipes/recipe.model';
- import {
- FormBuilder,
- FormGroup,
- ReactiveFormsModule,
- Validators,
- } from '@angular/forms';
- import { RecipeService } from '../../../services/recipe.service';
- import { CarouselComponent } from '../../../shared/carousel/carousel.component';
- import { HttpParams } from '@angular/common/http';
- import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
- import { faTurnUp } from '@fortawesome/free-solid-svg-icons';
- @Component({
- selector: 'app-profile-home',
- standalone: true,
- imports: [ReactiveFormsModule, CarouselComponent, FontAwesomeModule],
- templateUrl: './profile-search.component.html',
- styleUrl: './profile-search.component.scss',
- })
- export class ProfileHomeComponent implements OnInit {
- searchForm: FormGroup;
- recipes: Recipe[] | null = [];
- ingredients: string[] = [];
- pagination: number = 0;
- declare faArrowUp;
- constructor(
- private formBuilder: FormBuilder,
- private recipeService: RecipeService
- ) {
- this.faArrowUp = faTurnUp;
- this.searchForm = this.formBuilder.group({
- searchQuery: ['', Validators.required],
- });
- }
- ngOnInit(): void {}
- onSubmit(): void {
- if (this.searchForm.valid) {
- const searchQuery = this.searchForm.value.searchQuery;
- this.ingredients = searchQuery
- .split(',')
- .map((ingredient: string) => ingredient.trim());
- let params = new HttpParams();
- this.ingredients.forEach((ingredient: string) => {
- params = params.append('ingredients', ingredient);
- });
- this.recipeService.searchRecipesByIngredients(params).subscribe({
- next: (recipeData) => {
- this.recipes = recipeData.recipes;
- this.pagination = recipeData.count;
- },
- error: (error) => {
- console.error('Error searching recipes:', error);
- },
- });
- }
- }
- }
- <section class="search">
- <h2 class="search__heading subheading">Turn ingredients into inspiration</h2>
- <form class="search__form" [formGroup]="searchForm" (ngSubmit)="onSubmit()">
- <div class="search__form--controls">
- <input type="text" placeholder="placeholder" id="search" class="search__form--controls-input"
- formControlName="searchQuery" />
- <label for="search" class="search__form--controls-label">Search</label>
- </div>
- <button type="submit" class="search__form--btn btn btn--full">Search</button>
- </form>
- @if(recipes?.length) {
- <app-carousel class="app-carousel" [carouselType]="'search'" [ingredients]="ingredients" />
- } @else {
- <p class="search__no-content">Try searching for ingredients<span
- class="animate__animated animate__heartBeat animate__infinite"><fa-icon [icon]="faArrowUp"
- class="search__no-content--icon" /></span></p>
- }
- </section>
- import {
- Component,
- OnInit,
- Input,
- OnChanges,
- SimpleChanges,
- } from '@angular/core';
- import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
- import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons';
- import { Recipe, RecipeData } from '../../recipes/recipe.model';
- import { RecipeService } from '../../services/recipe.service';
- import { RecipeCardComponent } from '../../recipes/recipe-card/recipe-card.component';
- import { Store, select } from '@ngrx/store';
- import { getUserData } from '../../store/auth/auth.selectors';
- import { User } from '../../store/auth/user.model';
- import { ActivatedRoute, Router, RouterModule } from '@angular/router';
- import { HttpParams } from '@angular/common/http';
- import { CommonModule } from '@angular/common';
- import { Observable, Subject, switchMap, takeUntil } from 'rxjs';
- import { ProfileHomeComponent } from '../../user/profile/profile-search/profile-search.component';
- @Component({
- selector: 'app-carousel',
- standalone: true,
- imports: [RecipeCardComponent, FontAwesomeModule, CommonModule, RouterModule],
- templateUrl: './carousel.component.html',
- styleUrl: './carousel.component.scss',
- })
- export class CarouselComponent implements OnInit, OnChanges {
- @Input() carouselType: 'all' | 'user' | 'search' = 'all';
- @Input() title: string = '';
- @Input() ingredients: string[] = [];
- declare user: User | null;
- declare faArrowLeft;
- declare faArrowRight;
- recipes: Recipe[] = [];
- pagination: number[] = [];
- currentOffset = 0;
- currentPage = 0;
- recipesCount = 0;
- limit = 4;
- private unsubscribe$ = new Subject<void>();
- constructor(
- private recipeService: RecipeService,
- private store: Store,
- private route: ActivatedRoute
- ) {
- this.faArrowLeft = faAngleLeft;
- this.faArrowRight = faAngleRight;
- }
- ngOnChanges(changes: SimpleChanges) {
- if (changes['ingredients'] && !changes['ingredients'].firstChange) {
- // Only trigger if ingredients change and it's not the initial change
- this.fetchRecipes(0);
- }
- }
- ngOnInit(): void {
- this.route.queryParams
- .pipe(
- switchMap((params) => {
- const offset = parseInt(params['offset'] || '0');
- this.currentPage =
- this.currentPage >= Math.ceil(this.pagination.length / this.limit)
- ? Math.ceil(offset / this.limit + 1)
- : this.currentPage;
- this.currentOffset = offset <= 0 ? 0 : offset - this.limit;
- return this.fetchRecipes(offset);
- }),
- takeUntil(this.unsubscribe$)
- )
- .subscribe({
- next: (recipeData: RecipeData) => {
- this.recipes = recipeData.recipes;
- this.recipesCount = recipeData.count;
- this.pagination = new Array(Math.ceil(this.recipesCount / this.limit))
- .fill(0)
- .map((_, i) => i + 1);
- },
- error: () => {
- this.recipes = [];
- this.recipesCount = 0;
- },
- });
- this.store
- .pipe(select(getUserData), takeUntil(this.unsubscribe$))
- .subscribe((user: any) => {
- this.user = user?.user;
- });
- }
- ngOnDestroy(): void {
- this.unsubscribe$.next();
- this.unsubscribe$.complete();
- }
- private fetchRecipes(offset: number): Observable<RecipeData> {
- let queryParams = new HttpParams()
- .set('offset', offset.toString())
- .set('limit', this.limit.toString());
- if (this.carouselType === 'search' && this.ingredients.length > 0) {
- queryParams = queryParams.set('ingredients', this.ingredients.join(','));
- }
- const method = this.getMethod();
- return this.recipeService[method](queryParams);
- }
- private getMethod():
- | 'getRecipes'
- | 'getUserRecipes'
- | 'searchRecipesByIngredients' {
- switch (this.carouselType) {
- case 'user':
- return 'getUserRecipes';
- case 'search':
- return 'searchRecipesByIngredients';
- default:
- return 'getRecipes';
- }
- }
- }
- <section class="carousel" [ngClass]="{'search': carouselType === 'search'}">
- @if (recipes.length) {
- @if (carouselType !== 'search') {
- <h2 class="carousel__heading">{{title}}</h2>
- }
- @for (recipe of recipes; track recipe.id) {
- <app-recipe-card [recipe]="recipe" />
- }
- } @else {
- <div class="carousel__no-content">
- <p class="no-recipes">No recipes found</p>
- @if(user) {
- <a routerLink="/recipes/create" class="btn btn--accent">Create one</a>.
- }
- </div>
- }
- @if (recipes.length) {
- <div class="carousel__pagination">
- <a [routerLink]="['.']" [queryParams]="{ offset: currentOffset, limit: limit }"
- [class.disabled]="currentPage <= 1" class="carousel__pagination--up">
- <fa-icon [icon]="faArrowLeft"></fa-icon>
- </a>
- <div class="carousel__pagination--pages">
- @for (page of pagination; track $index) {
- <a [routerLink]="['.']" [queryParams]="{ offset: $index * limit, limit: limit }"
- [class.active-page]="currentPage === $index + 1" class="carousel__pagination--pages-page active-page">{{
- $index + 1 }}</a>
- }
- </div>
- <a [routerLink]="['.']"
- [queryParams]="{offset: currentPage === pagination.length ? 0 : currentPage * limit, limit: limit}"
- [class.disabled]="currentPage === pagination.length" class="carousel__pagination--down">
- <fa-icon [icon]="faArrowRight"></fa-icon>
- </a>
- </div>
- }
- </section>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement