diff --git a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs
index 6f7d8ef..8ee0b49 100644
--- a/MCTG/Tests/Model_UnitTests/Recipe_UT.cs
+++ b/MCTG/Tests/Model_UnitTests/Recipe_UT.cs
@@ -12,5 +12,20 @@ namespace Model_UnitTests
Assert.NotNull(r.Title);
}
+
+ [Theory]
+ [InlineData("recipe", RecipeType.Dish, Priority.Light, "recipe", RecipeType.Dish, Priority.Light)]
+ [InlineData("No title.", RecipeType.Unspecified, Priority.Light, "", RecipeType.Unspecified, Priority.Light)]
+ [InlineData("re cipe", RecipeType.Unspecified, Priority.Light, "re cipe", RecipeType.Unspecified, Priority.Light)]
+ public void TestValuesConstructor(
+ string expectedTitle, RecipeType expectedType, Priority expectedPriority,
+ string title, RecipeType type, Priority priority)
+ {
+ Recipe rc = new Recipe(title, type, priority);
+
+ Assert.Equal(expectedTitle, rc.Title);
+ Assert.Equal(expectedType, rc.Type);
+ Assert.Equal(expectedPriority, rc.Priority);
+ }
}
}
diff --git a/MCTG/Views/App.xaml.cs b/MCTG/Views/App.xaml.cs
index d5c1bbf..0dd959c 100644
--- a/MCTG/Views/App.xaml.cs
+++ b/MCTG/Views/App.xaml.cs
@@ -5,6 +5,7 @@ using Managers;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization.Json;
namespace Views
{
@@ -20,7 +21,7 @@ namespace Views
Debug.WriteLine("Hello, World!\n\n");
string path = FileSystem.Current.AppDataDirectory; // - path to the save file
- string strategy = "xml"; // - strategy is 'xml' or 'json' (/!\ this is case sensitive)
+ string strategy = "json"; // - strategy is 'xml' or 'json' (/!\ this is case sensitive)
// Initialize the data serializer
IDataSerializer dataSerializer = (strategy == "xml") ?
@@ -31,7 +32,7 @@ namespace Views
IDataManager dataManager;
if (!File.Exists(Path.Combine(path, $"data.{strategy}")))
{
- var data = LoadXMLBundledFilesAsync("data.xml");
+ var data = LoadJSONBundledFilesAsync("data.json");
dataManager = new DataDefaultManager(dataSerializer, data);
}
else
@@ -72,6 +73,7 @@ namespace Views
base.OnSleep();
}
+
///
/// Load XML raw assets from data.
///
@@ -79,9 +81,8 @@ namespace Views
/// A dictionary containing the data loaded.
private static IDictionary> LoadXMLBundledFilesAsync(string path)
{
- //using Stream stream = await FileSystem.Current.OpenAppPackageFileAsync(path);
- DataContractSerializerSettings _dataContractSerializerSettings
- = new DataContractSerializerSettings()
+ DataContractSerializerSettings _dataContractSerializerSettings =
+ new DataContractSerializerSettings()
{
KnownTypes = new Type[]
{
@@ -97,5 +98,29 @@ namespace Views
return data;
}
+
+ ///
+ /// Load JSON raw assets from data.
+ ///
+ /// The path in the raw assets directory.
+ /// A dictionary containing the data loaded.
+ private static IDictionary> LoadJSONBundledFilesAsync(string path)
+ {
+ DataContractJsonSerializerSettings _dataContractJsonSerializerSettings =
+ new DataContractJsonSerializerSettings()
+ {
+ KnownTypes = new Type[]
+ {
+ typeof(Recipe), typeof(RecipeType), typeof(Priority), typeof(Review), typeof(User), typeof(Ingredient), typeof(Quantity)
+ }
+ };
+ var jsonSerializer = new DataContractJsonSerializer(typeof(Dictionary>), _dataContractJsonSerializerSettings);
+ IDictionary> data;
+
+ using Stream stream = FileSystem.Current.OpenAppPackageFileAsync(path).Result;
+ data = jsonSerializer.ReadObject(stream) as IDictionary>;
+
+ return data;
+ }
}
}
diff --git a/MCTG/Views/ContentPages/AddRecipe.xaml.cs b/MCTG/Views/ContentPages/AddRecipe.xaml.cs
index aa95ce7..c6ca924 100644
--- a/MCTG/Views/ContentPages/AddRecipe.xaml.cs
+++ b/MCTG/Views/ContentPages/AddRecipe.xaml.cs
@@ -13,6 +13,9 @@ namespace Views
private Ingredient ingredient;
private PreparationStep preparationStep;
private string titleRecipe;
+
+ public FileResult ImageSource { get; private set; } = null;
+ public string? ImageSourcePath { get; private set; } = null;
public MasterManager Master => (Application.Current as App).Master;
public User CurrentUser => Master.User.CurrentConnected;
public Recipe RecipeToAdd{ get=> recipeToAdd; set => recipeToAdd = value; }
@@ -38,20 +41,30 @@ namespace Views
IngredientList = new List();
PreparationStepList = new List();
}
- private void PickPhoto(object sender, EventArgs e)
+ private async void PickPhoto(object sender, EventArgs e)
{
- MediaPicker.PickPhotoAsync();
+ ImageSource = await MediaPicker.Default.PickPhotoAsync();
}
- private void AddRecipeValidation(object sender, EventArgs e)
+ private async void AddRecipeValidation(object sender, EventArgs e)
{
-
if (string.IsNullOrWhiteSpace(TitleRecipe))
{
- DisplayAlert("Erreur", "Entrez un nom de recette.", "Ok");
+ await DisplayAlert("Erreur", "Entrez un nom de recette.", "Ok");
return;
}
+ if (ImageSource != null)
+ {
+ // save the file into local storage
+ ImageSourcePath = Path.Combine(FileSystem.Current.AppDataDirectory, $"{TitleRecipe.Replace(" ", "")}.{ImageSource.FileName}");
+
+ using Stream sourceStream = await ImageSource.OpenReadAsync();
+ using FileStream localFileStream = File.OpenWrite(ImageSourcePath);
+
+ await sourceStream.CopyToAsync(localFileStream);
+ }
+
RecipeType newRecipeType = GetSelectedRecipeType();
Priority selectedPriority = GetSelectedPriority();
string authorMail = CurrentUser.Mail;
@@ -62,26 +75,35 @@ namespace Views
newRecipeType,
selectedPriority,
null,
- authorMail
+ authorMail,
+ ImageSourcePath
);
newRecipe.PreparationSteps.AddRange(PreparationStepList);
newRecipe.Ingredients.AddRange(IngredientList);
bool isRecipeSave = Master.Recipe.AddRecipeToData(newRecipe);
+
+ // Save data.
+ Debug.Write($"[ {DateTime.Now:H:mm:ss} ] Saving...\t");
+ Master.Data.SaveData();
+
+ Debug.WriteLine("Done.");
+ Debug.WriteLine(FileSystem.Current.AppDataDirectory);
+
if (isRecipeSave)
{
- DisplayAlert("Succès", "La recette a été ajoutée avec succès", "OK");
+ await DisplayAlert("Succès", "La recette a été ajoutée avec succès", "OK");
}
else
{
- DisplayAlert("Echec", "La recette n'a pas été ajoutée", "OK");
+ await DisplayAlert("Echec", "La recette n'a pas été ajoutée", "OK");
}
newRecipe = new Recipe("Nouvelle Recette");
PreparationStepList.Clear();
IngredientList.Clear();
- Navigation.PopAsync();
+ await Navigation.PopModalAsync();
}
private void AddStepRecipe(object sender, EventArgs e)
@@ -115,6 +137,12 @@ namespace Views
private void AddIngredient(object sender, EventArgs e)
{
+ if (nameIngredient.Text is null || quantityNumber.Text is null)
+ {
+ DisplayAlert("Warning", "some values are null, please provide correct values.", "Ok");
+ return;
+ }
+
string ingredientName = nameIngredient.Text;
int numberQuantity = Convert.ToInt32(quantityNumber.Text);
Unit unitQuantity = (Unit)UnitPicker.SelectedItem;
diff --git a/MCTG/Views/ContentPages/Login.xaml.cs b/MCTG/Views/ContentPages/Login.xaml.cs
index ac40aa2..4bdb2c6 100644
--- a/MCTG/Views/ContentPages/Login.xaml.cs
+++ b/MCTG/Views/ContentPages/Login.xaml.cs
@@ -1,5 +1,6 @@
using AppException;
using Model;
+using System.Diagnostics;
namespace Views;
@@ -24,6 +25,13 @@ public partial class Login : ContentPage
try
{
usermgr.AddUserToData(usermgr.CreateUser(mail, password));
+
+ // Save data.
+ Debug.Write($"[ {DateTime.Now:H:mm:ss} ] Saving...\t");
+ Master.Data.SaveData();
+
+ Debug.WriteLine("Done.");
+ Debug.WriteLine(FileSystem.Current.AppDataDirectory);
}
catch (BadMailFormatException)
{
diff --git a/MCTG/Views/ContentPages/MyPosts.xaml b/MCTG/Views/ContentPages/MyPosts.xaml
index bf8dcac..fc7bc07 100644
--- a/MCTG/Views/ContentPages/MyPosts.xaml
+++ b/MCTG/Views/ContentPages/MyPosts.xaml
@@ -1,6 +1,7 @@
@@ -8,45 +9,59 @@
+
-
+
-
-
+
+
+
+
-
-
-
-
+
+
-
-
-
-
-
-
+ Margin="0, 15"
+ Wrap="Wrap"
+ JustifyContent="Start"
+ AlignItems="Center"
+ AlignContent="SpaceEvenly"
+ HorizontalOptions="Center"
+ BindableLayout.ItemsSource="{Binding RecipesDisplayed}">
+
+
+
+
+
+
+
+
-
diff --git a/MCTG/Views/ContentPages/MyPosts.xaml.cs b/MCTG/Views/ContentPages/MyPosts.xaml.cs
index d1d3c6f..2feebf1 100644
--- a/MCTG/Views/ContentPages/MyPosts.xaml.cs
+++ b/MCTG/Views/ContentPages/MyPosts.xaml.cs
@@ -1,9 +1,34 @@
+using Model;
+
namespace Views;
public partial class MyPosts : ContentPage
{
- public MyPosts()
+ public MasterManager Master => (Application.Current as App).Master;
+
+ private readonly RecipeCollection _recipesDisplayed;
+ public ReadOnlyObservableRecipeCollection RecipesDisplayed { get; private set; }
+
+ public Recipe Recipe => Master.Recipe.CurrentSelected;
+
+
+ public MyPosts()
{
- InitializeComponent();
- }
-}
\ No newline at end of file
+ _recipesDisplayed = Master.Recipe.GetRecipeByAuthor(Master.User.CurrentConnected.Mail);
+ RecipesDisplayed = new ReadOnlyObservableRecipeCollection(_recipesDisplayed);
+
+ InitializeComponent();
+
+ BindingContext = this;
+ }
+
+ private void MyInformations_Clicked(object sender, EventArgs e)
+ {
+ Navigation.PopModalAsync();
+ }
+
+ private void AddRecipe_Clicked(object sender, EventArgs e)
+ {
+ Navigation.PushModalAsync(new AddRecipe());
+ }
+}
diff --git a/MCTG/Views/ContentPages/MyProfil.xaml b/MCTG/Views/ContentPages/MyProfil.xaml
index dd28db0..d4ad66b 100644
--- a/MCTG/Views/ContentPages/MyProfil.xaml
+++ b/MCTG/Views/ContentPages/MyProfil.xaml
@@ -9,17 +9,17 @@
-
-
-
+
+
+
-
diff --git a/MCTG/Views/ContentViews/ContainerFlyout.xaml b/MCTG/Views/ContentViews/ContainerFlyout.xaml
index a6bd4e0..300304b 100644
--- a/MCTG/Views/ContentViews/ContainerFlyout.xaml
+++ b/MCTG/Views/ContentViews/ContainerFlyout.xaml
@@ -12,7 +12,7 @@
-
\ No newline at end of file
diff --git a/MCTG/Views/Resources/Raw/cookies1.jpg b/MCTG/Views/Resources/Raw/cookies1.jpg
new file mode 100644
index 0000000..faa1b31
Binary files /dev/null and b/MCTG/Views/Resources/Raw/cookies1.jpg differ
diff --git a/MCTG/Views/Resources/Raw/cookies2.jpg b/MCTG/Views/Resources/Raw/cookies2.jpg
new file mode 100644
index 0000000..9dd6ca9
Binary files /dev/null and b/MCTG/Views/Resources/Raw/cookies2.jpg differ
diff --git a/MCTG/Views/Resources/Raw/data.json b/MCTG/Views/Resources/Raw/data.json
new file mode 100644
index 0000000..2022b5a
--- /dev/null
+++ b/MCTG/Views/Resources/Raw/data.json
@@ -0,0 +1,376 @@
+[
+ {
+ "Key": "Recipe",
+ "Value": [
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "admin@mctg.fr",
+ "id": 9806,
+ "image": "cookies1.jpg",
+ "ingredient": [
+ {
+ "id": "Patates",
+ "quantity": {
+ "digit": 23,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Farine",
+ "quantity": {
+ "digit": 23,
+ "unit": 3
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Faire cuire.",
+ "order": 1
+ },
+ {
+ "description": "Manger.",
+ "order": 2
+ }
+ ],
+ "priority": 2,
+ "reviews": [
+ {
+ "authorMail": "admin@mctg.fr",
+ "content": "Bonne recette, je recommande !",
+ "id": 30967,
+ "stars": 4
+ },
+ {
+ "authorMail": "admin@mctg.fr",
+ "content": "Bof bof, mais mangeable...",
+ "id": 27370,
+ "stars": 3
+ }
+ ],
+ "title": "Cookies classiques",
+ "type": 3
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "admin@mctg.fr",
+ "id": 4678,
+ "image": "cookies2.jpg",
+ "ingredient": [
+ {
+ "id": "Farine",
+ "quantity": {
+ "digit": 200,
+ "unit": 3
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Moulinez la pĂąte.",
+ "order": 1
+ },
+ {
+ "description": "Faire cuire pendant une bonne heure.",
+ "order": 2
+ },
+ {
+ "description": "Sortir du four et mettre dans un plat.",
+ "order": 3
+ }
+ ],
+ "priority": 1,
+ "reviews": [],
+ "title": "Cookies au chocolat",
+ "type": 3
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "admin@mctg.fr",
+ "id": 28213,
+ "image": "room_service_icon.png",
+ "ingredient": [
+ {
+ "id": "Farine",
+ "quantity": {
+ "digit": 200,
+ "unit": 3
+ }
+ },
+ {
+ "id": "Lait",
+ "quantity": {
+ "digit": 2,
+ "unit": 4
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Achetez les ingrédients.",
+ "order": 1
+ },
+ {
+ "description": "Préparez le matériel. Ustensiles et tout.",
+ "order": 2
+ },
+ {
+ "description": "Pleurez.",
+ "order": 3
+ }
+ ],
+ "priority": 4,
+ "reviews": [
+ {
+ "authorMail": "pedrosamigos@hotmail.com",
+ "content": "C'était vraiment IN-CROY-ABLE !!!",
+ "id": 5127,
+ "stars": 5
+ }
+ ],
+ "title": "Gateau nature",
+ "type": 3
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "admin@mctg.fr",
+ "id": 27448,
+ "image": "room_service_icon.png",
+ "ingredient": [ ],
+ "preparation-steps": [
+ {
+ "description": "Achetez les légumes.",
+ "order": 1
+ },
+ {
+ "description": "Préparez le plat. Ustensiles et préchauffez le four.",
+ "order": 2
+ },
+ {
+ "description": "Coupez les pommes en morceaux et disposez-les sur le plat.",
+ "order": 3
+ },
+ {
+ "description": "Mettez enfin le plat au four, puis une fois cuit, dégustez !",
+ "order": 4
+ }
+ ],
+ "priority": 3,
+ "reviews": [ ],
+ "title": "Gateau au pommes",
+ "type": 3
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "pedrosamigos@hotmail.com",
+ "id": 14217,
+ "image": "room_service_icon.png",
+ "ingredient": [
+ {
+ "id": "Mais",
+ "quantity": {
+ "digit": 2,
+ "unit": 1
+ }
+ },
+ {
+ "id": "Sachet pépites de chocolat",
+ "quantity": {
+ "digit": 1,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Dinde",
+ "quantity": {
+ "digit": 2,
+ "unit": 3
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Ajouter les oeufs.",
+ "order": 1
+ },
+ {
+ "description": "Ajouter la farine.",
+ "order": 2
+ },
+ {
+ "description": "Ajouter 100g de chocolat fondu.",
+ "order": 3
+ },
+ {
+ "description": "Mélanger le tout.",
+ "order": 4
+ },
+ {
+ "description": "Faire cuire 45h au four traditionnel.",
+ "order": 5
+ }
+ ],
+ "priority": 0,
+ "reviews": [ ],
+ "title": "Gateau au chocolat",
+ "type": 3
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "pedrosamigos@hotmail.com",
+ "id": 3856,
+ "image": "room_service_icon.png",
+ "ingredient": [
+ {
+ "id": "Morceaux de bois",
+ "quantity": {
+ "digit": 2,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Sachet gélatine",
+ "quantity": {
+ "digit": 1,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Jambon",
+ "quantity": {
+ "digit": 2,
+ "unit": 1
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Faire une cuisson bien sec de la dinde Ă la poĂȘle",
+ "order": 1
+ },
+ {
+ "description": "Mettre la dinde au frigo.",
+ "order": 2
+ },
+ {
+ "description": "Mettre le jambon dans le micro-onde.",
+ "order": 3
+ },
+ {
+ "description": "Faire chauffer 3min.",
+ "order": 4
+ },
+ {
+ "description": "Présentez sur un plat la dinde et le jambon : Miam !",
+ "order": 5
+ }
+ ],
+ "priority": 2,
+ "reviews": [ ],
+ "title": "Dinde au jambon",
+ "type": 2
+ },
+ {
+ "__type": "recipe:#Model",
+ "authorMail": "pedrosamigos@hotmail.com",
+ "id": 29272,
+ "image": "room_service_icon.png",
+ "ingredient": [
+ {
+ "id": "Pissenlis",
+ "quantity": {
+ "digit": 200,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Boule de pétanque",
+ "quantity": {
+ "digit": 10,
+ "unit": 0
+ }
+ },
+ {
+ "id": "Poivre",
+ "quantity": {
+ "digit": 4,
+ "unit": 2
+ }
+ }
+ ],
+ "preparation-steps": [
+ {
+ "description": "Trouvez des épices de curry.",
+ "order": 1
+ },
+ {
+ "description": "Trouvez maintenant du poulet.",
+ "order": 2
+ },
+ {
+ "description": "Coupez la tĂȘte du poulet et posez-la dans un plat.",
+ "order": 3
+ },
+ {
+ "description": "Parsemez d'Ă©pices curry la tĂȘte de la poule.",
+ "order": 4
+ },
+ {
+ "description": "Mettre le tout au four traditionnel 30min.",
+ "order": 5
+ },
+ {
+ "description": "Dégustez en famille !",
+ "order": 6
+ }
+ ],
+ "priority": 4,
+ "reviews": [
+ {
+ "authorMail": "admin@mctg.fr",
+ "content": "Meilleure recette que j'ai avalé de tout les temps !!!!!!!",
+ "id": 7846,
+ "stars": 5
+ }
+ ],
+ "title": "Poulet au curry",
+ "type": 2
+ }
+ ]
+ },
+ {
+ "Key": "User",
+ "Value": [
+ {
+ "__type": "user:#Model",
+ "hashedpass": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
+ "mail": "admin@mctg.fr",
+ "name": "Admin",
+ "priorities": [
+ 4,
+ 0,
+ 1,
+ 3,
+ 2
+ ],
+ "profilepic": "default_picture.png",
+ "surname": "Admin"
+ },
+ {
+ "__type": "user:#Model",
+ "hashedpass": "df7415f099b2e105822cb6052a0de0a4eb6a4c4060b5ea191bff1271e1c377fa",
+ "mail": "pedrosamigos@hotmail.com",
+ "name": "Pedros",
+ "priorities": [
+ 4,
+ 0,
+ 1,
+ 3,
+ 2
+ ],
+ "profilepic": "default_picture.png",
+ "surname": "Amigos"
+ }
+ ]
+ }
+]
\ No newline at end of file