import { inject, Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { firstValueFrom, lastValueFrom, map, Observable } from 'rxjs'; import { Recipe, RecipeInfoViews, RecipeView } from '../models/Recipe.model'; import { AuthService } from './AuthService'; import { QueryClient } from '@tanstack/angular-query-experimental'; import { RecipeComment } from '../models/RecipeComment.model'; import { QueryParams } from '../models/Query.model'; import { EndpointService } from './EndpointService'; import { SliceView } from '../models/SliceView.model'; @Injectable({ providedIn: 'root', }) export class RecipeService { private readonly http = inject(HttpClient); private readonly authService = inject(AuthService); private readonly queryClient = inject(QueryClient); private readonly endpointService = inject(EndpointService); public getRecipes(): Promise { return firstValueFrom( this.http.get(this.endpointService.getUrl('recipes')).pipe(map((res) => res.content)), ); } public getRecipeView(username: string, slug: string): Promise { return firstValueFrom(this.http.get(this.endpointService.getUrl('recipes', [username, slug]))); } private getRecipeBaseUrl(recipeView: RecipeView): string { return this.endpointService.getUrl('recipes', [recipeView.recipe.owner.username, recipeView.recipe.slug]); } public async toggleStar(recipeView: RecipeView): Promise { if (this.authService.accessToken()) { if (recipeView.isStarred) { await lastValueFrom(this.http.delete(this.getRecipeBaseUrl(recipeView) + '/star')); } else { await lastValueFrom(this.http.post(this.getRecipeBaseUrl(recipeView) + '/star', null)); } await this.queryClient.invalidateQueries({ queryKey: ['recipe', recipeView.recipe.owner.username, recipeView.recipe.slug], }); } else { throw new Error('Cannot star a recipe when not logged in.'); } } public getComments(username: string, slug: string, queryParams?: QueryParams): Promise> { return firstValueFrom( this.http.get>( this.endpointService.getUrl('recipes', [username, slug, 'comments'], queryParams), ), ); } public async addComment(username: string, slug: string, commentText: string): Promise { const comment = await firstValueFrom( this.http.post(this.endpointService.getUrl('recipes', [username, slug, 'comments']), { text: commentText, }), ); await this.queryClient.invalidateQueries({ queryKey: ['recipeComments', username, slug], }); return comment; } public async aiSearch(prompt: string): Promise { const recipeInfoViews = await firstValueFrom( this.http.post<{ results: Recipe[] }>(this.endpointService.getUrl('recipes'), { type: 'AI_PROMPT', data: { prompt, }, }), ); return recipeInfoViews.results; } public deleteRecipe(username: string, slug: string): Observable { return this.http.delete(this.endpointService.getUrl('recipes', [username, slug])); } }