mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-23 15:19:41 +02:00
feat: Recipe Finder (aka Cocktail Builder) (#4542)
This commit is contained in:
parent
d26e29d1c5
commit
4e0cf985bc
28 changed files with 1959 additions and 151 deletions
|
@ -1,6 +1,6 @@
|
|||
import { BaseCRUDAPIReadOnly } from "~/lib/api/base/base-clients";
|
||||
import { route } from "../../base";
|
||||
import { Recipe } from "~/lib/api/types/recipe";
|
||||
import { Recipe, RecipeSuggestionQuery, RecipeSuggestionResponse } from "~/lib/api/types/recipe";
|
||||
import { ApiRequestInstance, PaginationData } from "~/lib/api/types/non-generated";
|
||||
import { RecipeSearchQuery } from "../../user/recipes/recipe";
|
||||
|
||||
|
@ -23,4 +23,10 @@ export class PublicRecipeApi extends BaseCRUDAPIReadOnly<Recipe> {
|
|||
async search(rsq: RecipeSearchQuery) {
|
||||
return await this.requests.get<PaginationData<Recipe>>(route(routes.recipesGroupSlug(this.groupSlug), rsq));
|
||||
}
|
||||
|
||||
async getSuggestions(q: RecipeSuggestionQuery, foods: string[] | null = null, tools: string[]| null = null) {
|
||||
return await this.requests.get<RecipeSuggestionResponse>(
|
||||
route(`${this.baseRoute}/suggestions`, { ...q, foods, tools })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
export type ExportTypes = "json";
|
||||
export type RegisteredParser = "nlp" | "brute" | "openai";
|
||||
export type OrderByNullPosition = "first" | "last";
|
||||
export type OrderDirection = "asc" | "desc";
|
||||
export type TimelineEventType = "system" | "info" | "comment";
|
||||
export type TimelineEventImage = "has image" | "does not have image";
|
||||
|
||||
|
@ -380,6 +382,26 @@ export interface RecipeShareTokenSummary {
|
|||
export interface RecipeSlug {
|
||||
slug: string;
|
||||
}
|
||||
export interface RecipeSuggestionQuery {
|
||||
orderBy?: string | null;
|
||||
orderByNullPosition?: OrderByNullPosition | null;
|
||||
orderDirection?: OrderDirection;
|
||||
queryFilter?: string | null;
|
||||
paginationSeed?: string | null;
|
||||
limit?: number;
|
||||
maxMissingFoods?: number;
|
||||
maxMissingTools?: number;
|
||||
includeFoodsOnHand?: boolean;
|
||||
includeToolsOnHand?: boolean;
|
||||
}
|
||||
export interface RecipeSuggestionResponse {
|
||||
items: RecipeSuggestionResponseItem[];
|
||||
}
|
||||
export interface RecipeSuggestionResponseItem {
|
||||
recipe: RecipeSummary;
|
||||
missingFoods: IngredientFood[];
|
||||
missingTools: RecipeTool[];
|
||||
}
|
||||
export interface RecipeTagResponse {
|
||||
name: string;
|
||||
id: string;
|
||||
|
@ -519,3 +541,10 @@ export interface UnitFoodBase {
|
|||
export interface UpdateImageResponse {
|
||||
image: string;
|
||||
}
|
||||
export interface RequestQuery {
|
||||
orderBy?: string | null;
|
||||
orderByNullPosition?: OrderByNullPosition | null;
|
||||
orderDirection?: OrderDirection;
|
||||
queryFilter?: string | null;
|
||||
paginationSeed?: string | null;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,13 @@ export interface FileTokenResponse {
|
|||
fileToken: string;
|
||||
}
|
||||
export interface PaginationQuery {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
orderBy?: string | null;
|
||||
orderByNullPosition?: OrderByNullPosition | null;
|
||||
orderDirection?: OrderDirection;
|
||||
queryFilter?: string | null;
|
||||
paginationSeed?: string | null;
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
}
|
||||
export interface QueryFilterJSON {
|
||||
parts?: QueryFilterJSONPart[];
|
||||
|
@ -47,6 +47,13 @@ export interface RecipeSearchQuery {
|
|||
requireAllFoods?: boolean;
|
||||
search?: string | null;
|
||||
}
|
||||
export interface RequestQuery {
|
||||
orderBy?: string | null;
|
||||
orderByNullPosition?: OrderByNullPosition | null;
|
||||
orderDirection?: OrderDirection;
|
||||
queryFilter?: string | null;
|
||||
paginationSeed?: string | null;
|
||||
}
|
||||
export interface SuccessResponse {
|
||||
message: string;
|
||||
error?: boolean;
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
UpdateImageResponse,
|
||||
RecipeZipTokenResponse,
|
||||
RecipeLastMade,
|
||||
RecipeSuggestionQuery,
|
||||
RecipeSuggestionResponse,
|
||||
RecipeTimelineEventIn,
|
||||
RecipeTimelineEventOut,
|
||||
RecipeTimelineEventUpdate,
|
||||
|
@ -31,6 +33,7 @@ const prefix = "/api";
|
|||
const routes = {
|
||||
recipesCreate: `${prefix}/recipes/create`,
|
||||
recipesBase: `${prefix}/recipes`,
|
||||
recipesSuggestions: `${prefix}/recipes/suggestions`,
|
||||
recipesTestScrapeUrl: `${prefix}/recipes/test-scrape-url`,
|
||||
recipesCreateUrl: `${prefix}/recipes/create/url`,
|
||||
recipesCreateUrlBulk: `${prefix}/recipes/create/url/bulk`,
|
||||
|
@ -109,6 +112,12 @@ export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
|
|||
});
|
||||
}
|
||||
|
||||
async getSuggestions(q: RecipeSuggestionQuery, foods: string[] | null = null, tools: string[]| null = null) {
|
||||
return await this.requests.get<RecipeSuggestionResponse>(
|
||||
route(routes.recipesSuggestions, { ...q, foods, tools })
|
||||
);
|
||||
}
|
||||
|
||||
async createAsset(recipeSlug: string, payload: CreateAsset) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", payload.file);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue