feat: new UX for add/edit/update recipes
Revised adding recipes to have untitled recipes with inline name editing (name edit box autofocused upon recipe creation)
This commit is contained in:
parent
805c8fd6ea
commit
d42e6ff74c
3 changed files with 96 additions and 12 deletions
|
|
@ -0,0 +1,7 @@
|
|||
package client.exception;
|
||||
|
||||
public class UpdateException extends RuntimeException {
|
||||
public UpdateException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -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:
|
||||
* <ol>
|
||||
* <li>User creates an untitled recipe</li>
|
||||
* <li>The application autofocuses on the edit box (not exactly automagically yet)</li>
|
||||
* <li>User edits the name to whatever they want</li>
|
||||
* <li>Profit??</li>
|
||||
* </ol>
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
15
client/src/main/java/client/utils/DefaultRecipeFactory.java
Normal file
15
client/src/main/java/client/utils/DefaultRecipeFactory.java
Normal file
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue