diff --git a/MCTG/ConsoleApp/Menu/AddRecipeMenu.cs b/MCTG/ConsoleApp/Menu/AddRecipeMenu.cs index 353e168..5e66b49 100644 --- a/MCTG/ConsoleApp/Menu/AddRecipeMenu.cs +++ b/MCTG/ConsoleApp/Menu/AddRecipeMenu.cs @@ -39,12 +39,13 @@ namespace ConsoleApp.Menu Recipe recipe = new Recipe( title: title, + type: RecipeType.Unspecified, id: null, authorMail: masterMgr.CurrentConnectedUser?.Mail, - picture: "", - ingredients: new List(), - preparationSteps: steps.ToArray() - ); + picture: null) + { + PreparationSteps = steps + }; masterMgr.AddRecipe(recipe); return null; diff --git a/MCTG/DataPersistence/DataContractJSON.cs b/MCTG/DataPersistence/DataContractJSON.cs index b0ae42d..524e049 100644 --- a/MCTG/DataPersistence/DataContractJSON.cs +++ b/MCTG/DataPersistence/DataContractJSON.cs @@ -37,6 +37,7 @@ namespace DataPersistence KnownTypes = new[] { typeof(Recipe), + typeof(RecipeType), typeof(Review), typeof(User), typeof(Ingredient), diff --git a/MCTG/DataPersistence/DataContractXML.cs b/MCTG/DataPersistence/DataContractXML.cs index 053c4ac..d088e37 100644 --- a/MCTG/DataPersistence/DataContractXML.cs +++ b/MCTG/DataPersistence/DataContractXML.cs @@ -45,6 +45,7 @@ namespace DataPersistence KnownTypes = new Type[] { typeof(Recipe), + typeof(RecipeType), typeof(Review), typeof(User), typeof(Ingredient), diff --git a/MCTG/DataPersistence/Stubs.cs b/MCTG/DataPersistence/Stubs.cs index b842202..393978a 100644 --- a/MCTG/DataPersistence/Stubs.cs +++ b/MCTG/DataPersistence/Stubs.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace DataPersistence @@ -21,77 +22,123 @@ namespace DataPersistence nameof(Recipe), new List(new[] { - new Recipe( - title: "Cookies classiques", - id: 50, - authorMail: "admin@mctg.fr", - picture : "room_service_icon.png", - ingredients: new List(new[] + new Recipe("Cookies classiques", RecipeType.Dessert, null, "admin@mctg.fr", "") + { + Ingredients = new List { new Ingredient("Patates", new Quantity(23, Unit.unit)), new Ingredient("Farine", new Quantity(23, Unit.G)) - }), - preparationSteps: new[] + }, + PreparationSteps = new List { new PreparationStep(1, "Faire cuire."), new PreparationStep(2, "Manger.") - }), + }, + Reviews = new List + { + new Review(4, "Bonne recette, je recommande !"), + new Review(3, "Bof bof, mais mangeable...") + } + }, new Recipe( - authorMail: "admin@mctg.fr", title: "Cookies au chocolat", - id: null, - preparationSteps: new[] + type: RecipeType.Dessert) + { + Ingredients = new List + { + new Ingredient("Farine", new Quantity(200, Unit.G)) + }, + PreparationSteps = new List() { new PreparationStep(1, "Moulinez la pâte."), new PreparationStep(2, "Faire cuire pendant une bonne heure."), new PreparationStep(3, "Sortir du four et mettre dans un plat.") - }), + } + }, new Recipe( - title: "Gateau nature", id: null, - authorMail: "admin@mctg.fr", - preparationSteps: new[] + title: "Gateau nature", + type: RecipeType.Dessert) + { + Ingredients = new List + { + new Ingredient("Farine", new Quantity(200, Unit.G)), + new Ingredient("Lait", new Quantity(2, Unit.L)) + }, + PreparationSteps = new List { new PreparationStep(1, "Achetez les ingrédients."), new PreparationStep(2, "Préparez le matériel. Ustensiles et tout."), new PreparationStep(3, "Pleurez.") - }), + }, + Reviews = new List + { + new Review("pedrosamigos@hotmail.com", 5, "C'était vraiment IN-CROY-ABLE !!!") + } + }, new Recipe( - title: "Gateau au pommes", id: null, - authorMail: "admin@mctg.fr", - preparationSteps: new[] + title: "Gateau au pommes", + type: RecipeType.Dessert) + { + PreparationSteps = new List { new PreparationStep(1, "Achetez les légumes."), new PreparationStep(2, "Préparez le plat. Ustensiles et préchauffez le four."), new PreparationStep(3, "Coupez les pommes en morceaux et disposez-les sur le plat."), new PreparationStep(4, "Mettez enfin le plat au four, puis une fois cuit, dégustez !") - }), + } + }, new Recipe( - title: "Gateau au chocolat", id: null, - authorMail: "pedrosamigos@hotmail.com", - preparationSteps: new[] + title: "Gateau au chocolat", + type: RecipeType.Dessert, + id: null, authorMail: "pedrosamigos@hotmail.com") + { + Ingredients = new List + { + new Ingredient("Mais", new Quantity(2, Unit.kG)), + new Ingredient("Sachet pépites de chocolat", new Quantity(1, Unit.unit)), + new Ingredient("Dinde", new Quantity(2, Unit.G)) + }, + PreparationSteps = new List { new PreparationStep(1, "Ajouter les oeufs."), new PreparationStep(2, "Ajouter la farine."), new PreparationStep(3, "Ajouter 100g de chocolat fondu."), new PreparationStep(4, "Mélanger le tout."), new PreparationStep(5, "Faire cuire 45h au four traditionnel.") - }), + } + }, new Recipe( title: "Dinde au jambon", - id: null, - authorMail: "pedrosamigos@hotmail.com", - preparationSteps: new[] + type: RecipeType.Dish, + id: null, authorMail: "pedrosamigos@hotmail.com") + { + Ingredients = new List + { + new Ingredient("Morceaux de bois", new Quantity(2, Unit.unit)), + new Ingredient("Sachet gélatine", new Quantity(1, Unit.unit)), + new Ingredient("Jambon", new Quantity(2, Unit.kG)) + }, + PreparationSteps = new List { new PreparationStep(1, "Faire une cuisson bien sec de la dinde à la poêle"), new PreparationStep(2, "Mettre la dinde au frigo."), new PreparationStep(3, "Mettre le jambon dans le micro-onde."), new PreparationStep(4, "Faire chauffer 3min."), new PreparationStep(5, "Présentez sur un plat la dinde et le jambon : Miam !") - }), + } + }, new Recipe( - title: "Poulet au curry", id: null, - authorMail: "pedrosamigos@hotmail.com", - preparationSteps: new[] + title: "Poulet au curry", + type: RecipeType.Dish, + id: null, authorMail: "pedrosamigos@hotmail.com") + { + Ingredients = new List + { + new Ingredient("Pissenlis", new Quantity(200, Unit.unit)), + new Ingredient("Boule de pétanque", new Quantity(10, Unit.unit)), + new Ingredient("Poivre", new Quantity(4, Unit.mG)) + }, + PreparationSteps = new List { new PreparationStep(1, "Trouvez des épices de curry."), new PreparationStep(2, "Trouvez maintenant du poulet."), @@ -99,7 +146,12 @@ namespace DataPersistence new PreparationStep(4, "Parsemez d'épices curry la tête de la poule."), new PreparationStep(5, "Mettre le tout au four traditionnel 30min."), new PreparationStep(6, "Dégustez en famille !") - }) + }, + Reviews = new List + { + new Review(5, "Meilleure recette que j'ai avalé de tout les temps !!!!!!!") + } + } }) #endregion }, diff --git a/MCTG/Model/Managers/MasterManager.cs b/MCTG/Model/Managers/MasterManager.cs index cd3cc83..76e3402 100644 --- a/MCTG/Model/Managers/MasterManager.cs +++ b/MCTG/Model/Managers/MasterManager.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Diagnostics; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -12,14 +14,28 @@ namespace Model.Managers /// /// The Main manager of the model. /// - public class MasterManager + public class MasterManager : INotifyPropertyChanged { #region Attributes & Properties + public event PropertyChangedEventHandler? PropertyChanged; + + private RecipeCollection _recipesInSearch = new RecipeCollection(""); + /// /// The currently connected user. 'null' if no user is connected. /// public User? CurrentConnectedUser { get; private set; } + public RecipeCollection RecipesInSearch + { + get => _recipesInSearch; + set + { + _recipesInSearch = value; + OnPropertyChange(); + } + } + /// /// The collection of all recipes loaded. /// @@ -46,6 +62,7 @@ namespace Model.Managers DataMgr = new DataManager(dataManager); CurrentConnectedUser = null; Recipes = DataMgr.GetRecipes("all recipes"); + RecipesInSearch = DataMgr.GetRecipes("search on"); Users = DataMgr.GetUsers(); } #endregion @@ -63,11 +80,13 @@ namespace Model.Managers if (Users is null || Users.Count == 0) throw new ArgumentNullException("There is no users registred."); +#if DEBUG if (mail == "admin") { CurrentConnectedUser = Users.FirstOrDefault(u => u.Mail == "admin@mctg.fr"); return true; } +#endif User? user = Users.Find(u => u.Mail == mail); @@ -129,7 +148,14 @@ namespace Model.Managers /// The current connected user's personal recipes. public RecipeCollection GetCurrentUserRecipes() => new RecipeCollection("User recipes", - DataMgr.GetRecipes().FindAll(r => r.AuthorMail == CurrentConnectedUser?.Mail).ToArray()); + DataMgr.GetRecipes().ToList().FindAll(r => r.AuthorMail == CurrentConnectedUser?.Mail).ToArray()); + + /// + /// Notify property change handler. + /// + /// the name of the property that change. + public void OnPropertyChange([CallerMemberName] string propertyName = "") + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion } diff --git a/MCTG/Model/Recipes/Recipe.cs b/MCTG/Model/Recipes/Recipe.cs index 9f220ca..7ba928a 100644 --- a/MCTG/Model/Recipes/Recipe.cs +++ b/MCTG/Model/Recipes/Recipe.cs @@ -19,6 +19,9 @@ namespace Model [DataMember(Name = "image")] private string _image = ""; + + [DataMember(Name = "authorMail")] + private string _authorMail = ""; #endregion #region Properties @@ -32,15 +35,22 @@ namespace Model /// List of reviews of this recipe. /// [DataMember(Name = "reviews")] - public List Reviews { get; private set; } + public List Reviews { get; set; } /// /// AuthorMail's mail of the recipe. /// - [DataMember(Name = "authorMail")] - public string? AuthorMail { get; private set; } - - public string Toto { get; set; } = "Coucou"; + public string? AuthorMail + { + get => _authorMail; + set + { + if (string.IsNullOrEmpty(value)) + _authorMail = "admin@mctg.fr"; + else + _authorMail = value; + } + } /// /// The Title of the recipe.
@@ -67,12 +77,14 @@ namespace Model get => _image; set { - if (!string.IsNullOrWhiteSpace(value)) + if (string.IsNullOrWhiteSpace(value)) _image = "room_service_icon.png"; - _image = value; + else + _image = value; } } + /// /// The list of ingredients. /// [DataMember(Name = "ingredient")] @@ -84,30 +96,34 @@ namespace Model ///
[DataMember(Name = "preparation-steps")] public List PreparationSteps { get; set; } + + /// + /// The type of recipe. + /// + [DataMember(Name = "type")] + public RecipeType Type { get; private set; } #endregion #region Constructors /// /// Construct a new recipe. /// - /// The title of the recipe - /// The id of the recipe. If not given, get a new id. - /// The name of the user that create this recipe. - /// The image that represent the recipe - /// Thr list of reviews. - /// Thr list of ingredients. - /// The steps of the preparation of the meal - public Recipe(string title, int? id, string? authorMail, string? picture, - List reviews, List ingredients, - params PreparationStep[] preparationSteps) + /// The title of the recipe + /// The type of the recipe. + /// The id of the recipe. If not given, get a new id. + /// The name of the user that create this recipe. + /// The image that represent the recipe + public Recipe(string title, RecipeType type, int? id, string? authorMail, string? picture) { Title = title; + Type = type; Image = picture; - PreparationSteps = new List(preparationSteps); - Ingredients = ingredients; - Reviews = reviews; AuthorMail = authorMail; + PreparationSteps = new List(); + Ingredients = new List(); + Reviews = new List(); + if (id == null) { var randomGenerator = RandomNumberGenerator.Create(); @@ -118,46 +134,20 @@ namespace Model else Id = (int)id; } - - /// - /// - /// - /// The title of the recipe. - /// The id of the recipe. If not given, get a new id. - /// Mail of the user that create the recipe - /// The steps of the preparation of the meal. - public Recipe(string title, int? id, string? authorMail, params PreparationStep[] preparationSteps) - : this(title, id, authorMail, null, new List(), new List(), preparationSteps) + public Recipe(string title, RecipeType type, int? id, string? authorMail) + : this(title, type, id, authorMail, null) { - } - /// - /// - /// - /// The title of the recipe. - /// The id of the recipe. If not given, get a new id. - /// Mail of the user that create the recipe - /// Mail of the user that create the recipe - /// List of ingredients that compose the recipe. - /// The steps of the preparation of the meal. - public Recipe(string title, int? id, string? authorMail, string? picture, List ingredients, params PreparationStep[] preparationSteps) - : this(title, id, authorMail, picture, new List(), ingredients, preparationSteps) + public Recipe(string title, RecipeType type) + : this(title, type, null, null) { } - /// - /// - /// - /// The title of the recipe. - /// The id of the recipe. If not given, get a new id. - /// Image that reppresent the recipe. - /// The steps of the preparation of the meal. - public Recipe() - : this("", null, null, null, new List(), new List(),new PreparationStep[0]) + public Recipe(string title) + : this(title, RecipeType.Unspecified) { } - #endregion #region Methods diff --git a/MCTG/Model/Recipes/RecipeCollection.cs b/MCTG/Model/Recipes/RecipeCollection.cs index ac7d17a..7579d5f 100644 --- a/MCTG/Model/Recipes/RecipeCollection.cs +++ b/MCTG/Model/Recipes/RecipeCollection.cs @@ -1,106 +1,118 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Text; - -namespace Model -{ - /// - /// Define a collection of . - ///
This class implement and . - ///
- public class RecipeCollection : List, IEquatable - { - #region Attributes - private string _description = ""; - #endregion - - #region Properties - /// - /// A short description of what this collection contain.
- /// Set to "No description." when the value passed is null, empty or contain white spaces. - ///
- public string Description - { - get => _description; - set - { - if (string.IsNullOrWhiteSpace(value)) - _description = "No description."; - else - _description = value; - } - } - #endregion - - #region Constructors - /// - /// Construct a new collection of _recipes. - /// - /// A short description of what this list will contain - /// Recipes to add in this new collection - public RecipeCollection(string description, params Recipe[] recipes) - : base(recipes) - { - Description = description; - } - #endregion - - #region Methods - /// - /// Find a recipe in this list by giving the id. - /// - /// The id of the list we are looking for - /// The recipe of the id given - /// - public Recipe? GetRecipeById(int id) - { - Recipe? recipe = this.Find(r => r.Id == id); - if (recipe == null) throw new ArgumentException("No _recipes match the given id."); - return recipe; - } - - /// - /// Utility to find a recipe by his _name. - /// - /// The string for the search - /// A collection of Recipe where their Title contain the string. - public RecipeCollection ResearchByName(string str) - { - return new RecipeCollection( - description: $"Results of the research: {str}", - recipes: this.FindAll(x => x.Title.ToLower().Contains(str.ToLower())).ToArray()); - } - - public virtual bool Equals(RecipeCollection? other) - { - if (other == null) return false; - if (other == this) return true; - return this.Description.Equals(other.Description); - } - - public override bool Equals(object? obj) - { - var item = obj as RecipeCollection; - if (item == null) return false; - return Equals(obj); - } - - public override int GetHashCode() - { - return Description.GetHashCode(); - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n"); - foreach (Recipe r in this) - { - sb.AppendFormat("\t - {0}\n", r.ToString()); - } - return sb.ToString(); - } - #endregion - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; + +namespace Model +{ + /// + /// Define a collection of . + ///
This class is derived from + /// and implement and . + ///
+ public class RecipeCollection : ObservableCollection, IEquatable, ICloneable + { + #region Attributes + private string _description = ""; + #endregion + + #region Properties + /// + /// A short description of what this collection contain.
+ /// Set to "No description." when the value passed is null, empty or contain white spaces. + ///
+ public string Description + { + get => _description; + set + { + if (string.IsNullOrWhiteSpace(value)) + _description = "No description."; + else + _description = value; + } + } + #endregion + + #region Constructors + /// + /// Construct a new collection of _recipes. + /// + /// A short description of what this list will contain + /// Recipes to add in this new collection + public RecipeCollection(string description, params Recipe[] recipes) + : base(recipes) + { + Description = description; + } + #endregion + + #region Methods + /// + /// Find a recipe in this list by giving the id. + /// + /// The id of the list we are looking for + /// The recipe of the id given + /// + public Recipe? GetRecipeById(int id) + { + Recipe? recipe = this.ToList().Find(r => r.Id == id); + + if (recipe == null) throw new ArgumentException("No _recipes match the given id."); + return recipe; + } + + /// + /// Utility to find a recipe by his _name. + /// + /// The string for the search + /// A collection of Recipe where their Title contain the string. + public RecipeCollection ResearchByName(string str) + { + if (string.IsNullOrEmpty(str)) + return this; + + return new RecipeCollection( + description: $"Results of the research: {str}", + recipes: this.ToList().FindAll(x => x.Title.ToLower().Contains(str.ToLower())).ToArray()); + } + + public virtual bool Equals(RecipeCollection? other) + { + if (other == null) return false; + if (other == this) return true; + return this.Description.Equals(other.Description); + } + + public override bool Equals(object? obj) + { + var item = obj as RecipeCollection; + if (item == null) return false; + return Equals(obj); + } + + public override int GetHashCode() + { + return Description.GetHashCode(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder($"[RecipeCollection] - {Description}:\n"); + foreach (Recipe r in this) + { + sb.AppendFormat("\t - {0}\n", r.ToString()); + } + return sb.ToString(); + } + + public object Clone() + { + return new RecipeCollection( + description: this.Description, + recipes: this.ToArray()); + } + #endregion + } +} diff --git a/MCTG/Model/Recipes/RecipeType.cs b/MCTG/Model/Recipes/RecipeType.cs new file mode 100644 index 0000000..be56ef7 --- /dev/null +++ b/MCTG/Model/Recipes/RecipeType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Model +{ + public enum RecipeType + { + Unspecified, + Starter, + Dish, + Dessert + } +} diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs index a16deb8..b98ab2a 100644 --- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs +++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs @@ -8,9 +8,8 @@ namespace Model_UnitTests public void TestVoidConstructor() { Recipe r = new Recipe( - title: "test recipe", - id: null, - authorMail: "test@test.fr"); + title: "test recipe", type: RecipeType.Unspecified); + Assert.NotNull(r.Title); } } diff --git a/MCTG/Views/App.xaml.cs b/MCTG/Views/App.xaml.cs index 7c3fbb7..da53cbf 100644 --- a/MCTG/Views/App.xaml.cs +++ b/MCTG/Views/App.xaml.cs @@ -16,12 +16,17 @@ using System.Runtime.CompilerServices; namespace Views { public partial class App : Application - { - //Point d'entrée de l'application - public MasterManager MasterMgr { get; private set; } = new MasterManager(new Stubs()); - //L'utilisateur courant de l'application - public User CurrentUser { get; set; } + { private Recipe currentRecipe { get; set; } + + /// + /// Master manager - access to the Model. + /// + public MasterManager MasterMgr { get; private set; } = new MasterManager(new Stubs()); + + /// + /// Current selected recipe. + /// public Recipe CurrentRecipe { get => currentRecipe; @@ -32,37 +37,26 @@ namespace Views } } - //collection de recette de l'application + /// + /// Get the current connected user. + /// + public User? CurrentUser { get; private set; } + + /// + /// Get all the recipes loaded. + /// public RecipeCollection AllRecipes { get; set; } - //const int WindowWidth = 1200; - //const int WindowHeight = 800; public App() { - CurrentUser = MasterMgr.DataMgr.GetUsers().Last(); + CurrentUser = MasterMgr.CurrentConnectedUser; AllRecipes = MasterMgr.DataMgr.GetRecipes("All recipes"); CurrentRecipe = MasterMgr.DataMgr.GetRecipes().First(); InitializeComponent(); - // Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) => - // { -//#if WINDOWS -// var mauiWindow = handler.VirtualView; -// var nativeWindow = handler.PlatformView; -// nativeWindow.Activate(); -// IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow); -// WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle); -// AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId); -// appWindow.Resize(new SizeInt32(WindowWidth, WindowHeight)); -//#endif -// }); - - - /* - Comment(ctrl-k + ctrl-c)/Uncomment(ctrl-k + ctrl-u) to change page - */ UserAppTheme = AppTheme.Light; MainPage = new Home(); - //MainPage = new MyPosts(); } } diff --git a/MCTG/Views/ContainerFlyout.xaml b/MCTG/Views/ContainerFlyout.xaml index 07193e3..2bfe91d 100644 --- a/MCTG/Views/ContainerFlyout.xaml +++ b/MCTG/Views/ContainerFlyout.xaml @@ -16,18 +16,20 @@ HorizontalOptions="Start" Padding="10, 10, 0, 0"/> + BackgroundColor="{StaticResource Secondary}" + WidthRequest="100" HeightRequest="100" + CornerRadius="50" Margin="0, 30, 0, 10" + BorderWidth="5" BorderColor="Black" + IsEnabled="{Binding IsNotConnected, Source={x:Reference fl}}" + Grid.RowSpan="2" + Clicked="ProfileButton_Clicked"/>