🗃️

🩺看護師が医療現場で使う計算ツールの開発に挑戦してみた #3:履歴ページを見やすく!UIデザイン改善で直感的な操作へ

に公開1

💡 はじめに

現役看護師として働きながら、Next.js × TypeScript × Tailwind CSS を学習し、
そのアウトプットとして「看護師向け計算ツールアプリ」の開発に挑戦しています。

このツールは、投薬量・点滴速度・体液バランス・栄養計算など、
医療現場でよく使う計算をひとまとめにした Web アプリです。

現場で使える実用性と、開発者としての再利用性・型安全性の両立を目指して、実装の過程を1ステップずつ公開しています。

⚙️ 使用技術

  • Next.js 15(App Router)
  • TypeScript
  • Tailwind CSS
  • PWA対応(オフライン動作)

📈 これまでの進捗

  1. 投薬・点滴・栄養など主要計算機能の実装
  2. 履歴データの保存・表示
  3. PWA対応によるオフライン化
  4. 型ガードによる安全な履歴再利用

前回の記事では、
ホーム画面の「計算ボタン」をスマホで見やすく、使いやすくするUI最適化
を紹介しました。

📋 今回のテーマ:履歴ページのデザイン改善

今回の記事では、履歴ページを見やすく整え、直感的に操作できるようにするためのUIデザイン改善についてまとめます。

🪧 Before → After

Before(変更前) After(変更後)
どの計算かわかりにくい 各履歴にアイコン+計算名を表示
結果が平坦で視認性が低い 白×グレー基調でカード風デザインに
タブのスタイルが統一されていない ALL/カテゴリ別タブで統一感UP

🧩 実装構成

対象コンポーネント:

components/
├─ history/
├─ HistoryList.tsx
└─ HistoryTabs.tsx

🧠 実装ポイント①:履歴リスト(HistoryList.tsx)

<div className="space-y-2">
  {items.map((item) => {
    const calc = getCalculatorById(item.typeId);

    return (
      <div
        key={item.id}
        className="flex items-center gap-3 bg-white rounded-lg shadow-sm p-3"
      >
        {calc && (
          <Image
            src={calc.iconPath}
            alt={calc.name}
            width={24}
            height={24}
          />
        )}
        <div>
          <p className="font-semibold text-gray-800">
            {calc?.name ?? "不明な計算"}
          </p>
          <p className="text-xs text-gray-500">{item.resultSummary}</p>
        </div>
      </div>
    );
  })}
</div>

💡 改善ポイント

変更内容 効果
各履歴にアイコン+計算名を表示 一目で内容が分かる
背景を bg-white shadow-sm rounded-lg カード風デザインで視認性UP
結果を text-xs text-gray-500 情報密度を抑えて可読性UP

一覧性UP × 情報密度DOWN
「どの計算をしたか」が一瞬で分かる履歴リストに。

🧠 実装ポイント②:タブ切替(HistoryTabs.tsx)


<div className="grid grid-cols-4 gap-2 overflow-x-auto pb-2">
  <button
    className={`px-3 py-2 rounded ${
      active === "all" ? "bg-gray-800 text-white" : "bg-gray-200"
    }`}
    onClick={() => onChange("all")}
  >
    ALL
  </button>

  {calculators.map((calc) => (
    <button
      key={calc.id}
      className={`flex items-center gap-2 px-3 py-2 rounded ${
        active === calc.id ? calc.color : "bg-gray-200"
      }`}
      onClick={() => onChange(calc.id)}
    >
      <Image src={calc.iconPath} alt={calc.name} width={24} height={24} />
      {calc.name}
    </button>
  ))}
</div>

💡 改善ポイント

変更内容 効果
ALLタブを先頭に固定 一括表示がすぐ選べる
選択中タブに calc.color を反映 計算カテゴリごとに色で識別
overflow-x-auto 横長画面でもスムーズにスクロール可能

🎨 UIの統一デザイン

全体を白×グレー基調に整えることで、
「どのページでも同じアプリ感」を維持しました。

医療アプリでは派手すぎず、視認性と落ち着きを両立することが大切。
Tailwindの shadow-sm や rounded-lg を組み合わせるだけでも、
印象がぐっと柔らかくなります。

🧠 学びと気づき

  • Tailwind CSSだけで十分モダンなUIを構築できる
  • 情報を“減らす”ことで見やすさが増す
  • 同系色の中で明暗をつけると医療アプリらしい落ち着きが出る

🚀 次回予告

次回は、オフライン対応(PWA化) に挑戦します。
アプリとしてインストールできるようにし、
現場でも電波に左右されず動作する仕組みを実装します。

Discussion

MukhammadbekMukhammadbek

You've come up with a great approach and an interesting project, thank you. However, I had a slightly different suggestion:

HistoryTabs.tsx

const allOption = { label: mainDictionary.all, value: null };

const transformedCalculators = useMemo(() => {
    const data = calculators?.map((calculator) => ({
        label: calculator?.name,
        value: calculator?.id
    }))

    return [allOption, ...(data || [])]
}, [calculators])

const handleHistoryTabClick = (value: number | null) => {
    setActive(value || allOption.label)
}

if (!calculators?.length) {
    return null
}

return (
<div className=`grid grid-cols-${transformedCalculators?.length} gap-2 overflow-x-auto mb-2`>
  {transformedCalculators.map((calculator) => (
    <button
      key={calculator.value}
      className={` gap-2 px-3 py-2 rounded ${
        active === calculator.value ? calculator.color : "bg-gray-200"
      }`}
      onClick={handleHistoryTabClick.bind(null, calculator.value)}
    >
      <Image src={calculator?.iconPath ?? ''} alt={calculator?.name} width={24} height={24} />
          {calculator.name}
    </button>
  ))}
  </div>