Skip to content
Snippets Groups Projects
Backend.jsx 4.51 KiB
Newer Older
Lucas García's avatar
Lucas García committed
// vendor
import React from "react";
import {
  TextControl,
  Button,
  __experimentalSpacer as Spacer,
} from "@wordpress/components";
import { useState, useRef, useEffect } from "@wordpress/element";

// source
import BackendHeaders from "./Headers";
Lucas García's avatar
Lucas García committed
import useBackendNames from "../../hooks/useBackendNames";
Lucas García's avatar
Lucas García committed
import { useI18n } from "../../providers/I18n";
Lucas García's avatar
Lucas García committed

function NewBackend({ add }) {
Lucas García's avatar
Lucas García committed
  const __ = useI18n();
Lucas García's avatar
Lucas García committed
  const backendNames = useBackendNames();

Lucas García's avatar
Lucas García committed
  const [name, setName] = useState("");
  const [baseUrl, setBaseUrl] = useState("https://");
Lucas García's avatar
Lucas García committed
  const [nameConflict, setNameConflict] = useState(false);

  const handleSetName = (name) => {
    setNameConflict(backendNames.has(name));
    setName(name.trim());
  };
Lucas García's avatar
Lucas García committed

  const onClick = () => add({ name, base_url: baseUrl, headers: [] });

  const disabled = !(name && baseUrl && !nameConflict);
Lucas García's avatar
Lucas García committed

  return (
    <div
      style={{
        padding: "calc(24px) calc(32px)",
        width: "calc(100% - 64px)",
        backgroundColor: "rgb(245, 245, 245)",
      }}
    >
      <div
        style={{
          display: "flex",
          gap: "1em",
        }}
      >
        <TextControl
          label={__("Backend name", "wpct-erp-forms")}
Lucas García's avatar
Lucas García committed
          help={
            nameConflict
              ? __("This name is already in use", "wpct-erp-forms")
              : ""
          }
Lucas García's avatar
Lucas García committed
          value={name}
          onChange={handleSetName}
Lucas García's avatar
Lucas García committed
          __nextHasNoMarginBottom
        />
        <TextControl
          style={{ minWidth: "250px" }}
          label={__("Backend base URL", "wpct-erp-forms")}
          value={baseUrl}
          onChange={setBaseUrl}
          __nextHasNoMarginBottom
        />
        <Button
          variant="primary"
          onClick={() => onClick()}
          style={{ marginTop: "auto", height: "32px" }}
          disabled={disabled}
        >
          {__("Add", "wpct-erp-forms")}
        </Button>
      </div>
    </div>
  );
}

let focus = false;
export default function Backend({ update, remove, ...data }) {
  if (data.name === "add") return <NewBackend add={update} />;

Lucas García's avatar
Lucas García committed
  const __ = useI18n();
Lucas García's avatar
Lucas García committed
  const [name, setName] = useState(data.name);
Lucas García's avatar
Lucas García committed
  const initialName = useRef(data.name);
Lucas García's avatar
Lucas García committed
  const nameInput = useRef();

Lucas García's avatar
Lucas García committed
  const backendNames = useBackendNames();
  const [nameConflict, setNameConflict] = useState(false);
  const handleSetName = (name) => {
    setNameConflict(name !== initialName.current && backendNames.has(name));
    setName(name.trim());
  };

Lucas García's avatar
Lucas García committed
  const setHeaders = (headers) => update({ ...data, headers });

  useEffect(() => {
    if (focus) {
      nameInput.current.focus();
    }
  }, []);

  const timeout = useRef(false);
  useEffect(() => {
    clearTimeout(timeout.current);
Lucas García's avatar
Lucas García committed
    if (!name || nameConflict) return;
Lucas García's avatar
Lucas García committed
    timeout.current = setTimeout(() => update({ ...data, name }), 500);
  }, [name]);

Lucas García's avatar
Lucas García committed
  useEffect(() => setName(data.name), [data.name]);
Lucas García's avatar
Lucas García committed

  return (
    <div
      style={{
        padding: "calc(24px) calc(32px)",
        width: "calc(100% - 64px)",
        backgroundColor: "rgb(245, 245, 245)",
      }}
    >
      <div
        style={{
          display: "flex",
          gap: "1em",
        }}
      >
        <TextControl
          ref={nameInput}
          label={__("Backend name", "wpct-erp-forms")}
Lucas García's avatar
Lucas García committed
          help={
            nameConflict
              ? __("This name is already in use", "wpct-erp-forms")
              : ""
          }
Lucas García's avatar
Lucas García committed
          value={name}
Lucas García's avatar
Lucas García committed
          onChange={handleSetName}
Lucas García's avatar
Lucas García committed
          onFocus={() => (focus = true)}
          onBlur={() => (focus = false)}
          __nextHasNoMarginBottom={true}
        />
        <TextControl
          style={{ minWidth: "250px" }}
          label={__("Backend base URL", "wpct-erp-forms")}
          value={data.base_url}
          onChange={(base_url) => update({ ...data, base_url })}
          __nextHasNoMarginBottom={true}
        />
        <div>
          <label
            style={{
              display: "block",
              fontWeight: 500,
              textTransform: "uppercase",
              fontSize: "11px",
              marginBottom: "calc(4px)",
            }}
          >
            {__("Remove backend", "wpct-erp-forms")}
          </label>
          <Button
            isDestructive
            variant="primary"
            onClick={() => remove(data)}
Lucas García's avatar
Lucas García committed
            style={{ width: "150px", justifyContent: "center", height: "32px" }}
Lucas García's avatar
Lucas García committed
          >
            {__("Remove", "wpct-erp-forms")}
          </Button>
        </div>
      </div>
      <Spacer paddingY="calc(8px)" />
      <BackendHeaders headers={data.headers} setHeaders={setHeaders} />
    </div>
  );
}