diff --git a/client/src/main/java/client/Main.java b/client/src/main/java/client/Main.java index 8be1175..6b9db4f 100644 --- a/client/src/main/java/client/Main.java +++ b/client/src/main/java/client/Main.java @@ -17,14 +17,13 @@ package client; import static com.google.inject.Guice.createInjector; -import java.io.IOException; -import java.net.URISyntaxException; - +import client.scenes.AddStepsCtrl; +import client.scenes.MainCtrl; +import client.scenes.AddIngredientCtrl; +import client.scenes.AddNameCtrl; +import client.scenes.FoodpalApplicationCtrl; import com.google.inject.Injector; -import client.scenes.AddQuoteCtrl; -import client.scenes.MainCtrl; -import client.scenes.QuoteOverviewCtrl; import client.utils.ServerUtilsExample; import javafx.application.Application; import javafx.stage.Stage; @@ -34,7 +33,7 @@ public class Main extends Application { private static final Injector INJECTOR = createInjector(new MyModule()); private static final MyFXML FXML = new MyFXML(INJECTOR); - public static void main(String[] args) throws URISyntaxException, IOException { + public static void main(String[] args){ launch(); } @@ -48,10 +47,12 @@ public class Main extends Application { return; } - var overview = FXML.load(QuoteOverviewCtrl.class, "client", "scenes", "QuoteOverview.fxml"); - var add = FXML.load(AddQuoteCtrl.class, "client", "scenes", "AddQuote.fxml"); + var addName = FXML.load(AddNameCtrl.class, "client", "scenes", "AddName.fxml"); + var foodpal = FXML.load(FoodpalApplicationCtrl.class, "client", "scenes", "FoodpalApplication.fxml"); + var addIngredient = FXML.load(AddIngredientCtrl.class, "client", "scenes", "AddIngredient.fxml"); + var addStep = FXML.load(AddStepsCtrl.class, "client", "scenes", "AddSteps.fxml"); var mainCtrl = INJECTOR.getInstance(MainCtrl.class); - mainCtrl.initialize(primaryStage, overview, add); + mainCtrl.initialize(primaryStage, addName, foodpal, addIngredient, addStep); } } \ No newline at end of file diff --git a/client/src/main/java/client/MyModule.java b/client/src/main/java/client/MyModule.java index 2f6678b..df14aa2 100644 --- a/client/src/main/java/client/MyModule.java +++ b/client/src/main/java/client/MyModule.java @@ -15,20 +15,20 @@ */ package client; +import client.scenes.FoodpalApplicationCtrl; import com.google.inject.Binder; import com.google.inject.Module; import com.google.inject.Scopes; -import client.scenes.AddQuoteCtrl; +import client.scenes.AddNameCtrl; import client.scenes.MainCtrl; -import client.scenes.QuoteOverviewCtrl; public class MyModule implements Module { @Override public void configure(Binder binder) { binder.bind(MainCtrl.class).in(Scopes.SINGLETON); - binder.bind(AddQuoteCtrl.class).in(Scopes.SINGLETON); - binder.bind(QuoteOverviewCtrl.class).in(Scopes.SINGLETON); + binder.bind(AddNameCtrl.class).in(Scopes.SINGLETON); + binder.bind(FoodpalApplicationCtrl.class).in(Scopes.SINGLETON); } } \ No newline at end of file diff --git a/client/src/main/java/client/scenes/AddIngredientCtrl.java b/client/src/main/java/client/scenes/AddIngredientCtrl.java new file mode 100644 index 0000000..11fcb25 --- /dev/null +++ b/client/src/main/java/client/scenes/AddIngredientCtrl.java @@ -0,0 +1,86 @@ +/* + * Copyright 2021 Delft University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package client.scenes; + +import client.utils.ServerUtils; +import com.google.inject.Inject; +import commons.Recipe; +import jakarta.ws.rs.WebApplicationException; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyEvent; +import javafx.stage.Modality; + +import java.io.IOException; + +public class AddIngredientCtrl { + + private final ServerUtils server; + private final MainCtrl mainCtrl; + private final FoodpalApplicationCtrl foodpalCtrl; + + @FXML + public TextField ingredient; + + + @Inject + public AddIngredientCtrl(ServerUtils server, MainCtrl mainCtrl, FoodpalApplicationCtrl foodpalCtrl) { + this.mainCtrl = mainCtrl; + this.server = server; + this.foodpalCtrl = foodpalCtrl; + } + + public void cancel() throws IOException, InterruptedException { + clearFields(); + mainCtrl.showFoodpal(); + } + + public void ok() throws IOException, InterruptedException { + try { + Recipe selected = foodpalCtrl.getSelectedRecipe(); + server.addRecipeIngredient(selected, ingredient.getText()); + } catch (WebApplicationException e) { + + var alert = new Alert(Alert.AlertType.ERROR); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + return; + } + + + clearFields(); + mainCtrl.showFoodpal(); + } + + private void clearFields() { + ingredient.clear(); + } + + public void keyPressed(KeyEvent e) throws IOException, InterruptedException { + switch (e.getCode()) { + case ENTER: + ok(); + break; + case ESCAPE: + cancel(); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/client/src/main/java/client/scenes/AddNameCtrl.java b/client/src/main/java/client/scenes/AddNameCtrl.java new file mode 100644 index 0000000..354c653 --- /dev/null +++ b/client/src/main/java/client/scenes/AddNameCtrl.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Delft University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package client.scenes; + +import client.utils.ServerUtils; +import com.google.inject.Inject; + +import jakarta.ws.rs.WebApplicationException; +import javafx.scene.control.Alert; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyEvent; +import javafx.stage.Modality; + +import java.io.IOException; + +public class AddNameCtrl { + + private final ServerUtils server; + private final MainCtrl mainCtrl; + public TextField recipeName; + + + @Inject + public AddNameCtrl(ServerUtils server, MainCtrl mainCtrl) { + this.mainCtrl = mainCtrl; + this.server = server; + } + + public void cancel() throws IOException, InterruptedException { + clearFields(); + mainCtrl.showFoodpal(); + } + + public void ok() throws IOException, InterruptedException { + try { + server.addRecipeName(recipeName.getText()); + } catch (WebApplicationException e) { + + var alert = new Alert(Alert.AlertType.ERROR); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + return; + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + + clearFields(); + mainCtrl.showFoodpal(); + } + + private void clearFields() { + recipeName.clear(); + } + + public void keyPressed(KeyEvent e) throws IOException, InterruptedException { + switch (e.getCode()) { + case ENTER: + ok(); + break; + case ESCAPE: + cancel(); + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/client/src/main/java/client/scenes/AddQuoteCtrl.java b/client/src/main/java/client/scenes/AddStepsCtrl.java similarity index 66% rename from client/src/main/java/client/scenes/AddQuoteCtrl.java rename to client/src/main/java/client/scenes/AddStepsCtrl.java index 1ddf889..e042f66 100644 --- a/client/src/main/java/client/scenes/AddQuoteCtrl.java +++ b/client/src/main/java/client/scenes/AddStepsCtrl.java @@ -15,11 +15,9 @@ */ package client.scenes; +import client.utils.ServerUtils; import com.google.inject.Inject; - -import client.utils.ServerUtilsExample; -import commons.Person; -import commons.Quote; +import commons.Recipe; import jakarta.ws.rs.WebApplicationException; import javafx.fxml.FXML; import javafx.scene.control.Alert; @@ -27,35 +25,34 @@ import javafx.scene.control.TextField; import javafx.scene.input.KeyEvent; import javafx.stage.Modality; -public class AddQuoteCtrl { +import java.io.IOException; - private final ServerUtilsExample server; +public class AddStepsCtrl { + + private final ServerUtils server; private final MainCtrl mainCtrl; + private final FoodpalApplicationCtrl foodpalCtrl; @FXML - private TextField firstName; + public TextField preparationStep; - @FXML - private TextField lastName; - - @FXML - private TextField quote; @Inject - public AddQuoteCtrl(ServerUtilsExample server, MainCtrl mainCtrl) { + public AddStepsCtrl(ServerUtils server, MainCtrl mainCtrl, FoodpalApplicationCtrl foodpalCtrl) { this.mainCtrl = mainCtrl; this.server = server; - + this.foodpalCtrl = foodpalCtrl; } - public void cancel() { + public void cancel() throws IOException, InterruptedException { clearFields(); - mainCtrl.showOverview(); + mainCtrl.showFoodpal(); } - public void ok() { + public void ok() throws IOException, InterruptedException { try { - server.addQuote(getQuote()); + Recipe selected = foodpalCtrl.getSelectedRecipe(); + server.addRecipeStep(selected, preparationStep.getText()); } catch (WebApplicationException e) { var alert = new Alert(Alert.AlertType.ERROR); @@ -65,23 +62,16 @@ public class AddQuoteCtrl { return; } - clearFields(); - mainCtrl.showOverview(); - } - private Quote getQuote() { - var p = new Person(firstName.getText(), lastName.getText()); - var q = quote.getText(); - return new Quote(p, q); + clearFields(); + mainCtrl.showFoodpal(); } private void clearFields() { - firstName.clear(); - lastName.clear(); - quote.clear(); + preparationStep.clear(); } - public void keyPressed(KeyEvent e) { + public void keyPressed(KeyEvent e) throws IOException, InterruptedException { switch (e.getCode()) { case ENTER: ok(); diff --git a/client/src/main/java/client/scenes/OverviewCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java similarity index 64% rename from client/src/main/java/client/scenes/OverviewCtrl.java rename to client/src/main/java/client/scenes/FoodpalApplicationCtrl.java index fb57a44..93a2507 100644 --- a/client/src/main/java/client/scenes/OverviewCtrl.java +++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java @@ -1,8 +1,10 @@ package client.scenes; +import java.io.IOException; import java.util.List; +import client.utils.ServerUtils; import commons.Recipe; import jakarta.inject.Inject; @@ -12,8 +14,10 @@ import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; -public class OverviewCtrl { +public class FoodpalApplicationCtrl { private final MainCtrl mainCtrl; + private final ServerUtils server; + // all of these aren't used with only my part of the code // everything in the top bar === @@ -68,12 +72,13 @@ public class OverviewCtrl { private Button addPreparationStepButton; @Inject - public OverviewCtrl(MainCtrl mainCtrl) { + public FoodpalApplicationCtrl(MainCtrl mainCtrl, ServerUtils server) { this.mainCtrl = mainCtrl; + this.server = server; } @FXML - private void initialize() { + private void initialize() throws IOException, InterruptedException { // Show recipe name in the list recipeList.setCellFactory(list -> new ListCell<>() { @Override @@ -101,14 +106,18 @@ public class OverviewCtrl { // till the all the code from everyone is implemented for now to not have errors private void showRecipeDetails(Recipe newRecipe) { + recipeNameLabel.setText(newRecipe.getName()); + ingredientsListView.getItems().setAll(newRecipe.getIngredients()); + preparationListView.getItems().setAll(newRecipe.getPreparationSteps()); + } // Button handlers @FXML - private void refresh() { + public void refresh() throws IOException, InterruptedException { // TODO: someone else doing this - List recipes = showRecipeDetails(); + List recipes = server.getRecipes(); recipeList.getItems().setAll(recipes); // Select first recipe in the list by default @@ -117,27 +126,26 @@ public class OverviewCtrl { } } - // to remove error till everything else is implemented - private List showRecipeDetails() { - return List.of(); - } + /** + * Adds a recipe, by going to a different scene, there you insert the title and bam recipe created + */ @FXML private void addRecipe() { // Navigate to "create recipe" screen (should be like a pop-up or new screen or just another place in the app) - mainCtrl.showOverview(); + mainCtrl.showAddName(); } @FXML - private void removeSelectedRecipe() { + private void removeSelectedRecipe() throws IOException, InterruptedException { Recipe selected = recipeList.getSelectionModel().getSelectedItem(); if (selected == null) { return; } - // TODO: someone else todo + server.deleteRecipe(selected.getId()); + recipeList.getItems().remove(selected); - showRecipeDetails(null); } @FXML @@ -147,7 +155,7 @@ public class OverviewCtrl { return; } // Let MainCtrl open the full detail screen - mainCtrl.showOverview(); //I had showrecipedetail but intelij says showoverview + mainCtrl.showAddName(); //I had showrecipedetail but intelij says showoverview } @FXML @@ -157,16 +165,27 @@ public class OverviewCtrl { openSelectedRecipe(); } + /** + * You can add ingredients. you get send to a different scene that creates the ingredient + * It doesn't automatically refresh yet so before you can see the new ingredient you have to first click on a + * different recipe and come back after + */ @FXML private void addIngredient() { - // TODO: make it possible to add ingredient to current recipe System.out.println("Add ingredient clicked"); + mainCtrl.showAddIngredient(); } + /** + * You can add steps. you get send to a different scene that creates the Step + * It doesn't automatically refresh yet so before you can see the new step you have to first click on a + * different recipe and come back after + */ @FXML private void addPreparationStep() { - // TODO: make it possible to add step to current recipe System.out.println("Add preparation step clicked"); + mainCtrl.showAddSteps(); + } // Language buttons @@ -185,6 +204,34 @@ public class OverviewCtrl { System.out.println("Switch language to PL"); } + + //without caused errors + @FXML + private void makePrintable() { + System.out.println("Recipe printed"); + } + + /** + * Get the recipe that was selected + * @return the selected recipe + */ + public Recipe getSelectedRecipe() { + return recipeList.getSelectionModel().getSelectedItem(); + } + + /** + * Clones a recipe, when clicking on the button "clone" + */ + public void cloneRecipe() throws IOException, InterruptedException { + Recipe selected = recipeList.getSelectionModel().getSelectedItem(); + if (selected == null) { + return; + } + + server.cloneRecipe(selected.getId()); + refresh(); + + } } diff --git a/client/src/main/java/client/scenes/MainCtrl.java b/client/src/main/java/client/scenes/MainCtrl.java index f231fb6..018eec1 100644 --- a/client/src/main/java/client/scenes/MainCtrl.java +++ b/client/src/main/java/client/scenes/MainCtrl.java @@ -20,38 +20,92 @@ import javafx.scene.Scene; import javafx.stage.Stage; import javafx.util.Pair; +import java.io.IOException; + public class MainCtrl { private Stage primaryStage; - private QuoteOverviewCtrl overviewCtrl; - private Scene overview; + private AddNameCtrl addNameCtrl; + private Scene addName; - private AddQuoteCtrl addCtrl; - private Scene add; + private FoodpalApplicationCtrl foodpalCtrl; + private Scene foodpal; + + private AddIngredientCtrl addIngredientCtrl; + private Scene addIngredient; + + private AddStepsCtrl addStepsCtrl; + private Scene addStep; + + public void initialize(Stage primaryStage, + Pair addName, + Pair foodpal, + Pair addIngredient, + Pair addStep + ) throws IOException, InterruptedException { - public void initialize(Stage primaryStage, Pair overview, - Pair add) { this.primaryStage = primaryStage; - this.overviewCtrl = overview.getKey(); - this.overview = new Scene(overview.getValue()); - this.addCtrl = add.getKey(); - this.add = new Scene(add.getValue()); + this.addNameCtrl = addName.getKey(); + this.addName = new Scene(addName.getValue()); - showOverview(); + this.foodpalCtrl = foodpal.getKey(); + this.foodpal = new Scene(foodpal.getValue()); + + this.addIngredientCtrl = addIngredient.getKey(); + this.addIngredient = new Scene(addIngredient.getValue()); + + this.addStepsCtrl = addStep.getKey(); + this.addStep = new Scene(addStep.getValue()); + + + showFoodpal(); primaryStage.show(); } - public void showOverview() { - primaryStage.setTitle("Quotes: Overview"); - primaryStage.setScene(overview); - overviewCtrl.refresh(); + + public void showAddName() { + primaryStage.setTitle("Naming recipes"); + primaryStage.setScene(addName); + addName.setOnKeyPressed(e -> { + try { + addNameCtrl.keyPressed(e); + } catch (IOException | InterruptedException ex) { + throw new RuntimeException(ex); + } + }); } - public void showAdd() { - primaryStage.setTitle("Quotes: Adding Quote"); - primaryStage.setScene(add); - add.setOnKeyPressed(e -> addCtrl.keyPressed(e)); + public void showFoodpal() throws IOException, InterruptedException { + primaryStage.setTitle("FoodPal"); + primaryStage.setScene(foodpal); + foodpalCtrl.refresh(); + } + + public void showAddIngredient() { + primaryStage.setTitle("To add ingredients"); + primaryStage.setScene(addIngredient); + addIngredient.setOnKeyPressed(e -> { + try { + addIngredientCtrl.keyPressed(e); + } catch (IOException | InterruptedException ex) { + throw new RuntimeException(ex); + } + }); + + } + + public void showAddSteps() { + primaryStage.setTitle("To add preparation steps"); + primaryStage.setScene(addStep); + addStep.setOnKeyPressed(e -> { + try { + addStepsCtrl.keyPressed(e); + } catch (IOException | InterruptedException ex) { + throw new RuntimeException(ex); + } + }); + } } \ No newline at end of file diff --git a/client/src/main/java/client/scenes/QuoteOverviewCtrl.java b/client/src/main/java/client/scenes/QuoteOverviewCtrl.java deleted file mode 100644 index 11b64c6..0000000 --- a/client/src/main/java/client/scenes/QuoteOverviewCtrl.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2021 Delft University of Technology - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package client.scenes; - -import java.net.URL; -import java.util.ResourceBundle; - -import com.google.inject.Inject; - -import client.utils.ServerUtilsExample; -import commons.Quote; -import javafx.beans.property.SimpleStringProperty; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; - -public class QuoteOverviewCtrl implements Initializable { - - private final ServerUtilsExample server; - private final MainCtrl mainCtrl; - - private ObservableList data; - - @FXML - private TableView table; - @FXML - private TableColumn colFirstName; - @FXML - private TableColumn colLastName; - @FXML - private TableColumn colQuote; - - @Inject - public QuoteOverviewCtrl(ServerUtilsExample server, MainCtrl mainCtrl) { - this.server = server; - this.mainCtrl = mainCtrl; - } - - @Override - public void initialize(URL location, ResourceBundle resources) { - colFirstName.setCellValueFactory(q -> new SimpleStringProperty(q.getValue().person.firstName)); - colLastName.setCellValueFactory(q -> new SimpleStringProperty(q.getValue().person.lastName)); - colQuote.setCellValueFactory(q -> new SimpleStringProperty(q.getValue().quote)); - } - - public void addQuote() { - mainCtrl.showAdd(); - } - - public void refresh() { - var quotes = server.getQuotes(); - data = FXCollections.observableList(quotes); - table.setItems(data); - } -} \ No newline at end of file diff --git a/client/src/main/java/client/utils/ServerUtils.java b/client/src/main/java/client/utils/ServerUtils.java index 37ebd30..7bf5de9 100644 --- a/client/src/main/java/client/utils/ServerUtils.java +++ b/client/src/main/java/client/utils/ServerUtils.java @@ -14,6 +14,7 @@ import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.ArrayList; import java.util.List; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; @@ -127,7 +128,7 @@ public class ServerUtils { //Get the recipe HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(SERVER + "/recipe/" + id)) - .GET() + .GET() //Needs to be changed to POST() when api is changed .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); @@ -156,4 +157,44 @@ public class ServerUtils { } return true; } + + public void addRecipeName(String name) throws IOException, InterruptedException { + Recipe newRecipe = new Recipe(); + newRecipe.setName(name); + addRecipe(newRecipe); + + } + + public void addRecipeIngredient(Recipe recipe, String ingredient) throws IOException, InterruptedException { + List ingredients = new ArrayList<>(recipe.getIngredients()); + ingredients.add(ingredient); + recipe.setIngredients(ingredients); + + updateRecipe(recipe); + } + + public void updateRecipe(Recipe recipe) throws IOException, InterruptedException { + String json = objectMapper.writeValueAsString(recipe); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(SERVER + "/recipe/" + recipe.getId())) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString((json))) // Needs to be changed to PUT() when api changed + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + if(response.statusCode() != statusOK){ + throw new IOException("Failed to update recipe: " + recipe.toDetailedString() + "body: " + response.body()); + } + + objectMapper.readValue(response.body(), Recipe.class); + } + + public void addRecipeStep(Recipe recipe, String preparationStep) throws IOException, InterruptedException { + List preparationSteps = new ArrayList<>(recipe.getPreparationSteps()); + preparationSteps.add(preparationStep); + recipe.setPreparationSteps(preparationSteps); + + updateRecipe(recipe); + } } \ No newline at end of file diff --git a/client/src/main/resources/client/scenes/AddIngredient.fxml b/client/src/main/resources/client/scenes/AddIngredient.fxml new file mode 100644 index 0000000..ebb0970 --- /dev/null +++ b/client/src/main/resources/client/scenes/AddIngredient.fxml @@ -0,0 +1,15 @@ + + + + + + + + + +