File size: 4,521 Bytes
c0a9bce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
125
126
127
128
129
130
131
132
133
134
135
136
import { useState, useEffect } from 'react';
import type { ServiceStatus } from './types';
import { ProviderStatusCheckerFactory } from './provider-factory';

export default function ServiceStatusTab() {
  const [serviceStatuses, setServiceStatuses] = useState<ServiceStatus[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const checkAllProviders = async () => {
      try {
        setLoading(true);
        setError(null);

        const providers = ProviderStatusCheckerFactory.getProviderNames();
        const statuses: ServiceStatus[] = [];

        for (const provider of providers) {
          try {
            const checker = ProviderStatusCheckerFactory.getChecker(provider);
            const result = await checker.checkStatus();

            statuses.push({
              provider,
              ...result,
              lastChecked: new Date().toISOString(),
            });
          } catch (err) {
            console.error(`Error checking ${provider} status:`, err);
            statuses.push({
              provider,
              status: 'degraded',
              message: 'Unable to check service status',
              incidents: ['Error checking service status'],
              lastChecked: new Date().toISOString(),
            });
          }
        }

        setServiceStatuses(statuses);
      } catch (err) {
        console.error('Error checking provider statuses:', err);
        setError('Failed to check service statuses');
      } finally {
        setLoading(false);
      }
    };

    checkAllProviders();

    // Set up periodic checks every 5 minutes
    const interval = setInterval(checkAllProviders, 5 * 60 * 1000);

    return () => clearInterval(interval);
  }, []);

  const getStatusColor = (status: ServiceStatus['status']) => {
    switch (status) {
      case 'operational':
        return 'text-green-500 dark:text-green-400';
      case 'degraded':
        return 'text-yellow-500 dark:text-yellow-400';
      case 'down':
        return 'text-red-500 dark:text-red-400';
      default:
        return 'text-gray-500 dark:text-gray-400';
    }
  };

  const getStatusIcon = (status: ServiceStatus['status']) => {
    switch (status) {
      case 'operational':
        return 'i-ph:check-circle';
      case 'degraded':
        return 'i-ph:warning';
      case 'down':
        return 'i-ph:x-circle';
      default:
        return 'i-ph:question';
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center h-full">
        <div className="animate-spin i-ph:circle-notch w-8 h-8 text-purple-500" />
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex flex-col items-center justify-center h-full text-red-500 dark:text-red-400">
        <div className="i-ph:warning w-8 h-8 mb-2" />
        <p>{error}</p>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <div className="grid grid-cols-1 gap-4">
        {serviceStatuses.map((service) => (
          <div
            key={service.provider}
            className="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"
          >
            <div className="flex items-center justify-between mb-2">
              <h3 className="text-lg font-semibold text-gray-900 dark:text-white">{service.provider}</h3>
              <div className={`flex items-center ${getStatusColor(service.status)}`}>
                <div className={`${getStatusIcon(service.status)} w-5 h-5 mr-2`} />
                <span className="capitalize">{service.status}</span>
              </div>
            </div>
            <p className="text-gray-600 dark:text-gray-300 mb-2">{service.message}</p>
            {service.incidents && service.incidents.length > 0 && (
              <div className="mt-2">
                <h4 className="text-sm font-semibold text-gray-700 dark:text-gray-300 mb-1">Recent Incidents:</h4>
                <ul className="text-sm text-gray-600 dark:text-gray-400 space-y-1">
                  {service.incidents.map((incident, index) => (
                    <li key={index}>{incident}</li>
                  ))}
                </ul>
              </div>
            )}
            <div className="mt-2 text-xs text-gray-500 dark:text-gray-400">
              Last checked: {new Date(service.lastChecked).toLocaleString()}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}