Merge branch 'master' of codefirst.iut.uca.fr:ShopNCook/ShopNCook
continuous-integration/drone/push Build is passing Details

master
Override-6 2 years ago
commit 424e5099d1
Signed by untrusted user who does not match committer: maxime.batista
GPG Key ID: 8002CC4B4DD9ECA5

@ -79,6 +79,26 @@ namespace LocalServices
} }
public bool RemoveFromWeeklyList(RecipeInfo info)
{
var weeklyDict = db.GetRecipeListOf(Account.User.Id);
if (!weeklyDict.ContainsKey(info.Id))
return false;
db.RemoveFromUserList(Account.User.Id, info.Id);
return true;
}
public bool IsInWeeklyList(RecipeInfo info)
{
foreach (var (inf, _) in GetWeeklyList())
{
if (inf == info) return true;
}
return false;
}
public void AddToFavorites(RecipeInfo info) public void AddToFavorites(RecipeInfo info)
{ {
Guid userId = Account.User.Id; Guid userId = Account.User.Id;

@ -172,11 +172,11 @@ namespace LocalServices.Data
} }
catch (IOException e) catch (IOException e)
{ {
Debug.WriteLine(e + " in thread " + Thread.CurrentThread); Debug.WriteLine(e.Message + " in thread " + Thread.CurrentThread.Name + " " + Thread.CurrentThread.ManagedThreadId);
if (fs != null) if (fs != null)
fs.Dispose(); fs.Dispose();
Thread.Sleep(100); Thread.Sleep(200);
} }
} }
throw new TimeoutException("Could not access file '" + fullPath + "', maximum attempts reached."); throw new TimeoutException("Could not access file '" + fullPath + "', maximum attempts reached.");

@ -51,5 +51,11 @@ namespace LocalServices
return data; return data;
} }
public ImmutableList<RecipeInfo> SearchRecipes(string prompt)
{
return db.ListAllRecipes()
.ConvertAll(r => r.Info)
.FindAll(i => i.Name.ToLower().Contains(prompt.ToLower()));
}
} }
} }

@ -14,6 +14,12 @@ namespace Services
/// <returns>A list containg the popular recipes of the week</returns> /// <returns>A list containg the popular recipes of the week</returns>
public ImmutableList<RecipeInfo> PopularRecipes(); public ImmutableList<RecipeInfo> PopularRecipes();
/// <summary>
/// performs a search over all the recipes
/// </summary>
/// <returns>A list containg the recipes that matches the prompt</returns>
public ImmutableList<RecipeInfo> SearchRecipes(string prompt);
/// <summary> /// <summary>
/// Retrieves a recipe from given RecipeInfo /// Retrieves a recipe from given RecipeInfo
/// </summary> /// </summary>

@ -1,149 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShoopNCook.Pages.ChangePassword"
Title="ChangePassword"
BackgroundColor="{StaticResource BackgroundPrimary}">
<ScrollView>
<Grid
Margin="20"
RowDefinitions="Auto, Auto, Auto, *">
<!-- Change Password label and return button -->
<Grid
Grid.Row="0"
RowDefinitions="Auto, *"
ColumnDefinitions="*, 3*"
Margin="0, 0, 0, 40">
<HorizontalStackLayout>
<ImageButton
Grid.Column="0"
Clicked="OnBackButtonClicked"
HeightRequest="50"
WidthRequest="50"
Source="arrow_back.svg"/>
</HorizontalStackLayout>
<Label
Grid.Column="1"
FontSize="24"
TextColor="{StaticResource TextColorPrimary}"
Text="Change Password"
FontFamily="PoppinsBold"
VerticalOptions="Center"/>
</Grid>
<!-- User inputs -->
<Grid
Grid.Row="2"
Margin="0, 20, 0, 0"
RowDefinitions="Auto, *, Auto, *,Auto,*">
<VerticalStackLayout>
<Label
Grid.Row="0"
Text="Old Password Here :"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Style="{StaticResource SecondaryBorder}"
Margin="0,30,10,20">
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="password_icon.svg">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="Old Password"
IsPassword="True"/>
</Grid>
</Border>
<Label
Grid.Row="0"
Text="New Password Here :"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Style="{StaticResource SecondaryBorder}"
Margin="0,30,0,20">
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="password_icon.svg">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="New Password"
IsPassword="True"/>
</Grid>
</Border>
<Label
Grid.Row="0"
Text="Confirm New Password Here :"
FontFamily="PoppinsBold"
Margin="0,0,0,0"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Style="{StaticResource SecondaryBorder}"
Margin="0,30,0,20">
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="password_icon.svg">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="New Password"
IsPassword="True"/>
</Grid>
</Border>
</VerticalStackLayout>
</Grid>
<!-- Save button -->
<VerticalStackLayout
Grid.Row="3"
VerticalOptions="End">
<Border
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
HeightRequest="50"
Style="{StaticResource UserButton}"
BackgroundColor="{StaticResource ActionButton}"
Text="SAVE"/>
</Border>
</VerticalStackLayout>
</Grid>
</ScrollView>
</ContentPage>

@ -1,13 +0,0 @@
namespace ShoopNCook.Pages;
public partial class ChangePassword : ContentPage
{
public ChangePassword()
{
InitializeComponent();
}
private async void OnBackButtonClicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
}

@ -3,6 +3,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShoopNCook.Views.CounterView" x:Class="ShoopNCook.Views.CounterView"
x:Name="Counter"> x:Name="Counter">
<ContentView.BindingContext>
<x:Reference Name="Counter"/>
</ContentView.BindingContext>
<Grid <Grid
ColumnDefinitions="*, Auto, *"> ColumnDefinitions="*, Auto, *">
@ -23,15 +26,13 @@
Spacing="3" Spacing="3"
Margin="10, 0, 10, 0"> Margin="10, 0, 10, 0">
<Label <Label
x:Name="CountLabel" Text="{Binding Count}"
Text="{Binding Count, Source={x:Reference Counter}}"
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
VerticalTextAlignment="Center" VerticalTextAlignment="Center"
FontFamily="PoppinsMedium"/> FontFamily="PoppinsMedium"/>
<Label <Label
x:Name="CounterLabel" Text="{Binding CounterText}"
Text="{Binding CounterText, Source={x:Reference Counter}}"
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
VerticalTextAlignment="Center" VerticalTextAlignment="Center"
FontFamily="PoppinsMedium"/> FontFamily="PoppinsMedium"/>

@ -1,51 +1,36 @@
namespace ShoopNCook.Views; namespace ShoopNCook.Views;
// Classe représentant une vue avec un compteur
public partial class CounterView : ContentView public partial class CounterView : ContentView
{ {
// Propriété liée pour le nombre à afficher public static readonly BindableProperty CountProperty =
private readonly BindableProperty CountProperty = BindableProperty.Create(nameof(Count), typeof(uint), typeof(CounterView), default(uint) + 1);
BindableProperty.Create(nameof(CountLabel), typeof(uint), typeof(CounterView), default(uint) + 1);
// Propriété liée pour le texte à afficher public static readonly BindableProperty CounterTextProperty =
private readonly BindableProperty CounterLabelProperty = BindableProperty.Create(nameof(CounterText), typeof(string), typeof(CounterView), default(string));
BindableProperty.Create(nameof(CounterLabel), typeof(string), typeof(CounterView), default(string));
public CounterView() public CounterView()
{ {
InitializeComponent(); InitializeComponent();
// Liaison des propriétés à leurs étiquettes respectives
CountLabel.BindingContext = this;
CountLabel.SetBinding(Label.TextProperty, nameof(Count));
CounterLabel.BindingContext = this;
CounterLabel.SetBinding(Label.TextProperty, nameof(CounterText));
} }
// Accesseurs pour Count
public uint Count public uint Count
{ {
get => (uint)GetValue(CountProperty); get => (uint)GetValue(CountProperty);
set set
{ {
// Assure que la valeur est toujours au minimum 1
SetValue(CountProperty, value <= 1 ? 1 : uint.Parse(value.ToString())); SetValue(CountProperty, value <= 1 ? 1 : uint.Parse(value.ToString()));
OnPropertyChanged(nameof(Count));
} }
} }
// Accesseurs pour CounterText
public string CounterText public string CounterText
{ {
get => (string)GetValue(CounterLabelProperty); get => (string)GetValue(CounterTextProperty);
set set
{ {
SetValue(CounterLabelProperty, value); SetValue(CounterTextProperty, value);
OnPropertyChanged(nameof(CounterText));
} }
} }
// Méthodes pour augmenter et diminuer le compteur
private void OnPlus(object o, EventArgs e) private void OnPlus(object o, EventArgs e)
{ {
Count += 1; Count += 1;
@ -56,3 +41,4 @@ public partial class CounterView : ContentView
Count -= 1; Count -= 1;
} }
} }

@ -3,6 +3,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShoopNCook.Views.IngredientView" x:Class="ShoopNCook.Views.IngredientView"
x:Name="Ingredient"> x:Name="Ingredient">
<ContentView.BindingContext>
<x:Reference Name="Ingredient"/>
</ContentView.BindingContext>
<HorizontalStackLayout <HorizontalStackLayout
Spacing="2"> Spacing="2">
<Label <Label
@ -10,15 +15,15 @@
Style="{StaticResource Small}"/> Style="{StaticResource Small}"/>
<Label <Label
Text="{Binding Name, Source={x:Reference Ingredient}}" Text="{Binding Name}"
Style="{StaticResource Small}"/> Style="{StaticResource Small}"/>
<Label <Label
Text="{Binding Quantity, Source={x:Reference Ingredient}}" Text="{Binding Quantity}"
Style="{StaticResource Small}"/> Style="{StaticResource Small}"/>
<Label <Label
Text="{Binding Unit, Source={x:Reference Ingredient}}" Text="{Binding Unit}"
Style="{StaticResource Small}"/> Style="{StaticResource Small}"/>
</HorizontalStackLayout> </HorizontalStackLayout>
</ContentView> </ContentView>

@ -9,10 +9,10 @@ public partial class IngredientView : ContentView
private readonly BindableProperty NameProperty = private readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name), typeof(string), typeof(IngredientView), default(string)); BindableProperty.Create(nameof(Name), typeof(string), typeof(IngredientView), default(string));
private readonly BindableProperty QuantityProperty = public static readonly BindableProperty QuantityProperty =
BindableProperty.Create(nameof(Quantity), typeof(float), typeof(IngredientView), default(float)); BindableProperty.Create(nameof(Quantity), typeof(float), typeof(IngredientView), default(float));
private readonly BindableProperty UnitProperty = public static readonly BindableProperty UnitProperty =
BindableProperty.Create(nameof(Unit), typeof(string), typeof(IngredientView), default(string)); BindableProperty.Create(nameof(Unit), typeof(string), typeof(IngredientView), default(string));
public string Name public string Name

@ -28,7 +28,7 @@
StrokeShape="RoundRectangle 20" StrokeShape="RoundRectangle 20"
BackgroundColor="{StaticResource ImageBackground}"> BackgroundColor="{StaticResource ImageBackground}">
<Grid> <Grid>
<Image x:Name="RecipeImage" <Image Source="{Binding Image}"
MinimumHeightRequest="175" MinimumHeightRequest="175"
MinimumWidthRequest="150" MinimumWidthRequest="150"
MaximumHeightRequest="175" MaximumHeightRequest="175"
@ -61,7 +61,7 @@
<VerticalStackLayout Grid.Row="1"> <VerticalStackLayout Grid.Row="1">
<Label <Label
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
x:Name="TitleLabel"/> Text="{Binding Name}"/>
<Border <Border
BackgroundColor="{StaticResource Selected}" BackgroundColor="{StaticResource Selected}"
Stroke="Transparent" Stroke="Transparent"

@ -13,12 +13,9 @@ public partial class OwnedRecipeView : ContentView
{ {
InitializeComponent(); InitializeComponent();
if (info.Image != null)
RecipeImage.Source = ImageSource.FromUri(info.Image);
Note = info.AverageNote; Note = info.AverageNote;
Title = info.Name;
this.recipeInfo = info; BindingContext = info;
this.clickCallback = onClickCallback; this.clickCallback = onClickCallback;
this.removeCallback = onRemoveCallback; this.removeCallback = onRemoveCallback;
} }
@ -32,10 +29,6 @@ public partial class OwnedRecipeView : ContentView
set => SetNote(value); set => SetNote(value);
} }
public string Title
{
set => TitleLabel.Text = value;
}
private void SetNote(float note) private void SetNote(float note)
{ {

@ -4,7 +4,6 @@
x:Class="ShoopNCook.Views.RecipeView" x:Class="ShoopNCook.Views.RecipeView"
Margin="4,2"> Margin="4,2">
<Border <Border
Style="{StaticResource SecondaryBorderShadow}" Style="{StaticResource SecondaryBorderShadow}"
StrokeShape="RoundRectangle 30"> StrokeShape="RoundRectangle 30">
@ -21,21 +20,23 @@
<Grid.GestureRecognizers> <Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="OnRecipeTapped"/> <TapGestureRecognizer Tapped="OnRecipeTapped"/>
</Grid.GestureRecognizers> </Grid.GestureRecognizers>
<Border <Border
Grid.Row="0" Grid.Row="0"
Stroke="Transparent" Stroke="Transparent"
StrokeShape="RoundRectangle 20" StrokeShape="RoundRectangle 20"
BackgroundColor="{StaticResource ImageBackground}"> BackgroundColor="{StaticResource ImageBackground}">
<Grid> <Grid>
<Image x:Name="RecipeImage" <Image
Aspect="AspectFill" Source="{Binding Image}"
MinimumHeightRequest="155" Aspect="AspectFill"
MinimumWidthRequest="130" MinimumHeightRequest="155"
MaximumHeightRequest="155" MinimumWidthRequest="130"
MaximumWidthRequest="130"/> MaximumHeightRequest="155"
MaximumWidthRequest="130"/>
<HorizontalStackLayout <HorizontalStackLayout
x:Name="Stars"
VerticalOptions="End" VerticalOptions="End"
x:Name="Stars"
HorizontalOptions="End" HorizontalOptions="End"
Margin="0, 0, 15, 2"> Margin="0, 0, 15, 2">
<Image <Image
@ -60,10 +61,10 @@
<VerticalStackLayout Grid.Row="1"> <VerticalStackLayout Grid.Row="1">
<Label <Label
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
x:Name="TitleLabel"/> Text="{Binding Name}"/>
<Label <Label
TextColor="{StaticResource TextColorSecondary}" TextColor="{StaticResource TextColorSecondary}"
x:Name="SubtitleLabel"/> Text="{Binding CookTimeMins, StringFormat='{0} mins'}"/>
</VerticalStackLayout> </VerticalStackLayout>
</Grid> </Grid>
</Border> </Border>

@ -1,59 +1,44 @@
using ShoopNCook.Pages;
using Models; using Models;
namespace ShoopNCook.Views;
public partial class RecipeView : ContentView namespace ShoopNCook.Views
{ {
public partial class RecipeView : ContentView
private readonly Action callback;
public RecipeView(RecipeInfo info, Action onClickCallback)
{
InitializeComponent();
if (info.Image != null)
RecipeImage.Source = ImageSource.FromUri(info.Image);
Note = info.AverageNote;
Title = info.Name;
Subtitle = info.CookTimeMins + " min";
callback = onClickCallback;
}
public float Note
{ {
set => SetNote(value); private readonly Action callback;
} public RecipeInfo Info { get; private init; }
public string Title public RecipeView(RecipeInfo info, Action callback)
{ {
set => TitleLabel.Text = value; this.callback = callback;
} Info = info;
BindingContext = info;
InitializeComponent();
Note = info.AverageNote;
}
public string Subtitle public float Note
{ {
set => SubtitleLabel.Text = value; set => SetNote(value);
} }
private void SetNote(float note)
{ private void SetNote(float note)
note = (uint)note; //truncate integer as we currently do not handle semi stars
foreach (Image img in Stars.Children.Reverse())
{ {
if (note > 0) note = (uint)note; //truncate integer as we currently do not handle semi stars
foreach (Image img in Stars.Children.Reverse())
{ {
img.Opacity = 1; if (note > 0)
note--; {
img.Opacity = 1;
note--;
}
else img.Opacity = 0;
} }
else img.Opacity = 0;
} }
}
private void OnRecipeTapped(object sender, EventArgs e) private void OnRecipeTapped(object sender, EventArgs e)
{ {
callback(); callback();
}
} }
} }

@ -26,7 +26,7 @@
MaximumHeightRequest="300" MaximumHeightRequest="300"
BackgroundColor="{StaticResource ImageBackground}"> BackgroundColor="{StaticResource ImageBackground}">
<Grid> <Grid>
<Image x:Name="RecipeImage" <Image Source="{Binding Image}"
Aspect="AspectFill"/> Aspect="AspectFill"/>
<HorizontalStackLayout <HorizontalStackLayout
x:Name="Stars" x:Name="Stars"
@ -57,7 +57,7 @@
Grid.Row="1"> Grid.Row="1">
<Label <Label
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
x:Name="TitleLabel"/> Text="{Binding Name}"/>
<views:CounterView <views:CounterView
CounterText="pers" CounterText="pers"
x:Name="Counter"/> x:Name="Counter"/>

@ -12,11 +12,8 @@ public partial class StoredRecipeView : ContentView
{ {
InitializeComponent(); InitializeComponent();
if (info.Image != null)
RecipeImage.Source = ImageSource.FromUri(info.Image);
Note = info.AverageNote; Note = info.AverageNote;
Title = info.Name; BindingContext = info;
clickCallback = onClickCallback; clickCallback = onClickCallback;
Counter.Count = personCount; Counter.Count = personCount;
} }
@ -26,10 +23,6 @@ public partial class StoredRecipeView : ContentView
set => SetNote(value); set => SetNote(value);
} }
public string Title
{
set => TitleLabel.Text = value;
}
private void SetNote(float note) private void SetNote(float note)
{ {

@ -1,148 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShoopNCook.Pages.ConfirmMail"
Title="ConfirmMail"
BackgroundColor="{StaticResource BackgroundPrimary}">
<ScrollView>
<Grid
Padding="20"
RowDefinitions="Auto, Auto, Auto, *">
<!-- Profile label and return button -->
<Grid
Grid.Row="0"
RowDefinitions="Auto, *"
ColumnDefinitions="*, 1.5*"
Margin="0, 0, 0, 40">
<HorizontalStackLayout>
<ImageButton
Grid.Column="0"
HeightRequest="50"
WidthRequest="50"
Source="arrow_back.svg"
Clicked="OnBackButtonClicked"/>
</HorizontalStackLayout>
<Label
Margin="-40,10,0,0"
Grid.Column="1"
FontSize="24"
TextColor="{StaticResource TextColorPrimary}"
Text="Confirm Email"
FontFamily="PoppinsBold"
VerticalOptions="Start"/>
</Grid>
<!-- Email entry -->
<Grid
Grid.Row="1"
RowDefinitions="*, Auto, Auto">
<Label
Grid.Row="0"
FontSize="15"
TextColor="{StaticResource TextColorSecondary}"
Text="The following email address is yours ?"
FontFamily="PoppinsBold"
VerticalOptions="Center"/>
<Border
Grid.Row="1"
Style="{StaticResource SecondaryBorder}"
Margin="0,30,0,20">
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="email_icon.svg">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Text="%Profile_Mail%"></Entry>
</Grid>
</Border>
<VerticalStackLayout
Grid.Row="2"
VerticalOptions="End">
<Border
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
BackgroundColor="{StaticResource ActionButton}"
FontFamily="PoppinsMedium"
TextColor="White"
Text="That's been my email"
/>
</Border>
</VerticalStackLayout>
</Grid>
<Grid>
</Grid>
<!-- Sendmail grid -->
<Grid
Grid.Row="2"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto"
RowSpacing="10">
<Label
Grid.Row="0"
Margin="20"
Text="A recuperation code get send to your email address. Type it here to confirm your email. "
FontFamily="PoppinsBold"
TextColor="LightGreen"/>
<Label
Grid.Row="1"
Text="Enter the code here"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Grid.Row="2"
Style="{StaticResource SecondaryBorder}"
>
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="code.png">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="Code"/>
</Grid>
</Border>
</Grid>
<!-- Confirm button -->
<VerticalStackLayout
Grid.Row="3"
VerticalOptions="End">
<Border
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
BackgroundColor="{StaticResource ActionButton}"
FontFamily="PoppinsMedium"
TextColor="White"
Text="Confirm my email"
Clicked="OnRegiterButtonTapped"/>
</Border>
</VerticalStackLayout>
</Grid>
</ScrollView>
</ContentPage>

@ -1,17 +0,0 @@
namespace ShoopNCook.Pages;
public partial class ConfirmMail : ContentPage
{
public ConfirmMail()
{
InitializeComponent();
}
private async void OnRegiterButtonTapped(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//LoginPage");
}
private async void OnBackButtonClicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
}

@ -1,4 +1,3 @@
using Models;
namespace ShoopNCook.Pages; namespace ShoopNCook.Pages;

@ -1,173 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShoopNCook.Pages.ForgotPassword"
Title="ForgotPassword"
BackgroundColor="{StaticResource BackgroundPrimary}">
<ScrollView>
<Grid
Padding="20"
RowDefinitions="Auto, Auto, Auto, *">
<!-- Profile label and return button -->
<Grid
Grid.Row="0"
RowDefinitions="Auto, *"
ColumnDefinitions="*, 1.5*"
Margin="0, 0, 0, 40">
<HorizontalStackLayout>
<ImageButton
Grid.Column="0"
HeightRequest="50"
WidthRequest="50"
Source="arrow_back.svg"
Clicked="OnBackButtonClicked"/>
</HorizontalStackLayout>
<Label
Margin="-40,10,0,0"
Grid.Column="1"
FontSize="24"
TextColor="{StaticResource TextColorPrimary}"
Text="Forgot Password"
FontFamily="PoppinsBold"
VerticalOptions="Start"/>
</Grid>
<!-- Email entry -->
<Grid
Grid.Row="1"
RowDefinitions="*, Auto, Auto"
>
<Label
Grid.Row="0"
FontSize="15"
TextColor="{StaticResource TextColorSecondary}"
Text="Enter your email here : "
FontFamily="PoppinsBold"
VerticalOptions="Center"/>
<Border
Grid.Row="1"
Style="{StaticResource SecondaryBorder}"
Margin="0,30,0,20">
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="email_icon.svg">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="User Name"/>
</Grid>
</Border>
<VerticalStackLayout
Grid.Row="2"
VerticalOptions="End">
<Border
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
BackgroundColor="{StaticResource ActionButton}"
FontFamily="PoppinsMedium"
TextColor="White"
Text="Recup my Password"/>
</Border>
</VerticalStackLayout>
</Grid>
<Grid>
</Grid>
<!-- Sendmail grid -->
<Grid
Grid.Row="2"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto"
RowSpacing="10">
<Label
Grid.Row="0"
Margin="20"
Text="A recuperation code as been send to your email address ! "
FontFamily="PoppinsBold"
TextColor="LightGreen"/>
<Label
Grid.Row="1"
Text="Enter the code here"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Grid.Row="2"
Style="{StaticResource SecondaryBorder}"
>
<Grid
Padding="5"
BackgroundColor="{StaticResource BackgroundSecondary}"
ColumnDefinitions="Auto,Auto,*">
<Image
Grid.Column="1"
Source="code.png">
</Image>
<Entry
Style="{StaticResource UserInput}"
Grid.Column="2"
Placeholder="Code"/>
</Grid>
</Border>
<Label
Grid.Row="3"
Text="Enter new Password here"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Grid.Row="4"
Style="{StaticResource SecondaryBorderShadow}">
<Entry
Style="{StaticResource UserInput}"
Placeholder="New password"
IsPassword="True"/>
</Border>
<Label
Grid.Row="5"
Text="Confirm your new Password here"
FontFamily="PoppinsBold"
TextColor="{StaticResource TextColorSecondary}"/>
<Border
Grid.Row="6"
Style="{StaticResource SecondaryBorderShadow}">
<Entry
Style="{StaticResource UserInput}"
Placeholder="New password"
IsPassword="True"/>
</Border>
</Grid>
<!-- Save button -->
<VerticalStackLayout
Grid.Row="3"
VerticalOptions="End">
<Border
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
BackgroundColor="{StaticResource ActionButton}"
FontFamily="PoppinsMedium"
TextColor="White"
Text="Save Change"/>
</Border>
</VerticalStackLayout>
</Grid>
</ScrollView>
</ContentPage>

@ -1,13 +0,0 @@
namespace ShoopNCook.Pages;
public partial class ForgotPassword : ContentPage
{
public ForgotPassword()
{
InitializeComponent();
}
private async void OnBackButtonClicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
}

@ -20,12 +20,14 @@
BackgroundColor="{StaticResource BackgroundSecondary}" BackgroundColor="{StaticResource BackgroundSecondary}"
StrokeShape="RoundRectangle 1500"> StrokeShape="RoundRectangle 1500">
<ImageButton <ImageButton
x:Name="ProfilePictureImage" Source="{Binding ProfilePicture}"
WidthRequest="65" WidthRequest="65"
HeightRequest="65"/> HeightRequest="65"/>
</Border> </Border>
<Label Style="{StaticResource h1}" x:Name="ProfilePictureName"/> <Label
Style="{StaticResource h1}"
Text="{Binding Name}"/>
</FlexLayout> </FlexLayout>
<Grid <Grid
ColumnDefinitions="*,Auto" ColumnDefinitions="*,Auto"
@ -38,7 +40,8 @@
<Entry <Entry
Style="{StaticResource UserInput}" Style="{StaticResource UserInput}"
Grid.Column="0" Grid.Column="0"
Placeholder="Search here..."/> Placeholder="Search here..."
x:Name="SearchPrompt"/>
</Border> </Border>
<ImageButton <ImageButton
@ -89,8 +92,7 @@
JustifyContent="SpaceBetween" JustifyContent="SpaceBetween"
AlignItems="Center" AlignItems="Center"
Margin="20,0,20,20" Margin="20,0,20,20"
HeightRequest="30" HeightRequest="30">
>
<Label <Label
Text="Recommended for you" Text="Recommended for you"
Style="{StaticResource h2}"/> Style="{StaticResource h2}"/>

@ -1,25 +1,27 @@
namespace ShoopNCook.Pages; namespace ShoopNCook.Pages;
using Models; using Models;
using ShoopNCook.Views; using ShoopNCook.Views;
using Services; using Services;
using Services;
public partial class HomePage : ContentPage public partial class HomePage : ContentPage
{ {
public HomePage(Account account, IEndpoint endpoint) private readonly IRecipesService recipes;
private readonly IAccountRecipesPreferencesService preferences;
public HomePage(Account account, IEndpoint endpoint)
{ {
InitializeComponent(); InitializeComponent();
IRecipesService service = endpoint.RecipesService; BindingContext = account.User;
IAccountRecipesPreferencesService preferences = service.GetPreferencesOf(account); recipes = endpoint.RecipesService;
preferences = recipes.GetPreferencesOf(account);
//TODO this code can be factorised
void PushRecipe(Layout layout, RecipeInfo info) void PushRecipe(Layout layout, RecipeInfo info)
{ {
layout.Children.Add(new RecipeView(info, () => layout.Children.Add(new RecipeView(info, () =>
{ {
Recipe recipe = service.GetRecipe(info); Recipe recipe = recipes.GetRecipe(info);
if (recipe != null) if (recipe != null)
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, preferences, 1)); Shell.Current.Navigation.PushAsync(new RecipePage(recipe, preferences, 1));
else else
@ -29,15 +31,18 @@ public partial class HomePage : ContentPage
})); }));
} }
service.PopularRecipes().ForEach(recipe => PushRecipe(PopularsList, recipe)); recipes.PopularRecipes().ForEach(recipe => PushRecipe(PopularsList, recipe));
preferences.GetRecommendedRecipes().ForEach(recipe => PushRecipe(RecommendedList, recipe)); preferences.GetRecommendedRecipes().ForEach(recipe => PushRecipe(RecommendedList, recipe));
ProfilePictureImage.Source = ImageSource.FromUri(account.User.ProfilePicture);
ProfilePictureName.Text = account.User.Name;
} }
private async void OnSyncButtonClicked(object sender, EventArgs e) private async void OnSyncButtonClicked(object sender, EventArgs e)
{ {
await Shell.Current.Navigation.PushAsync(new SearchPage()); string prompt = SearchPrompt.Text;
if (string.IsNullOrEmpty(prompt))
return;
var searchPage = new SearchPage(recipes, preferences);
await Shell.Current.Navigation.PushAsync(searchPage);
searchPage.MakeSearch(SearchPrompt.Text);
} }
} }

@ -69,16 +69,6 @@
</Grid> </Grid>
</Border> </Border>
<Label
TextColor="{StaticResource TextColorSecondary}"
HorizontalOptions="End"
Text="Forgot Password ?"
BackgroundColor="Transparent">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="ForgotPasswordTapped" />
</Label.GestureRecognizers>
</Label>
<Border <Border
Margin="0, 30, 0, 0" Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}" Stroke="{StaticResource BackgroundPrimary}"

@ -17,10 +17,7 @@ public partial class LoginPage : ContentPage
string password = PasswordEntry.Text; string password = PasswordEntry.Text;
controller.Login(email, password); controller.Login(email, password);
} }
private async void ForgotPasswordTapped(object sender, EventArgs e)
{
await Shell.Current.Navigation.PushAsync(new ForgotPassword());
}
private async void RegisterLabbelTapped(object sender, EventArgs e) private async void RegisterLabbelTapped(object sender, EventArgs e)
{ {
await Shell.Current.GoToAsync("//Register"); await Shell.Current.GoToAsync("//Register");

@ -15,11 +15,10 @@
ColumnDefinitions="*, 2*" ColumnDefinitions="*, 2*"
ColumnSpacing="30"> ColumnSpacing="30">
<Image <Image Source="{Binding Account.User.ProfilePicture}"/>
x:Name="ProfileImage"/>
<Label <Label
x:Name="ProfileName" Text="{Binding Account.User.Name}"
Grid.Column="1" Grid.Column="1"
FontSize="24" FontSize="24"
VerticalTextAlignment="Center" VerticalTextAlignment="Center"

@ -7,12 +7,13 @@ public partial class MorePage : ContentPage
{ {
private readonly MorePageController controller; private readonly MorePageController controller;
public Account Account { get; private init; }
public MorePage(Account account, MorePageController controller) public MorePage(Account account, MorePageController controller)
{ {
Account = account;
BindingContext = this;
InitializeComponent(); InitializeComponent();
ProfileImage.Source = ImageSource.FromUri(account.User.ProfilePicture);
ProfileName.Text = account.User.Name;
this.controller = controller; this.controller = controller;
} }

@ -36,15 +36,5 @@
</VerticalStackLayout> </VerticalStackLayout>
</ScrollView> </ScrollView>
<!-- Footer button -->
<Border
Margin="20, 0, 20, 5"
Grid.Row="2"
Style="{StaticResource SecondaryBorder}">
<Button
Style="{StaticResource UserButton}"
BackgroundColor="{StaticResource Selected}"
Text="Show Ingredient List"/>
</Border>
</Grid> </Grid>
</ContentPage> </ContentPage>

@ -50,9 +50,7 @@
HorizontalOptions="Center" HorizontalOptions="Center"
Stroke="{StaticResource BackgroundPrimary}" Stroke="{StaticResource BackgroundPrimary}"
BackgroundColor="{StaticResource BackgroundSecondary}"> BackgroundColor="{StaticResource BackgroundSecondary}">
<ImageButton <ImageButton x:Name="ProfilePicture"/>
Grid.Row="0"
Source="default_profile_picture.png"/>
</Border> </Border>
<Label <Label
@ -60,7 +58,7 @@
FontSize="30" FontSize="30"
HorizontalOptions="Center" HorizontalOptions="Center"
TextColor="{StaticResource TextColorPrimary}" TextColor="{StaticResource TextColorPrimary}"
Text="%Profile_Name%" Text="{Binding Account.User.Name}"
FontFamily="PoppinsBold"/> FontFamily="PoppinsBold"/>
<Label <Label
Grid.Row="2" Grid.Row="2"
@ -88,8 +86,8 @@
Style="{StaticResource SecondaryBorderShadow}"> Style="{StaticResource SecondaryBorderShadow}">
<Entry <Entry
Style="{StaticResource UserInput}" Style="{StaticResource UserInput}"
Text="%Profile_Name%" Text="{Binding User.Name}"
Placeholder="Place your name here"/> IsReadOnly="True"/>
</Border> </Border>
<Label <Label
@ -103,23 +101,9 @@
Style="{StaticResource SecondaryBorderShadow}"> Style="{StaticResource SecondaryBorderShadow}">
<Entry <Entry
Style="{StaticResource UserInput}" Style="{StaticResource UserInput}"
Text="%Profile_Mail%" Text="{Binding Email}"
Placeholder="Place your email address here"/> IsReadOnly="True"/>
</Border> </Border>
<Border
Grid.Row="4"
Margin="0, 30, 0, 0"
Stroke="{StaticResource BackgroundPrimary}"
StrokeShape="RoundRectangle 12">
<Button
BackgroundColor="{StaticResource ActionButton}"
FontFamily="PoppinsMedium"
TextColor="White"
Text="Change My Password"
Clicked="ChangeMyPasswordClicked"/>
</Border>
</Grid> </Grid>

@ -4,16 +4,18 @@ namespace ShoopNCook.Pages;
public partial class ProfilePage : ContentPage public partial class ProfilePage : ContentPage
{ {
public ProfilePage(Account account) public ProfilePage(Account account)
{ {
BindingContext = account;
InitializeComponent(); InitializeComponent();
}
ProfilePicture.Source = ImageSource.FromUri(account.User.ProfilePicture);
}
private async void OnBackButtonClicked(object sender, EventArgs e) private async void OnBackButtonClicked(object sender, EventArgs e)
{ {
await Navigation.PopAsync(); await Navigation.PopAsync();
} }
private async void ChangeMyPasswordClicked(object sender, EventArgs e)
{
await Shell.Current.Navigation.PushAsync(new ChangePassword()) ;
}
} }

@ -30,8 +30,7 @@
<Label <Label
Style="{StaticResource h1}" Style="{StaticResource h1}"
x:Name="RecipeName" Text="{Binding Recipe.Info.Name}"/>
Text="Recipe name"/>
<ImageButton <ImageButton
x:Name="Favorite" x:Name="Favorite"
@ -50,7 +49,7 @@
<Image <Image
Aspect="AspectFill" Aspect="AspectFill"
HeightRequest="250" HeightRequest="250"
x:Name="RecipeImage"/> Source="{Binding Recipe.Info.Image}"/>
</Border> </Border>
<!--Steps--> <!--Steps-->
@ -61,38 +60,22 @@
<!--Cook time--> <!--Cook time-->
<VerticalStackLayout> <VerticalStackLayout>
<HorizontalStackLayout> <Label
<Label Style="{StaticResource Small}"
Style="{StaticResource Small}" Text="{Binding Recipe.Info.CookTimeMins, StringFormat='Cooking time: {0} mins'}"/>
Text="Cooking time: "/>
<Label
Style="{StaticResource Small}"
x:Name="CookTime"/>
<Label
Style="{StaticResource Small}"
Text=" min"/>
</HorizontalStackLayout>
<!--Energy--> <!--Energy-->
<Label
Style="{StaticResource Small}"
Text="{Binding Recipe.Info.CalPerPers, StringFormat='Energy: {0}/pers'}"/>
<HorizontalStackLayout>
<Label
Style="{StaticResource Small}"
Text="Energy: "/>
<Label
Style="{StaticResource Small}"
x:Name="Energy"/>
<Label
Style="{StaticResource Small}"
Text="/pers"/>
</HorizontalStackLayout>
</VerticalStackLayout> </VerticalStackLayout>
<!--Ingredient list-->
<Label <Label
Style="{StaticResource h2}" Style="{StaticResource h2}"
Text="Ingredients"/> Text="Ingredients"/>
<!--Ingredient list-->
<VerticalStackLayout <VerticalStackLayout
x:Name="IngredientList"/> x:Name="IngredientList"/>
@ -155,25 +138,26 @@
<!--Footer--> <!--Footer-->
<FlexLayout <Grid
Grid.Row="1" Grid.Row="1"
Direction="Row" ColumnDefinitions="Auto, *, Auto"
JustifyContent="SpaceBetween" HeightRequest="50"
AlignItems="Center"
> >
<views:CounterView <views:CounterView
Grid.Column="0"
x:Name="Counter" x:Name="Counter"
CounterText="pers" CounterText="pers"
HeightRequest="41"
Count="1"/> Count="1"/>
<Button <Button
Grid.Column="1" Grid.Column="2"
Text="Add to list"
Style="{StaticResource UserButton}" Style="{StaticResource UserButton}"
TextColor="White"
BackgroundColor="Gray" BackgroundColor="Gray"
Clicked="OnAddToMyListClicked"> Text="Add To Weekly List"
</Button> x:Name="MyListStateButton"
</FlexLayout> Clicked="OnFooterButtonClicked"/>
</Grid>
</Grid> </Grid>
</ContentPage> </ContentPage>

@ -2,28 +2,30 @@ using ShoopNCook.Views;
using System.Windows.Input; using System.Windows.Input;
using Models; using Models;
using Services; using Services;
using Services;
namespace ShoopNCook.Pages; namespace ShoopNCook.Pages;
public partial class RecipePage : ContentPage public partial class RecipePage : ContentPage
{ {
private readonly IAccountRecipesPreferencesService preferences;
private uint note; private uint note;
private bool isFavorite; private bool isFavorite;
public Recipe Recipe { get; init; }
private IAccountRecipesPreferencesService preferences;
private RecipeInfo info;
public ICommand StarCommand => new Command<string>(count => SetNote(uint.Parse(count))); public ICommand StarCommand => new Command<string>(count => SetNote(uint.Parse(count)));
public RecipePage(Recipe recipe, IAccountRecipesPreferencesService preferences, uint amount) public RecipePage(Recipe recipe, IAccountRecipesPreferencesService preferences, uint amount)
{ {
Recipe = recipe;
BindingContext = this;
InitializeComponent(); InitializeComponent();
this.preferences = preferences; this.preferences = preferences;
this.info = recipe.Info;
RecipeRate rate = preferences.GetRate(recipe.Info); RecipeRate rate = preferences.GetRate(recipe.Info);
@ -33,15 +35,7 @@ public partial class RecipePage : ContentPage
SetFavorite(isFavorite); SetFavorite(isFavorite);
SetNote(note); SetNote(note);
RecipeInfo info = recipe.Info;
Counter.Count = amount; Counter.Count = amount;
CookTime.Text = info.CookTimeMins.ToString();
Energy.Text = info.CalPerPers.ToString() + " cal/pers";
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));
@ -50,7 +44,8 @@ public partial class RecipePage : ContentPage
var styles = Application.Current.Resources.MergedDictionaries.ElementAt(1); var styles = Application.Current.Resources.MergedDictionaries.ElementAt(1);
int count = 0; int count = 0;
foreach (PreparationStep step in recipe.Steps) { foreach (PreparationStep step in recipe.Steps)
{
//TODO display name of PreparationSteps. //TODO display name of PreparationSteps.
Label label = new Label(); Label label = new Label();
label.Style = (Style)styles["Small"]; label.Style = (Style)styles["Small"];
@ -75,24 +70,29 @@ public partial class RecipePage : ContentPage
} }
} }
private async void OnFavorite(object o, EventArgs e) private void OnFavorite(object o, EventArgs e)
{ {
SetFavorite(!isFavorite); SetFavorite(!isFavorite);
if (isFavorite) if (isFavorite)
preferences.AddToFavorites(info); preferences.AddToFavorites(Recipe.Info);
else else
preferences.RemoveFromFavorites(info); preferences.RemoveFromFavorites(Recipe.Info);
} }
private async void OnSubmitReviewClicked(object o, EventArgs e) private void OnSubmitReviewClicked(object o, EventArgs e)
{ {
preferences.SetReviewScore(info, note); preferences.SetReviewScore(Recipe.Info, note);
UserNotifier.Success("Your review has been successfuly submited"); UserNotifier.Success("Your review has been successfuly submited");
} }
private async void OnAddToMyListClicked(object o, EventArgs e) private void OnFooterButtonClicked(object o, EventArgs e)
{ {
if (!preferences.AddToWeeklyList(info, Counter.Count)) AddToMyList();
}
private void AddToMyList()
{
if (!preferences.AddToWeeklyList(Recipe.Info, Counter.Count))
UserNotifier.Notice("You already added this recipe to you weekly list!"); UserNotifier.Notice("You already added this recipe to you weekly list!");
else else
UserNotifier.Success("Recipe added to your weekly list."); UserNotifier.Success("Recipe added to your weekly list.");
@ -106,9 +106,8 @@ public partial class RecipePage : ContentPage
else else
Favorite.Source = ImageSource.FromFile("hearth_off.svg"); Favorite.Source = ImageSource.FromFile("hearth_off.svg");
} }
private async void OnBackButtonClicked(object sender, EventArgs e) private void OnBackButtonClicked(object sender, EventArgs e)
{ {
await Navigation.PopAsync(); Navigation.PopAsync();
} }
} }

@ -49,18 +49,28 @@
Style="{StaticResource SecondaryBorderShadow}"> Style="{StaticResource SecondaryBorderShadow}">
<Entry <Entry
Style="{StaticResource UserInput}" Style="{StaticResource UserInput}"
Placeholder="Cake, Lasagna, Vegetarian..."/> Placeholder="Cake, Lasagna, Vegetarian..."
x:Name="SearchPrompt"/>
</Border> </Border>
<Border <Border
Style="{StaticResource SecondaryBorderShadow}" Style="{StaticResource SecondaryBorderShadow}"
Grid.Column="1" Grid.Column="1"
BackgroundColor="{StaticResource ActionButton}" BackgroundColor="{StaticResource ActionButton}"
Stroke="{StaticResource ActionButton}"> Stroke="{StaticResource ActionButton}">
<ImageButton <Label
Source="search_options.svg" BackgroundColor="Transparent"
Text="GO"
FontFamily="PoppinsMedium"
TextColor="White"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Center"
HeightRequest="40" HeightRequest="40"
WidthRequest="40"/> WidthRequest="40">
<Label.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnSearchClicked"/>
</Label.GestureRecognizers>
</Label>
</Border> </Border>
</Grid> </Grid>
@ -69,34 +79,10 @@
<!-- Selection result count --> <!-- Selection result count -->
<Label <Label
Grid.Row="2" Grid.Row="2"
Text="%Nb_Recipes% Recipes Found" Text="{Binding FoundRecipes.Count, StringFormat='{0} Recipes found'}"
TextColor="{StaticResource TextColorSecondary}" TextColor="{StaticResource TextColorSecondary}"
FontSize="20"/> FontSize="20"/>
<!-- Sort selection -->
<Grid
Grid.Row="3"
ColumnSpacing="10"
ColumnDefinitions="*, *">
<Button
Grid.Column="0"
Text="Most Relevent"
Style="{StaticResource UserButton}"
TextColor="{StaticResource White}"
BackgroundColor="{StaticResource Selected}">
</Button>
<Button
Grid.Column="1"
Text="Most Recent"
Style="{StaticResource UserButton}"
TextColor="{StaticResource TextColorSecondary}"
BackgroundColor="{StaticResource BackgroundSecondary}">
</Button>
</Grid>
<!-- Search result items --> <!-- Search result items -->
<ScrollView <ScrollView
Grid.Row="4"> Grid.Row="4">
@ -106,9 +92,22 @@
AlignContent="Start" AlignContent="Start"
Direction="Row" Direction="Row"
Wrap="Wrap" Wrap="Wrap"
x:Name="ResultSearchView"> BindableLayout.ItemsSource="{Binding FoundRecipes}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
<BindableLayout.EmptyViewTemplate>
<DataTemplate>
<Label
Style="{StaticResource h1}"
Text="No recipes found"/>
</DataTemplate>
</BindableLayout.EmptyViewTemplate>
</FlexLayout> </FlexLayout>
</ScrollView> </ScrollView>
</Grid> </Grid>

@ -1,12 +1,52 @@
using Models;
using Services;
using ShoopNCook.Views;
using System.Collections.ObjectModel;
namespace ShoopNCook.Pages; namespace ShoopNCook.Pages;
public partial class SearchPage : ContentPage public partial class SearchPage : ContentPage
{ {
public SearchPage() private readonly IRecipesService recipesService;
private readonly IAccountRecipesPreferencesService preferences;
public ObservableCollection<RecipeView> FoundRecipes { get; private init; } = new ObservableCollection<RecipeView>();
public SearchPage(IRecipesService recipes, IAccountRecipesPreferencesService preferences)
{ {
InitializeComponent(); BindingContext = this;
this.recipesService = recipes;
this.preferences = preferences;
InitializeComponent();
} }
public void MakeSearch(string prompt)
{
if (string.IsNullOrEmpty(prompt))
{
return;
}
SearchPrompt.Text = prompt;
FoundRecipes.Clear();
foreach (RecipeInfo info in recipesService.SearchRecipes(prompt))
{
FoundRecipes.Add(new RecipeView(info, () =>
{
Recipe recipe = recipesService.GetRecipe(info);
if (recipe != null)
Shell.Current.Navigation.PushAsync(new RecipePage(recipe, preferences, 1));
else
UserNotifier.Error("Could not find recipe");
}));
}
}
private async void OnBackButtonClicked(object sender, EventArgs e) private async void OnBackButtonClicked(object sender, EventArgs e)
{ {
await Navigation.PopAsync(); await Navigation.PopAsync();
} }
private void OnSearchClicked(object sender, EventArgs e)
{
MakeSearch(SearchPrompt.Text);
}
} }
Loading…
Cancel
Save