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