開発misc-devメモ
Nuxt 4で人生計画シミュレーターのUIを実装する
Excelで作成していた人生計画シミュレーターをWebアプリに移植した。今回はUIコンポーネントをハードコードで実装し、後からロジックを接続する方針で進めた。
完成したUI構成
ミラーカラム(3段階ナビゲーション)
macOS Finderのミラーカラム形式を採用した。
┌─────────────┬────────────────┬────────────────┬───────────────────────┐
│ 大カテゴリ │ 中カテゴリ │ 小カテゴリ │ プレビュー │
│ │ │ │ │
│ ▶ サマリー │ (なし) │ (なし) │ サラリーマンの生涯年収 │
│ 年次収支 │ ▶ まとめ │ (なし) │ テーブル表示 │
│ 収入詳細 │ フロー詳細 │ │ │
│ │ 資産形成 │ │ │
└─────────────┴────────────────┴────────────────┴───────────────────────┘
特徴:
- 矢印キーでタブ内の全項目を順繰りに移動可能
- ナビバーにパス形式でタイトルを表示(例:「表示 > サマリー | サラリーマンの生涯年収」)
- クエリパラメータで表示状態をURLに反映
サマリー画面(段階損益形式)
当初はカード3枚(本人・配偶者・世帯合計)で表示していたが、Excelのようなマトリックス形式に変更した。
┌───────────────────────────────────────────────────────────────────────┐
│ サラリーマンの生涯年収 │
├───────────────────────────────────────────────────────────────────────┤
│ ウォーターフォールチャート │
│ [生涯年収] → [-社会保障費] → [手取り] → [-生活費] → [-教育費] → [可処分所得] │
├─────────────┬─────────┬─────────┬─────────┬─────────┬─────────┬───────┤
│ 項目 │ 夫(48) │ 妻(48) │ 子供1 │ 子供2 │ 子供3 │ 合計 │
├─────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼───────┤
│ 生涯年収 │ 2.9億 │ 0.7億 │ - │ - │ - │ 3.7億 │
│ 社会保障費 │ ▲0.6億 │ ▲0.1億 │ - │ - │ - │▲0.8億 │
│ 手取り合計 │ 2.2億 │ 0.5億 │ - │ - │ - │ 2.8億 │
│ 居住費・生活費│▲1.4億 │ - │ - │ - │ - │▲1.4億 │
│ 教育費 │ - │ - │▲1420万 │▲1420万 │▲1420万 │▲4263万│
│ 可処分所得 │ - │ - │ - │ - │ - │ 1.0億 │
└─────────────┴─────────┴─────────┴─────────┴─────────┴─────────┴───────┘
ポイント:
- 段階損益として手取り合計、生活費控除後が明確に表示される
- ヘッダーに「夫(48)」のように現在年齢を表示
- 合計行をstickyで固定
年次収支テーブル
42年分(2024〜2065年)の年次データを一覧表示。Excelのシミュレーション_sumシートを再現した。
┌──────┬──────┬────────────┬────────────┬────────────┬────────────┐
│ 年度 │ 年齢 │ 手取り合計 │ 居住費生活費│ 教育費 │ 収支累計 │
│ │ │ │ │ │(Σ年間収支) │
├──────┼──────┼────────────┼────────────┼────────────┼────────────┤
│ 2024 │ 46 │ 6,800,000 │ ▲3,408,000 │ ▲1,245,000│ 2,147,000 │
│ 2025 │ 47 │ 6,950,000 │ ▲3,408,000 │ ▲1,398,000│ 4,291,000 │
│ ... │ │ │ │ │ │
│ 合計 │ - │ 286,000,000│▲143,136,000│▲42,629,109│100,234,891 │
└──────┴──────┴────────────┴────────────┴────────────┴────────────┘
実装のポイント:
- theadにposition: stickyを設定
- 「収支累計」の下に「(Σ年間収支)」と注釈を表示し、利息なしの単純積み上げであることを明示
実装で苦労した点
stickyヘッダーが効かない問題
Flexboxレイアウト内でposition: stickyが効かなかった。解決策は以下。
/* 親コンテナにmin-height: 0を追加 */
.detail-pane {
flex: 1;
min-height: 0; /* これが重要 */
display: flex;
flex-direction: column;
}
/* テーブルを包むコンテナをスクロールコンテナに */
.table-container {
flex: 1;
overflow: auto;
}
詳細は CSSでテーブルヘッダーを固定する を参照。
Nuxtのキャッシュ問題
CSSの変更がブラウザに反映されなかった。ハードリフレッシュでも直らず、.nuxtフォルダを削除してサーバー再起動で解決。
詳細は Nuxtでスタイルが反映されない時は.nuxtフォルダを削除する を参照。
技術選定
クエリパラメータによるナビゲーション状態の共有
URLでナビゲーション状態を共有できるようにした。
/life-plan?tab=display&l1=summary
/life-plan?tab=display&l1=yearly&l2=income
パスベースではなくクエリパラメータを選んだ理由:
- 「別々のコンテンツ」ではなく「同じデータの異なるビュー」
- 検索エンジンに個別ページとしてインデックスさせる必要がない
- 実装がシンプル
詳細は URLルーティング設計:クエリパラメータとパスベースの使い分け を参照。
ウォーターフォールチャート
サマリー画面の冒頭に段階損益をビジュアル化したウォーターフォールチャートを追加した。
- 生涯年収(夫妻の積み棒)
- 社会保障費(マイナス)
- 手取り合計
- 居住費・生活費(マイナス)
- 教育費(マイナス)
- 可処分所得
夫と妻の内訳は積み棒で表示し、合計値がわかるようにした。
今後の予定
現在はハードコードでUIを作成している段階。次のステップは以下。
- Excelデータを読み込んでハードコード値を置き換え
- 入力フォームから値を変更できるようにする
- 計算ロジックの実装
- ローカルストレージへのデータ保存
- ユーザー登録・家族データ共有機能
まとめ
Excelの人生計画シミュレーターをWebアプリに移植する第一段階として、UIコンポーネントを実装した。ミラーカラム構成のナビゲーション、段階損益形式のサマリーテーブル、ウォーターフォールチャートなど、Excelの表現力をWebでも実現できた。
次はロジックの実装に進む。