Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | import * as sdk from '@/api/sdk' import type { ShoppingListItemWithRefs, Product, Meal } from '@/domain/types' export type GroupByProduct = { type: 'product'; product: Product; shoppingListItems: ShoppingListItemWithRefs[] } export type GroupByName = { type: 'name'; name: string; shoppingListItems: ShoppingListItemWithRefs[] } export type Group = GroupByProduct | GroupByName export function groupsToItems(groups: Group[]): ShoppingListItemWithRefs[] { return groups.map((g) => g.shoppingListItems).flat() } export function uniqueMeals(shoppingListItems: ShoppingListItemWithRefs[]): Meal[] { const mealsWithDuplicates = shoppingListItems.map((item) => item.meal).filter((m): m is Meal => !!m) const mealsLookup: Record<string | number, Meal> = mealsWithDuplicates.reduce<Record<string | number, Meal>>( (acc, meal) => { acc[meal.id] ??= meal return acc }, {} ) return Object.values(mealsLookup) } export function itemsToGroups(shoppingListItems: ShoppingListItemWithRefs[]): Group[] { const ingredients_by_product_id: Record<string | number, GroupByProduct> = {} const ingredients_by_name: Record<string, GroupByName> = {} for (const item of shoppingListItems) { if (item.ingredient?.product) { let group = ingredients_by_product_id[item.ingredient.product.id] if (!group) { group = ingredients_by_product_id[item.ingredient.product.id] = { type: 'product', product: item.ingredient.product, shoppingListItems: [], } } group.shoppingListItems.push(item) } else { const name = item.ingredient?.name ?? '' let group = ingredients_by_name[name] if (!group) { group = ingredients_by_name[name] = { type: 'name', name, shoppingListItems: [], } } group.shoppingListItems.push(item) } } return [...Object.values(ingredients_by_product_id), ...Object.values(ingredients_by_name)] } export function useShopping() { const groupsFrom = (items?: ShoppingListItemWithRefs[]): Group[] => itemsToGroups(items ?? []) const mealsFrom = (items?: ShoppingListItemWithRefs[]): Meal[] => uniqueMeals(items ?? []) return { getCurrentShoppingList: sdk.getCurrentShoppingList, getShoppingList: sdk.getShoppingList, purchaseShoppingList: sdk.purchaseShoppingList, requestMeal: sdk.requestMeal, unrequestMeal: sdk.unrequestMeal, getMyShoppingList: sdk.getMyShoppingList, saveMyShoppingList: sdk.saveMyShoppingList, // View-model helpers groupsFrom, mealsFrom, async purchaseFromGroups(groups: Group[]) { const items = groupsToItems(groups).map((i): sdk.PurchaseRequest => { if (typeof i.id === 'number' && i.id >= 0) { return { type: 'existing', id: i.id, personId: i.personId, ingredientId: i.ingredient?.id ?? null } } return { type: 'refs', personId: i.personId, ingredientId: i.ingredient?.id ?? null, recipeId: i.recipe?.id ?? null, mealId: i.meal?.id ?? null, } }) if (!items?.length) return null return sdk.purchaseShoppingList(items) }, } } |