laravelの認証機構を見てみよう(5) : 手直し(アイコンなどなど詳細をつめる)

roleの表示

とりあえず何のroleになってるんかわからないのでそれを何とかわかるようにしたいというもの。

一覧と詳細に出しますかー

一覧の加工

<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
    Roles
</th>
...
<td className="px-6 py-4 whitespace-nowrap">TODO</td>

こんな風味にしておく。

roles列とTODOが生成された

でまあ、rolesというのは実は所有してるんだけどリレーションがloadされてないんすよね

    public function index(): Response
    {
        $users = User::all();
        dd($users->toArray());

        return Inertia::render('Users/Index', ['users' => $users]);
    }

こんなんで確認してみると

rolesは見当たらない

こうなるだけだけど

    public function index(): Response
    {
        $users = User::with('roles')->get();
        dd($users->toArray());
// 略

こうやってwithで読みこんどくと

roles列が追加される

こうなるので、最終的にindexのコードは

    public function index(): Response
    {
        $users = User::with('roles')->get();

        return Inertia::render('Users/Index', ['users' => $users]);
    }

こんな感じにして、viewは

<td className="px-6 py-4 whitespace-nowrap">
    {user.roles && user.roles.length > 0 ? (
        user.roles.map((role, index) => (
            <span
            key={index}
            className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
        >
                {role.name}
        </span>
        ))
    ) : (
        <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-200 text-gray-600">
            No roles
        </span>
    )}
</td>

みたいな

roleが表示されている

同様にshowも。ただし、こちらは $user が既に引数につっこまれているのでwithは使わない

    public function show(User $user): Response
    {
        $user->load('roles');
        return Inertia::render('Users/Show', ['user' => $user]);
    }

としておいたら
resources/js/Pages/Users/Show.jsx

<div>
    <h3 className="text-lg font-medium leading-6 text-gray-900">Roles</h3>
    <p className="mt-2 text-lg text-gray-500">
        {user.roles && user.roles.length > 0 ? (
            user.roles.map((role, index) => (
                <span
                key={index}
                className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
            >
                    {role.name}
            </span>
            ))
        ) : (
            <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-200 text-gray-600">
                No roles
            </span>
        )}
    </p>
</div>
showでもroleが表示された

こんな感じでRolesを出力する。これらはほぼコピペ対応なので最終的にはcomponentにする(TODO)

アイコン (react-icon)

email verifiedとかの状況を何とか出したいのでこれを呼びこんでくる。

npm install react-icons

でinstall

% ./vendor/bin/sail npm install react-icons

added 1 package, removed 183 packages, and audited 174 packages in 4s

29 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

でまあ適当に検索してみると…


とか出てくるので最初にヒットしたGoVerifiedを使ってみましょうか

import { GoVerified, GoUnverified } from "react-icons/go";

とか書いといて

                                        <td className="px-6 py-4 whitespace-nowrap">
                                            <GoVerified />
                                            <GoUnverified />
                                            {user.email}
                                        </td>

みたいにすると


こうなるので、これを加工する

まあこんな感じである。ちなみに塗り潰されているのがよければセットを変更した方がよさそう。VscVerifiedFilledとかに変更してみる

import { VscVerifiedFilled, VscUnverified } from "react-icons/vsc";

略

{ user.email_verified_at !== null ? (
    <VscVerifiedFilled className="text-green-500 mr-2" />
) : (
    <VscUnverified className="text-red-500 mr-2" />
)}
<span>{user.email}</span>


この辺は好みによるけど、このようにサクっと変更可能なのがよいところであろう。なお、text-xlとかtext-lgとかいれるとちょっとでかくなる。

ちょっとでかくした例

まあこれもcomponentにするとよいだろう。

showに関しては

<div>
    <h3 className="text-lg font-medium leading-6 text-gray-900">Email</h3>
    <div className="mt-2 flex items-center text-lg text-gray-500">
        { user.email_verified_at !== null ? (
            <VscVerifiedFilled className="text-green-500 mr-2 text-xl" />
        ) : (
            <VscUnverified className="text-red-500 mr-2 text-lg" />
        )}
            <span>{user.email}</span>
    </div>
</div>

とかやっておけば

とまあこんなのでいいんじゃないかな?

detailsボタン

でまあ今VSCアイコンを使ってるんで、まあなるべくこういうのは統一感があった方がいんじゃなかろうかということで…

import { VscVerifiedFilled, VscUnverified, VscInfo } from "react-icons/vsc";
略
<button className="bg-blue-500 hover:bg-blue-700 text-white py-1 px-2 rounded flex items-center">
    <VscInfo className="mr-2"/>
    Details
</button>


Detailsの前にinfomationアイコンが追加された

まあこの辺はいろいろ遊んでみてくださいなっと。

Usersメニューで詳細に入ったら下線がなくなるやつ


下線がない

これ自体は ./vendor/tightenco/ziggy/src/js/Router.js ってやつがやってるんですがー、まあ読むと面倒なくらい長いのでとりあえず

                            <div className="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
                                <NavLink href={route('dashboard')} active={route().current('dashboard')}>
                                    Dashboard
                                </NavLink>
                                {props.auth.isAdmin && (
                                    <NavLink href={route('users.index')} active={route().current('users.*')}>
                                        Users
                                    </NavLink>
                                )}
                            </div>

みたいにワイルドカードで書いといたらええと思うで(それだけかーいw)


breadcrumb

これはまあ

ここでやった奴を導入するだけね(てかこれ最終的にsurveyの奴と統合する予定)。

% ./vendor/bin/sail composer require robertboes/inertia-breadcrumbs
% ./vendor/bin/sail artisan vendor:publish --tag="inertia-breadcrumbs-config"
% ./vendor/bin/sail composer require diglactic/laravel-breadcrumbs


import React from 'react';
import { usePage } from '@inertiajs/react';
import { AiOutlineDoubleRight } from 'react-icons/ai';

const Breadcrumbs = () => {
  const { props: { breadcrumbs } } = usePage();

  if (!breadcrumbs) {
    return null;
  }

  return (
    <div className="border-t border-gray-200 py-2">
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <ol className="flex space-x-2">
          {breadcrumbs.map((breadcrumb, index, arr) => (
            <React.Fragment key={index}>
              <li>
                <a href={breadcrumb.url} className={breadcrumb.current ? "border-b-2 border-blue-400" : ""}>
                  {breadcrumb.title}
                </a>
              </li>
              {index < arr.length - 1 && <li className="flex items-center text-gray-500"><AiOutlineDoubleRight className="mx-1" size={12} /></li>}
            </React.Fragment>
          ))}
        </ol>
      </div>
    </div>
  );
};

export default Breadcrumbs;

さすがにちょいチューニングした

次回

もうちょい踏みこんでいくやつ。ユーザーの削除検討活動ログ収集(ログイン時間とかそれ以外とか)

新規とか編集はまだやりません。面倒だからやらないかもしれないし、ここまで読んでたら自作できるんじゃないかな?

この記事が気に入ったらサポートをしてみませんか?