Next.jsとTypescriptとTailwindでコヨーテのメモアプリを作成

# Welcome to Coyote!

最近弊社の息抜きで流行している、コヨーテのゲームで、どのカードが使われたかをまとめておけるWEBアプリを作成しました。

![E4oL1T9VoAA6po3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/deb90c73-932e-ac66-ca8d-7019e2ddcad1.jpeg)


コヨーテの詳しい説明はこちら!!
 [コヨーテは頭を使うインディアン・ポーカー。割と傑作【ボードゲーム感想・レビュー】](https://alpaca-blog.com/boardgame/coyote)

特殊カードを含めた、１５種類のカードを使ったインディアンポーカーのようなもので心理戦と自分のカードの推理がメインのゲームです。
一度利用されたカードは場に出されたままになるので、山に残っているカードはそれから推測できるのですが、それを管理できるページを今回は実装します。

以前に投稿した、 [Next.js & Tailwind CSS入門
](https://qiita.com/araya/items/1492b0be97b5faa59280) こちらのシンプルなNextアプリをベースに構築していきます。

Tailwindがアップデートされたのか、Nextがアップデートしたのかわからないのですが結構変わっていたので、 [Install Tailwind CSS with Next.js
](https://tailwindcss.com/docs/guides/nextjs) も参考にしつつ初期設定を行いました。

# 1. Tailwindによるざっくり見た目の作成

コヨーテのカードの見た目を参考にこのような見た目を仮で作りました。
項目やそれぞれの数はつぎのセクションで設定していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/0bf3b290-bfc9-3541-0e53-ccc10822ea6b.png)


```typescript:index.tsx
import Head from "next/head";

export default function Home() {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <main className="flex flex-col items-center justify-center w-full flex-1 px-20 text-center bg-blue-50">
        <h1 className="text-6xl font-bold mb-12">Welcome to Coyote</h1>

        <div className="flex w-1/2 min-w-max">
          <div className="flex flex-1 justify-center p-4 bg-white rounded-lg shadow-xs">
            <div>
              <span className="text-lg font-bold">20</span>
              <div className="flex items-center justify-center w-full mb-4">
                <label
                  htmlFor="toggleB"
                  className="flex items-center cursor-pointer"
                >
                  <div className="relative">
                    <input type="checkbox" id="toggleB" className="sr-only" />
                    <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                    <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                  </div>
                </label>
              </div>
            </div>
          </div>
          <div className="flex flex-1 justify-center p-4 ml-5 bg-white rounded-lg shadow-xs">
            <div>
              <span className="text-lg font-bold">20</span>
              <div className="flex items-center justify-center w-full mb-4">
                <label
                  htmlFor="toggleB"
                  className="flex items-center cursor-pointer"
                >
                  <div className="relative">
                    <input type="checkbox" id="toggleB" className="sr-only" />
                    <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                    <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                  </div>
                </label>
              </div>
            </div>
          </div>
        </div>

        <div className="flex w-1/2 min-w-max mt-5">
          <div className="flex flex-1 justify-center p-4 bg-white rounded-lg shadow-xs">
            <div>
              <span className="text-lg font-bold">15</span>
              <div className="flex items-center justify-center w-full mb-4">
                <label
                  htmlFor="toggleB"
                  className="flex items-center cursor-pointer"
                >
                  <div className="relative">
                    <input type="checkbox" id="toggleB" className="sr-only" />
                    <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                    <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                  </div>
                </label>
              </div>
            </div>
          </div>
          <div className="flex flex-1 justify-center p-4 bg-white rounded-lg shadow-xs ml-5">
            <div>
              <span className="text-lg font-bold">15</span>
              <div className="flex items-center justify-center w-full mb-4">
                <label
                  htmlFor="toggleB"
                  className="flex items-center cursor-pointer"
                >
                  <div className="relative">
                    <input type="checkbox" id="toggleB" className="sr-only" />
                    <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                    <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                  </div>
                </label>
              </div>
            </div>
          </div>
          <div className="flex flex-1 justify-center p-4 bg-white rounded-lg shadow-xs ml-5">
            <div>
              <span className="text-lg font-bold">15</span>
              <div className="flex items-center justify-center w-full mb-4">
                <label
                  htmlFor="toggleB"
                  className="flex items-center cursor-pointer"
                >
                  <div className="relative">
                    <input type="checkbox" id="toggleB" className="sr-only" />
                    <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                    <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                  </div>
                </label>
              </div>
            </div>
          </div>
        </div>
      </main>

      <footer className="flex items-center justify-center w-full h-24 border-t">
        <a
          className="flex items-center justify-center"
          href="https://arkth.co.jp"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by Arkth Inc.
        </a>
      </footer>
    </div>
  );
}
```

# 2. カードの種類や数の設定
JSONでカードの種類や数を設定します。
こうしておくことで、かんたんにカードの数や種類を増減したり、UIを作る上でコンポーネントでの管理がしやすくなります。

```json:cards.json
export const cards = [
  {
    "20": {
      num: 1,
    },
  },
  {
    "15": {
      num: 2,
    },
  },
  {
    "10": {
      num: 3,
    },
  },
  {
    "5": {
      num: 4,
    },
  },
  {
    "4": {
      num: 4,
    },
  },
  {
    "3": {
      num: 4,
    },
  },
  {
    "2": {
      num: 4,
    },
  },
  {
    "1": {
      num: 4,
    },
  },
  {
    "0": {
      num: 3,
    },
    "0 CLEAR": {
      num: 1,
    },
  },
  {
    "-5": {
      num: 2,
    },
  },
  {
    "-10": {
      num: 1,
    },
  },
  {
    x2: {
      num: 1,
    },
  },
  {
    "MAX->0": {
      num: 1,
    },
  },
  {
    "?": {
      num: 1,
    },
  },
];
```

```typescript:index.tsx
import { cards } from "./cards";

export default function Home() {
  const rows = cards.map((row, key) => (
    <div key={key} className="flex w-1/2 min-w-max mt-5">
      {Object.entries(row).map((v) =>
        [...Array(v[1].num)].map((_, i) => {
          return (
            <div
              key={`${v[0]}_${i}`}
              className="flex flex-1 justify-center p-2 bg-white rounded-lg shadow-xs ml-5 bg-gradient-to-r from-green-400 to-blue-500"
            >
              <div>
                <span className="text-lg font-bold">{v[0]}</span>
                <div className="flex items-center justify-center w-full mb-2">
                  <label
                    htmlFor={`${v[0]}_${i}`}
                    className="flex items-center cursor-pointer"
                  >
                    <div className="relative">
                      <input
                        type="checkbox"
                        id={`${v[0]}_${i}`}
                        className="sr-only"
                      />
                      <div className="block bg-gray-600 w-14 h-8 rounded-full"></div>
                      <div className="dot absolute left-1 top-1 bg-white w-6 h-6 rounded-full transition"></div>
                    </div>
                  </label>
                </div>
              </div>
            </div>
          );
        })
      )}
    </div>
  ));

  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <main className="flex flex-col items-center justify-center w-full flex-1 px-20 text-center bg-blue-50">
        <h1 className="text-4xl font-bold mt-6">Welcome to Coyote</h1>
        {rows}
      </main>

      <footer className="flex items-center justify-center w-full h-24 border-t">
        <a
          className="flex items-center justify-center"
          href="https://arkth.co.jp"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by Arkth Inc.
        </a>
      </footer>
    </div>
  );
}
```

# 3. 完成図

Tailwindで見つけたので、なんとなくグラデーションにしてみました。
コヨーテで一度出たカードのスイッチをONにしておけば今残っているカードが一目瞭然です。
少し各ボックスが大きくて一覧性に欠けるのでもう少しUIの調整はしたほうが良さそうですが今回はこれくらいにしておこうと思います！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74622/d00d8954-ea8b-6578-24ab-c97bb6379d81.png)

# 4. github
githubはこちらです！
https://github.com/arkth-araya/coyote