Merge branch 'fix/favourites-rendering' into 'main'
fix: favourites rendering properly after a list change propagated from server. See merge request cse1105/2025-2026/teams/csep-team-76!89
This commit is contained in:
commit
bfe6505c54
1 changed files with 24 additions and 130 deletions
|
|
@ -2,12 +2,10 @@ package client.scenes;
|
|||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import client.exception.InvalidModificationException;
|
||||
import client.scenes.nutrition.NutritionViewCtrl;
|
||||
|
|
@ -21,7 +19,6 @@ import client.utils.LocaleManager;
|
|||
import client.utils.server.ServerUtils;
|
||||
import client.utils.WebSocketDataService;
|
||||
import client.utils.WebSocketUtils;
|
||||
import commons.Ingredient;
|
||||
import commons.Recipe;
|
||||
|
||||
import commons.ws.Topics;
|
||||
|
|
@ -32,13 +29,16 @@ import commons.ws.messages.Message;
|
|||
import commons.ws.messages.UpdateRecipeMessage;
|
||||
import jakarta.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ListProperty;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.TextInputDialog;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
|
|
@ -66,8 +66,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
@FXML
|
||||
public ListView<Recipe> recipeList;
|
||||
|
||||
@FXML
|
||||
private ListView<Ingredient> ingredientListView;
|
||||
private final ListProperty<Recipe> favouriteRecipeList = new SimpleListProperty<>();
|
||||
|
||||
@FXML
|
||||
private Button addRecipeButton;
|
||||
|
|
@ -88,8 +87,6 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
@FXML
|
||||
private Button manageIngredientsButton;
|
||||
|
||||
private List<Recipe> allRecipes = new ArrayList<>();
|
||||
|
||||
@FXML
|
||||
private Label updatedBadge;
|
||||
|
||||
|
|
@ -287,6 +284,13 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
openSelectedRecipe();
|
||||
}
|
||||
});
|
||||
recipeList.getItems().addListener((ListChangeListener.Change<? extends Recipe> c) -> {
|
||||
favouriteRecipeList.set(
|
||||
FXCollections.observableList(
|
||||
recipeList.getItems().stream().filter(r -> config.isFavourite(r.getId())).toList()
|
||||
));
|
||||
System.out.println(favouriteRecipeList);
|
||||
});
|
||||
|
||||
this.initializeSearchBar();
|
||||
refresh();
|
||||
|
|
@ -325,8 +329,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
logger.severe(msg);
|
||||
printError(msg);
|
||||
}
|
||||
|
||||
allRecipes = new ArrayList<>(recipes);
|
||||
recipeList.getItems().setAll(recipes);
|
||||
applyRecipeFilterAndKeepSelection();
|
||||
|
||||
showUpdatedBadge();
|
||||
|
|
@ -422,16 +425,20 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
public void applyRecipeFilterAndKeepSelection() {
|
||||
Recipe selected = recipeList.getSelectionModel().getSelectedItem();
|
||||
Long selectedId = selected == null ? null : selected.getId();
|
||||
|
||||
List<Recipe> view = allRecipes;
|
||||
List<Recipe> view = recipeList.getItems().stream().toList();
|
||||
|
||||
if (favouritesOnlyToggle != null && favouritesOnlyToggle.isSelected()) {
|
||||
view = allRecipes.stream()
|
||||
.filter(r -> config.isFavourite(r.getId()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
view = favouriteRecipeList.get();
|
||||
recipeList.getItems().setAll(view);
|
||||
}
|
||||
try {
|
||||
if (favouritesOnlyToggle != null && !favouritesOnlyToggle.isSelected()) {
|
||||
recipeList.getItems().setAll(server.getRecipes(config.getRecipeLanguages()));
|
||||
}
|
||||
}
|
||||
catch (IOException | InterruptedException e) {
|
||||
logger.severe(e.getMessage());
|
||||
}
|
||||
|
||||
// restore selection if possible
|
||||
if (selectedId != null) {
|
||||
|
|
@ -452,119 +459,6 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
this.recipeDetailController.refreshFavouriteButton();
|
||||
this.recipeDetailController.setVisible(!recipeList.getItems().isEmpty());
|
||||
}
|
||||
|
||||
//Delete Ingredient button click
|
||||
@FXML
|
||||
private void handleDeleteIngredient() {
|
||||
// Get selected ingredient
|
||||
Ingredient selectedIngredient = ingredientListView.getSelectionModel().getSelectedItem();
|
||||
|
||||
if (selectedIngredient == null) {
|
||||
// Show an error message if no ingredient is selected
|
||||
showError("No ingredient selected", "Please select an ingredient to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the ingredient is used in any recipe
|
||||
checkIngredientUsage(selectedIngredient);
|
||||
}
|
||||
|
||||
// Check if ingredient is used in any recipe before deleting
|
||||
private void checkIngredientUsage(Ingredient ingredient) {
|
||||
try {
|
||||
long usageCount = server.getIngredientUsage(ingredient.getId()); // Check ingredient usage via ServerUtils
|
||||
|
||||
if (usageCount > 0) {
|
||||
// If ingredient is used, show a warning dialog
|
||||
showWarningDialog(ingredient, usageCount);
|
||||
} else {
|
||||
// If not used, delete
|
||||
deleteIngredient(ingredient);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
showError("Error", "Failed to check ingredient usage: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteIngredient(Ingredient ingredient) {
|
||||
try {
|
||||
server.deleteIngredient(ingredient.getId()); // Call ServerUtils to delete the ingredient
|
||||
showConfirmation("Success", "Ingredient '" + ingredient.getName() + "' has been deleted.");
|
||||
refreshIngredientList(); // refresh the ingredient list
|
||||
} catch (IOException | InterruptedException e) {
|
||||
showError("Error", "Failed to delete ingredient: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showWarningDialog(Ingredient ingredient, long usedInRecipes) {
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING);
|
||||
}
|
||||
|
||||
private void showError(String title, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle(title);
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
private void showConfirmation(String title, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle(title);
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
private void refreshIngredientList() {
|
||||
// Refresh
|
||||
ingredientListView.getItems().clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
private void handleAddIngredient() {
|
||||
//ask the user for the ingredient name
|
||||
TextInputDialog dialog = new TextInputDialog();
|
||||
dialog.setTitle("Add Ingredient");
|
||||
dialog.setHeaderText("Enter the ingredient name:");
|
||||
dialog.setContentText("Ingredient:");
|
||||
|
||||
// Wait for the user to enter a value
|
||||
Optional<String> result = dialog.showAndWait();
|
||||
|
||||
result.ifPresent(recipeName ->{
|
||||
String trim = recipeName.trim();
|
||||
if(trim.isEmpty()){
|
||||
showError("Invalid Input", "Cannot have empty ingredient name");
|
||||
return;
|
||||
}
|
||||
if(ingredientListView.getItems().stream()
|
||||
.map(Ingredient::getName)
|
||||
.anyMatch(ingName -> ingName.equalsIgnoreCase(trim))){
|
||||
showError("Duplicate Ingredient", "Cannot have duplicate ingredients," +
|
||||
" Please provide unique Ingredient names");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// display ingredient name
|
||||
@FXML
|
||||
private void initializeIngredients() {
|
||||
ingredientListView.setCellFactory(list -> new ListCell<Ingredient>() {
|
||||
@Override
|
||||
protected void updateItem(Ingredient item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null) {
|
||||
setText(null);
|
||||
} else {
|
||||
setText(item.getName()); // Display the ingredient name in the ListView
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void openIngredientsPopup() {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue