<?php
namespace App\Controller\Api;
use App\Controller\Response;
use App\Data\Recipes\Recipes;
use App\Data\SearchMenus;
use App\Entity\CardiometabolicProfiles;
use App\Entity\FavouriteMenus;
use App\Entity\FavouriteMenusSessions;
use App\Entity\Language;
use App\Entity\MenuRecipes;
use App\Entity\Menus;
use App\Entity\RecipeIngredients;
use App\Entity\Users;
use App\Helper\ConvertUnitMeasures;
use App\Services\Gamification\DailyMenuReward;
use App\Services\Gamification\Gamification;
use App\Services\Notifications\FcmNotifications;
use App\Services\ShoppingList\QuantitiesCalculator;
use App\Services\ShoppingList\IngredientsBag;
use App\Services\ShoppingList\Response\CategoryGroup;
use App\Services\ShoppingList\ShoppingList;
use DateInterval;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/api/menus", name="api_menus_")
*/
class MenusController extends AbstractController
{
use Response;
use \App\Controller\Request;
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* @Route("/search", name="search", methods={"POST"})
*/
public function searchAction(Request $request, EntityManagerInterface $em, Recipes $recipes)
{
try {
$user = $this->getUser();
# get Request json
$content = $request->getContent();
# parse JSON to Array
$data = json_decode($content, true);
$lang = $this->getLangFromData($data);
$profile = $em->getRepository(CardiometabolicProfiles::class)->getLastByUser($user->getId());
$menuRecipesRepository = $em->getRepository(MenuRecipes::class);
$searchService = new SearchMenus($data, $profile, $em, $lang);
$data = $recipes->getMenusRecipes($searchService->getData(), $menuRecipesRepository, $lang);
return $this->jsonResponse(['data' => $data, 'categoryPath' => $request->getUriForPath('/assets/images/category/')]);
} catch (\Exception $e) {
return $this->errorJsonResponse(['message' => $e->getMessage()]);
}
}
/**
* @Route("/{id}", name="view", methods={"GET"})
*/
public function viewMenuAction(
$id,
Recipes $recipes,
TranslatorInterface $translator,
EntityManagerInterface $em
)
{
try {
$user = $this->getUser(); // TOKEN
$menu = $em->getRepository(Menus::class)->findById($id, $user->getLang());
if (!$menu) {
throw new \Exception($translator->trans('Menu not found', [], 'messages', $user->getLang()));
}
$menuRecipesRepository = $em->getRepository(MenuRecipes::class);
$profile = $em->getRepository(CardiometabolicProfiles::class)->getLastByUser($user->getId());
if ($profile) {
$profile->addFavouriteMenus(1);
$em->flush();
}
return $this->jsonResponse(['data' => $recipes->getMenuRecipes($menu, $menuRecipesRepository, $user->getLang()), 'profile' => $profile?->getId() ?? null]);
} catch (\Exception $e) {
return $this->errorJsonResponse(['message' => $e->getMessage()]);
}
}
/**
* @Route("/shopping_list/{userid}", name="shopping_list", methods={"POST"})
*/
public function shoppingListAction(
$userid,
Request $request,
EntityManagerInterface $em,
FcmNotifications $fcmNotification
)
{
try {
$user = $this->getUser(); // TOKEN
$unitMeasure = $user->getUnitMeasure();
# get Request json
$content = $request->getContent();
# parse JSON to Array
$data = \json_decode($content, true);
$lang = $em->getRepository(Language::class)->findOneBy(['language_shortname' => $user->getLang()]);
$shoppingList = [];
if (isset($data['menus']) && is_array($data['menus'])) {
$daySessions = $em->getRepository(FavouriteMenusSessions::class)->getDaySessions($user->getId(), new DateTime());
$favouriteSession = new FavouriteMenusSessions();
$favouriteSession->setUserId($user->getId());
$favouriteSession->setCreatedAt(new DateTime());
$em->persist($favouriteSession);
$em->flush();
$day = 1;
$bag = new IngredientsBag();
foreach ($data['menus'] as $menuData) {
$date = new DateTime();
$date->add(new DateInterval('P' . $day . 'D'));
$menuPcs = (isset($menuData['quantity']) && $menuData['quantity'] > 0 ? $menuData['quantity'] : 1);
# favourites
$favourite = new FavouriteMenus();
$favourite->setUserId($user->getId());
$favourite->setMenuId($menuData['menu']);
$favourite->setSessionId($favouriteSession->getId());
$favourite->setPlannedNotification($date);
$favourite->setAddedAt($date);
$em->persist($favourite);
$menu = $em->getRepository(Menus::class)->findOneBy([
'id' => $menuData['menu'],
'active' => 1,
'removed' => 0,
]);
if ($menu) {
$menuRecipes = $em->getRepository(MenuRecipes::class)->findByMenu($menu->getId());
if ($menuRecipes) {
foreach ($menuRecipes as $recipe) {
$recipeIngredients = $em->getRepository(RecipeIngredients::class)->findByRecipe($recipe['id'], $lang->getLanguageShortname());
if (count($recipeIngredients)) {
foreach ($recipeIngredients as &$ingredient) {
if($unitMeasure == 2){
if($ingredient['abbreviation'] === 'g'){
$ingredient['converted_unit_measure'] = ConvertUnitMeasures::convertGrams($ingredient['quantity'], $lang->getLanguageShortname());
} else if($ingredient['abbreviation'] === 'ml'){
$ingredient['converted_unit_measure'] = ConvertUnitMeasures::convertMl($ingredient['quantity'], $lang->getLanguageShortname());
} else {
$ingredient['converted_unit_measure'] = $ingredient['quantity'] . ' ' . $ingredient['abbreviation'];
}
} else {
$ingredient['converted_unit_measure'] = $ingredient['quantity'] . ' ' . $ingredient['abbreviation'];
}
$bag->addIngredientToBag($ingredient, $menuPcs);
}
}
}
}
}
$day++;
}
$em->flush();
$shoppingList = new ShoppingList($bag, new QuantitiesCalculator, $unitMeasure, $lang->getLanguageShortname());
if (count($daySessions) === 0 && $user->hasValidSubscription()) {
$reward = new DailyMenuReward($lang, $em);
(new Gamification($user, $em, $this->logger, $this->getParameter('fcm_api_key')))
->saveReward($reward)
->sendNotification($fcmNotification, $reward->getNotification());
}
}
return $this->jsonResponse([
'data' => $shoppingList->getList(),
'path' => $request->getUriForPath('/assets/images/ingredient_categories/'),
]);
} catch (\Exception $e) {
return $this->errorJsonResponse(['message' => $e->getMessage()]);
}
}
/**
* @Route("/shopping_list/{userid}/categories", name="shopping_list_categories", methods={"POST"})
*/
public function shoppingListCategoriesAction(
$userid,
Request $request,
EntityManagerInterface $em,
TranslatorInterface $translator,
FcmNotifications $fcmNotification
)
{
try {
$user = $this->getUser(); // TOKEN
$unitMeasure = $user->getUnitMeasure();
# get Request json
$content = $request->getContent();
# parse JSON to Array
$data = \json_decode($content, true);
$lang = $em->getRepository(Language::class)->findOneBy(['language_shortname' => $user->getLang()]);
$shoppingList = [];
if (isset($data['menus']) && is_array($data['menus'])) {
$daySessions = $em->getRepository(FavouriteMenusSessions::class)->getDaySessions($user->getId(), new DateTime());
$favouriteSession = new FavouriteMenusSessions();
$favouriteSession->setUserId($user->getId());
$favouriteSession->setCreatedAt(new DateTime());
$em->persist($favouriteSession);
$em->flush();
$day = 1;
$bag = new IngredientsBag();
foreach ($data['menus'] as $menuData) {
$date = new DateTime();
$date->add(new DateInterval('P' . $day . 'D'));
$menuPcs = (isset($menuData['quantity']) && $menuData['quantity'] > 0 ? $menuData['quantity'] : 1);
# favourites
$favourite = new FavouriteMenus();
$favourite->setUserId($user->getId());
$favourite->setMenuId($menuData['menu']);
$favourite->setSessionId($favouriteSession->getId());
$favourite->setPlannedNotification($date);
$favourite->setAddedAt(new DateTime());
$em->persist($favourite);
$menu = $em->getRepository(Menus::class)->findOneBy([
'id' => $menuData['menu'],
'active' => 1,
'removed' => 0,
]);
if ($menu) {
$menuRecipes = $em->getRepository(MenuRecipes::class)->findByMenu($menu->getId());
if ($menuRecipes) {
foreach ($menuRecipes as $recipe) {
$recipeIngredients = $em->getRepository(RecipeIngredients::class)->findByRecipe($recipe['id'], $lang->getLanguageShortname());
if (count($recipeIngredients)) {
foreach ($recipeIngredients as $ingredient) {
$bag->addIngredientToBag($ingredient, $menuPcs);
}
}
}
}
}
$day++;
}
$em->flush();
$shoppingList = new ShoppingList($bag, new QuantitiesCalculator, $unitMeasure, $lang->getLanguageShortname());
if (count($daySessions) === 0 && $user->hasValidSubscription()) {
$reward = new DailyMenuReward($lang, $em);
(new Gamification($user, $em, $this->logger, $this->getParameter('fcm_api_key')))
->saveReward($reward)
->sendNotification($fcmNotification, $reward->getNotification());
}
}
return $this->jsonResponse([
'data' => $shoppingList->getList(new CategoryGroup()),
'path' => $request->getUriForPath('/assets/images/ingredient_categories/'),
]);
} catch (\Exception $e) {
return $this->errorJsonResponse(['message' => $e->getMessage()]);
}
}
/**
* @Route("/{id}/healthy_minutes", name="count_healthy_minutes", methods={"POST"})
*/
public function countMenuHealthyMinutes(
$id,
TranslatorInterface $translator,
EntityManagerInterface $em
)
{
try {
$user = $this->getUser(); // TOKEN
$menu = $em->getRepository(Menus::class)->findById($id, $user->getLang());
if (!$menu) {
throw new \Exception($translator->trans('Menu not found', [], 'messages', $user->getLang()));
}
$user->addHealthyMinutes($menu['healthy_minutes']);
$em->flush();
return $this->jsonResponse(['status' => 'ok']);
} catch (\Exception $e) {
return $this->errorJsonResponse(['message' => $e->getMessage()]);
}
}
}