import { plainToClass, Transform } from 'class-transformer' import { parseISO } from 'date-fns' import { isNil } from 'lodash' import { generateUUID, parseDate } from '../utils' import { BaseModel } from './base.model' import { Meal } from './meal.model' import { MealItem } from './meal_item.model' import { MealType } from './meal_type.model' export class MealGroup extends BaseModel { id: string time: string meal_type_id: string food_record_id?: string food_plan_id: string orientations?: string menu_id?: string @Transform(value => parseISO(value), { toClassOnly: true }) created_at: Date @Transform(value => parseISO(value), { toClassOnly: true }) delete_requested_at?: Date @Transform(value => parseDate(value), { toClassOnly: true }) updated_at: Date @Transform( meals => meals.map(value => ({ ...value, items: (value.items || []).map((item: MealItem) => plainToClass(MealItem, item)), })), { toClassOnly: true }, ) meals?: Array type?: MealType clone(): MealGroup { return plainToClass(MealGroup, { time: this.time, meal_type_id: this.meal_type_id, type: this.type, meals: (this.meals || []).map(meal => this.cloneMeal(meal)), }) } private cloneMeal(meal: Meal): Meal { const id = generateUUID() const items = meal.items.reduce((previous, item) => { if (!isNil(item.substitute_meal_item_id) || !isNil(item.ingredients_meal_item_id)) return previous return [...previous, this.cloneMealItem(meal.items, item, id)] }, []) return new Meal({ id, items }) } private cloneMealItem(mealItems: Array, item: MealItem, mealId: string, isNested = false): MealItem { const clone = item.clone() if (mealId && isNested) clone.meal_id = mealId clone.ingredients = this.filterAndCloneNestedMealItems(mealItems, item, mealId, 'ingredients_meal_item_id') clone.substitutes = this.filterAndCloneNestedMealItems(mealItems, item, mealId, 'substitute_meal_item_id') return clone } private filterAndCloneNestedMealItems( mealItems: Array, item: MealItem, mealId: string, identifierProperty: string, ): Array { return mealItems.reduce((previous, mealItem) => { if (mealItem[identifierProperty] !== item.id) return previous return [...previous, this.cloneMealItem(mealItems, mealItem, mealId, true)] }, []) } }