BluePeriod Docs
開発コンポーネント

作品詳細ページコンポーネント

作品詳細ページを構成するコンポーネント群の設計

作品詳細ページコンポーネント

このドキュメントは、作品詳細ページ(/explore/details/[id])を構成するコンポーネント群について記述します。

概要

作品詳細ページは、ユーザーが作品を深く知り、読む決意を固めるための専用ページです。Exploreページでの「発見」と、Readerページでの「読書」の間に位置する重要な「玄関」の役割を果たします。

このページは、Exploreでの「発見」とReaderでの「読書」の間に位置する重要な「玄関」の役割を果たします。以下のコンポーネントで構成されています:

  • [ActionButtons]: Open Book、Libraryボタン

ページ構成

  • ルート: /explore/details/[id]
  • 実装: Next.js App Routerのサーバーコンポーネント
  • レイアウト: 2カラム(左: メインコンテンツ、右: サイドバー)

コンポーネント一覧

ProjectDetailsPage

作品詳細ページのメインコンポーネント(サーバーコンポーネント)です。

  • ファイル: src/app/explore/details/[id]/page.tsx
  • 責務:
    • Supabaseから作品メタデータと著者情報を取得
    • Supabase Storageからコンテンツ(プロット、原稿)を取得
    • ライブラリステータスの確認
    • 2カラムレイアウトの構築
  • データ取得:
    • published_projects テーブル(JOINでprofilesも取得)
    • contents バケットからコンテンツJSON
    • library_items テーブルでブックマーク状態を確認
  • レイアウト:
    • モバイル: 1カラム(縦並び)
    • デスクトップ: 2カラム(lg:grid-cols-3で左2列、右1列)

HeroSection

作品の第一印象を形成するヒーローセクションコンポーネントです。

  • ファイル: src/components/details/HeroSection.tsx
  • 責務:
    • カバー画像の大きな表示(aspect-video md:aspect-[2/1]
    • 作品タイトル(h1タグ)
    • ヘッドライン/キャッチコピー(左ボーダー付き)
    • 著者情報(アバター + 名前)
  • 主要なProps:
    • title: 作品タイトル(string)
    • headline: ヘッドライン(string | null)
    • coverImageUrl: カバー画像URL(string | null)
    • author: 著者情報({ username, avatar_url } | null)
  • スタイル特性:
    • カバー画像にホバー時のズーム効果(hover:scale-105
    • 画像がない場合はプレースホルダー表示
    • レスポンシブなタイポグラフィ(text-3xl md:text-4xl lg:text-5xl

ActionButtons

読者の次のアクションを促すボタン群を提供するコンポーネントです。

  • ファイル: src/components/details/ActionButtons.tsx
  • 責務:
    • Open in Readerボタン: 最初の話へ遷移(/read/[projectId]/[firstStoryId]
    • Libraryボタン: ライブラリへの追加/削除(Optimistic UI実装)
    • 将来の機能用プレースホルダー(Like, Share)
  • 主要なProps:
    • projectId: プロジェクトID(string)
    • firstStoryId: 最初の話のID(string | null)
    • initialInLibrary: 初期のライブラリ状態(boolean)
  • API連携:
    • POST /api/library: ライブラリに追加
    • DELETE /api/library: ライブラリから削除
  • UX特性:
    • 楽観的UI更新で即座にフィードバック
    • エラー時は自動的にロールバック
    • トースト通知で操作結果を表示

Synopsis

作品のあらすじを表示するコンポーネントです。

  • ファイル: src/components/details/Synopsis.tsx
  • 責務:
    • あらすじテキストの表示
    • 長文の場合の折りたたみ機能(300文字を閾値)
    • 「Read More / Show Less」トグル
  • 主要なProps:
    • synopsis: あらすじテキスト(string | null)
  • 使用しているUIコンポーネント:
    • Collapsible, CollapsibleContent, CollapsibleTrigger (shadcn/ui)
    • Button (variant="ghost")
  • スタイル特性:
    • 折りたたみ時にグラデーションフェード効果(bg-gradient-to-t from-background
    • whitespace-pre-wrapで改行を保持

TableOfContents

作品の階層的な目次を表示するコンポーネントです。

  • ファイル: src/components/details/TableOfContents.tsx
  • 責務:
    • Part > Arc > Chapter > Story の階層構造を表示
    • 各話のタイトルをReaderページへのリンクとして提供
    • アコーディオン形式で階層を開閉可能
    • 旧構造(chapters直接)への後方互換性
  • 主要なProps:
    • structuredPlot: プロット構造(StructuredPlot型)
    • projectId: プロジェクトID(string)
  • 使用しているUIコンポーネント:
    • Accordion, AccordionItem, AccordionTrigger, AccordionContent (shadcn/ui)
  • リンク生成:
    • 各話: /read/[projectId]/[storyId]
  • デフォルト動作:
    • すべてのPartをデフォルトで展開(defaultValueにすべてのpart.idを設定)

ProjectInfoCard

作品のメタデータを整理して表示するカードコンポーネントです。

  • ファイル: src/components/details/ProjectInfoCard.tsx
  • 責務:
    • タグの表示(Badge形式、クリック可能)
    • ステータス表示(完結済み/連載中)
    • 文字数の表示
    • 公開日/最終更新日の表示
  • 主要なProps:
    • tags: タグの配列(string[] | null)
    • status: ステータス("completed" | "ongoing")
    • wordCount: 文字数(number | undefined)
    • publishedAt: 公開日(string | null)
    • updatedAt: 最終更新日(string | null)
  • 使用しているUIコンポーネント:
    • Card, CardHeader, CardTitle, CardContent (shadcn/ui)
    • Badge (shadcn/ui)
  • アイコン:
    • FileText: 文字数
    • Calendar: 日付
    • Tag: タグ

ReviewChart

AI査読結果を視覚化するチャートコンポーネントです。

  • ファイル: src/components/details/ReviewChart.tsx
  • 責務:
    • 動的評価軸(dynamic_detailed_ratings)をレーダーチャートで表示
    • AI品質チェック通過のメッセージ表示
    • 査読結果がない場合は非表示
  • 主要なProps:
    • reviewReport: AI査読レポート(ReviewReport | null
  • 使用しているライブラリ:
    • recharts: レーダーチャートの描画
    • ChartContainer, ChartTooltip (shadcn/ui chart components)
  • データ変換:
    const data = reviewReport.dynamic_detailed_ratings.map((rating) => ({
      axis: rating.axis,
      score: rating.score,
    }));
  • スタイル特性:
    • aspect-square max-h-[300px]: 正方形で最大300px
    • outerRadius="70%": チャートサイズ
    • プライマリカラーで統一(hsl(var(--primary))

OriginalLanguageBadge

作品のオリジナル言語を表示するバッジコンポーネントです。

  • ファイル: src/components/ui/original-language-badge.tsx
  • 責務:
    • 言語コード(例: 'ja', 'en')を人間が読める言語名に変換して表示
    • グローバルアイコン(Globe)と共にコンパクトなバッジとして表示
    • 言語コードがnullの場合は非表示
  • 主要なProps:
    • languageCode: 言語コード(string | null)
    • className: 追加のCSSクラス(オプション)
  • 技術的特徴:
    • Intl.DisplayNames APIを使用して言語コードをローカライズされた言語名に変換
    • shadcn/uiのBadgeコンポーネントをベースに使用
    • フォールバック処理: Intl APIが利用できない場合は言語コードをそのまま表示
  • スタイル特性:
    • text-[10px] h-5: コンパクトなサイズ
    • bg-background/50 backdrop-blur-sm: 半透明の背景にぼかし効果
    • gap-1: アイコンとテキストの間隔
  • 使用箇所:
    • ProjectDetailsContainer: ヒーローセクションの左上に表示
    • ProjectDetailView: プロジェクト詳細モーダル内に表示
    • ProjectCard: カードの右下に表示(Explore、Library、My Worksページ)

設計思想

1. 情報の階層化

  • 左カラム: 読者が最も求める情報(あらすじ、目次)
  • 右カラム: 補助的な情報(メタデータ、査読結果)

2. アクションの明確化

  • 「Open in Reader」を最も目立つプライマリボタンとして配置
  • ライブラリ追加は二次的なアクションとして控えめに

3. 拡張性

  • 右カラムには将来の機能(レビュー、関連作品など)を追加するスペースを確保
  • コンポーネントは独立しており、個別に拡張可能

4. ユーザージャーニー

Explore → 作品カード → 詳細ページ → Open in Reader → Reader

              Library追加

5. 役割分担の明確化

  • Explore: 「偶然の出会い」の場所
  • 作品詳細: 「深く知る」場所
  • Reader: 「没入する」場所

関連ドキュメント

  • /doc/system/06_routing_architecture.md - ルーティング設計
  • /doc/system/07_component_bible.md - 全体のコンポーネント設計
  • /doc/system/04_database_schema_supabase.md - データベーススキーマ
  • /doc/log/reports/2025-12-02_report_implement-project-details-page.md - 実装レポート

On this page