add favorite list handlings on app side and LocalEnpoint. Add 'RecipeDatabase' class to simulate a Recipe database
continuous-integration/drone/push Build is passing Details

pull/50/head
maxime.BATISTA@etu.uca.fr 2 years ago
parent ebeed7a28c
commit 4638b3efd6

@ -0,0 +1,23 @@
using Models;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LocalEndpoint
{
public interface IAccountOwnedRecipes
{
public Account Account { get; }
public bool UploadRecipe(Recipe recipe);
public bool RemoveRecipe(RecipeInfo info);
public ImmutableList<RecipeInfo> GetAccountRecipes();
}
}

@ -6,27 +6,24 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LocalEndpoint namespace Endpoint
{ {
public interface IAccountRecipes public interface IAccountRecipesPreferences
{ {
public Account Account { get; } public Account Account { get; }
public bool UploadRecipe(Recipe recipe);
public bool RemoveRecipe(RecipeInfo info);
public void SetRate(RecipeInfo info, AccountRecipeRate rate); public void AddToFavorites(RecipeInfo info);
public void RemoveFromFavorites(RecipeInfo info);
public void SetReviewScore(RecipeInfo info, uint score);
public AccountRecipeRate? FindRate(RecipeInfo info); public AccountRecipeRate GetRate(RecipeInfo info);
public ImmutableList<RecipeInfo> GetAccountRecipes(); public ImmutableList<RecipeInfo> GetFavorites();
public ImmutableList<RecipeInfo> GetRecommendedRecipes(); public ImmutableList<RecipeInfo> GetRecommendedRecipes();
public ImmutableList<RecipeInfo> GetFavorites();
public ImmutableList<(RecipeInfo, uint)> GetWeeklyList(); public ImmutableList<(RecipeInfo, uint)> GetWeeklyList();
} }
} }

@ -2,6 +2,7 @@
using Models; using Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,11 +11,12 @@ namespace Endpoint
{ {
public interface IRecipesService public interface IRecipesService
{ {
public List<RecipeInfo> PopularRecipes(); public ImmutableList<RecipeInfo> PopularRecipes();
public Recipe GetRecipe(RecipeInfo info); public Recipe GetRecipe(RecipeInfo info);
public IAccountRecipes GetRecipesOf(Account account); public IAccountOwnedRecipes GetRecipesOf(Account account);
public IAccountRecipesPreferences GetPreferencesOf(Account account);
} }

@ -0,0 +1,11 @@
using Endpoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LocalEndpoint
{
internal record AccountData(IAccountOwnedRecipes Recipes, IAccountRecipesPreferences Preferences);
}

@ -1,38 +0,0 @@
using Models;
using Endpoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LocalEndpoint
{
internal class AccountManager : IAccountManager
{
private static readonly Uri DEFAULT_ACCOUNT_IMAGE = new Uri("https://www.pngkey.com/png/full/115-1150152_default-profile-picture-avatar-png-green.png");
private Account userAccount = new Account(new User(DEFAULT_ACCOUNT_IMAGE, "Stub Account"), "test@example.com");
private string userPassword = "123456";
public Account? Login(string email, string password)
{
if (userAccount.Email == email && userPassword == password)
{
return userAccount;
}
return null;
}
public Account? Register(string email, string username, string password)
{
if (email == null || username == null || password == null)
return null;
userAccount = new Account(new User(DEFAULT_ACCOUNT_IMAGE, username), email);
userPassword = password;
return userAccount;
}
}
}

@ -0,0 +1,52 @@
using LocalEndpoint;
using Models;
using System.Collections.Immutable;
namespace Endpoint
{
internal class AccountOwnedRecipes : IAccountOwnedRecipes
{
public Account Account { get; init; }
private readonly Dictionary<Guid, Recipe> ownedRecipes = new Dictionary<Guid, Recipe>();
private readonly RecipesDatabase db;
public AccountOwnedRecipes(Account account, RecipesDatabase db)
{
Account = account;
this.db = db;
//Retrieve all owned recipes from database.
db.ListAll().ForEach(recipe =>
{
if (recipe.Owner == account.User) ownedRecipes[recipe.Info.Id] = recipe;
});
}
public bool UploadRecipe(Recipe recipe)
{
Guid id = recipe.Info.Id;
if (ownedRecipes.ContainsKey(id))
{
return false;
}
db.Insert(recipe);
ownedRecipes.Add(id, recipe);
return true;
}
public bool RemoveRecipe(RecipeInfo info)
{
db.Remove(info.Id);
return ownedRecipes.Remove(info.Id);
}
public ImmutableList<RecipeInfo> GetAccountRecipes()
{
return ownedRecipes.Values.ToImmutableList().ConvertAll(r => r.Info);
}
}
}

@ -1,84 +0,0 @@
using LocalEndpoint;
using Models;
using System.Collections.Immutable;
namespace Endpoint
{
internal class AccountRecipes : IAccountRecipes
{
public Account Account { get; init; }
private readonly Dictionary<Guid, Recipe> ownedRecipes = new Dictionary<Guid, Recipe>();
private readonly Dictionary<Guid, AccountRecipeRate> ratedRecipes = new Dictionary<Guid, AccountRecipeRate>();
public AccountRecipes(Account account)
{
Account = account;
}
public bool UploadRecipe(Recipe recipe)
{
Guid id = recipe.Info.Id;
if (ownedRecipes.ContainsKey(id))
{
return false;
}
ownedRecipes.Add(id, recipe);
return true;
}
public bool RemoveRecipe(RecipeInfo info)
{
return ownedRecipes.Remove(info.Id);
}
public ImmutableList<RecipeInfo> GetAccountRecipes()
{
return ownedRecipes.Values.ToImmutableList().ConvertAll(r => r.Info);
}
public ImmutableList<RecipeInfo> GetRecommendedRecipes()
{
return new List<RecipeInfo> {
new RecipeInfo("Chicken Salad", 500, 20, new Uri("https://healthyfitnessmeals.com/wp-content/uploads/2021/04/Southwest-chicken-salad-7-500x500.jpg"), 4, Guid.NewGuid()),
new RecipeInfo("Chocolate Cake", 2500, 10, new Uri("https://bakewithshivesh.com/wp-content/uploads/2022/08/IMG_0248-scaled.jpg"), 3, Guid.NewGuid()),
new RecipeInfo("Salmon", 20, 10, new Uri("https://www.wholesomeyum.com/wp-content/uploads/2021/06/wholesomeyum-Pan-Seared-Salmon-Recipe-13.jpg"), 4, Guid.NewGuid()),
new RecipeInfo("Fish", 50, 30, new Uri("https://www.ciaanet.org/wp-content/uploads/2022/07/Atlantic-and-Pacific-whole-salmon-1024x683.jpg"), 4.5F, Guid.NewGuid()),
new RecipeInfo("Space Cake", 800, 5, new Uri("https://static.youmiam.com/images/recipe/1500x1000/space-cake-22706?placeholder=web_recipe&sig=f14a7a86da837c6b8cc678cde424d6d5902f99ec&v3"), 5, Guid.NewGuid())
}.ToImmutableList();
}
public ImmutableList<RecipeInfo> GetFavorites()
{
return new List<RecipeInfo> {
new RecipeInfo("Chicken Salad", 500, 20, new Uri("https://healthyfitnessmeals.com/wp-content/uploads/2021/04/Southwest-chicken-salad-7-500x500.jpg"), 4, Guid.NewGuid()),
new RecipeInfo("Space Cake", 800, 5, new Uri("https://static.youmiam.com/images/recipe/1500x1000/space-cake-22706?placeholder=web_recipe&sig=f14a7a86da837c6b8cc678cde424d6d5902f99ec&v3"), 5, Guid.NewGuid()),
new RecipeInfo("Fish And Ships", 450, 15, new Uri("https://upload.wikimedia.org/wikipedia/commons/f/ff/Fish_and_chips_blackpool.jpg"), 4, Guid.NewGuid()),
new RecipeInfo("Caesar Salad", 150, 20, new Uri("https://www.galbani.fr/wp-content/uploads/2020/04/AdobeStock_157570276-2.jpeg"), 1, Guid.NewGuid())
}.ToImmutableList();
}
public ImmutableList<(RecipeInfo, uint)> GetWeeklyList()
{
return new List<(RecipeInfo, uint)> {
(new RecipeInfo("Space Cake", 800, 5, new Uri("https://static.youmiam.com/images/recipe/1500x1000/space-cake-22706?placeholder=web_recipe&sig=f14a7a86da837c6b8cc678cde424d6d5902f99ec&v3"), 5, Guid.NewGuid()), 4),
(new RecipeInfo("Chicken Curry", 500, 45, new Uri("https://cdn.chefclub.tools/uploads/recipes/cover-thumbnail/f287b191-dc8e-4c85-bbb6-e26387c354d3.jpg"), 3, Guid.NewGuid()), 4),
(new RecipeInfo("Spaghetti Bolognese", 1000, 30, new Uri("https://media.istockphoto.com/id/1144823591/fr/photo/spaghetti-dans-un-plat-sur-un-fond-blanc.jpg?s=612x612&w=0&k=20&c=qFzd8iE185mpsX7hWqYaieOWlzJVCkzFdYsxmwUT3-Q="), 1, Guid.NewGuid()), 1),
}.ToImmutableList();
}
public void SetRate(RecipeInfo info, AccountRecipeRate rate)
{
ratedRecipes.Add(info.Id, rate);
}
public AccountRecipeRate? FindRate(RecipeInfo info)
{
AccountRecipeRate? rate = null;
ratedRecipes.TryGetValue(info.Id, out rate);
return rate;
}
}
}

@ -0,0 +1,91 @@
using Endpoint;
using Models;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LocalEndpoint
{
internal class AccountRecipesPreferences : IAccountRecipesPreferences
{
//Binds a recipe's id to it's account review ratings.
private readonly Dictionary<Guid, AccountRecipeRate> ratings = new Dictionary<Guid, AccountRecipeRate>();
//Binds a recipe's id to its amount of person stored in the account's weekly list
private readonly Dictionary<Guid, uint> weekly = new Dictionary<Guid, uint>();
private readonly RecipesDatabase db;
public AccountRecipesPreferences(Account account, RecipesDatabase db)
{
Account = account;
this.db = db;
}
public Account Account { get; init; }
public ImmutableList<RecipeInfo> GetRecommendedRecipes()
{
return db.ListAll().ConvertAll(recipe => recipe.Info);
}
public ImmutableList<RecipeInfo> GetFavorites()
{
List<RecipeInfo> favorites = new List<RecipeInfo>();
foreach (Recipe recipe in db.ListAll())
{
if (ratings.TryGetValue(recipe.Info.Id, out AccountRecipeRate? rate))
{
if (rate.IsFavorite)
favorites.Add(recipe.Info);
}
}
return favorites.ToImmutableList();
}
public ImmutableList<(RecipeInfo, uint)> GetWeeklyList()
{
List<(RecipeInfo, uint)> weekly = new List<(RecipeInfo, uint)>();
foreach (Recipe recipe in db.ListAll())
{
if (this.weekly.TryGetValue(recipe.Info.Id, out uint personAmmount))
{
weekly.Add((recipe.Info, personAmmount));
}
}
return weekly.ToImmutableList();
}
public AccountRecipeRate GetRate(RecipeInfo info)
{
AccountRecipeRate rate = null;
if (!ratings.TryGetValue(info.Id, out rate))
{
rate = new AccountRecipeRate();
ratings.Add(info.Id, rate);
}
return rate;
}
public void AddToFavorites(RecipeInfo info)
{
AccountRecipeRate rate = GetRate(info);
ratings[info.Id] = new AccountRecipeRate(true, rate.Rate);
}
public void RemoveFromFavorites(RecipeInfo info)
{
AccountRecipeRate rate = GetRate(info);
ratings[info.Id] = new AccountRecipeRate(false, rate.Rate);
}
public void SetReviewScore(RecipeInfo info, uint score)
{
AccountRecipeRate rate = GetRate(info);
ratings[info.Id] = new AccountRecipeRate(rate.IsFavorite, score);
}
}
}

@ -0,0 +1,33 @@
using Models;
using Endpoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LocalEndpoint
{
internal class ConnectionManager : IAccountManager
{
private Account userAccount = Constants.MAIN_USER_ACCOUNT;
private string userPassword = Constants.MAIN_USER_PASSWORD;
public Account? Login(string email, string password)
{
if (Constants.MAIN_USER_ACCOUNT.Email == email && Constants.MAIN_USER_PASSWORD == password)
return Constants.MAIN_USER_ACCOUNT;
return null;
}
public Account? Register(string email, string username, string password)
{
if (email == null || username == null || password == null)
return null;
userAccount = new Account(new User(Constants.DEFAULT_ACCOUNT_IMAGE, username), email);
userPassword = password;
return userAccount;
}
}
}

@ -0,0 +1,20 @@
using Models;
namespace LocalEndpoint
{
internal class Constants
{
public static readonly Uri DEFAULT_ACCOUNT_IMAGE = new Uri("https://www.pngkey.com/png/full/115-1150152_default-profile-picture-avatar-png-green.png");
// User account for tests
public static readonly Account MAIN_USER_ACCOUNT = new Account(new User(DEFAULT_ACCOUNT_IMAGE, "Example Account"), "test@example.com");
public static readonly string MAIN_USER_PASSWORD = "123456";
// other user samples
public static readonly User USER1 = new User(new Uri("https://i.ibb.co/L6t6bGR/DALL-E-2023-05-10-20-27-31-cook-looking-at-the-camera-with-a-chef-s-hat-laughing-in-an-exaggerated-w.png"), "The Funny Chief");
public static readonly User USER2 = new User(DEFAULT_ACCOUNT_IMAGE, "Yanis");
public static readonly User USER3 = new User(DEFAULT_ACCOUNT_IMAGE, "Leo");
}
}

@ -1,11 +1,34 @@
using Endpoint; using Endpoint;
using Models;
using System.Collections.Immutable;
namespace LocalEndpoint namespace LocalEndpoint
{ {
/// <summary>
/// The local endpoint is an implementation of the Endpoint API definition.
///
/// </summary>
public class LocalEndpoint : IEndpoint public class LocalEndpoint : IEndpoint
{ {
private IAccountManager accountManager = new AccountManager(); private readonly IAccountManager accountManager = new ConnectionManager();
private IRecipesService recipesService = new RecipesService(); private readonly IRecipesService recipesService;
public LocalEndpoint()
{
RecipesDatabase db = new RecipesDatabase();
//miam
db.Insert(new Recipe(new RecipeInfo("Chicken Salad", 500, 20, new Uri("https://healthyfitnessmeals.com/wp-content/uploads/2021/04/Southwest-chicken-salad-7-500x500.jpg"), 4, Guid.NewGuid()), Constants.USER1, new List<Ingredient> { new Ingredient("Ingredient 1", 6) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Step 1", "Bake the eggs") }.ToImmutableList()));
db.Insert(new Recipe(new RecipeInfo("Chocolate Cake", 2500, 10, new Uri("https://bakewithshivesh.com/wp-content/uploads/2022/08/IMG_0248-scaled.jpg"), 3, Guid.NewGuid()), Constants.USER2, new List<Ingredient> { new Ingredient("Ingredient 1", 6) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Step 1", "Bake the eggs") }.ToImmutableList()));
db.Insert(new Recipe(new RecipeInfo("Salmon", 20, 10, new Uri("https://www.wholesomeyum.com/wp-content/uploads/2021/06/wholesomeyum-Pan-Seared-Salmon-Recipe-13.jpg"), 4, Guid.NewGuid()), Constants.MAIN_USER_ACCOUNT.User, new List<Ingredient> { new Ingredient("Ingredient 1", 6) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Step 1", "Bake the eggs") }.ToImmutableList()));
db.Insert(new Recipe(new RecipeInfo("Fish", 50, 30, new Uri("https://www.ciaanet.org/wp-content/uploads/2022/07/Atlantic-and-Pacific-whole-salmon-1024x683.jpg"), 4.5F, Guid.NewGuid()), Constants.MAIN_USER_ACCOUNT.User, new List<Ingredient> { new Ingredient("Ingredient 1", 6) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Step 1", "Bake the eggs") }.ToImmutableList()));
db.Insert(new Recipe(new RecipeInfo("Space Cake", 800, 5, new Uri("https://static.youmiam.com/images/recipe/1500x1000/space-cake-22706?placeholder=web_recipe&sig=f14a7a86da837c6b8cc678cde424d6d5902f99ec&v3"), 5, Guid.NewGuid()), Constants.USER3, new List<Ingredient> { new Ingredient("Ingredient 1", 6) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Step 1", "Bake the eggs") }.ToImmutableList()));
recipesService = new RecipesService(db);
}
public IAccountManager AccountManager => accountManager; public IAccountManager AccountManager => accountManager;
public IRecipesService RecipesService => recipesService; public IRecipesService RecipesService => recipesService;

@ -0,0 +1,43 @@
using Models;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace LocalEndpoint
{
//Simple class to simulate a recipe database
internal class RecipesDatabase
{
private Dictionary<Guid, Recipe> recipes = new Dictionary<Guid, Recipe>();
public Recipe? Lookup(Guid id)
{
Recipe? recipe;
recipes.TryGetValue(id, out recipe);
return recipe;
}
public Recipe Get(Guid id)
{
return recipes[id];
}
public void Insert(Recipe recipe)
{
recipes[recipe.Info.Id] = recipe;
}
public void Remove(Guid id)
{
recipes.Remove(id);
}
public ImmutableList<Recipe> ListAll()
{
return recipes.Values.ToImmutableList();
}
}
}

@ -7,41 +7,49 @@ namespace LocalEndpoint
internal class RecipesService : IRecipesService internal class RecipesService : IRecipesService
{ {
private readonly Dictionary<Account, IAccountRecipes> accountsRecipes = new Dictionary<Account, IAccountRecipes>(); private readonly RecipesDatabase db;
private readonly Dictionary<Account, AccountData> accountsData = new Dictionary<Account, AccountData>();
public List<RecipeInfo> PopularRecipes() public RecipesService(RecipesDatabase db)
{ {
return new List<RecipeInfo> { this.db = db;
new RecipeInfo("Chicken Curry", 500, 45, new Uri("https://cdn.chefclub.tools/uploads/recipes/cover-thumbnail/f287b191-dc8e-4c85-bbb6-e26387c354d3.jpg"), 3, Guid.NewGuid()), }
new RecipeInfo("Spaghetti Bolognese", 1000, 30, new Uri("https://media.istockphoto.com/id/1144823591/fr/photo/spaghetti-dans-un-plat-sur-un-fond-blanc.jpg?s=612x612&w=0&k=20&c=qFzd8iE185mpsX7hWqYaieOWlzJVCkzFdYsxmwUT3-Q="), 1, Guid.NewGuid()),
new RecipeInfo("Beef Stroganoff", 100, 10, new Uri("https://www.cookwithnabeela.com/wp-content/uploads/2023/02/BeefStroganoff.webp"), 5, Guid.NewGuid()), public ImmutableList<RecipeInfo> PopularRecipes()
new RecipeInfo("Fish And Ships", 450, 15, new Uri("https://upload.wikimedia.org/wikipedia/commons/f/ff/Fish_and_chips_blackpool.jpg"), 4, Guid.NewGuid()), {
new RecipeInfo("Caesar Salad", 150, 20, new Uri("https://www.galbani.fr/wp-content/uploads/2020/04/AdobeStock_157570276-2.jpeg"), 1, Guid.NewGuid()) return db.ListAll().Take(4).ToImmutableList().ConvertAll(v => v.Info);
};
} }
public Recipe GetRecipe(RecipeInfo info) public Recipe GetRecipe(RecipeInfo info)
{ {
User owner = new User(new Uri("https://i.ibb.co/L6t6bGR/DALL-E-2023-05-10-20-27-31-cook-looking-at-the-camera-with-a-chef-s-hat-laughing-in-an-exaggerated-w.png"), "The Funny Chief"); return db.Get(info.Id);
var ingredients = new List<Ingredient> { new Ingredient("Banana", 12), new Ingredient("Apple", 2) }.ToImmutableList();
var steps = new List<PreparationStep> { new PreparationStep("Step 1", "This step is an hardcoded step from a stub implementation of IRecipesSeervice") }.ToImmutableList();
return new Recipe(info, owner, ingredients, steps);
} }
public IAccountRecipes GetRecipesOf(Account account) public IAccountOwnedRecipes GetRecipesOf(Account account)
{
return GetOrInitData(account).Recipes;
}
public IAccountRecipesPreferences GetPreferencesOf(Account account)
{ {
IAccountRecipes? recipes; return GetOrInitData(account).Preferences;
accountsRecipes.TryGetValue(account, out recipes); }
private AccountData GetOrInitData(Account account)
{
AccountData? data;
accountsData.TryGetValue(account, out data);
if (recipes == null) { if (data == null)
recipes = new AccountRecipes(account); {
AccountOwnedRecipes recipes = new AccountOwnedRecipes(account, db);
recipes.UploadRecipe(new Recipe(new RecipeInfo("Cupcake", 500, 12, new Uri("https://www.mycake.fr/wp-content/uploads/2015/12/rs_cupcake_4x3.jpg"), 4.2F, Guid.NewGuid()), account.User, new List<Ingredient> { new Ingredient("Chocolate", 4) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Eat Chocolate", "Eat the chocolate") }.ToImmutableList())); recipes.UploadRecipe(new Recipe(new RecipeInfo("Cupcake", 500, 12, new Uri("https://www.mycake.fr/wp-content/uploads/2015/12/rs_cupcake_4x3.jpg"), 4.2F, Guid.NewGuid()), account.User, new List<Ingredient> { new Ingredient("Chocolate", 4) }.ToImmutableList(), new List<PreparationStep> { new PreparationStep("Eat Chocolate", "Eat the chocolate") }.ToImmutableList()));
accountsRecipes.Add(account, recipes); AccountRecipesPreferences preferences = new AccountRecipesPreferences(account, db);
data = new AccountData(recipes, preferences);
accountsData.Add(account, data);
} }
return recipes; return data;
} }
} }
} }

@ -9,9 +9,9 @@ public partial class MainAppShell : Shell
public MainAppShell(Account account, IEndpoint endpoint, IApp app) public MainAppShell(Account account, IEndpoint endpoint, IApp app)
{ {
InitializeComponent(); InitializeComponent();
HomeTab.ContentTemplate = new DataTemplate(() => new HomePage(account, endpoint)); HomeTab.ContentTemplate = new DataTemplate(() => new HomePage(account, app.Notifier, endpoint));
FavoritesTab.ContentTemplate = new DataTemplate(() => new FavoritesPage(account, endpoint.RecipesService)); FavoritesTab.ContentTemplate = new DataTemplate(() => new FavoritesPage(account, app.Notifier, endpoint.RecipesService));
MyListTab.ContentTemplate = new DataTemplate(() => new MyListPage(account, endpoint.RecipesService)); MyListTab.ContentTemplate = new DataTemplate(() => new MyListPage(account, app.Notifier, endpoint.RecipesService));
MoreTab.ContentTemplate = new DataTemplate(() => new MorePage(account, new MorePageController(account, endpoint, app))); MoreTab.ContentTemplate = new DataTemplate(() => new MorePage(account, new MorePageController(account, endpoint, app)));
} }
} }

@ -1,5 +1,5 @@
 
namespace Models namespace Models
{ {
public record AccountRecipeRate(bool IsFavorite, uint Rate); public record AccountRecipeRate(bool IsFavorite = false, uint Rate = 0);
} }

@ -4,7 +4,8 @@
x:Class="ShoopNCook.Pages.FavoritesPage" x:Class="ShoopNCook.Pages.FavoritesPage"
Title="FavoritesPage" Title="FavoritesPage"
xmlns:views="clr-namespace:ShoopNCook.Views" xmlns:views="clr-namespace:ShoopNCook.Views"
BackgroundColor="{StaticResource BackgroundPrimary}"> BackgroundColor="{StaticResource BackgroundPrimary}"
NavigatedTo="ContentPage_NavigatedTo">
<Grid <Grid
RowDefinitions="Auto, *"> RowDefinitions="Auto, *">

@ -6,24 +6,41 @@ using Endpoint;
using LocalEndpoint; using LocalEndpoint;
using Models; using Models;
using ShoopNCook.Views; using ShoopNCook.Views;
using System.Security.Principal;
public partial class FavoritesPage : ContentPage public partial class FavoritesPage : ContentPage
{ {
public FavoritesPage(Account account, IRecipesService service)
private readonly Account account;
private readonly IUserNotifier notifier;
private IRecipesService service;
public FavoritesPage(Account account, IUserNotifier notifier, IRecipesService service)
{ {
InitializeComponent(); InitializeComponent();
this.account = account;
this.notifier = notifier;
this.service = service;
UpdateFavorites();
}
IAccountRecipes recipes = service.GetRecipesOf(account); private void UpdateFavorites()
recipes.GetFavorites().ForEach(info => {
IAccountRecipesPreferences preferences = service.GetPreferencesOf(account);
RecipeViewLayout.Children.Clear();
preferences.GetFavorites().ForEach(info =>
{ {
RecipeViewLayout.Children.Add(new RecipeView(info, () => RecipeViewLayout.Children.Add(new RecipeView(info, () =>
{ {
Recipe recipe = service.GetRecipe(info); Recipe recipe = service.GetRecipe(info);
AccountRecipeRate? rate = recipes.FindRate(info); Shell.Current.Navigation.PushAsync(new RecipePage(recipe, notifier, preferences, 1));
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, rate, 1));
})); }));
}); });
}
private void ContentPage_NavigatedTo(object sender, NavigatedToEventArgs e)
{
UpdateFavorites();
} }
} }

@ -7,12 +7,12 @@ using LocalEndpoint;
public partial class HomePage : ContentPage public partial class HomePage : ContentPage
{ {
public HomePage(Account account, IEndpoint endpoint) public HomePage(Account account, IUserNotifier notifier, IEndpoint endpoint)
{ {
InitializeComponent(); InitializeComponent();
IRecipesService service = endpoint.RecipesService; IRecipesService service = endpoint.RecipesService;
IAccountRecipes recipes = service.GetRecipesOf(account); IAccountRecipesPreferences preferences = service.GetPreferencesOf(account);
//TODO this code can be factorised //TODO this code can be factorised
@ -21,13 +21,12 @@ public partial class HomePage : ContentPage
layout.Children.Add(new RecipeView(info, () => layout.Children.Add(new RecipeView(info, () =>
{ {
Recipe recipe = service.GetRecipe(info); Recipe recipe = service.GetRecipe(info);
AccountRecipeRate rate = recipes.FindRate(info); Shell.Current.Navigation.PushAsync(new RecipePage(recipe, notifier, preferences, 1));
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, rate, 1));
})); }));
} }
service.PopularRecipes().ForEach(recipe => PushRecipe(PopularsList, recipe)); service.PopularRecipes().ForEach(recipe => PushRecipe(PopularsList, recipe));
recipes.GetRecommendedRecipes().ForEach(recipe => PushRecipe(RecommendedList, recipe)); preferences.GetRecommendedRecipes().ForEach(recipe => PushRecipe(RecommendedList, recipe));
ProfilePictureImage.Source = ImageSource.FromUri(account.User.ProfilePicture); ProfilePictureImage.Source = ImageSource.FromUri(account.User.ProfilePicture);
ProfilePictureName.Text = account.User.Name; ProfilePictureName.Text = account.User.Name;

@ -7,19 +7,18 @@ namespace ShoopNCook.Pages;
public partial class MyListPage : ContentPage public partial class MyListPage : ContentPage
{ {
public MyListPage(Account account, IRecipesService service) public MyListPage(Account account, IUserNotifier notifier, IRecipesService service)
{ {
InitializeComponent(); InitializeComponent();
IAccountRecipes recipes = service.GetRecipesOf(account); IAccountRecipesPreferences preferences = service.GetPreferencesOf(account);
recipes.GetWeeklyList().ForEach(tuple => preferences.GetWeeklyList().ForEach(tuple =>
{ {
RecipeInfo info = tuple.Item1; RecipeInfo info = tuple.Item1;
RecipesLayout.Children.Add(new StoredRecipeView(info, tuple.Item2, amount => RecipesLayout.Children.Add(new StoredRecipeView(info, tuple.Item2, amount =>
{ {
Recipe recipe = service.GetRecipe(info); Recipe recipe = service.GetRecipe(info);
AccountRecipeRate? rate = recipes.FindRate(info); Shell.Current.Navigation.PushAsync(new RecipePage(recipe, notifier, preferences, amount));
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, rate, amount));
})); }));
}); });

@ -10,7 +10,7 @@ public partial class MyRecipesPage : ContentPage
private IUserNotifier notifier; private IUserNotifier notifier;
private IRecipesService service; private IRecipesService service;
private IAccountRecipes recipes; private Account account;
public MyRecipesPage( public MyRecipesPage(
Account account, Account account,
@ -21,9 +21,12 @@ public partial class MyRecipesPage : ContentPage
this.notifier = notifier; this.notifier = notifier;
this.service = service; this.service = service;
this.recipes = service.GetRecipesOf(account); this.account = account;
recipes.GetAccountRecipes().ForEach(AddRecipeView); service
.GetRecipesOf(account)
.GetAccountRecipes()
.ForEach(AddRecipeView);
} }
private void AddRecipeView(RecipeInfo info) private void AddRecipeView(RecipeInfo info)
@ -31,8 +34,8 @@ public partial class MyRecipesPage : ContentPage
RecipesLayout.Children.Add(new OwnedRecipeView(info, () => RecipesLayout.Children.Add(new OwnedRecipeView(info, () =>
{ {
Recipe recipe = service.GetRecipe(info); Recipe recipe = service.GetRecipe(info);
AccountRecipeRate? rate = recipes.FindRate(info); IAccountRecipesPreferences preferences = service.GetPreferencesOf(account);
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, rate, 1)); Shell.Current.Navigation.PushAsync(new RecipePage(recipe, notifier, preferences, 1));
}, },
() => RemoveRecipe(info) () => RemoveRecipe(info)
)); ));
@ -40,6 +43,8 @@ public partial class MyRecipesPage : ContentPage
private void RemoveRecipe(RecipeInfo info) private void RemoveRecipe(RecipeInfo info)
{ {
IAccountOwnedRecipes recipes = service.GetRecipesOf(account);
if (!recipes.RemoveRecipe(info)) if (!recipes.RemoveRecipe(info))
{ {
notifier.Error("Could not remove recipe"); notifier.Error("Could not remove recipe");
@ -62,7 +67,9 @@ public partial class MyRecipesPage : ContentPage
} }
private void OnAddRecipeButtonClicked(object sender, EventArgs e) private void OnAddRecipeButtonClicked(object sender, EventArgs e)
{ {
var page = new CreateRecipePage(recipes.Account.User, notifier, recipe => IAccountOwnedRecipes recipes = service.GetRecipesOf(account);
var page = new CreateRecipePage(account.User, notifier, recipe =>
{ {
if (!recipes.UploadRecipe(recipe)) if (!recipes.UploadRecipe(recipe))
{ {

@ -8,7 +8,6 @@
BackgroundColor="{StaticResource BackgroundPrimary}"> BackgroundColor="{StaticResource BackgroundPrimary}">
<Grid <Grid
RowDefinitions="90*, 10*" RowDefinitions="90*, 10*"
Padding="10"> Padding="10">
@ -51,7 +50,8 @@
StrokeShape="RoundRectangle 20" StrokeShape="RoundRectangle 20"
BackgroundColor="{StaticResource ImageBackground}"> BackgroundColor="{StaticResource ImageBackground}">
<Image <Image
HeightRequest="250"/> HeightRequest="250"
x:Name="RecipeImage"/>
</Border> </Border>
<!--Steps--> <!--Steps-->
@ -146,7 +146,8 @@
BackgroundColor="{StaticResource Selected}" BackgroundColor="{StaticResource Selected}"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
Text="Submit"/> Text="Submit"
Clicked="OnSubmitReviewClicked"/>
</Border> </Border>
</HorizontalStackLayout> </HorizontalStackLayout>
</Grid> </Grid>

@ -1,6 +1,9 @@
using ShoopNCook.Views; using ShoopNCook.Views;
using System.Windows.Input; using System.Windows.Input;
using Models; using Models;
using LocalEndpoint;
using Endpoint;
namespace ShoopNCook.Pages; namespace ShoopNCook.Pages;
public partial class RecipePage : ContentPage public partial class RecipePage : ContentPage
@ -9,27 +12,39 @@ public partial class RecipePage : ContentPage
private uint note; private uint note;
private bool isFavorite; private bool isFavorite;
public ICommand StarCommand => new Command<string>(count => SetNote(uint.Parse(count)));
private IAccountRecipesPreferences preferences;
private IUserNotifier notifier;
private RecipeInfo info;
public ICommand StarCommand => new Command<string>(count => SetNote(uint.Parse(count)));
public RecipePage(Recipe recipe, AccountRecipeRate? rate, uint amount) public RecipePage(Recipe recipe, IUserNotifier notifier, IAccountRecipesPreferences preferences, uint amount)
{ {
InitializeComponent(); InitializeComponent();
Counter.Count = amount; this.preferences = preferences;
this.notifier = notifier;
this.info = recipe.Info;
AccountRecipeRate rate = preferences.GetRate(recipe.Info);
note = rate?.Rate ?? 0; note = rate.Rate;
isFavorite = rate?.IsFavorite ?? false; isFavorite = rate.IsFavorite;
SetFavorite(isFavorite); SetFavorite(isFavorite);
SetNote(note); SetNote(note);
RecipeInfo info = recipe.Info; RecipeInfo info = recipe.Info;
Counter.Count = amount;
CookTime.Text = info.CookTimeMins.ToString(); CookTime.Text = info.CookTimeMins.ToString();
Energy.Text = info.CalPerPers.ToString() + " cal/pers"; Energy.Text = info.CalPerPers.ToString() + " cal/pers";
RecipeName.Text = info.Name; RecipeName.Text = info.Name;
if (info.Image != null)
RecipeImage.Source = ImageSource.FromUri(info.Image);
foreach (Ingredient ingredient in recipe.Ingredients) foreach (Ingredient ingredient in recipe.Ingredients)
IngredientList.Add(new IngredientView(ingredient)); IngredientList.Add(new IngredientView(ingredient));
@ -58,9 +73,7 @@ public partial class RecipePage : ContentPage
i++; i++;
} }
else else
{
img.Source = ImageSource.FromFile("star_empty.svg"); img.Source = ImageSource.FromFile("star_empty.svg");
}
} }
} }
@ -69,21 +82,30 @@ public partial class RecipePage : ContentPage
SetFavorite(!isFavorite); SetFavorite(!isFavorite);
} }
private void OnSubmitReviewClicked(object o, EventArgs e)
{
preferences.SetReviewScore(info, note);
notifier.Success("Your review has been successfuly submited");
}
private void SetFavorite(bool isFavorite) private void SetFavorite(bool isFavorite)
{ {
this.isFavorite = isFavorite; this.isFavorite = isFavorite;
if (isFavorite) if (isFavorite)
{ {
Favorite.Source = ImageSource.FromFile("hearth_on.svg"); Favorite.Source = ImageSource.FromFile("hearth_on.svg");
preferences.AddToFavorites(info);
} }
else else
{ {
Favorite.Source = ImageSource.FromFile("hearth_off.svg"); Favorite.Source = ImageSource.FromFile("hearth_off.svg");
preferences.RemoveFromFavorites(info);
} }
} }
private async void OnBackButtonClicked(object sender, EventArgs e) private void OnBackButtonClicked(object sender, EventArgs e)
{ {
await Navigation.PopAsync();
Navigation.PopAsync();
} }
} }
Loading…
Cancel
Save