DashboardStats.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { useQuery } from 'react-query';
  2. import {
  3. Users,
  4. Building,
  5. Code,
  6. Database,
  7. Activity,
  8. HardDrive,
  9. } from 'lucide-react';
  10. import apiService from '@/services/api';
  11. import type { DashboardStats } from '@/types';
  12. const StatCard = ({ title, value, icon: Icon, change, changeType }: any) => (
  13. <div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
  14. <div className="flex items-center">
  15. <div className="flex-shrink-0">
  16. <Icon className="h-8 w-8 text-primary-600" />
  17. </div>
  18. <div className="ml-5 w-0 flex-1">
  19. <dl>
  20. <dt className="text-sm font-medium text-gray-500 truncate">{title}</dt>
  21. <dd className="flex items-baseline">
  22. <div className="text-2xl font-semibold text-gray-900">{value}</div>
  23. {change && (
  24. <div
  25. className={`ml-2 flex items-baseline text-sm font-medium ${
  26. changeType === 'increase' ? 'text-green-600' : 'text-red-600'
  27. }`}
  28. >
  29. {changeType === 'increase' ? '↑' : '↓'} {change}
  30. </div>
  31. )}
  32. </dd>
  33. </dl>
  34. </div>
  35. </div>
  36. </div>
  37. );
  38. export default function DashboardStatsComponent() {
  39. const { data: stats, isLoading } = useQuery<DashboardStats>(
  40. 'dashboard-stats',
  41. () => apiService.getDashboardStats(),
  42. {
  43. refetchInterval: 30000, // Refetch every 30 seconds
  44. }
  45. );
  46. if (isLoading) {
  47. return (
  48. <div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
  49. {[...Array(4)].map((_, i) => (
  50. <div key={i} className="animate-pulse">
  51. <div className="bg-gray-200 rounded-xl h-32"></div>
  52. </div>
  53. ))}
  54. </div>
  55. );
  56. }
  57. return (
  58. <div className="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
  59. <StatCard
  60. title="Total Users"
  61. value={stats?.total_users || 0}
  62. icon={Users}
  63. change="+12%"
  64. changeType="increase"
  65. />
  66. <StatCard
  67. title="Organizations"
  68. value={stats?.total_organizations || 0}
  69. icon={Building}
  70. change="+8%"
  71. changeType="increase"
  72. />
  73. <StatCard
  74. title="Applications"
  75. value={stats?.total_applications || 0}
  76. icon={Code}
  77. change="+15%"
  78. changeType="increase"
  79. />
  80. <StatCard
  81. title="Deployments"
  82. value={stats?.total_deployments || 0}
  83. icon={Activity}
  84. change="+20%"
  85. changeType="increase"
  86. />
  87. </div>
  88. );
  89. }