コンテンツにスキップ
Documents for MorningStatusApp
Esc
移動開く⌘Jプレビュー
このページの内容

平均年齢の変遷グラフ画面設計書

最終更新: 2026-09-10 関連 Issue: #1595(平均年齢の変遷グラフ追加)


1. 画面概要

項目 内容
URL /average-age
レンダリング方式 SSR(動的)。Server Component(app/average-age/page.tsx)でVercel Blobからメンバーデータを取得し、算出済みの年次データをクライアントコンポーネントに渡す
ライブラリ recharts(LineChart)。本リポジトリでrechartsを使った既存グラフ(DiscographyStatusChart.tsxGeniusLinksStatusChart.tsx)はいずれもBarChartのみで、LineChartの採用は本画面が初出
対象データ 結成年(1997年)から現在までの、毎年の結成日(9月14日)時点における在籍メンバーの平均年齢

2. 表示目的

結成から加入・卒業を繰り返すことでグループの平均年齢が上がったり下がったりし、それがグループのカラーの変化に表れているという仮説を、時系列の折れ線グラフとして可視化する。


3. 集計ロジック

3-1. 対象日の算出

結成日(1997-09-14constants/group.tsGROUP_FORMATION_DATEとして定数化)を基準に、毎年の「結成記念日」({年}-09-14)を対象日とする。

  • 開始年: 1997年
  • 終了年: 現在の年。ただし現在の年の結成記念日({現在年}-09-14)が未到来の場合(現在日 < 現在年の9/14)は、その年を対象から除外し前年までとする(起こっていない未来時点の値を確定値として表示しないため)

3-2. 在籍メンバーの判定

各対象日について、lib/member-map-utils.tsgetActiveMemberIdsAtKeyframe(members, targetDate)(レーダーチャート時系列化 #1308 で実装済み)をそのまま転用し、在籍メンバー(joinDate <= 対象日 かつ (gradDate が null または gradDate > 対象日))を判定する。

3-3. 平均年齢の算出

対象日時点の在籍メンバー全員について、profile.dob(生年月日、必須・全メンバー公開)から満年齢を算出し、単純平均を取る。

  • 満年齢の算出: 対象日の年 − 生年の年 − (対象日の月日 < 誕生日の月日 の場合は1)
  • 在籍メンバーが0人の年(結成前後の理論上のエッジケース)はデータ点として出力しない

4. 画面遷移

4-1. 遷移元

Topページのナビゲーションリンク(メンバー・ユニット・関係性マップ・リリース…の横並び)に「平均年齢」リンクを追加し、/average-ageへ遷移できるようにする。関係性マップと同様、メンバーデータ全体を俯瞰する機能として、ナビゲーション上は「関係性マップ」の直後に配置する。

4-2. 復帰導線

画面上部に「Topに戻る」リンクを設置する(他の主要一覧画面と同様のパターン)。


5. 画面構成

┌───────────────────────────────────────────┐
│ 「Topに戻る」                               │
├───────────────────────────────────────────┤
│ 見出し「平均年齢の変遷」+説明文             │
│ (結成から現在まで、毎年の結成記念日時点の    │
│  在籍メンバーの平均年齢の推移です)          │
├───────────────────────────────────────────┤
│                                           │
│      折れ線グラフ(横軸: 年、縦軸: 平均年齢) │
│                                           │
└───────────────────────────────────────────┘
  • 単一系列の折れ線グラフとして表示する(グループ全体の平均年齢のみ、系列の切り替えUIは設けない)
  • 横軸は西暦年(例: 1997, 1998, …)、縦軸は平均年齢(歳、小数第1位まで)
  • グラフ上にカーソルを合わせると、その年の平均年齢をツールチップで表示する(DiscographyStatusChart.tsxと同様のTooltipスタイルを踏襲)

6. コンポーネント方針

  • Server Component(app/average-age/page.tsx)でgetMembersFromBlob()によりメンバーデータを取得し、lib/average-age-utils.tscalculateAverageAgeTimeline()で年次データ({ year: number; averageAge: number }[])に変換してからクライアントコンポーネントに渡す(app/sync-status/page.tsxと同じ「Server Componentで計算 → Client Componentで描画」の分担パターン)
  • 描画は新規クライアントコンポーネントcomponents/AverageAgeChart.tsx'use client')で行う。recharts のLineChartCartesianGridXAxisYAxisTooltipResponsiveContainerを用い、配色・グリッド線・ツールチップのスタイルはDiscographyStatusChart.tsxを踏襲する

7. ローディング・エラー状態

状態 表示内容
データ取得エラー(Blob未取得等) 「メンバーデータが取得できませんでした」等のエラーメッセージ
算出結果が空(理論上発生しない) グラフの代わりに「表示できるデータがありません」を表示

本画面はServer Componentでレンダリング時に同期的にデータを取得するため、クライアント側のローディング状態(スピナー等)は発生しない。


改訂履歴(バージョン降順に記載)

更新日 変更内容
1.0 2026-09-10 初版作成(#1595)

このページは役に立ちましたか?