StatsSection.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. "use client";
  2. import { useQueryClient } from "@tanstack/react-query";
  3. import { useEffect } from "react";
  4. import ApiHealth from "./ApiHealth";
  5. import Card from "./Card";
  6. import FilesProcessedCard from "./FilesProcessedCard";
  7. import FileWatcherCard from "./FileWatcherCard";
  8. import TaskProcessingCard from "./TaskProcessingCard";
  9. import WatcherHealthStatus from "./WatcherHealthStatus";
  10. export default function StatsSection() {
  11. const queryClient = useQueryClient();
  12. // Listen for WebSocket updates to refresh stats
  13. useEffect(() => {
  14. const handleTaskUpdate = (event: CustomEvent) => {
  15. const taskData = event.detail;
  16. // Refresh task-related queries when tasks are updated
  17. if (
  18. taskData.type === "progress" ||
  19. taskData.type === "completed" ||
  20. taskData.type === "failed"
  21. ) {
  22. queryClient.invalidateQueries({ queryKey: ["tasks"] });
  23. queryClient.invalidateQueries({
  24. queryKey: ["tasks", "processing-status"],
  25. });
  26. queryClient.invalidateQueries({
  27. queryKey: ["tasks", "queue", "status"],
  28. });
  29. }
  30. };
  31. const handleFileUpdate = (event: CustomEvent) => {
  32. const fileData = event.detail;
  33. // Refresh file stats when files are processed
  34. if (fileData.type === "processed" || fileData.type === "success") {
  35. queryClient.invalidateQueries({ queryKey: ["files-stats-successful"] });
  36. queryClient.invalidateQueries({ queryKey: ["files-stats-processed"] });
  37. }
  38. };
  39. window.addEventListener("taskUpdate", handleTaskUpdate as EventListener);
  40. window.addEventListener("fileUpdate", handleFileUpdate as EventListener);
  41. return () => {
  42. window.removeEventListener(
  43. "taskUpdate",
  44. handleTaskUpdate as EventListener
  45. );
  46. window.removeEventListener(
  47. "fileUpdate",
  48. handleFileUpdate as EventListener
  49. );
  50. };
  51. }, [queryClient]);
  52. return (
  53. <div className="space-y-6">
  54. <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
  55. {/* API Health Widget */}
  56. <ApiHealth />
  57. {/* File Watcher Card */}
  58. <FileWatcherCard />
  59. {/* Task Processing Card */}
  60. <TaskProcessingCard />
  61. {/* Files Processed Card */}
  62. <FilesProcessedCard />
  63. </div>
  64. {/* Watcher Health Status - Full Width */}
  65. <div>
  66. <Card>
  67. <div className="space-y-4">
  68. <div className="flex items-center gap-x-3 mb-6">
  69. <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-amber-500/20 ring-1 ring-amber-500/30">
  70. <svg
  71. className="h-6 w-6 text-amber-400"
  72. fill="none"
  73. viewBox="0 0 24 24"
  74. strokeWidth="1.5"
  75. stroke="currentColor"
  76. >
  77. <path
  78. strokeLinecap="round"
  79. strokeLinejoin="round"
  80. d="M9.348 14.652a3.75 3.75 0 010-5.304m5.304 0a3.75 3.75 0 010 5.304m6.632-7.08a9 9 0 11-12.728 0m12.728 0A9 9 0 003.75 12c0 4.478 2.943 8.268 7-9.542"
  81. />
  82. </svg>
  83. </div>
  84. <div>
  85. <h3 className="text-lg font-bold text-white">Watcher Health</h3>
  86. <p className="text-xs text-gray-400">Status & Monitoring</p>
  87. </div>
  88. </div>
  89. <WatcherHealthStatus />
  90. </div>
  91. </Card>
  92. </div>
  93. </div>
  94. );
  95. }