All files / src/components/features/admin/monitoring/performance/PerformanceSkeleton index.tsx

0% Statements 0/123
100% Branches 0/0
0% Functions 0/1
0% Lines 0/123

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                                                                                                                                                                                                       
'use client';

import React from 'react';
import { cn } from '@/lib/core';

export interface PerformanceSkeletonProps {
  /** Number of metric cards to show */
  metricCardCount?: number;
  /** Show chart skeletons */
  showCharts?: boolean;
  /** Number of chart skeletons */
  chartCount?: number;
  /** Show slow requests list skeleton */
  showSlowRequests?: boolean;
  /** Additional CSS classes */
  className?: string;
}

/**
 * Skeleton card for metric cards
 */
function MetricCardSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-4 animate-pulse">
      <div className="h-4 w-24 bg-gray-200 dark:bg-gray-700 rounded mb-2" />
      <div className="h-8 w-16 bg-gray-200 dark:bg-gray-700 rounded mb-1" />
      <div className="h-3 w-20 bg-gray-200 dark:bg-gray-700 rounded" />
    </div>
  );
}

/**
 * Skeleton for chart components
 */
function ChartSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-4 animate-pulse">
      <div className="h-5 w-32 bg-gray-200 dark:bg-gray-700 rounded mb-4" />
      <div className="h-64 bg-gray-200 dark:bg-gray-700 rounded" />
    </div>
  );
}

/**
 * Skeleton for slow requests list
 */
function SlowRequestsSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-4 animate-pulse">
      <div className="h-5 w-40 bg-gray-200 dark:bg-gray-700 rounded mb-4" />
      <div className="space-y-3">
        {[1, 2, 3, 4, 5].map((i) => (
          <div key={i} className="h-14 bg-gray-200 dark:bg-gray-700 rounded" />
        ))}
      </div>
    </div>
  );
}

/**
 * Skeleton for time range selector and controls
 */
function ControlsSkeleton() {
  return (
    <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 animate-pulse">
      <div className="flex items-center gap-4">
        <div className="h-9 w-32 bg-gray-200 dark:bg-gray-700 rounded" />
      </div>
      <div className="flex items-center gap-4">
        <div className="h-5 w-24 bg-gray-200 dark:bg-gray-700 rounded" />
        <div className="h-9 w-20 bg-gray-200 dark:bg-gray-700 rounded" />
        <div className="h-4 w-32 bg-gray-200 dark:bg-gray-700 rounded" />
      </div>
    </div>
  );
}

/**
 * PerformanceSkeleton - Loading skeleton for the performance dashboard
 *
 * Matches the layout of PerformanceDashboard with animated pulse skeletons.
 */
export function PerformanceSkeleton({
  metricCardCount = 5,
  showCharts = true,
  chartCount = 4,
  showSlowRequests = true,
  className,
}: PerformanceSkeletonProps) {
  return (
    <div
      className={cn('space-y-6', className)}
      data-testid="performance-skeleton"
      aria-busy="true"
      aria-label="Loading performance data"
    >
      {/* Header Controls Skeleton */}
      <ControlsSkeleton />

      {/* Metric Cards Skeleton */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4">
        {Array.from({ length: metricCardCount }).map((_, i) => (
          <MetricCardSkeleton key={i} />
        ))}
      </div>

      {/* Charts Skeleton */}
      {showCharts && (
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
          {Array.from({ length: chartCount }).map((_, i) => (
            <ChartSkeleton key={i} />
          ))}
        </div>
      )}

      {/* Slow Requests Skeleton */}
      {showSlowRequests && <SlowRequestsSkeleton />}
    </div>
  );
}

// Export sub-components for flexible usage
export { MetricCardSkeleton, ChartSkeleton, SlowRequestsSkeleton, ControlsSkeleton };