プロジェクト

全般

プロフィール

SMART-CONTACT 全体管理画面 要件定義書

項目 内容
プロジェクト名 SMART-CONTACT
バージョン 1.0
作成日 2026-02-17
ステータス 開発中 (develop ブランチ)
対象スコープ Admin Panel (/admin/*)

1. 概要

SMART-CONTACT の運営者向け管理画面。ユーザー管理、KPI可視化、通知配信、送信ログ監視、サブスクリプション管理など、SaaS運営に必要なCRM機能を提供する。

項目 内容
ルート /admin/*
ミドルウェア auth + verified + admin (is_admin = true)
フレームワーク Laravel Inertia.js + React (TypeScript)
UIコンポーネント shadcn/ui + Tailwind CSS 4
チャート Recharts
アニメーション Framer Motion
テーブル TanStack Table v8
認証方式 Laravel セッション認証 (Cookie)
デザイン セクション 4.9 デザインシステム準拠 (ダーク/ライト切替対応)

1.1 アクセス制御

app/Http/Middleware/EnsureUserIsAdmin.php
  -> users.is_admin = true のみアクセス可
  -> false の場合は 403 Forbidden を返却

管理画面へのアクセスには以下の3つのミドルウェアを通過する必要がある。

  1. auth -- ログイン済みであること
  2. verified -- メール認証済みであること
  3. admin -- is_admin = true であること

2. KPIダッシュボード

FR-ADMIN-001: KPIサマリーカード

画面上部に主要10指標をカード形式でリアルタイム表示する。各カードはカウントアップアニメーション、前日比/前月比の矢印バッジ (緑: 上昇 / 赤: 下降) を含む。非同期更新API (GET /admin/kpi/summary) で30秒ごとにポーリングまたは手動リフレッシュ可能。

# 指標 算出方法 表示例
1 総ユーザー数 users テーブルの全件数 1,234
2 有料ユーザー数 subscriptionsstripe_status = active のユーザー数 456
3 Premium (ホワイト) ユーザー数 is_white_user = true のユーザー数 12
4 トライアルユーザー数 trial_ends_at > now() かつサブスクリプション未契約 78
5 DAU (日次アクティブユーザー) user_activity_logs で当日ログインまたは実行があったユニークユーザー数 89
6 WAU (週次アクティブユーザー) 直近7日間のユニークアクティブユーザー数 234
7 MAU (月次アクティブユーザー) 直近30日間のユニークアクティブユーザー数 567
8 MRR (月次経常収益) アクティブなサブスクリプションの月額合計 \1,234,000
9 解約率 (Churn Rate) 直近30日間の解約数 / 前月アクティブ数 x 100 3.2%
10 総送信数 (今月) contact_mail_logs + 拡張機能からの実行報告 (user_activity_logsexecution_complete) の今月合計 12,345

KPIカードUI仕様:

  • 数値は font-variant-numeric: tabular-nums で等幅表示
  • 数値変化時にカウントアップアニメーション (Framer Motion animate, 500ms easeOut)
  • 前日比/前月比を矢印 + 色付きバッジで表示 (緑: 上昇 / 赤: 下降)
  • カードの上辺にアクセントカラーのグラデーションライン (高さ2px)
  • 各指標に対応するLucideアイコン + アクセントカラー背景の円形アイコンエリア

FR-ADMIN-002: KPIグラフ

ダッシュボード下部に5種類のグラフを表示する。各グラフはデータ取得API (GET /admin/kpi/chart/{type}) から期間パラメータ付きでJSON取得する。

# グラフ 種別 内容 期間選択
1 ユーザー数推移 折れ線グラフ (Line) 累計 / 新規 / 解約 の3本線 7日 / 30日 / 90日 / 1年
2 DAU/MAU推移 折れ線グラフ (Line) DAUとMAUの2本線 30日 / 90日 / 1年
3 売上推移 棒グラフ (Bar) MRR月次推移 6ヶ月 / 1年
4 送信数推移 棒グラフ (Bar) フォーム送信 / メール送信 の積み上げ 7日 / 30日
5 コンバージョンファネル ファネルチャート (Funnel) 登録 -> トライアル -> 有料 の転換率 30日 / 90日

グラフUI仕様:

  • Recharts ベース、ダークテーマ対応 (背景透明、グリッド線 rgba(255, 255, 255, 0.05))
  • ツールチップ: ダーク背景 + ゴールドアクセント
  • エリアチャートはグラデーションフィル (linearGradient ゴールド -> 透明)
  • 初回表示時に左からフェードインアニメーション (800ms)
  • 期間セレクターはタブ形式 (shadcn/ui Tabs)

3. ユーザー管理

FR-ADMIN-003: ユーザー一覧

TanStack Table v8 ベースのデータテーブルでユーザーを一覧表示する。

項目 内容
表示項目 ID, 名前, メール, ユーザー種別バッジ, ステータス, 登録日, 最終アクティブ日
検索 名前・メールアドレスでの部分一致検索 (サーバーサイド)
フィルター ユーザー種別 (Premium / 有料 / トライアル / 無料 / BAN)、ステータス (アクティブ / 非アクティブ / BAN)
ソート 登録日 (デフォルト降順), 最終アクティブ日, 送信数
ページネーション 20件/ページ、件数表示 + ページ番号 + 前後ボタン
一括操作 チェックボックス選択 -> 一括BAN, 一括通知送信

ユーザー種別バッジ:

種別 バッジスタイル
Premium ゴールド光沢 (shimmer アニメーション)
Standard シルバー
Trial ブルー
Free グレー

BANユーザーの行表示: 赤い Banned バッジ + 行背景に薄い赤オーバーレイ (rgba(239, 68, 68, 0.08))

FR-ADMIN-004: ユーザー詳細

ユーザー詳細画面は6セクションのタブまたはアコーディオンレイアウトで構成する。

# セクション 表示内容
1 基本情報 名前, メール, ユーザー種別バッジ, 登録日, 最終ログイン日, BANステータス
2 サブスクリプション プラン名, ステータス, 開始日, 次回請求日, デバイス上限数, Stripe顧客ID
3 デバイス一覧 登録デバイス (UUID, デバイス名, 最終アクセス日)。個別削除ボタン付き
4 利用統計 総送信数, 今月送信数, フォーム送信/メール送信の内訳, 成功率, 日別送信グラフ (ミニチャート)
5 アクティビティログ 直近のログイン・実行・設定変更等のタイムライン (最新50件)。タイムライン形式 (左にドット付き縦線、アクション種別ごとに色分け)
6 管理者メモ 自由記述のメモ欄 (対応履歴等の記録用)。users.admin_memo に保存。リアルタイム自動保存 (debounce 1秒)

FR-ADMIN-005: BAN (利用停止)

BAN実行

ユーザー詳細画面またはー覧の一括操作から実行する。BAN実行時は確認モーダルで理由入力を必須とする。

BAN時の処理 (4ステップ):

Step 処理 対象
1 users.banned_at に現在のタイムスタンプを設定 users テーブル
2 users.ban_reason にBAN理由を記録 users テーブル
3 該当ユーザーの全 Sanctum トークンを削除 (即時ログアウト) personal_access_tokens テーブル
4 該当ユーザーの全デバイス情報を無効化 user_devices テーブル

BAN解除

  • banned_atNULL に戻す
  • ban_reason は履歴として保持 (クリアしない)
  • ユーザーは再ログイン可能になる

拡張機能側の挙動

ライセンスチェック (POST /api/check-license) 時に banned_at IS NOT NULL を検出した場合:

{
  "status": "denied",
  "reason": "account_banned",
  "message": "このアカウントは利用停止されています。管理者にお問い合わせください。"
}

拡張機能側ではエラーメッセージを表示し、全操作をブロックする。

FR-ADMIN-006: ユーザー編集

操作 説明 対象カラム
ユーザー種別変更 Premium <-> Standard の切り替え users.is_white_user
デバイス上限変更 デバイス登録可能台数の手動調整 users.stripe_subscription_quantity
パスワードリセット パスワードリセットメールを送信 (Laravel 標準の Password::sendResetLink) -
デバイス削除 個別デバイスの登録解除 (デバイス枠が1つ空く) user_devices テーブル

4. 通知管理

FR-ADMIN-007: 通知種別

種別 target_type 対象 使用例
全体お知らせ all 全ユーザー メンテナンス告知、新機能リリース、利用規約変更
セグメント通知 segment ユーザー種別指定 プラン別のお知らせ (例: トライアル終了リマインド、Premium向け新機能案内)
個別通知 individual 特定ユーザー1名 サポート対応、警告通知、アカウント関連の連絡

セグメント指定値:

target_segment 対象ユーザー
premium is_white_user = true のユーザー
paid subscriptions.stripe_status = active のユーザー
trial trial_ends_at > now() かつサブスクリプション未契約のユーザー
free 上記いずれにも該当しないユーザー

FR-ADMIN-008: 通知データ構造

interface AdminNotification {
  id: number;
  title: string;                // 通知タイトル (最大255文字)
  body: string;                 // 通知本文 (Markdown対応)
  type: 'info' | 'warning' | 'maintenance' | 'update';
  target_type: 'all' | 'segment' | 'individual';
  target_segment?: 'premium' | 'paid' | 'trial' | 'free';
  target_user_id?: number;      // 個別通知の場合のユーザーID
  is_published: boolean;        // 公開状態 (true: 公開 / false: 下書き)
  published_at?: string;        // 公開日時 (予約投稿対応、ISO 8601)
  expires_at?: string;          // 表示期限 (ISO 8601、NULL = 無期限)
  created_by: number;           // 作成した管理者のユーザーID
  created_at: string;
  updated_at: string;
}

通知種別 (type) 別の表示スタイル:

type アイコン 左ボーダーカラー 用途
info Info (Lucide) 青 (#3B82F6) 一般的なお知らせ
warning AlertTriangle (Lucide) 黄 (#F59E0B) 注意喚起
maintenance Wrench (Lucide) 紫 (#8B5CF6) メンテナンス告知
update Sparkles (Lucide) 緑 (#22C55E) 新機能・アップデート

通知作成画面のUI:

  • Markdown -> HTML リアルタイム分割プレビュー (左: エディタ / 右: プレビュー)
  • 予約投稿の日時ピッカー (date-fns)
  • 対象タイプ切り替え時にフォームフィールドが動的に変化

FR-ADMIN-009: 通知のユーザー側表示

項目 内容
取得API GET /api/notices (拡張機能から定期取得)
表示場所 拡張機能ダッシュボードの上部バナー
既読管理 Chrome Storage に既読通知IDリスト (readNoticeIds: number[]) を保存
未読バッジ ダッシュボードタブに未読件数を赤いバッジで表示

取得条件 (サーバーサイドクエリ):

WHERE 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})
  )
ORDER BY published_at DESC

5. 送信ログ管理

FR-ADMIN-010: 送信ログ一覧

サーバー経由メール送信 (POST /api/send-contact-mail) の全履歴を管理・検索する。データソースは contact_mail_logs テーブル。

項目 内容
表示項目 ID, ユーザー名, 送信先メール (to_email), 件名 (subject), 送信元URL (source_url), ステータス (status), 送信日時 (sent_at)
検索 送信先メール, ユーザー名, 送信元URL での部分一致検索 (サーバーサイド)
フィルター ステータス (success / failed), 期間指定 (日付範囲ピッカー)
ソート 送信日時 (デフォルト降順), ユーザー名, ステータス
ページネーション 20件/ページ
詳細表示 行クリックまたは展開ボタンで以下を表示:
- 送信本文 (body) のフル表示
- 送信者名 (from_name) + 送信元メール (from_email)
- エラー詳細 (error_message) -- 失敗時のみ
- 送信元URL (source_url) のリンク表示

ステータス表示:

status バッジ
success 成功 緑 (#22C55E)
failed 失敗 赤 (#EF4444)

6. サブスクリプション管理

FR-ADMIN-011: サブスクリプション一覧

項目 内容
表示項目 ユーザー名, プラン名, ステータス, 数量 (デバイス数), 開始日, 次回請求日, 月額金額
フィルター ステータス (active / trialing / canceled / past_due)
ページネーション 20件/ページ
集計 (ヘッダー) ステータス別ユーザー数のサマリーカード, MRR合計

ステータスバッジ:

stripe_status バッジ
active Active
trialing Trial
canceled Canceled グレー
past_due Past Due

FR-ADMIN-012: 手動サブスクリプション操作

Stripeを介さず管理画面から直接ユーザーの契約状態を変更する操作。操作時は確認モーダルを表示し、アクティビティログに記録する。

操作 説明 対象カラム
Premium付与 is_white_user = true に設定。Stripeサブスクリプションに関係なく無制限利用可能にする users.is_white_user
トライアル延長 トライアル終了日を任意の日付に変更 (日付ピッカーで選択) users.trial_ends_at
デバイス枠変更 デバイス登録可能台数を任意の値に手動調整 users.stripe_subscription_quantity

7. アクティビティログ

FR-ADMIN-013: システム全体のアクティビティ

全ユーザーの操作をタイムライン形式で監視する。データソースは user_activity_logs テーブル。

7種のアクション種別:

# アクション種別 (action) 記録タイミング 記録内容 (details JSON) タイムラインの色
1 login ログイン成功時 IP, デバイス名, user_agent 青 (#3B82F6)
2 logout ログアウト時 - グレー (#6B7280)
3 license_check ライセンスチェック時 デバイスUUID, 結果 (allowed / denied), 拒否理由 黄 (#F59E0B)
4 execution_start バッチ実行開始時 URL件数, テンプレートID, テストモードフラグ 紫 (#8B5CF6)
5 execution_complete バッチ実行完了時 成功数, 失敗数, メール送信数, 所要時間(秒) 緑 (#22C55E)
6 mail_sent メール送信時 送信先メール, 結果 (success / failed) ゴールド (#D4AF37)
7 ban BAN実行/解除時 対象ユーザーID, 理由, 操作 (ban / unban), 管理者ID 赤 (#EF4444)

一覧画面のUI:

  • TanStack Table v8 によるテーブル表示
  • 検索: ユーザー名, アクション種別でフィルター
  • フィルター: アクション種別のマルチセレクト, 期間指定
  • ソート: 記録日時 (デフォルト降順)
  • ページネーション: 50件/ページ
  • ユーザー詳細内のアクティビティログはタイムライン形式 (左にドット付き縦線、色分け)

保持期間: 90日間 (古いログは日次バッチで自動削除)


8. システム設定

FR-ADMIN-014: 管理画面から変更可能なシステム設定

5つの設定項目を管理画面から変更可能。設定値はDBの system_settings テーブル (key-value 形式) またはキャッシュに保存する。変更時は即座に反映され、アクティビティログに記録される。

# 設定 キー 説明 デフォルト
1 メール送信レート制限 rate_limit_per_minute integer ユーザーあたり1分間のメール送信上限 10 件/分
2 デフォルトトライアル日数 default_trial_days integer 新規ユーザー登録時のトライアル期間 14
3 デフォルトデバイス上限 default_device_limit integer 無料ユーザー / 新規ユーザーのデバイス登録上限 1
4 メンテナンスモード maintenance_mode boolean true の場合、拡張機能からのAPI呼び出しを一時停止し、メンテナンス中メッセージを返す false (OFF)
5 全体お知らせバナー global_banner string 即時表示の緊急お知らせテキスト。空でない場合、拡張機能と管理画面にバナー表示 空文字列

設定画面UI:

  • フォームは React Hook Form + Zod バリデーション
  • 各設定項目の説明テキストをラベル下に表示
  • メンテナンスモードは確認モーダル付きトグルスイッチ
  • 保存ボタン押下で PUT /admin/settings を実行
  • 保存成功時にトースト通知 (shadcn/ui Sonner)

9. 画面一覧

# 画面 URL 説明
1 ログイン /admin/login 管理者ログイン (共通ログイン画面からリダイレクト)
2 ダッシュボード /admin KPIサマリーカード + グラフ
3 ユーザー一覧 /admin/users 検索・フィルター付きユーザーリスト
4 ユーザー詳細 /admin/users/{id} 詳細情報・編集・BAN操作
5 通知一覧 /admin/notifications 通知の管理 (一覧・削除)
6 通知作成 /admin/notifications/create 新規通知の作成 (Markdownエディタ + プレビュー)
7 送信ログ /admin/mail-logs メール送信履歴の検索・閲覧
8 サブスクリプション /admin/subscriptions 契約状況一覧 + 手動操作
9 アクティビティログ /admin/activity-logs システム全体の操作ログ
10 システム設定 /admin/settings 運営パラメータの変更

10. ルーティング

管理画面はInertia.jsで構築するため、以下はサーバーサイドルート (Webミドルウェア + auth + verified + admin ガード) で提供する。

# メソッド URL 説明
1 GET /admin KPIダッシュボード
2 GET /admin/users ユーザー一覧
3 GET /admin/users/{id} ユーザー詳細
4 PUT /admin/users/{id} ユーザー情報更新 (種別変更・デバイス上限変更・メモ保存)
5 POST /admin/users/{id}/ban BAN実行
6 POST /admin/users/{id}/unban BAN解除
7 POST /admin/users/{id}/reset-password パスワードリセットメール送信
8 DELETE /admin/users/{id}/devices/{deviceId} デバイス削除
9 POST /admin/users/bulk-ban 一括BAN実行
10 POST /admin/users/bulk-notify 一括通知送信
11 GET /admin/notifications 通知一覧
12 GET /admin/notifications/create 通知作成画面
13 POST /admin/notifications 通知作成 (保存)
14 GET /admin/notifications/{id}/edit 通知編集画面
15 PUT /admin/notifications/{id} 通知編集 (保存)
16 DELETE /admin/notifications/{id} 通知削除
17 GET /admin/mail-logs 送信ログ一覧
18 GET /admin/mail-logs/{id} 送信ログ詳細
19 GET /admin/subscriptions サブスクリプション一覧
20 GET /admin/activity-logs アクティビティログ一覧
21 GET /admin/settings システム設定表示
22 PUT /admin/settings システム設定更新
23 GET /admin/kpi/summary KPIサマリーJSON (非同期更新用)
24 GET /admin/kpi/chart/{type} KPIグラフデータJSON (type: users, active, revenue, sends, funnel)

11. 固有デザイン仕様

管理画面は基本デザインシステム (セクション 4.9) に準拠しつつ、以下の管理画面固有のデザインを適用する。

11.1 BANステータス表示

要素 仕様
バッジ 赤背景 (bg-red-500/20) + 赤テキスト (text-red-400) で Banned テキスト
テーブル行 行全体に薄い赤オーバーレイ (rgba(239, 68, 68, 0.08))
ユーザー詳細 ヘッダーに赤い警告バナー (BAN理由 + BAN日時を表示)
.user-row--banned {
  background: rgba(239, 68, 68, 0.08);
  border-left: 3px solid #EF4444;
}
.badge--banned {
  background: rgba(239, 68, 68, 0.2);
  color: #F87171;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 9999px;
  font-size: 12px;
}

11.2 ユーザー種別バッジ

種別 背景 テキスト色 特殊効果
Premium linear-gradient(135deg, #D4AF37, #F5D060, #D4AF37) #1A1A1A shimmer アニメーション (CSS @keyframes shimmer でゴールド光沢が左から右に移動、3秒ループ)
Standard rgba(168, 162, 158, 0.2) #A8A29E なし
Trial rgba(59, 130, 246, 0.2) #60A5FA なし
Free rgba(107, 114, 128, 0.2) #9CA3AF なし
@keyframes shimmer {
  0% { background-position: -200% center; }
  100% { background-position: 200% center; }
}
.badge--premium {
  background: linear-gradient(
    90deg,
    #D4AF37 0%,
    #F5D060 25%,
    #D4AF37 50%,
    #F5D060 75%,
    #D4AF37 100%
  );
  background-size: 200% auto;
  animation: shimmer 3s linear infinite;
  color: #1A1A1A;
  font-weight: 700;
}

11.3 KPIカードアイコン

各KPI指標に対応するLucideアイコンと、アクセントカラー背景の円形アイコンエリアを表示する。

指標 Lucideアイコン アイコン背景色
総ユーザー数 Users rgba(212, 175, 55, 0.15)
有料ユーザー数 CreditCard rgba(34, 197, 94, 0.15)
Premium数 Crown rgba(212, 175, 55, 0.15)
トライアル数 Clock rgba(59, 130, 246, 0.15)
DAU Activity rgba(168, 85, 247, 0.15)
WAU TrendingUp rgba(168, 85, 247, 0.15)
MAU BarChart3 rgba(168, 85, 247, 0.15)
MRR DollarSign rgba(34, 197, 94, 0.15)
解約率 UserMinus rgba(239, 68, 68, 0.15)
総送信数 Send rgba(59, 130, 246, 0.15)

アイコンエリアCSS:

.kpi-icon-area {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.kpi-icon-area svg {
  width: 24px;
  height: 24px;
}

11.4 アクティビティタイムライン

ユーザー詳細内のアクティビティログはタイムライン形式で表示する。

要素 仕様
縦線 左マージン24pxの位置に、点線 (border-left: 2px dotted rgba(255, 255, 255, 0.1)) で縦に接続
ドット 各ログエントリの左側に直径10pxの円形ドット。アクション種別ごとに色分け (セクション7の色定義に準拠)
エントリ ドットの右側にアクション名 + タイムスタンプ + 詳細テキスト
間隔 エントリ間は16pxの垂直マージン
.timeline-line {
  position: absolute;
  left: 24px;
  top: 0;
  bottom: 0;
  border-left: 2px dotted rgba(255, 255, 255, 0.1);
}
.timeline-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  position: absolute;
  left: 20px;
  box-shadow: 0 0 0 3px var(--bg-card);
}
.timeline-entry {
  padding-left: 48px;
  margin-bottom: 16px;
}

11.5 通知プレビュー

通知作成・編集画面では、Markdown入力とHTMLプレビューのリアルタイム分割表示を提供する。

要素 仕様
レイアウト 左右50:50の分割レイアウト (レスポンシブ時は上下に切り替え)
左パネル (エディタ) Markdown テキストエリア。シンタックスハイライトなし、等幅フォント (font-family: monospace)
右パネル (プレビュー) Markdown -> HTML 変換のリアルタイムレンダリング。通知カードのスタイルを適用した状態で表示
変換タイミング 入力から300msのdebounce後にプレビュー更新
Markdown対応記法 見出し (#), 太字 (**), リスト (-), リンク ([text](url)), コードブロック, 改行

付録A: 関連テーブル定義 (参照)

管理画面が参照・操作する主要テーブル。詳細は database/schema.md を参照。

テーブル 管理画面での用途
users ユーザー管理 (CRUD, BAN, 種別変更)
user_devices デバイス一覧表示・削除
subscriptions サブスクリプション一覧・集計
admin_notifications 通知の作成・編集・削除・公開管理
user_activity_logs アクティビティログ一覧・KPI算出 (DAU/WAU/MAU)
contact_mail_logs 送信ログ一覧・検索
personal_access_tokens BAN時のトークン一括削除

付録B: ユーザー種別判定ロジック

管理画面内でユーザー種別バッジを表示する際の判定ロジック。

type UserType = 'premium' | 'standard' | 'trial' | 'free';

function getUserType(user: User): UserType {
  // 1. Premium (ホワイトユーザー)
  if (user.is_white_user) return 'premium';

  // 2. Standard (有料サブスクリプション)
  if (user.subscription?.stripe_status === 'active') return 'standard';

  // 3. Trial (トライアル期間中)
  if (user.trial_ends_at && new Date(user.trial_ends_at) > new Date()) return 'trial';

  // 4. Free (上記いずれにも該当しない)
  return 'free';
}