AddPopup.java

package no.ntnu.idatt1002.demo.view.components;

import java.util.ArrayList;
import java.util.function.Consumer;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Popup;
import no.ntnu.idatt1002.demo.Logger;
import no.ntnu.idatt1002.demo.dao.DAO;
import no.ntnu.idatt1002.demo.dao.DBConnectionProvider;
import no.ntnu.idatt1002.demo.data.Storable;
import no.ntnu.idatt1002.demo.repo.ItemRegister;

/**
 * A popup for adding items to the inventory.
 * TODO: Make this class be able to add recipes. Maybe make a superclas?
 */
public class AddPopup extends Popup {
  private OnAdd onAdd;
  private ArrayList<Field> fields = new ArrayList<>();
  private String type;
  private Text specialPrompt = null;

  /**
   * A callback for when the form is submitted.
   */
  public interface OnAdd {
    void cb(Object[] values);
  }

  /**
   * Constructor for the AddPopup.
   */
  public AddPopup(String type) {
    super();
    this.setAutoHide(true); // close the popup automatically
    this.type = type;
    render();
  }

  private void render() {
    // Create a container for the popup
    StackPane container = new StackPane();

    // Create a VBox to hold the content of the popup
    VBox background = new VBox();
    background.getStyleClass().add("popup-background");
    background.setSpacing(20);
    this.getContent().add(container);
    container.getChildren().add(background);

    // create a cross button to close the popup
    CrossButton crossButton = new CrossButton();
    crossButton.setOnAction(e -> this.hide());
    crossButton.setPadding(new Insets(10));

    container.getChildren().add(crossButton);
    StackPane.setAlignment(crossButton, Pos.TOP_RIGHT);

    // Add a title to the popup
    Text title = new Text("Adding " + type);
    title.getStyleClass().addAll("popup-title", "centered");

    // Add a button to submit the form
    PrimaryButton submitButton = new PrimaryButton("Add");
    submitButton.setOnAction(e -> {
      addItem();
    });
    submitButton.setPrefWidth(200);
    submitButton.setPrefHeight(50);
    background.getChildren().add(title);

    for (Field<?> field : fields) {
      background.getChildren().add(field.getRenderedField());
    }

    if (specialPrompt != null) {
      background.getChildren().add(specialPrompt);
    }

    // Add the content to the VBox
    background.getChildren().add(submitButton);
  }

  /**
   * Adds a new field to the popup.
   *
   * @param <T>   the type of the field
   * @param field the field to add
   * @return the field
   */
  public <T> Field<T> addField(Field<T> field) {
    fields.add(field);
    render();
    return field;
  }

  /**
   * Adds an item to the inventory.
   */
  private void addItem() {
    // TODO: check fields!!

    if (onAdd == null) {
      Logger.error("onAdd callback is not set. Cannot add item.");
      return;
    }

    ArrayList<Object> values = new ArrayList<>();
    for (Field<?> field : fields) {
      values.add(field.getValue());
    }

    onAdd.cb(values.toArray());

    // If no errors, close the popup
    this.hide();

  }

  /**
   * Set the callback for when the form is submitted.
   *
   * @param cb the callback
   * @return this input field
   */
  public AddPopup setOnAdd(OnAdd cb) {
    this.onAdd = cb;
    return this;
  }

  /**
   * Set a special prompt at the bottom of the popup.
   * <p>
   * This is useful for displaying a clickable text that performs an action.
   * Closes the popup when clicked.
   * </p>
   *
   * @param text     the text to display
   * @param onAction the action to perform when the text is clicked
   */
  public void setSpecialPrompt(Text text, Consumer<Void> onAction) {
    this.specialPrompt = text;
    text.getStyleClass().addAll("centered", "link");
    text.setOnMouseClicked(e -> {
      this.hide();
      onAction.accept(null);
    });
    render();
  }
}