Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/notanexus.git
export default class DialogBox {
  constructor() {
    this.dialog = null;
    this.isDragging = false;
    this.dragOffset = { x: 0, y: 0 };

    this._isEdit = false;
    this._existingNote = null;
    this._highlightElement = null;
    this._onSave = null;
    this._onCancel = null;
    this._onDelete = null;
    this._timestamp = null;
  }

  show(
    selectionRect,
    isEdit = false,
    existingNote = null,
    onSave,
    onCancel,
    onDelete,
    highlightElement = null,
    timestamp
  ) {
    this._removeExistingDialog();

    this._isEdit = isEdit;
    this._existingNote = existingNote;
    this._highlightElement = highlightElement;
    this._onSave = onSave;
    this._onCancel = onCancel;
    this._onDelete = onDelete;
    this._timestamp = timestamp;

    const dialog = document.createElement("div");
    dialog.id = "dialog";
    dialog.className = "dialog";

    this._positionDialog(dialog, selectionRect);

    const titleBar = this._createTitleBar();
    const textarea = this._createTextArea();

    dialog.appendChild(titleBar);
    dialog.appendChild(textarea);

    document.body.appendChild(dialog);
    this.dialog = dialog;

    textarea.focus();
  }

  handleOutsideClick(event) {
    if (this._isClickOutside(event.target)) {
      this._processCloseAction();
    }
  }

  _positionDialog(dialog, selectionRect) {
    const scrollX = window.scrollX;
    const scrollY = window.scrollY;
    dialog.style.left = `${selectionRect.left + scrollX}px`;
    dialog.style.top = `${selectionRect.bottom + scrollY + 10}px`;
  }

  _createTitleBar() {
    const titleBar = document.createElement("div");
    titleBar.className = "dialogTitleBar";

    const displayTimestamp = this._formatTimestamp(
      this._isEdit && this._existingNote
        ? this._existingNote.timestamp
        : this._timestamp
    );

    const timestampElement = document.createElement("span");
    timestampElement.className = "dialogTimestamp";
    timestampElement.textContent = displayTimestamp;

    const closeButton = document.createElement("span");
    closeButton.className = "dialogCloseButton";
    closeButton.textContent = "×";
    closeButton.addEventListener("click", () => {
      this._processCloseAction();
    });

    titleBar.appendChild(timestampElement);
    titleBar.appendChild(closeButton);
    this._setupDragHandlers(titleBar);

    return titleBar;
  }

  _createTextArea() {
    const textarea = document.createElement("textarea");
    textarea.placeholder = "Add your note...";
    textarea.rows = 3;
    textarea.className = "dialogTextarea";

    if (this._isEdit && this._existingNote) {
      textarea.value = this._existingNote.note;
    }

    textarea.addEventListener("keydown", (event) => {
      if (event.key === "Escape") {
        this._processCloseAction();
      }
    });

    return textarea;
  }

  _processCloseAction() {
    const noteText = this._getTextContent().trim();
    if (noteText === "") {
      this._onDelete();
    } else {
      this._onSave(noteText);
    }
    this._removeExistingDialog();
  }

  _setupDragHandlers(titleBar) {
    titleBar.style.cursor = "move";

    titleBar.addEventListener("mousedown", (e) => {
      if (e.button === 0 && !e.target.classList.contains("dialogCloseButton")) {
        this.isDragging = true;
        const rect = this.dialog.getBoundingClientRect();
        this.dragOffset = {
          x: e.clientX - rect.left,
          y: e.clientY - rect.top,
        };
        e.preventDefault();
      }
    });

    document.addEventListener("mousemove", (e) => {
      if (this.isDragging) {
        const x = e.clientX - this.dragOffset.x;
        const y = e.clientY - this.dragOffset.y;
        this.dialog.style.left = `${x}px`;
        this.dialog.style.top = `${y}px`;
      }
    });

    document.addEventListener("mouseup", () => {
      this.isDragging = false;
    });
  }

  _removeExistingDialog() {
    if (this.dialog) {
      this.dialog.remove();
      this.dialog = null;
    }
  }

  _isClickOutside(target) {
    return this.dialog && !this.dialog.contains(target);
  }

  _getTextContent() {
    const textarea = this.dialog?.querySelector(".dialogTextarea");
    return textarea ? textarea.value : "";
  }

  _formatTimestamp(date) {
    const formatDate = new Intl.DateTimeFormat("en", {
      day: "2-digit",
      month: "short",
      year: "numeric",
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      hour12: false,
    });

    const parts = formatDate.formatToParts(date);
    return `${parts.find((part) => part.type === "year").value}-${
      parts.find((part) => part.type === "month").value
    }-${parts.find((part) => part.type === "day").value} ${
      parts.find((part) => part.type === "hour").value
    }:${parts.find((part) => part.type === "minute").value}:${
      parts.find((part) => part.type === "second").value
    }`;
  }
}