ユーザー管理画面 要件定義書¶
| 項目 |
内容 |
| プロジェクト名 |
SMART-CONTACT |
| バージョン |
1.0 |
| 作成日 |
2026-02-17 |
| ステータス |
開発中 (develop ブランチ) |
1. 概要¶
ユーザー向けWebダッシュボードであり、Chrome拡張機能のアカウント設定画面からリンクされる管理画面である。ユーザーは本画面からプロフィール編集、契約・請求管理、デバイス管理、利用統計の確認、運営からのお知らせ閲覧を行う。
| 項目 |
内容 |
| ルートプレフィックス |
/dashboard/* |
| ミドルウェア |
auth, verified
|
| 認証方式 |
Session認証 (Cookie) |
| フレームワーク |
Laravel Inertia.js + React + TypeScript |
| UIコンポーネント |
shadcn/ui (Radix UI ベース) |
| スタイリング |
Tailwind CSS 4 |
| チャートライブラリ |
Recharts |
| アニメーション |
Framer Motion |
| アイコン |
Lucide React |
| テーブル |
TanStack Table v8 |
| フォーム |
React Hook Form + Zod |
| デザイン |
ダーク/ライト切替対応 (デザインシステム準拠) |
2. 画面一覧¶
| 画面 |
URL |
説明 |
| ユーザーダッシュボード |
/dashboard |
利用状況サマリー + お知らせ |
| プロフィール |
/dashboard/profile |
名前・メール・パスワード変更 |
| 契約・請求管理 |
/dashboard/billing |
プラン確認・変更、請求履歴、カード情報 |
| デバイス管理 |
/dashboard/devices |
登録デバイス一覧・削除・再紐付け |
| 利用統計 |
/dashboard/stats |
送信実績グラフ (日次/月次) |
| お知らせ |
/dashboard/notices |
運営からの通知一覧 |
3. 機能要件¶
FR-USER-WEB-001: ユーザーダッシュボード (/dashboard)¶
ログイン後のトップ画面。ユーザーの利用状況を一覧できるサマリーページ。
ウェルカムヘッダー¶
| 項目 |
内容 |
| 表示内容 |
ユーザー名 + プラン種別バッジ |
| プランバッジ |
Premium: ゴールド光沢 / Standard: シルバー / Trial: ブルー |
| 表示例 |
こんにちは、山田太郎さん + Premium バッジ |
利用サマリーカード¶
4枚のKPIカードを横並びで表示する。
| カード |
算出方法 |
表示例 |
| 今月の送信数 |
当月の user_activity_logs (execution_complete) から合計 |
128 件 |
| 成功率 |
成功数 / 総送信数 × 100 |
94.5% |
| 残りデバイス枠 |
デバイス上限 - 登録済みデバイス数 |
1 台 |
| 契約残日数 |
trial_ends_at または subscriptions.ends_at までの日数 |
23 日 (Premium は 無期限) |
送信数グラフ¶
| 項目 |
内容 |
| 種別 |
棒グラフ (Bar Chart) |
| 期間 |
直近7日間の日別送信数 |
| データソース |
user_activity_logs (execution_complete) |
| ライブラリ |
Recharts |
お知らせバナー¶
| 項目 |
内容 |
| 表示件数 |
未読通知の最新3件 |
| 表示要素 |
type バッジ + タイトル + 公開日 |
| クリック動作 |
/dashboard/notices へ遷移 |
| 未読判定 |
admin_notifications.id が readNoticeIds に含まれないもの |
クイックリンク¶
| リンク先 |
説明 |
/dashboard/profile |
プロフィール編集 |
/dashboard/devices |
デバイス管理 |
/dashboard/billing |
プラン変更 |
FR-USER-WEB-002: プロフィール (/dashboard/profile)¶
ユーザーの基本情報を表示・編集する画面。
基本情報セクション¶
| フィールド |
型 |
バリデーション |
備考 |
| 名前 |
text |
必須, 最大255文字 |
インライン編集可能 |
| メールアドレス |
email |
必須, ユニーク, 最大255文字 |
変更時にメール認証を再送 |
パスワード変更セクション¶
| フィールド |
型 |
バリデーション |
| 現在のパスワード |
password |
必須, 現在のパスワードと一致 |
| 新しいパスワード |
password |
必須, 最小8文字 |
| パスワード確認 |
password |
必須, 新しいパスワードと一致 |
メール変更フロー¶
1. ユーザーが新しいメールアドレスを入力
2. サーバーが確認メールを新アドレスに送信
3. email_verified_at を NULL にリセット
4. ユーザーが確認リンクをクリック
5. email_verified_at にタイムスタンプを設定
6. メール変更完了
FR-USER-WEB-003: 契約・請求管理 (/dashboard/billing)¶
サブスクリプションの状態確認、プラン変更、請求履歴の閲覧を行う画面。
現在のプラン表示¶
| 表示項目 |
データソース |
表示例 |
| プラン名 |
is_white_user / subscriptions.stripe_price
|
Premium / Standard
|
| ステータス |
subscriptions.stripe_status |
active / trialing / canceled
|
| 次回請求日 |
Stripe API から取得 |
2026-03-17 |
| デバイス上限数 |
stripe_subscription_quantity |
3 台 |
プラン変更¶
| 項目 |
内容 |
| 操作 |
デバイス枠の増減 (quantity 変更) |
| 実装方式 |
Stripe Checkout Session または Stripe Customer Portal へ遷移 |
| 増枠 |
即時反映、日割り課金 |
| 減枠 |
次回請求日に反映 |
請求履歴¶
| 表示項目 |
データソース |
| 請求日 |
Stripe Invoice created
|
| 金額 |
Stripe Invoice amount_paid
|
| ステータス |
Stripe Invoice status (paid / open / void) |
| PDF |
Stripe Invoice invoice_pdf URL |
Stripe Invoice API を利用して一覧取得する。ページネーション対応 (10件/ページ)。
支払い方法¶
| 項目 |
内容 |
| 表示 |
カードブランド + 末尾4桁 (users.pm_type, users.pm_last_four) |
| カード変更 |
Stripe Customer Portal へ遷移 |
| 項目 |
内容 |
| 即時解約 |
サブスクリプションを即座にキャンセル。残期間のアクセスは不可 |
| 期末解約 |
現在の請求期間終了時にキャンセル (ends_at を設定) |
| 確認ダイアログ |
解約理由の選択 + 確認ボタン |
| 解約後の表示 |
解約済み (xxxx年xx月xx日まで利用可能) |
FR-USER-WEB-004: デバイス管理 (/dashboard/devices)¶
登録済みデバイスの一覧表示と管理を行う画面。
デバイス一覧¶
| 表示項目 |
データソース |
表示例 |
| デバイス名 |
user_devices.device_name |
Chrome on MacOS |
| UUID |
user_devices.device_uuid (マスク表示) |
550e****-****-****-****-****55440000 |
| 最終アクセス日時 |
user_devices.last_active_at |
2026-02-17 14:30 |
| 登録日 |
user_devices.created_at |
2026-01-15 |
| 操作 |
説明 |
| デバイス削除 |
個別のデバイスを削除 (デバイス枠が1つ空く) |
| 削除確認 |
このデバイスを削除しますか?再度このブラウザで利用するにはデバイス枠が必要です。 |
上限表示¶
| 項目 |
内容 |
| 表示形式 |
プログレスバー + テキスト |
| テキスト例 |
使用中 2 / 上限 3 台 |
| プログレスバー |
ゴールドグラデーション (使用率に応じて色変化: 80%超で警告色) |
| Premium |
無制限 表示 (プログレスバー非表示) |
デバイス名変更¶
| 項目 |
内容 |
| 編集方式 |
インライン編集 (テキストクリックで入力モードに切替) |
| バリデーション |
最大100文字 |
| 保存 |
blur またはEnterキーで即時保存 |
FR-USER-WEB-005: 利用統計 (/dashboard/stats)¶
送信実績のグラフ表示と分析を行う画面。
送信数推移グラフ¶
| 項目 |
内容 |
| 種別 |
棒グラフ (Bar Chart) |
| 切り替え |
日別 / 月別 トグルスイッチ |
| データソース |
user_activity_logs (execution_complete) |
送信内訳グラフ¶
| 項目 |
内容 |
| 種別 |
積み上げ棒グラフ (Stacked Bar Chart) |
| 内訳 |
フォーム送信 (ゴールド) vs メール送信 (シルバー) |
| データソース |
user_activity_logs.details の success / mail_sent
|
成功率推移グラフ¶
| 項目 |
内容 |
| 種別 |
折れ線グラフ (Line Chart) |
| Y軸 |
0% ~ 100% |
| データソース |
成功数 / 総送信数 × 100 |
期間選択¶
| 期間 |
説明 |
| 7日 |
直近7日間 (デフォルト) |
| 30日 |
直近30日間 |
| 90日 |
直近90日間 |
| 全期間 |
ユーザー登録日からの全データ |
期間選択はセグメントボタン (タブ形式) で切り替える。選択中の期間はゴールドアクセントでハイライト。
FR-USER-WEB-006: お知らせ (/dashboard/notices)¶
運営からのお知らせ通知を一覧表示する画面。
通知一覧¶
| 表示項目 |
データソース |
備考 |
| タイトル |
admin_notifications.title |
クリックで詳細展開 |
| type バッジ |
admin_notifications.type |
info / warning / maintenance / update |
| 公開日 |
admin_notifications.published_at |
2026-02-17 形式 |
| 既読/未読 |
readNoticeIds (Chrome Storage またはサーバー管理) |
未読は左に青ドット表示 |
取得条件¶
is_published = true
AND published_at <= now()
AND (expires_at IS NULL OR expires_at > now())
AND (target_type = 'all'
OR (target_type = 'segment' AND target_segment = ユーザーのセグメント)
OR (target_type = 'individual' AND target_user_id = ユーザーID))
type バッジ¶
| type |
ラベル |
色 |
info |
お知らせ |
青 (#3B82F6) |
warning |
重要 |
黄 (#F59E0B) |
maintenance |
メンテナンス |
紫 (#8B5CF6) |
update |
アップデート |
緑 (#22C55E) |
既読/未読管理¶
| 項目 |
内容 |
| 未読表示 |
タイトル左に青いドット + 太字 |
| 既読化 |
通知詳細を展開した時点で既読にマーク |
| 保存先 |
サーバー側で管理 (ユーザーごとの既読テーブル or JSON) |
本文レンダリング¶
| 項目 |
内容 |
| 形式 |
Markdown |
| レンダリング |
react-markdown またはサーバーサイドで HTML 変換 |
| サニタイズ |
XSS対策として rehype-sanitize を適用 |
4. 固有デザイン仕様¶
ユーザーパネルに固有のリッチUIデザイン要素。デザインシステム (カラートークン・アニメーション等) は全体共通仕様に準拠する。
プランカード¶
| 項目 |
仕様 |
| 現在のプラン |
ゴールドボーダー (2px solid #D4AF37) で囲み |
| グロー効果 |
box-shadow: 0 0 20px rgba(212, 175, 55, 0.3) |
| 他のプラン |
通常ボーダー + ホバーで薄いハイライト |
| アニメーション |
選択時にスケールアップ + ボーダーフェードイン |
デバイス枠プログレスバー¶
| 項目 |
仕様 |
| バー色 |
ゴールドグラデーション (linear-gradient(90deg, #D4AF37, #F5D060)) |
| 背景 |
rgba(255, 255, 255, 0.08) |
| 高さ |
8px, border-radius: 4px
|
| 警告表示 |
使用率80%超で赤グラデーション (linear-gradient(90deg, #EF4444, #F87171)) |
| アニメーション |
初回表示時に左から右へスライドイン (500ms, easeOut) |
請求履歴ステータスドット¶
| ステータス |
色 |
アニメーション |
paid |
緑 (#22C55E) |
緑の点滅パルスアニメーション (1.5s loop) |
open |
黄 (#F59E0B) |
なし (静的) |
void |
グレー (#6B7280) |
なし (静的) |
@keyframes pulse-dot {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.6; transform: scale(1.2); }
}
.status-dot-active {
animation: pulse-dot 1.5s ease-in-out infinite;
}
お知らせカード¶
| type |
アイコン |
左ボーダー色 |
背景ティント |
info |
Info (Lucide) |
青 (#3B82F6) |
rgba(59, 130, 246, 0.05) |
warning |
AlertTriangle (Lucide) |
黄 (#F59E0B) |
rgba(245, 158, 11, 0.05) |
maintenance |
Wrench (Lucide) |
紫 (#8B5CF6) |
rgba(139, 92, 246, 0.05) |
update |
Sparkles (Lucide) |
緑 (#22C55E) |
rgba(34, 197, 94, 0.05) |
カードの左ボーダーは border-left: 4px solid {color} で表現する。
統計数値¶
| 項目 |
仕様 |
| 数値フォント |
text-4xl font-bold font-variant-numeric: tabular-nums |
| カウントアップ |
Framer Motion animate で0から目標値まで500msかけてカウントアップ |
| 前期比バッジ |
上昇: 緑背景 + ArrowUp アイコン / 下降: 赤背景 + ArrowDown アイコン |
| バッジ形式 |
+12.3% または -5.1% のテキスト |
| アニメーション |
バッジ出現時にフェードイン + スライドアップ (200ms) |
5. ルーティング¶
すべてのルートは Laravel Inertia.js を使用した GET リクエストでレンダリングする。
| メソッド |
URL |
Inertia コンポーネント |
説明 |
| GET |
/dashboard |
Dashboard/Index |
ユーザーダッシュボード |
| GET |
/dashboard/profile |
Dashboard/Profile |
プロフィール編集 |
| PUT |
/dashboard/profile |
- |
プロフィール更新 (API) |
| PUT |
/dashboard/profile/password |
- |
パスワード変更 (API) |
| GET |
/dashboard/billing |
Dashboard/Billing |
契約・請求管理 |
| POST |
/dashboard/billing/checkout |
- |
Stripe Checkout セッション作成 (API) |
| POST |
/dashboard/billing/portal |
- |
Stripe Customer Portal セッション作成 (API) |
| POST |
/dashboard/billing/cancel |
- |
サブスクリプション解約 (API) |
| GET |
/dashboard/devices |
Dashboard/Devices |
デバイス管理 |
| PUT |
/dashboard/devices/{id} |
- |
デバイス名変更 (API) |
| DELETE |
/dashboard/devices/{id} |
- |
デバイス削除 (API) |
| GET |
/dashboard/stats |
Dashboard/Stats |
利用統計 |
| GET |
/dashboard/stats/data |
- |
統計データ JSON (非同期取得用) |
| GET |
/dashboard/notices |
Dashboard/Notices |
お知らせ一覧 |
| POST |
/dashboard/notices/{id}/read |
- |
お知らせ既読マーク (API) |
ミドルウェア設定¶
// routes/web.php
Route::middleware(['auth', 'verified'])->prefix('dashboard')->group(function () {
// ダッシュボード
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
// プロフィール
Route::get('/profile', [ProfileController::class, 'edit'])->name('dashboard.profile');
Route::put('/profile', [ProfileController::class, 'update'])->name('dashboard.profile.update');
Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('dashboard.profile.password');
// 契約・請求管理
Route::get('/billing', [BillingController::class, 'index'])->name('dashboard.billing');
Route::post('/billing/checkout', [BillingController::class, 'checkout'])->name('dashboard.billing.checkout');
Route::post('/billing/portal', [BillingController::class, 'portal'])->name('dashboard.billing.portal');
Route::post('/billing/cancel', [BillingController::class, 'cancel'])->name('dashboard.billing.cancel');
// デバイス管理
Route::get('/devices', [DeviceController::class, 'index'])->name('dashboard.devices');
Route::put('/devices/{device}', [DeviceController::class, 'update'])->name('dashboard.devices.update');
Route::delete('/devices/{device}', [DeviceController::class, 'destroy'])->name('dashboard.devices.destroy');
// 利用統計
Route::get('/stats', [StatsController::class, 'index'])->name('dashboard.stats');
Route::get('/stats/data', [StatsController::class, 'data'])->name('dashboard.stats.data');
// お知らせ
Route::get('/notices', [NoticeController::class, 'index'])->name('dashboard.notices');
Route::post('/notices/{notice}/read', [NoticeController::class, 'markAsRead'])->name('dashboard.notices.read');
});
6. Inertia コンポーネント構成¶
resources/js/pages/Dashboard/
├── Index.tsx # ダッシュボード (FR-USER-WEB-001)
├── Profile.tsx # プロフィール (FR-USER-WEB-002)
├── Billing.tsx # 契約・請求管理 (FR-USER-WEB-003)
├── Devices.tsx # デバイス管理 (FR-USER-WEB-004)
├── Stats.tsx # 利用統計 (FR-USER-WEB-005)
├── Notices.tsx # お知らせ (FR-USER-WEB-006)
└── components/
├── DashboardLayout.tsx # 共通レイアウト (サイドバー + ヘッダー)
├── SummaryCard.tsx # KPIサマリーカード
├── PlanBadge.tsx # プラン種別バッジ
├── DeviceProgressBar.tsx # デバイス枠プログレスバー
├── NoticeBanner.tsx # お知らせバナー
├── NoticeCard.tsx # お知らせカード (type別デザイン)
├── SendChart.tsx # 送信数グラフ
├── SuccessRateChart.tsx # 成功率グラフ
├── BreakdownChart.tsx # 送信内訳グラフ
└── PeriodSelector.tsx # 期間選択セグメントボタン