# ログイン後のレイアウトを作成

次にログイン後のレイアウトを作成しましょう。

`feature/after-login-layout-page`にて作業します。

```bash
git switch -c feature/after-login-layout-page
```

`templates`配下に`LoginLayout.tsx`を作成しましょう。内容は以下のように記述します。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx"><strong>import { Outlet } from "react-router-dom";
</strong><strong>
</strong><strong>export const LoginLayout = () => {
</strong><strong>  return (
</strong><strong>    &#x3C;div className="relative">
</strong><strong>      &#x3C;header className="bg-white fixed top-0 left-0 right-0 leading-[50px]">
</strong><strong>        &#x3C;div className="sm:container sm:mx-auto flex justify-between">
</strong><strong>          &#x3C;p className="logo">
</strong><strong>            スケジュール管理APP
</strong><strong>          &#x3C;/p>
</strong><strong>          &#x3C;nav>
</strong><strong>            &#x3C;ul className="flex justify-center gap-5 text-lime-800">
</strong><strong>              &#x3C;li className="flex items-center">ユーザー名&#x3C;/li>
</strong><strong>              &#x3C;li className="flex items-center">ログアウト&#x3C;/li>
</strong><strong>            &#x3C;/ul>
</strong><strong>          &#x3C;/nav>
</strong><strong>        &#x3C;/div>
</strong><strong>      &#x3C;/header>
</strong><strong>      &#x3C;main className="pt-[50px] bg-gradient-to-r from-lime-100 to-lime-200 h-screen flex flex-col justify-center items-center">
</strong><strong>        &#x3C;Outlet />
</strong><strong>      &#x3C;/main>
</strong><strong>    &#x3C;/div>
</strong><strong>  );
</strong><strong>}
</strong>
</code></pre>

ロゴの部分を押した際は、Topページに遷移するようにしましょう。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx"><strong>import { Link, Outlet } from "react-router-dom";
</strong>import { loginUserState } from "../../store/loginUserState";

export const LoginLayout = () => {
  const loginUser = useRecoilValue(loginUserState);

  return (
    &#x3C;div className="relative">
      &#x3C;header className="bg-white fixed top-0 left-0 right-0 leading-[50px]">
        &#x3C;div className="sm:container sm:mx-auto flex justify-between">
<strong>          &#x3C;p className="logo">
</strong><strong>            &#x3C;Link to="/">スケジュール管理APP&#x3C;/Link>
</strong><strong>          &#x3C;/p>
</strong>          &#x3C;nav>
            &#x3C;ul className="flex justify-center gap-5 text-lime-800">
              &#x3C;li className="flex items-center">ユーザー名&#x3C;/li>
              &#x3C;li className="flex items-center">ログアウト&#x3C;/li>
            &#x3C;/ul>
          &#x3C;/nav>
        &#x3C;/div>
      &#x3C;/header>
      &#x3C;main className="pt-[50px] bg-gradient-to-r from-lime-100 to-lime-200 h-screen flex flex-col justify-center items-center">
        &#x3C;Outlet />
      &#x3C;/main>
    &#x3C;/div>
  );
}
</code></pre>

ユーザー名の部分はglobal stateの`loginUser.name`を表示するようにしましょう。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx">import { Link, Outlet } from "react-router-dom";
<strong>import { useRecoilValue } from "recoil";
</strong><strong>import { loginUserState } from "../../store/loginUserState";
</strong>
export const LoginLayout = () => {
<strong>  const loginUser = useRecoilValue(loginUserState);
</strong>
  return (
    &#x3C;div className="relative">
      &#x3C;header className="bg-white fixed top-0 left-0 right-0 leading-[50px]">
        &#x3C;div className="sm:container sm:mx-auto flex justify-between">
          &#x3C;p className="logo">
            &#x3C;Link to="/">スケジュール管理APP&#x3C;/Link>
          &#x3C;/p>
          &#x3C;nav>
            &#x3C;ul className="flex justify-center gap-5 text-lime-800">
<strong>              &#x3C;li className="flex items-center">{loginUser.name}&#x3C;/li>
</strong>              &#x3C;li className="flex items-center">ログアウト&#x3C;/li>
            &#x3C;/ul>
          &#x3C;/nav>
        &#x3C;/div>
      &#x3C;/header>
      &#x3C;main className="pt-[50px] bg-gradient-to-r from-lime-100 to-lime-200 h-screen flex flex-col justify-center items-center">
        &#x3C;Outlet />
      &#x3C;/main>
    &#x3C;/div>
  );
}
</code></pre>

ログアウトのリンクを押した際は、`loginUser`を初期値に戻して、ログインページに戻るようにしましょう。現在`useRecoilValue`を使用してstateのみを扱っていましたが、setStateも扱うため、`useRecoilState`に変更しましょう。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx"><strong>import { Link, Outlet, useNavigate } from "react-router-dom";
</strong><strong>import { useRecoilState } from "recoil";
</strong>import { loginUserState } from "../../store/loginUserState";

export const LoginLayout = () => {
<strong>  const navitate = useNavigate()
</strong><strong>  const [loginUser, setLoginUser] = useRecoilState(loginUserState)
</strong>
<strong>  const handleLogout = () => {
</strong><strong>    setLoginUser({ id: 0, name: "" })
</strong><strong>    navitate("/login")
</strong><strong>  }
</strong>
  return (
    &#x3C;div className="relative">
      &#x3C;header className="bg-white fixed top-0 left-0 right-0 leading-[50px]">
        &#x3C;div className="sm:container sm:mx-auto flex justify-between">
          &#x3C;p className="logo">
            &#x3C;Link to="/">スケジュール管理APP&#x3C;/Link>
          &#x3C;/p>
          &#x3C;nav>
            &#x3C;ul className="flex justify-center gap-5 text-lime-800">
              &#x3C;li className="flex items-center">{loginUser.name}&#x3C;/li>
              &#x3C;li className="flex items-center">
<strong>                &#x3C;a onClick={handleLogout}>ログアウト&#x3C;/a>
</strong>              &#x3C;/li>
            &#x3C;/ul>
          &#x3C;/nav>
        &#x3C;/div>
      &#x3C;/header>
      &#x3C;main className="pt-[50px] bg-gradient-to-r from-lime-100 to-lime-200 h-screen flex flex-col justify-center items-center">
        &#x3C;Outlet />
      &#x3C;/main>
    &#x3C;/div>
  )
}

</code></pre>

また、各ナビゲーションメニューのリンクに、アイコンを表示しましょう。

`react-icons`をインストールします。

```bash
npm i react-icons
```

アイコンは以下サイトから調べることができます。

{% embed url="<https://react-icons.github.io/react-icons/>" %}

今回はユーザーネームの部分に`<FaUser />`を使用し、ログアウトの部分に`<MdLogout />`を使用します。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx">import { Link, Outlet, useNavigate } from "react-router-dom";
import { useRecoilState } from "recoil";
import { loginUserState } from "../../store/loginUserState";
<strong>import { FaUser } from "react-icons/fa";
</strong><strong>import { MdLogout } from "react-icons/md";
</strong>

export const LoginLayout = () => {
  const navitate = useNavigate()
  const [loginUser, setLoginUser] = useRecoilState(loginUserState)

  const handleLogout = () => {
    setLoginUser({ id: 0, name: "" })
    navitate("/login")
  }

  return (
    &#x3C;div className="relative">
      &#x3C;header className="bg-white fixed top-0 left-0 right-0 leading-[50px]">
        &#x3C;div className="sm:container sm:mx-auto flex justify-between">
          &#x3C;p className="logo">
            &#x3C;Link to="/">スケジュール管理APP&#x3C;/Link>
          &#x3C;/p>
          &#x3C;nav>
            &#x3C;ul className="flex justify-center gap-5 text-lime-800">
<strong>              &#x3C;li className="flex items-center">
</strong><strong>                &#x3C;FaUser />
</strong><strong>                {loginUser.name}
</strong><strong>                &#x3C;/li>
</strong><strong>              &#x3C;li className="flex items-center">
</strong><strong>                &#x3C;MdLogout />
</strong><strong>                &#x3C;a onClick={handleLogout}>ログアウト&#x3C;/a>
</strong><strong>              &#x3C;/li>
</strong>            &#x3C;/ul>
          &#x3C;/nav>
        &#x3C;/div>
      &#x3C;/header>
      &#x3C;main className="pt-[50px] bg-gradient-to-r from-lime-100 to-lime-200 h-screen flex flex-col justify-center items-center">
        &#x3C;Outlet />
      &#x3C;/main>
    &#x3C;/div>
  )
}

</code></pre>

最後にこちらのコンポーネントにて、ログインしていない場合にログインページにリダイレクトさせるようにします。

ログインしていない場合は、global stateの`loginUser.id`にて判断しましょう。リダイレクトは、`react-router-dom`の`Navigate`タグにて実現することができます。

<pre class="language-tsx" data-title="templates/LoginLaoyout.tsx◎"><code class="lang-tsx">import { useRecoilState } from 'recoil'
import { loginUserState } from '../../store/loginUser'
<strong>import { Link, Navigate, Outlet, useNavigate } from 'react-router-dom'
</strong>import { FaUser } from "react-icons/fa";
import { MdLogout } from "react-icons/md";

export const LoginLayouts = () => {
  const navigate = useNavigate();
  const [loginUser, setLoginUser] = useRecoilState(loginUserState)
  const handleLogout = () => {
    setLoginUser({ id: 0, name: "" })
    navigate("/login")
  }

<strong>  if (loginUser.id === 0) return &#x3C;Navigate to="/login" />;
</strong>
  return (
...
</code></pre>

ではこちらを`routes.ts`にて呼び出しましょう。

まず`{ path: "/calendar", element: <CalendarPage />}`を削除して、カレンダーページのパスを削除します。そして、ログインしている場合は`<LoginLayout />`を表示するので、配列に新しい要素を追加します。その中の`elements`に`<LoginLayout />`を指定して、`children`にログインしている場合に表示するページを格納していきます。ですので、`/calendar`の場合に`<CalendarPage />`を表示するようにセットします。

<pre class="language-tsx"><code class="lang-tsx">import { createBrowserRouter } from "react-router-dom";
import { TopPage } from "./components/pages/TopPage";
import { LoginPage } from "./components/pages/LoginPage";
import { NotLoginLayout } from "./components/templates/NotLoginLayouts";
import { CalendarPage } from "./components/pages/CalendarPage";
<strong>import { LoginLayout } from "./components/templates/LoginLayout";
</strong>
export const router = createBrowserRouter([
  {
    path: "/",
    element: &#x3C;NotLoginLayout />,
    children: [
      { index: true, element: &#x3C;TopPage /> },
      { path: "/login", element: &#x3C;LoginPage /> },
    ],
  },
<strong>  {
</strong><strong>    element: &#x3C;LoginLayout />,
</strong><strong>    children: [{ path: "/calendar", element: &#x3C;CalendarPage /> }],
</strong><strong>  },
</strong>]);

</code></pre>

これでログインしていない場合に`/calendar`に遷移すると、ログインページにリダイレクトし、ログインすると`/calendar`ページに遷移することができるかと思います。

ここまでの作業をcommitしましょう。

```bash
git add .
```

```bash
git commit
```

commitメッセージは

```
feat: ログイン後のレイアウトを作成
```

としましょう。

ではログイン後のレイアウトの実装が完了したので、GitHubにpushしましょう。

```bash
git push origin feature/after-login-layout-page
```

これでGitHubのリポジトリのページにいき、main <- feature/after-login-layout-pageのPRを作成しましょう。

PRのタイトルは

```
feat: ログイン後のレイアウトを作成
```

としましょう。

作成したら自身で`Merge pull request`を押してmergeしましょう。

mergeが完了したらWarpに戻り、mainをpullしましょう。

```bash
git switch main
```

```bash
git pull origin main
```
