• #Nuxt
  • #Vue
  • #Excel
  • #設計
  • #ミラーカラムUI
  • #フロントエンド
開発未分類アクティブ

背景と目的

長年使ってきた人生計画のExcelファイル(20シート構成)をWebアプリに移植するプロジェクトを開始した。Excelでは限界を感じていた点がいくつかある。

  • シートが多すぎて全体像が把握しにくい
  • 計算ロジックとデータが混在している
  • 家族構成の変更(配偶者、子供の増減)に対応しづらい
  • スマートフォンから確認できない

Webアプリ化することで、これらの課題を解決しつつ、より使いやすいUIを実現したい。

Excelファイルの分析

Claude Codeでxlsxスキルを使い、Excelファイルの構造を分析した。20シートの内訳は以下の通り。

入力系シート:

  • 基本情報(生年月日、退職予定年齢など)
  • 本人の収入
  • 配偶者の収入
  • 子供情報(3人分)

計算系シート:

  • 社会保険料計算
  • 所得税・住民税計算
  • 年金受給額計算

出力系シート:

  • 年次キャッシュフロー表
  • 累計資産推移グラフ
  • ライフイベント一覧

ミラーカラムUIの採用

UIとしてミラーカラムUIを採用することにした。

採用理由

  1. 全体像が常に見える: Excelではシートタブが隠れがちだが、ミラーカラムなら階層が一覧できる
  2. 入出力の分離: タブで「入力」と「出力」を分け、それぞれをミラーカラムで表現できる
  3. 数値の参照関係が追いやすい: どの入力がどの出力に影響するか、視覚的に理解しやすい

想定レイアウト

[タブ: 入力]
├─ 本人
│  ├─ 基本情報
│  ├─ 収入
│  └─ 社会保険
├─ 配偶者
│  └─ ...
└─ 子供1〜5
   └─ ...

[タブ: 出力]
├─ 年次CF
├─ 資産推移
└─ 結論

冗長バッファ設計

ミラーカラムUIと相性が良い設計として「冗長バッファ」を採用した。

考え方

  • 配偶者は「夫/妻」ではなく「配偶者」として汎用的に定義
  • 子供は最初から5人分の枠を用意
  • 使わない項目はゼロまたはdisplay: noneで非表示

メリット

  1. 動的追加が不要: フォーム項目を動的に追加する複雑なロジックが要らない
  2. 男女どちらでも対応: 「配偶者の収入」という汎用的な項目名なら性別を問わない
  3. ビューで邪魔にならない: ミラーカラムなら未使用項目は折りたためるので、Excelほど冗長さが目立たない

日本の家庭で子供が5人を超えるケースは稀なので、これで実用上は十分カバーできる。

フロントエンド先行開発

計算ロジックは後回しにして、まずフロントエンドから作る方針にした。

理由

  1. 見た目の最適化が先: ExcelのビューをそのままWebに移植すると冗長になる。必要な情報だけを見やすく配置したい
  2. 計算ロジックは変わらない: Excelの数式を移植すればいいので、後からでも対応できる
  3. 早期にフィードバックが得られる: 画面を見ながら「ここはもっとシンプルにしたい」という気づきが出てくる

進め方

  1. Excelの固定値をそのままハードコードして画面を作る
  2. 見た目を調整し、不要な項目を削る
  3. 計算ロジックを実装してハードコードを置き換える
  4. マスターデータ(税率テーブルなど)を外部化

技術スタック

Nuxt 4 + Scoped CSS

TailwindではなくScoped CSSを採用した。

Tailwindを避けた理由:

  • クラス名が長くなりHTMLが読みづらい
  • Claude Codeで編集する際、クラス名の組み合わせを覚えるコストがある
  • 今回はコンポーネント単位でスタイルを閉じ込められればいい

Scoped CSSのメリット:

  • コンポーネントファイル内で完結する
  • CSSの記法がそのまま使える
  • Claude Codeとの相性が良い(普通のCSSを書くだけ)
<style scoped>
.income-table {
  width: 100%;
  border-collapse: collapse;
}
.income-table th {
  background: #f3f4f6;
  padding: 8px;
}
</style>

データ保存

初期段階ではJSONまたはCSVで十分。将来的にはSQLiteも検討するが、性能が問題になるほどのデータ量ではない。

別プロジェクトとしての運用

このプロジェクトは既存のtax-assistantリポジトリとは別に作成することにした。

理由

  1. 関心事が異なる: tax-assistantは税務計算、こちらは人生設計
  2. 依存関係を減らせる: 独立したリポジトリならそれぞれ自由に変更できる
  3. 規模が大きくなりそう: 最初から分けておいた方が管理しやすい

@add-directoryによる参照

Claude Codeでは@add-directoryコマンドで別プロジェクトを参照できる。

@add-directory C:\Users\numbe\Git_repo\tax-assistant

これで両方のコードベースを見ながら作業できる。ただし、明示的に「tax-assistantのミラーカラムコンポーネントを参考にして」と指示する必要がある。自動では参照してくれない。

参照すべきコンポーネント

既存のtax-assistantで使っているミラーカラム関連のコンポーネントは以下の通り。

ファイル説明
MillerColumnsView.vueメインレイアウト
MillerSidebar.vue左サイドバー
MillerContent.vueコンテンツエリア

ただし、これらはtax-assistant固有のロジックと結合しているため、そのままコピーはできない。CSSのレイアウト部分を参考にして、新規に作成する必要がある。

ミラーカラムUIの本質

確認してわかったこと: ミラーカラムUIの核心はCSSにある。

.miller-layout {
  display: flex;
  height: 100vh;
}
.miller-column {
  flex: 0 0 200px;
  border-right: 1px solid #e5e7eb;
  overflow-y: auto;
}
.miller-content {
  flex: 1;
  overflow-y: auto;
}

Vueの実装は階層データの管理とクリック時の選択状態更新がメインで、それほど複雑ではない。新規プロジェクトでは、この基本構造をベースに、人生計画に特化したUIを構築する。

今後の計画

  1. Phase 1: 結論画面とインプット画面のUIを作成
  2. Phase 2: Excelの固定値をハードコードして表示確認
  3. Phase 3: 計算ロジックの実装
  4. Phase 4: マスターデータの外部化

計算ロジックより先にUIを作り込むことで、本当に必要な機能だけに絞り込める。Excelをそのまま移植するのではなく、Webならではの使いやすさを追求したい。

関連リンク