[Advent Calendar 2021][Day14]カレンダー登録機能を作る

はじめに

Advent Calendar 2021のDay14。 カレンダー登録機能を作っていきます。 すこし、UIがなんのCSSも入っておらず、さみしいので徐々にUIも作っていこうと思います。とりあえず、UI関連のパッケージを追加します。

UI関連パッケージ追加

UIに関するパッケージをいくつか追加します。

yarn add tailwindcss --dev
npx tailwindcss init -p
yarn add daisyui --dev
yarn add @heroicons/vue --dev

tailwindは定番になったとおもいます。 他にHeroiconとDaisyUIというパッケージをインストールしました。

  • daisyUI

https://daisyui.com/

tailwindは、CSSのFrameworkですが、それを利用してComponentを作ったのがDaisyUIです。定番のコンポーネントが少ないコード量でかけるので気に入っています。

  • Heroicons

tailwindの作者が作成しているアイコンセットです。他にマテリアルアイコンや、Fontawesomeなどありますが、特に見劣りせず使えると思います。

https://heroicons.com/

Nuxt3でTailwindとdaisyUIを使う

下記の記述を追記します。

  • nuxt.config.ts
    css: ['tailwindcss/tailwind.css'],
    build: {
        postcss: {
            // add Postcss options
            postcssOptions: require('./postcss.config.js'),
        },
    },
  • taiwlwind.config.js
module.exports = {
  content: [
    "./components/**/*.{vue,js,jsx,ts,tsx}",
    "./layouts/**/*.{vue,js,jsx,ts,tsx}",
    "./pages/**/*.{vue,js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require('daisyui'),
  ],
}

カレンダー登録機能を作る

すでに前回にHasuraの権限設定は終わっているので、Mutationの実装をすれば動くと思います。

InsertCalendarMutationを記述する

Hasuraのコンソールから、Mutationのクエリを作れるので、それをgql/queries/calendar.graphqlに追記します。

  • gql/queries/calendar.graphql

カレンダー名を指定してカレンダーを登録できるようにします。

mutation InsertCalendarMutation($name: String!) {
  insert_calendars_one(object: {name: $name}) {
    updated_at
    id
    name
    uid
  }
}

typescriptのコードを自動生成します。

yarn graphql-codegen

モーダルを表示してMutationを実行する

daisyUIが提供してくれるModalコンポーネントを使って、カレンダー名を入力してカレンダーを作るボタンを押すと、カレンダーが作られるようにします。

        <template v-else>
            <button @click="nuxtApp.$firebase.signOut()">logout</button>
            <button v-if="user" @click="nuxtApp.$firebase.deleteUser()">deleteUser</button>
+            <button @click="openModal">カレンダーを作る</button>
        </template>
+        <div id="my-modal" :class="modalClass">
+            <div class="modal-box">
+                <p>タイトル</p>
+                <div class="form-control">
+                    <label class="label">
+                        <span class="label-text">カレンダー名</span>
+                    </label>
+                    <input
+                        v-model="calendarName"
+                        type="text"
+                        class="input input-primary input-bordered"
+                    />
+                </div>
+                <div class="modal-action">
+                    <a @click="insert" class="btn btn-primary">カレンダーを作る</a>
+                    <a @click="closeModal" class="btn">閉じる</a>
+                </div>
+            </div>
+        </div>
    </section>
</template>

<script setup lang="ts">
-import { MyQueryDocument } from "~/gql/queries/calendar";
+import { MyQueryDocument, InsertCalendarMutationDocument, InsertCalendarMutationMutationVariables } from "~/gql/queries/calendar";
import { useClientHandle } from "@urql/vue";
import { useNuxtApp } from '#app'
const urql = useClientHandle();
-const { data, fetching } = await urql.useQuery({ query: MyQueryDocument })
+const queryResult = await urql.useQuery({ query: MyQueryDocument })
const { data, fetching } = await queryResult
const nuxtApp = useNuxtApp()
const user = useState<boolean>('user')
+const modalClass = useState<any>('modalClass', () => ({ 'modal': true, 'modal-open': false }))
+const openModal = () => {
+    modalClass.value = { 'modal': true, 'modal-open': true }
+}
+const closeModal = () => {
+    modalClass.value = { 'modal': true, 'modal-open': false }
+}
+let calendarName = useState<string>('calendarName', () => '')
+const insertCalendarResult = urql.useMutation(InsertCalendarMutationDocument);
+const insert = () => {
+    const variables: InsertCalendarMutationMutationVariables = {
+        name: calendarName.value
+    };
+    insertCalendarResult.executeMutation(variables).then(async (result) => {
+        await queryResult.executeQuery({
+            requestPolicy: 'network-only',
+        })
+        closeModal()
+    });
+}
</script>

まとめ

今回は、カレンダー登録機能を作りました。 次回は、カレンダー参加機能を作ります。