24日目にLINEミニアプリが完成する初心者 ── Day9. 完了画面の作成


# はじめに

前回は「24 日目に LINE ミニアプリが完成する初心者 ── Day8. スプレッドシートとの連携」と題して、資料請求フォームのデータをスプレッドシートに保存する機能を実装しました。

https://qiita.com/non_watanabe/private/14baa5efed3912b4fe67

<br/>
今回は、フォーム送信後に表示される完了画面を作成して、資料請求フォームの完成を目指します。

# 完了画面の実装

今回の完了画面は資料請求フォームの`CatalogPage.tsx`と同じ、`components/pages/catalog`ディレクトリ内に`Complete.tsx`として実装していきます。

## 完了画面コンポーネントの作成

完了画面は画面下に「閉じる」ボタンを配置したいと思います。

クリックすると LIFF の画面を閉じるようにしたいため、LIFF SDK の`closeWindow()`を使用しています。

```tsx:src/nextjs/components/pages/catalog/Complete.tsx
import liff from "@line/liff";

export default function Complete() {
  return (
    <div className="flex flex-col justify-center items-center min-h-screen text-center">
      <h1 className="text-3xl font-medium p-12">
        カタログをご請求いただき
        <br />
        ありがとうございます！
      </h1>

      <p>カタログのご到着までしばしお待ち下さい。</p>
      <p>なにかご不明点があれば、お気軽にお問い合わせください！</p>
      <div className="py-12">
        <a className="underline" onClick={() => liff.closeWindow()}>
          閉じる
        </a>
      </div>
    </div>
  );
}
```

## ページの分岐

完了画面への切り替えは`useState`を使いました。

```tsx:src/nextjs/pages/catalog/index.tsx
import { useState } from "react";
import CatalogPage from "@/components/pages/catalog/CatalogPage";
import Complete from "@/components/pages/catalog/Complete";
export default function Catalog() {
  const [isComplete, setIsComplete] = useState(false);

  if (isComplete) return <Complete />;
  else return <CatalogPage setIsComplete={setIsComplete} />;
}
```

`CatalogPage`コンポーネントに`setIsComplete`を渡していますが、この時点では props の型に`setIsComplete`は渡されていないのでこの後修正を行っていきます。

## CatalogPage コンポーネントの修正

はじめに`setIsComplete`を受け取るための型を定義します。

```tsx:src/nextjs/components/pages/catalog/CatalogPage.tsx
export default function CatalogPage({
  setIsComplete,
}: {
  setIsComplete: (isComplete: boolean) => void;
})
```
<br/>

ページの切り替えはフォームの送信処理が完了した段階で行いたいため、`setIsComplete`は`trigger`の`onSuccess`で呼び出しています。

```tsx:src/nextjs/components/pages/catalog/CatalogPage.tsx
  const onSubmit: SubmitHandler<CatalogPageProps> = (data) => {
    console.log(data);
    trigger(data, {
    onSuccess: () => {
        setIsComplete(true);
      },
    });
  };
```

## 完了画面の動作確認

では実際に完了画面への切り替えができるか確認してみましょう。

フォームに入力を行い「送信する」ボタンをクリックすると完了画面が表示されました！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/41b74e98-b005-0db4-0ecb-697bfa639584.png" width="50%">

<br/>
なお、「閉じる」ボタンはあくまで LIFF の画面を閉じるためのものなので、ブラウザ側では確認ができません。

後ほどデプロイをして確認を行っていきたいと思います。

# ボタンのローディング

「送信する」ボタンを押した際にローディングがないことが気になるので、ボタンにローディングをつけていきたいと思います。

## ボタンコンポーネントの追記

ローディングを表示するために`Button`コンポーネントを以下の通り修正していきます。

```tsx:src/nextjs/components/ui/Button/Button.tsx
import { Button as MUIButton } from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton";
import { ButtonProps } from "./type";

export default function Button({
  label,
  type,
  bgColor = "bg-primary",
  textColor = "text-white",
  isLoading = false,
  ...props
}: ButtonProps) {
  if (!isLoading)
    return (
      <div>
        <MUIButton
          type={type}
          className={`${bgColor} ${textColor} w-full py-4`}
          {...props}
        >
          {label}
        </MUIButton>
      </div>
    );
  else
    return (
      <LoadingButton className={`bg-neutral-500  w-full py-4`} loading>
        {label}
      </LoadingButton>
    );
}
```

`props`に`isLoading`を追加して、その値に応じて使うコンポーネントを変えています。

## CatalogPage コンポーネントの修正

ローディング中かを確認するために`useSWRMutation`から`isMutating`を取得します。

```tsx:src/nextjs/components/pages/catalog/CatalogPage.tsx
  const { trigger, isMutating } = useSWRMutation("/api/catalog", updateUser);
```

<br/>

`Button`コンポーネントの`isLoading`に`isMutating`を指定します。

```tsx:src/nextjs/components/pages/catalog/CatalogPage.tsx
        <Button type="submit" label="送信する" isLoading={isMutating} />
```
これでローディングの追加は完了です。

## ローディングの動作確認

再度フォームを送信してみるとボタンがローディング表示に変わるのが確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/e6f039ff-1566-b1d5-412e-89d3864cc3c4.png)

# デプロイ

ここまでで資料請求フォームの実装が大体完了したので、一旦デプロイを行って動作確認の確認を行っていきたいと思います。

line-liff-v2-starter ディレクトリ配下で以下のコマンドを実行します。

```terminal
$ netlify deploy --build --prod
```

# 動作確認

デプロイが完了したら動作確認を行っていきます。

LIFF アプリの URL を開いてたら資料請求フォームが出てくるので内容を入力して送信ボタンを押してみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/cdf9ffe9-453d-da1a-29c6-b2394e07a81e.jpeg" width="50%">

ちゃんとローディングが表示されていますね！
<br/>

ローディングが終わると、完了画面も表示されました！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/0b318b60-4158-af58-3730-4c7767229d95.jpeg" width="50%">

もちろん「閉じる」ボタンを押すと LIFF の画面が閉じるのも確認ができました。

<br/>
スプレッドシートの出力はどうなっているのでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/4e30c776-3e0d-b5a0-475d-13a326c05c22.png)

ちゃんと入ってる！これで完成ですね！

# まとめ

今回はフォーム送信後の完了画面を実装してきました。

次回はせっかくなので資料請求が完了したタイミングで完了メッセージが届くよう実装していきたいと思います。

残りは 15 日！
気になる方は是非フォローやカレンダー購読をお願いします:star: