From b130381154eabb69fea20f9ddebe883eba542051 Mon Sep 17 00:00:00 2001 From: Natalia Cholewa Date: Fri, 9 Jan 2026 23:35:30 +0100 Subject: [PATCH] feat: clientside language filter and recipe language selector --- .../client/scenes/LanguageFilterCtrl.java | 87 +++++++++++++++++++ .../scenes/recipe/RecipeDetailCtrl.java | 21 +++++ client/src/main/java/client/utils/Config.java | 24 +++++ .../main/java/client/utils/ServerUtils.java | 13 ++- .../client/scenes/FoodpalApplication.fxml | 1 + .../client/scenes/LanguageFilter.fxml | 12 +++ .../scenes/recipe/RecipeDetailView.fxml | 2 + .../src/main/resources/locale/lang.properties | 2 + .../main/resources/locale/lang_en.properties | 3 + .../main/resources/locale/lang_nl.properties | 2 + .../main/resources/locale/lang_pl.properties | 3 + 11 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 client/src/main/java/client/scenes/LanguageFilterCtrl.java create mode 100644 client/src/main/resources/client/scenes/LanguageFilter.fxml diff --git a/client/src/main/java/client/scenes/LanguageFilterCtrl.java b/client/src/main/java/client/scenes/LanguageFilterCtrl.java new file mode 100644 index 0000000..56d79af --- /dev/null +++ b/client/src/main/java/client/scenes/LanguageFilterCtrl.java @@ -0,0 +1,87 @@ +package client.scenes; + +import client.utils.ConfigService; +import client.utils.LocaleAware; +import client.utils.LocaleManager; +import com.google.inject.Inject; +import javafx.fxml.FXML; +import javafx.scene.control.CheckMenuItem; +import javafx.scene.control.MenuButton; + +import java.util.ArrayList; +import java.util.List; + +public class LanguageFilterCtrl implements LocaleAware { + private final LocaleManager manager; + private final ConfigService configService; + private final FoodpalApplicationCtrl appCtrl; + + @Inject + public LanguageFilterCtrl(LocaleManager manager, ConfigService configService, FoodpalApplicationCtrl appCtrl) { + this.manager = manager; + this.configService = configService; + this.appCtrl = appCtrl; + } + + @FXML + MenuButton langFilterMenu; + + List selectedLanguages = new ArrayList<>(); + + private String getSelectedLanguagesDisplay() { + String joined = String.join(", ", selectedLanguages); + if (joined.isEmpty()) { + return "none"; + } else { + return joined; + } + } + + private void updateMenuButtonDisplay() { + langFilterMenu.setText(getLocaleString("menu.label.selected-langs") + ": " + this.getSelectedLanguagesDisplay()); + } + + @Override + public void updateText() { + this.updateMenuButtonDisplay(); + } + + @Override + public LocaleManager getLocaleManager() { + return this.manager; + } + + public void initializeComponents() { + var items = this.langFilterMenu.getItems(); + + final List languages = List.of("en", "nl", "pl"); + this.selectedLanguages = this.configService.getConfig().getRecipeLanguages(); + this.updateMenuButtonDisplay(); + + items.clear(); + + languages.forEach(lang -> { + CheckMenuItem it = new CheckMenuItem(lang); + + if (selectedLanguages.contains(it.getText())) { + it.setSelected(true); + } + + it.selectedProperty().addListener((observable, _, value) -> { + if (value) { + selectedLanguages.add(it.getText()); + } else { + selectedLanguages.remove(it.getText()); + } + + configService.save(); + selectedLanguages.sort(String::compareTo); + appCtrl.refresh(); + + this.updateMenuButtonDisplay(); + }); + + items.add(it); + }); + } +} diff --git a/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java b/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java index 716a128..62d98bd 100644 --- a/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java +++ b/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java @@ -19,6 +19,7 @@ import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.control.TextField; +import javafx.scene.control.ComboBox; import javafx.scene.input.KeyCode; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; @@ -77,6 +78,9 @@ public class RecipeDetailCtrl implements LocaleAware { @FXML private Button favouriteButton; + @FXML + private ComboBox langSelector; + private ListView getParentRecipeList() { return this.appCtrl.recipeList; } @@ -138,6 +142,7 @@ public class RecipeDetailCtrl implements LocaleAware { this.showName(recipe.getName()); this.ingredientListController.refetchFromRecipe(recipe); this.stepListController.refetchFromRecipe(recipe); + this.langSelector.setValue(recipe.getLocale()); this.refreshFavouriteButton(); } @@ -294,6 +299,20 @@ public class RecipeDetailCtrl implements LocaleAware { editableTitleArea.getChildren().add(nameLabel); } + /** + * Switch the recipe's language. + */ + @FXML + void changeLanguage() { + recipe.setLocale(this.langSelector.getValue()); + + try { + server.updateRecipe(this.recipe); + } catch (IOException | InterruptedException e) { + throw new UpdateException("Error occurred when updating recipe locale!"); + } + } + @Override public void updateText() { editRecipeTitleButton.setText(getLocaleString("menu.button.edit")); @@ -309,5 +328,7 @@ public class RecipeDetailCtrl implements LocaleAware { @Override public void initializeComponents() { initStepsIngredientsList(); + + langSelector.getItems().addAll("en", "nl", "pl"); } } diff --git a/client/src/main/java/client/utils/Config.java b/client/src/main/java/client/utils/Config.java index 97eaca1..3933e6f 100644 --- a/client/src/main/java/client/utils/Config.java +++ b/client/src/main/java/client/utils/Config.java @@ -7,6 +7,7 @@ public class Config { private String language = "en"; + private List recipeLanguages = new ArrayList<>(); private String serverUrl = "http://localhost:8080"; private List favourites = new ArrayList<>(); @@ -66,5 +67,28 @@ public class Config { public void removeFavourite(long recipeId) { getFavourites().remove(recipeId); } + + /** + * Get a list of languages that should filter the displayed recipes. + * + * @return The desired languages the user would like to see. + */ + public List getRecipeLanguages() { + return this.recipeLanguages; + } + + /** + * Add a language to the list of filtering languages. + */ + public void addRecipeLanguage(String lang) { + this.recipeLanguages.add(lang); + } + + /** + * Remove a language from the list of filtering languages. + */ + public void removeRecipeLanguage(String lang) { + this.recipeLanguages.remove(lang); + } } diff --git a/client/src/main/java/client/utils/ServerUtils.java b/client/src/main/java/client/utils/ServerUtils.java index 9c89508..8e48d6e 100644 --- a/client/src/main/java/client/utils/ServerUtils.java +++ b/client/src/main/java/client/utils/ServerUtils.java @@ -29,9 +29,11 @@ public class ServerUtils { private final HttpClient client; private final ObjectMapper objectMapper = new ObjectMapper(); private final int statusOK = 200; + private final ConfigService configService; @Inject - public ServerUtils() { + public ServerUtils(ConfigService configService) { + this.configService = configService; client = HttpClient.newHttpClient(); } @@ -40,8 +42,15 @@ public class ServerUtils { * @return a JSON string with all the recipes */ public List getRecipes() throws IOException, InterruptedException { + + String uri = + SERVER + + "/recipes" + + "?locales=" + + String.join(",", this.configService.getConfig().getRecipeLanguages()); + HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(SERVER + "/recipes")) + .uri(URI.create(uri)) .GET() .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); diff --git a/client/src/main/resources/client/scenes/FoodpalApplication.fxml b/client/src/main/resources/client/scenes/FoodpalApplication.fxml index 310e78d..da76f5c 100644 --- a/client/src/main/resources/client/scenes/FoodpalApplication.fxml +++ b/client/src/main/resources/client/scenes/FoodpalApplication.fxml @@ -47,6 +47,7 @@ + diff --git a/client/src/main/resources/client/scenes/LanguageFilter.fxml b/client/src/main/resources/client/scenes/LanguageFilter.fxml new file mode 100644 index 0000000..b57790a --- /dev/null +++ b/client/src/main/resources/client/scenes/LanguageFilter.fxml @@ -0,0 +1,12 @@ + + + + + diff --git a/client/src/main/resources/client/scenes/recipe/RecipeDetailView.fxml b/client/src/main/resources/client/scenes/recipe/RecipeDetailView.fxml index ebd3a61..9357274 100644 --- a/client/src/main/resources/client/scenes/recipe/RecipeDetailView.fxml +++ b/client/src/main/resources/client/scenes/recipe/RecipeDetailView.fxml @@ -27,6 +27,8 @@