Merge branch 'feature/client-shopping-list-view' into 'main'
Client shopping list view Closes #79 See merge request cse1105/2025-2026/teams/csep-team-76!84
This commit is contained in:
commit
186e74ddd3
13 changed files with 225 additions and 0 deletions
|
|
@ -21,6 +21,9 @@ import client.scenes.nutrition.NutritionDetailsCtrl;
|
||||||
import client.scenes.nutrition.NutritionViewCtrl;
|
import client.scenes.nutrition.NutritionViewCtrl;
|
||||||
import client.scenes.recipe.IngredientListCtrl;
|
import client.scenes.recipe.IngredientListCtrl;
|
||||||
import client.scenes.recipe.RecipeStepListCtrl;
|
import client.scenes.recipe.RecipeStepListCtrl;
|
||||||
|
import client.service.NonFunctionalShoppingListService;
|
||||||
|
import client.service.ShoppingListService;
|
||||||
|
import client.service.ShoppingListViewModel;
|
||||||
import client.utils.ConfigService;
|
import client.utils.ConfigService;
|
||||||
import client.utils.LocaleManager;
|
import client.utils.LocaleManager;
|
||||||
import client.utils.server.ServerUtils;
|
import client.utils.server.ServerUtils;
|
||||||
|
|
@ -57,6 +60,8 @@ public class MyModule implements Module {
|
||||||
binder.bind(new TypeLiteral<WebSocketDataService<Long, Recipe>>() {}).toInstance(
|
binder.bind(new TypeLiteral<WebSocketDataService<Long, Recipe>>() {}).toInstance(
|
||||||
new WebSocketDataService<>()
|
new WebSocketDataService<>()
|
||||||
);
|
);
|
||||||
|
binder.bind(ShoppingListViewModel.class).toInstance(new ShoppingListViewModel());
|
||||||
|
binder.bind(ShoppingListService.class).to(NonFunctionalShoppingListService.class);
|
||||||
binder.bind(new TypeLiteral<WebSocketDataService<Long, Ingredient>>() {}).toInstance(
|
binder.bind(new TypeLiteral<WebSocketDataService<Long, Ingredient>>() {}).toInstance(
|
||||||
new WebSocketDataService<>()
|
new WebSocketDataService<>()
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ import javafx.beans.property.SimpleListProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.scene.Parent;
|
||||||
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
|
|
@ -41,6 +44,7 @@ import javafx.scene.control.ListCell;
|
||||||
import javafx.scene.control.ListView;
|
import javafx.scene.control.ListView;
|
||||||
import javafx.scene.control.ToggleButton;
|
import javafx.scene.control.ToggleButton;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import org.apache.commons.lang3.NotImplementedException;
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
@ -510,6 +514,15 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
||||||
updatedBadgeTimer.playFromStart();
|
updatedBadgeTimer.playFromStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void openShoppingListWindow() throws IOException {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("shopping/ShoppingList.fxml"));
|
||||||
|
Parent root = (Parent)loader.load();
|
||||||
|
Stage stage = new Stage();
|
||||||
|
stage.setTitle(this.getLocaleString("menu.shopping.title"));
|
||||||
|
stage.setScene(new Scene(root));
|
||||||
|
stage.show();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package client.scenes.shopping;
|
||||||
|
|
||||||
|
import client.service.ShoppingListService;
|
||||||
|
import client.utils.LocaleAware;
|
||||||
|
import client.utils.LocaleManager;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import commons.FormalIngredient;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ShoppingListCtrl implements LocaleAware {
|
||||||
|
ShoppingListService shopping;
|
||||||
|
|
||||||
|
LocaleManager localeManager;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ListView<Pair<FormalIngredient, Optional<String>>> shoppingListView;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ShoppingListCtrl(
|
||||||
|
ShoppingListService shopping,
|
||||||
|
LocaleManager localeManager
|
||||||
|
) {
|
||||||
|
this.shopping = shopping;
|
||||||
|
this.localeManager = localeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateText() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocaleManager getLocaleManager() {
|
||||||
|
return this.localeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeComponents() {
|
||||||
|
this.shoppingListView.setCellFactory(l -> new ListCell<>() {
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Pair<FormalIngredient, Optional<String>> item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
this.setText("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String display = item.getKey().toString() +
|
||||||
|
item.getValue().map(recipe -> {
|
||||||
|
return " (" + recipe + ")";
|
||||||
|
}).orElse("");
|
||||||
|
|
||||||
|
this.setText(display);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.shoppingListView.getItems().setAll(
|
||||||
|
this.shopping.getItems()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package client.service;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import commons.FormalIngredient;
|
||||||
|
import commons.Recipe;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class NonFunctionalShoppingListService extends ShoppingListService {
|
||||||
|
@Inject
|
||||||
|
public NonFunctionalShoppingListService(ShoppingListViewModel viewModel) {
|
||||||
|
super(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putIngredient(FormalIngredient ingredient) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putIngredient(FormalIngredient ingredient, Recipe recipe) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putIngredient(FormalIngredient ingredient, String recipeName) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putArbitraryItem(String name) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormalIngredient purgeIngredient(Long id) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormalIngredient purgeIngredient(String ingredientName) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Pair<FormalIngredient, Optional<String>>> getItems() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String makePrintable() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
29
client/src/main/java/client/service/ShoppingListService.java
Normal file
29
client/src/main/java/client/service/ShoppingListService.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package client.service;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import commons.FormalIngredient;
|
||||||
|
import commons.Recipe;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class ShoppingListService {
|
||||||
|
private ShoppingListViewModel viewModel;
|
||||||
|
@Inject
|
||||||
|
public ShoppingListService(ShoppingListViewModel viewModel) {
|
||||||
|
this.viewModel = viewModel;
|
||||||
|
}
|
||||||
|
public abstract void putIngredient(FormalIngredient ingredient);
|
||||||
|
public abstract void putIngredient(FormalIngredient ingredient, Recipe recipe);
|
||||||
|
public abstract void putIngredient(FormalIngredient ingredient, String recipeName);
|
||||||
|
public abstract void putArbitraryItem(String name);
|
||||||
|
|
||||||
|
public abstract FormalIngredient purgeIngredient(Long id);
|
||||||
|
public abstract FormalIngredient purgeIngredient(String ingredientName);
|
||||||
|
|
||||||
|
public abstract void reset();
|
||||||
|
|
||||||
|
public abstract List<Pair<FormalIngredient, Optional<String>>> getItems();
|
||||||
|
public abstract String makePrintable();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package client.service;
|
||||||
|
|
||||||
|
import commons.FormalIngredient;
|
||||||
|
import javafx.beans.property.ListProperty;
|
||||||
|
import javafx.beans.property.SimpleListProperty;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
import org.apache.commons.lang3.NotImplementedException;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ShoppingListViewModel {
|
||||||
|
/**
|
||||||
|
* The formal ingredient provides the ingredient and its amount,
|
||||||
|
* and the string (optional) describes the recipe where it came from.
|
||||||
|
*/
|
||||||
|
private final ListProperty<Pair<FormalIngredient, Optional<String>>> listItems = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||||
|
public void addArbitrary() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -70,6 +70,9 @@
|
||||||
<ToggleButton fx:id="favouritesOnlyToggle" text="Favourites" onAction="#toggleFavouritesView" />
|
<ToggleButton fx:id="favouritesOnlyToggle" text="Favourites" onAction="#toggleFavouritesView" />
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
||||||
|
<Button fx:id="shoppingListButton"
|
||||||
|
onAction="#openShoppingListWindow"
|
||||||
|
text="Shopping List" />
|
||||||
<Button fx:id="manageIngredientsButton"
|
<Button fx:id="manageIngredientsButton"
|
||||||
onAction="#openIngredientsPopup"
|
onAction="#openIngredientsPopup"
|
||||||
text="Ingredients..." />
|
text="Ingredients..." />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.ListView?>
|
||||||
|
<?import javafx.scene.control.TitledPane?>
|
||||||
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
|
||||||
|
<TitledPane animated="false" collapsible="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="Shopping List" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/25">
|
||||||
|
<content>
|
||||||
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
|
<children>
|
||||||
|
<ListView fx:id="shoppingListView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
</TitledPane>
|
||||||
|
|
@ -38,6 +38,8 @@ menu.search=Search...
|
||||||
|
|
||||||
menu.label.selected-langs=Languages
|
menu.label.selected-langs=Languages
|
||||||
|
|
||||||
|
menu.shopping.title=Shopping list
|
||||||
|
|
||||||
lang.en.display=English
|
lang.en.display=English
|
||||||
lang.nl.display=Dutch
|
lang.nl.display=Dutch
|
||||||
lang.pl.display=Polish
|
lang.pl.display=Polish
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ menu.button.close=Sluiten
|
||||||
|
|
||||||
menu.label.selected-langs=Talen
|
menu.label.selected-langs=Talen
|
||||||
|
|
||||||
|
menu.shopping.title=Boodschappenlijst
|
||||||
|
|
||||||
menu.search=Zoeken...
|
menu.search=Zoeken...
|
||||||
lang.en.display=Engels
|
lang.en.display=Engels
|
||||||
lang.nl.display=Nederlands
|
lang.nl.display=Nederlands
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ menu.search=Szukaj...
|
||||||
|
|
||||||
menu.label.selected-langs=Języki
|
menu.label.selected-langs=Języki
|
||||||
|
|
||||||
|
menu.shopping.title=Lista zakupów
|
||||||
|
|
||||||
lang.en.display=Inglisz
|
lang.en.display=Inglisz
|
||||||
lang.nl.display=Holenderski
|
lang.nl.display=Holenderski
|
||||||
lang.pl.display=Polski
|
lang.pl.display=Polski
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ menu.search=o alasa
|
||||||
|
|
||||||
menu.label.selected-langs=toki wile
|
menu.label.selected-langs=toki wile
|
||||||
|
|
||||||
|
menu.shopping.title=ijo wile mani mute
|
||||||
|
|
||||||
lang.en.display=toki Inli
|
lang.en.display=toki Inli
|
||||||
lang.nl.display=toki Netelan
|
lang.nl.display=toki Netelan
|
||||||
lang.pl.display=toki Posuka
|
lang.pl.display=toki Posuka
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ menu.search=Arama...
|
||||||
|
|
||||||
menu.label.selected-langs=Diller
|
menu.label.selected-langs=Diller
|
||||||
|
|
||||||
|
menu.shopping.title=Al??veri? listesi
|
||||||
|
|
||||||
lang.en.display=\u0130ngilizce
|
lang.en.display=\u0130ngilizce
|
||||||
lang.nl.display=Hollandaca
|
lang.nl.display=Hollandaca
|
||||||
lang.pl.display=Leh\u00E7e
|
lang.pl.display=Leh\u00E7e
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue