implement search
continuous-integration/drone/push Build is passing Details

master
maxime.BATISTA@etu.uca.fr 2 years ago
parent 1b6f6b25bf
commit feb052e286

@ -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>

@ -6,6 +6,7 @@ public partial class RecipeView : ContentView
{ {
private readonly Action callback; private readonly Action callback;
public RecipeInfo Info { get; set; }
public RecipeView(RecipeInfo info, Action onClickCallback) public RecipeView(RecipeInfo info, Action onClickCallback)
{ {

@ -38,7 +38,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

@ -2,24 +2,24 @@ 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
{ {
private readonly IRecipesService recipes;
private readonly IAccountRecipesPreferencesService preferences;
public HomePage(Account account, IEndpoint endpoint) public HomePage(Account account, IEndpoint endpoint)
{ {
InitializeComponent(); InitializeComponent();
IRecipesService service = endpoint.RecipesService; recipes = endpoint.RecipesService;
IAccountRecipesPreferencesService preferences = service.GetPreferencesOf(account); 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,7 +29,7 @@ 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); ProfilePictureImage.Source = ImageSource.FromUri(account.User.ProfilePicture);
@ -38,6 +38,14 @@ public partial class HomePage : ContentPage
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);
} }
} }

@ -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,7 +79,7 @@
<!-- 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"/>
@ -77,22 +87,15 @@
<Grid <Grid
Grid.Row="3" Grid.Row="3"
ColumnSpacing="10" ColumnSpacing="10"
ColumnDefinitions="*, *"> ColumnDefinitions="*">
<Button <Button
Grid.Column="0" Grid.Column="0"
Text="Most Relevent" Text="Best Rated"
Style="{StaticResource UserButton}" Style="{StaticResource UserButton}"
TextColor="{StaticResource White}" TextColor="{StaticResource White}"
BackgroundColor="{StaticResource Selected}"> BackgroundColor="{StaticResource Selected}"
</Button> Clicked="OnSortByRateClicked">
<Button
Grid.Column="1"
Text="Most Recent"
Style="{StaticResource UserButton}"
TextColor="{StaticResource TextColorSecondary}"
BackgroundColor="{StaticResource BackgroundSecondary}">
</Button> </Button>
</Grid> </Grid>
@ -106,9 +109,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,60 @@
using Microsoft.Maui.Storage;
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)
{ {
BindingContext = this;
this.recipesService = recipes;
this.preferences = preferences;
InitializeComponent(); InitializeComponent();
} }
public void MakeSearch(string prompt)
{
if (string.IsNullOrEmpty(prompt))
{
return;
}
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 OnSortByRateClicked(object sender, EventArgs e)
{
}
private void OnSearchClicked(object sender, EventArgs e)
{
MakeSearch(SearchPrompt.Text);
}
} }
Loading…
Cancel
Save