0.1.6Updated a month ago
import type { I_FeatureFlag } from "@infinity-beyond/modules/features/feature_flag.ts";
import type { JSX } from "preact";

import { Postify } from "../../islands/utils/postify.tsx";
import { Reload } from "../../islands/utils/reload.tsx";

interface FeatureFlagsFormProps {
  flags: I_FeatureFlag[]
}
export default function FeatureFlagsForm({ flags }: FeatureFlagsFormProps) {
  return (
    <div class="mx-auto max-w-256 py-12">
      <form action="/api/admin/feature_flags" onSubmit={Postify({
        callback() {
          document.querySelectorAll(`.${CHECKBOX_ROW_CLASS}.${HIGHLIGHT_ROW_CLASS}`).forEach(row => row.classList.remove(HIGHLIGHT_ROW_CLASS));
          document.getElementById(SAVE_BUTTON_ID)?.setAttribute('disabled', '');

          Reload();
        }
      })}>
        <div class="flex flex-col flex-wrap pb-8">
          {
            flags.map(({key, description, value}) => 
              <fieldset class="fieldset bg-base-100 border border-base-300 rounded-box p-0" key={key}>
                <label class={"fieldset-label flex p-0 " + CHECKBOX_ROW_CLASS}>
                  <span class="p-4">
                    <input type="checkbox" checked={value} data-was-active={value} name={key} onChange={onFlagToggled} class="checkbox shrink-0 grow-0" />
                  </span>
                  <span class="flex-1 border-s-1 border-gray-700 p-4">{ key }</span>
                  { description && 
                    <span class="flex-5 border-s-1 border-gray-700 p-4 leading-none">{description}</span>
                  }
                </label>
              </fieldset>
            )
          }
        </div>
        <button id={SAVE_BUTTON_ID} type="submit" class="btn btn-accent px-10" disabled>Save</button>
      </form>
    </div>
  )
}

const SAVE_BUTTON_ID = 'save-flags-button';
const CHECKBOX_ROW_CLASS = 'checkbox-row';
const HIGHLIGHT_ROW_CLASS = 'bg-accent-content';

const changed_values: Map<string, boolean> = new Map();

const onFlagToggled = ({ currentTarget: checkbox }: JSX.TargetedEvent<HTMLInputElement, Event>) => {
  const wasActive = checkbox.dataset.wasActive == "true";
  const changed = checkbox.checked !== wasActive;

  let row: HTMLElement | null = checkbox;
  let depth = 0;
  while(row && ++depth < 5 && !row.classList.contains(CHECKBOX_ROW_CLASS)) {
    row = row.parentElement;
  }
  if(!row?.classList.contains(CHECKBOX_ROW_CLASS)) row = null;

  const save_button = document.getElementById(SAVE_BUTTON_ID);

  if(changed) {
    changed_values.set(checkbox.name, true);
    save_button?.removeAttribute('disabled');
    row?.classList.add(HIGHLIGHT_ROW_CLASS);
    return;
  }

  row?.classList.remove(HIGHLIGHT_ROW_CLASS);

  changed_values.delete(checkbox.name);

  if(changed_values.size == 0) return save_button?.setAttribute('disabled', "");
}