mcpField
A
admin-dashboard

admin-dashboard

github.com/curiositech開発257323 回インストール2 日前に更新
リポジトリ

admin-dashboard について

既存の管理ダッシュボードを拡張し、プロジェクトの既定パターンに沿って内部ツールを開発するためのスキルです。タブ、APIエンドポイント、アクセス制御、データ取得、HIPAAに配慮したエラー表示を扱います。

主な機能

  1. 01管理ダッシュボードのタブ拡張
  2. 02管理用APIエンドポイントの作成
  3. 03共通のデータ取得パターンの利用
  4. 04管理者アクセス制御の適用
  5. 05集約エラーの安全な表示
  6. 06管理機能のテスト

活用シーン

  1. 01ダッシュボードに管理機能を追加
  2. 02アクセス制御付き管理エンドポイントの開発
  3. 03ユーザー・アクセス申請・分析データの表示
  4. 04管理者権限に関わる機能のテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/curiositech/some_claude_skills --skill admin-dashboard

インストール後、Claude Code で/admin-dashboardを入力して読み込まれたか確認します。

同梱ファイル.claude-plugin/plugin.json

詳細

管理者・開発者向けスイートの開発

このスキルでは、既存のパターンに沿って管理者ダッシュボードを拡張し、内部ツールを構築する方法を説明します。

アーキテクチャの概要

/admin     - Admin Dashboard (user metrics, access control, audit)
/dev       - Developer Portal (docs, code browser, feature map) [PLANNED]
/ops       - Operations Console (infrastructure, logs, incidents) [PLANNED]

設計仕様の全文については、docs/ADMIN-DEVELOPER-SUITE.md を参照してください。

現在の管理者ダッシュボードの構成

場所:src/app/admin/page.tsx

既存のタブ
タブ目的データソース
概要簡易統計(ユーザー、チェックイン、メッセージ)/api/admin/stats
ファネルユーザーエンゲージメントの推移/api/admin/stats
ページビューページパス別の分析/api/admin/stats
ユーザーアクティビティ付きユーザー一覧/api/admin/stats
アクセスリクエスト承認待ち/承認済み/拒否済みのリクエスト/api/admin/access-requests
許可済みメールメールの許可リスト管理/api/admin/allowed-emails
メールテンプレートシステムメールのプレビューローカルデータ
予定されているタブ(設計より)
タブ目的ステータス
本番環境の健全性API のレイテンシ、Core Web Vitals保留中
エラー追跡HIPAA に準拠したエラーの集約保留中
外部サービスAnthropic、DB、Push のステータス保留中
AI 分析会話のメトリクス、トークン保留中
監査ログHIPAA コンプライアンスビューアー保留中

新しい管理者タブを追加する

1. タブのコンテンツコンポーネントを作成する
// In src/app/admin/page.tsx, add a new tab component

function ProductionHealthTab() {
  const [metrics, setMetrics] = useState<APIMetrics | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchMetrics() {
      const res = await fetch('/api/admin/metrics');
      const data = await res.json();
      setMetrics(data);
      setLoading(false);
    }
    fetchMetrics();
  }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <div className="space-y-6">
      <div className="grid grid-cols-4 gap-4">
        <StatCard label="Uptime" value={metrics.uptime} />
        <StatCard label="Avg Latency" value={`${metrics.avgLatency}ms`} />
        <StatCard label="Errors (24h)" value={metrics.errorCount} />
        <StatCard label="Active Users" value={metrics.activeUsers} />
      </div>
      {/* More content */}
    </div>
  );
}
2. タブリストにタブを追加する
const tabs = [
  { id: 'overview', label: 'Overview' },
  { id: 'health', label: 'Production Health' }, // NEW
  { id: 'funnel', label: 'Funnel' },
  // ...
];
3. タブのコンテンツレンダラーを追加する
function renderTabContent(tabId: string) {
  switch (tabId) {
    case 'overview':
      return <OverviewTab stats={stats} />;
    case 'health':
      return <ProductionHealthTab />; // NEW
    // ...
  }
}

管理者 API エンドポイントを作成する

パターン:管理者統計エンドポイント
// src/app/api/admin/metrics/route.ts
import { requireAdmin } from '@/db/secure-db';
import { createRateLimiter } from '@/lib/rate-limit';
import { logAdminAction } from '@/lib/hipaa/audit';

const rateLimiter = createRateLimiter({
  windowMs: 60000,
  maxRequests: 60,
  keyPrefix: 'admin:metrics'
});

export async function GET(request: Request) {
  // 1. Check admin access
  const admin = await requireAdmin();
  if (!admin) {
    return Response.json({ error: 'Forbidden' }, { status: 403 });
  }

  // 2. Apply rate limiting
  const rateLimitResult = await rateLimiter.check(admin.id);
  if (!rateLimitResult.allowed) {
    return Response.json(
      { error: 'Rate limit exceeded' },
      { status: 429, headers: rateLimitResult.headers }
    );
  }

  // 3. Log admin action
  await logAdminAction(
    admin.id,
    AuditAction.ADMIN_STATS_VIEW,
    'metrics',
    null
  );

  // 4. Fetch and return data
  const metrics = await getAPIMetrics();
  return Response.json(metrics);
}

主なパターン

StatCard コンポーネント
function StatCard({
  label,
  value,
  trend,
  status
}: {
  label: string;
  value: string | number;
  trend?: 'up' | 'down' | 'neutral';
  status?: 'good' | 'warning' | 'error';
}) {
  return (
    <div className="rounded-lg border bg-card p-4">
      <div className="text-sm text-muted-foreground">{label}</div>
      <div className="text-2xl font-bold">{value}</div>
      {trend && <TrendIndicator direction={trend} />}
      {status && <StatusBadge status={status} />}
    </div>
  );
}
データ取得パターン
// Use SWR or React Query for real-time updates
import useSWR from 'swr';

function useAdminMetrics() {
  const { data, error, isLoading } = useSWR(
    '/api/admin/metrics',
    fetcher,
    { refreshInterval: 30000 } // Refresh every 30s
  );

  return { metrics: data, error, isLoading };
}
HIPAA に準拠したエラー表示
// Never show user-specific error details
function ErrorList({ errors }: { errors: AggregatedError[] }) {
  return (
    <div>
      {errors.map(error => (
        <div key={error.hash}>
          <span className="font-mono">{error.type}</span>
          <span>{error.path}</span>
          <span>{error.count} occurrences</span>
          <span>{error.affectedUsers} users</span>
          {/* NO user IDs, NO error messages with PHI */}
        </div>
      ))}
    </div>
  );
}

管理者機能用のデータベーステーブル

既存のテーブル:

  • adminUsers - 管理者ロールの割り当て
  • allowedEmails - メールの許可リスト
  • accessRequests - アクセスリクエストのキュー
  • auditLog - HIPAA 監査証跡
  • pageViews - ナビゲーション分析

予定されているテーブル(設計より):

  • api_metrics - API の所要時間データ
  • app_errors - 集約されたエラー
  • service_health - 外部サービスのステータス
  • conversation_analytics - AI チャットのメタデータ
  • incidents - インシデントの追跡

アクセス制御

// Always use requireAdmin() for admin routes
import { requireAdmin } from '@/db/secure-db';

// For super-admin only features
const admin = await requireAdmin();
if (admin.role !== 'super_admin') {
  return Response.json({ error: 'Super admin required' }, { status: 403 });
}

管理者機能のテスト

// Mock admin authentication for tests
vi.mock('@/db/secure-db', () => ({
  requireAdmin: vi.fn().mockResolvedValue({
    id: 'test-admin',
    role: 'admin'
  })
}));

describe('Admin Metrics Endpoint', () => {
  it('returns metrics for authenticated admin', async () => {
    const response = await GET(mockRequest);
    expect(response.status).toBe(200);
  });

  it('returns 403 for non-admin', async () => {
    vi.mocked(requireAdmin).mockResolvedValueOnce(null);
    const response = await GET(mockRequest);
    expect(response.status).toBe(403);
  });
});

デザインリソース

  • 設計仕様の全文:docs/ADMIN-DEVELOPER-SUITE.md
  • デザインシステム:src/components/ui/ の既存コンポーネントを使用してください
  • 色:セラピー向けの配色(ネイビー、ティール、コーラル、クリーム)に従ってください

コメント