diff --git a/client/src/main/java/client/exception/UpdateException.java b/client/src/main/java/client/exception/UpdateException.java
new file mode 100644
index 0000000..5439018
--- /dev/null
+++ b/client/src/main/java/client/exception/UpdateException.java
@@ -0,0 +1,7 @@
+package client.exception;
+
+public class UpdateException extends RuntimeException {
+ public UpdateException(String message) {
+ super(message);
+ }
+}
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index 93a2507..bc39741 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -4,20 +4,30 @@ package client.scenes;
import java.io.IOException;
import java.util.List;
+import client.exception.UpdateException;
+import client.utils.DefaultRecipeFactory;
import client.utils.ServerUtils;
import commons.Recipe;
import jakarta.inject.Inject;
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.TextField;
+import javafx.scene.input.KeyCode;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
public class FoodpalApplicationCtrl {
private final MainCtrl mainCtrl;
private final ServerUtils server;
+ public VBox detailsScreen;
+ public HBox editableTitleArea;
+
// all of these aren't used with only my part of the code
// everything in the top bar ===
@@ -103,10 +113,13 @@ public class FoodpalApplicationCtrl {
refresh();
}
-
+ private void showName(String name) {
+ editableTitleArea.getChildren().clear();
+ editableTitleArea.getChildren().add(new Label(name));
+ }
// till the all the code from everyone is implemented for now to not have errors
private void showRecipeDetails(Recipe newRecipe) {
- recipeNameLabel.setText(newRecipe.getName());
+ showName(newRecipe.getName());
ingredientsListView.getItems().setAll(newRecipe.getIngredients());
preparationListView.getItems().setAll(newRecipe.getPreparationSteps());
@@ -123,17 +136,40 @@ public class FoodpalApplicationCtrl {
// Select first recipe in the list by default
if (!recipes.isEmpty()) {
recipeList.getSelectionModel().selectFirst();
+ detailsScreen.visibleProperty().set(true);
}
}
-
+ private void printError(String msg) {
+ Alert alert = new Alert(Alert.AlertType.ERROR);
+ alert.setContentText(msg);
+ alert.showAndWait();
+ }
/**
- * Adds a recipe, by going to a different scene, there you insert the title and bam recipe created
+ * Adds a recipe, by providing a default name "Untitled recipe (n)"
+ * The UX flow is now:
+ *
+ * - User creates an untitled recipe
+ * - The application autofocuses on the edit box (not exactly automagically yet)
+ * - User edits the name to whatever they want
+ * - Profit??
+ *
*/
@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.showAddName();
+ // a default factory provides the value
+ Recipe newRecipe = DefaultRecipeFactory.getDefaultRecipe();
+ try {
+ server.addRecipe(newRecipe);
+ refresh();
+ // the list focuses on the new recipe
+ // otherwise strange issues occur when the autofocus on edit box is called
+ recipeList.getFocusModel().focus(recipeList.getItems().indexOf(newRecipe));
+ } catch (IOException | InterruptedException e) {
+ printError("Error occurred when adding recipe!");
+ }
+ // Calls edit after the recipe has been created, seamless name editing
+ editRecipeTitle();
}
@FXML
@@ -145,7 +181,10 @@ public class FoodpalApplicationCtrl {
server.deleteRecipe(selected.getId());
- recipeList.getItems().remove(selected);
+ // prefer a global refresh (or WS-based update upon its impl)
+ // rather than recipeList.getItems().remove(selected);
+ // to maintain single source of truth from the server.
+ refresh();
}
@FXML
@@ -154,15 +193,38 @@ public class FoodpalApplicationCtrl {
if (selected == null) {
return;
}
- // Let MainCtrl open the full detail screen
- mainCtrl.showAddName(); //I had showrecipedetail but intelij says showoverview
+ detailsScreen.visibleProperty().set(true);
}
+ /**
+ * Revised edit recipe control flow, deprecates the use of a separate AddNameCtrl
+ * This is automagically called when a new recipe is created, making for a more seamless UX
+ */
@FXML
private void editRecipeTitle() {
- // TODO: someone else todo
- // For now reuse openSelectedRecipe()
- openSelectedRecipe();
+ editableTitleArea.getChildren().clear();
+ TextField edit = new TextField();
+ edit.setOnKeyPressed(event -> {
+ if (event.getCode() != KeyCode.ENTER) {
+ return;
+ }
+ String newName = edit.getText();
+ Recipe selected = recipeList.getSelectionModel().getSelectedItem();
+ if (selected == null) {
+ // edge case, prob won't happen but best to handle it later
+ throw new NullPointerException("No recipe selected while name was changed!");
+ }
+ selected.setName(newName);
+ try {
+ server.updateRecipe(selected);
+ refresh();
+ } catch (IOException | InterruptedException e) {
+ // throw a nice blanket UpdateException
+ throw new UpdateException("Error occurred when updating recipe name!");
+ }
+ showName(edit.getText());
+ });
+ editableTitleArea.getChildren().add(edit);
}
/**
diff --git a/client/src/main/java/client/utils/DefaultRecipeFactory.java b/client/src/main/java/client/utils/DefaultRecipeFactory.java
new file mode 100644
index 0000000..0a94786
--- /dev/null
+++ b/client/src/main/java/client/utils/DefaultRecipeFactory.java
@@ -0,0 +1,15 @@
+package client.utils;
+
+import commons.Recipe;
+
+import java.util.List;
+
+public class DefaultRecipeFactory {
+ public static Recipe getDefaultRecipe() {
+ return new Recipe(
+ null,
+ "Untitled recipe",
+ List.of(),
+ List.of());
+ }
+}