JSFiddle - React, Tailwind, and code Playground

by Atsushi Nakatsugawa

HTML

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/@hexabase/hexabase-js@latest/dist/umd/hexabase.js"></script>
<div class="container" style="padding-top: 1em;">
  <div class="row justify-content-md-center">
    <div class="col-10">
      <div class="row justify-content-end">
        <div class="col-5">
          <button type="button" id="add" class="btn btn-primary">➕ 新しいタスク</button>
        </div>
      </div>
      <table class="table">
        <thead>
          <tr>
            <th scope="col">タスク</th>
            <th scope="col">担当者名</th>
            <th scope="col">カテゴリ</th>
            <th scope="col">ステータス</th>
            <th scope="col">アクション</th>
          </tr>
        </thead>
        <tbody>
          
        </tbody>
      </table>
      <form>
        <div class="row g-3">
          <input type="hidden" name="id" />
          <div class="col">
            <input type="text" class="form-control" name="Title" aria-describedby="emailHelp" placeholder="新しいタスク">
          </div>
          <div class="col">
            <input type="text" class="form-control" name="Assignee" placeholder="担当者名">
          </div>
          <div class="col">
            <select name="Category" class="form-control">
            
            </select>
          </div>
          <div class="col">
            <button type="submit" name="Button" id="button" class="btn btn-primary" disabled>追加</button>
          </div>
        </div>
      </form>
      <div class="row g-3" style="padding-top: 1em;">
        <div class="col">
          <div id="Status">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

JavaScript

const { HexabaseClient } = hexabase;
const client = new HexabaseClient();

// 認証用のメールアドレスとパスワード
const email = 'demo5@moongift.jp';
const password = 'K4c%j%vzR7sQKS$u&Uo%';

// Hexabaseのワークスペース、プロジェクト、ワークスペースのID
const workspaceId = '644f6e5ab30d853869ec919f';
const projectId = '650a30501222568b1ae7a2c2';
const datastoreId = '65895ba97b4300d37757d562';

// 複数の処理で使う変数用
const params = {
	datastore: null, // データストア
  items: [], // 既存タスク一覧
};

// DOM
const table = document.querySelector('.table tbody');
const form = document.querySelector('form');
const addButton = document.querySelector('#add');
const Status = document.querySelector('#Status');

// 初期設定
const init = async () => {
	// ログイン
	const res = await client.login({email, password});
  // ワークスペース・プロジェクト・データストアの取得
  await client.setWorkspace(workspaceId);
  const project = await client.currentWorkspace.project(projectId);
  params.datastore = await project.datastore(datastoreId);  
  // 追加ボタンを押せるようにする
  addButton.disabled = false;
};

// 既存のアイテム一覧を取得する処理
const load = async () => {
	const query = client.query(projectId);
  const items = await query
      .from(datastoreId)
      .select('*');
  params.items = items;
  // 表示更新
  showTable();
};

// フォームの作成処理
const makeForm = async () => {
	// ドロップダウンの項目を取得
  const field = await params.datastore.field('Category');
  // オプション項目を取得
  const options = await field.options();
  // HTMLに反映
  const html = options.map(option => `
  	<option id="${option.id}">${option.value.ja}</option>
  `);
  document.querySelector('form [name="Category"]').innerHTML = html;
}

document.querySelector('#button').onclick = async (e) => {
	e.preventDefault();
  
	const { id } = form.elements;
  
  const item = id.value === '' ?
        await params.datastore.item() :
        params.items.find(item => item.id === id.value);
  // アイテムに値をセット
  for (const input of Array.from(form.elements)) {
    if (['Button', 'id'].indexOf(input.name) > -1) continue;
    // 新規保存時はステータスをスキップ
    if (input.name...