chore: fix failed build
This commit is contained in:
parent
e065e56f5c
commit
e8666ee5ec
@ -1,186 +1,193 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { AlertCircle, CheckCircle, Clock, RefreshCw } from 'lucide-react';
|
||||
import React, { useState, useEffect, useCallback } from 'react'
|
||||
import { AlertCircle, CheckCircle, Clock, RefreshCw } from 'lucide-react'
|
||||
|
||||
interface StatusData {
|
||||
status: 'operational' | 'degraded' | 'partial_outage' | 'major_outage' | 'under_maintenance' | 'unknown';
|
||||
lastUpdated: string;
|
||||
status:
|
||||
| 'operational'
|
||||
| 'degraded'
|
||||
| 'partial_outage'
|
||||
| 'major_outage'
|
||||
| 'under_maintenance'
|
||||
| 'unknown'
|
||||
lastUpdated: string
|
||||
incidents: Array<{
|
||||
name: string;
|
||||
status: string;
|
||||
impact: string;
|
||||
}>;
|
||||
name: string
|
||||
status: string
|
||||
impact: string
|
||||
}>
|
||||
}
|
||||
|
||||
const StatusIcon = ({ status }: { status: string }) => {
|
||||
switch (status) {
|
||||
case 'operational':
|
||||
return <CheckCircle className="w-5 h-5 text-green-500" />;
|
||||
return <CheckCircle className="w-5 h-5 text-green-500" />
|
||||
case 'degraded':
|
||||
case 'partial_outage':
|
||||
return <AlertCircle className="w-5 h-5 text-yellow-500" />;
|
||||
return <AlertCircle className="w-5 h-5 text-yellow-500" />
|
||||
case 'major_outage':
|
||||
return <AlertCircle className="w-5 h-5 text-red-500" />;
|
||||
return <AlertCircle className="w-5 h-5 text-red-500" />
|
||||
case 'under_maintenance':
|
||||
return <Clock className="w-5 h-5 text-blue-500" />;
|
||||
return <Clock className="w-5 h-5 text-blue-500" />
|
||||
default:
|
||||
return <AlertCircle className="w-5 h-5 text-gray-500" />;
|
||||
return <AlertCircle className="w-5 h-5 text-gray-500" />
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'operational':
|
||||
return 'bg-green-100 text-green-800 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800';
|
||||
return 'bg-green-100 text-green-800 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800'
|
||||
case 'degraded':
|
||||
case 'partial_outage':
|
||||
return 'bg-yellow-100 text-yellow-800 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-800';
|
||||
return 'bg-yellow-100 text-yellow-800 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-800'
|
||||
case 'major_outage':
|
||||
return 'bg-red-100 text-red-800 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800';
|
||||
return 'bg-red-100 text-red-800 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800'
|
||||
case 'under_maintenance':
|
||||
return 'bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800';
|
||||
return 'bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800'
|
||||
default:
|
||||
return 'bg-gray-100 text-gray-800 border-gray-200 dark:bg-gray-900/20 dark:text-gray-300 dark:border-gray-800';
|
||||
return 'bg-gray-100 text-gray-800 border-gray-200 dark:bg-gray-900/20 dark:text-gray-300 dark:border-gray-800'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
switch (status) {
|
||||
case 'operational':
|
||||
return 'All Systems Operational';
|
||||
return 'All Systems Operational'
|
||||
case 'degraded':
|
||||
return 'Degraded Performance';
|
||||
return 'Degraded Performance'
|
||||
case 'partial_outage':
|
||||
return 'Partial Service Outage';
|
||||
return 'Partial Service Outage'
|
||||
case 'major_outage':
|
||||
return 'Major Service Outage';
|
||||
return 'Major Service Outage'
|
||||
case 'under_maintenance':
|
||||
return 'Under Maintenance';
|
||||
return 'Under Maintenance'
|
||||
default:
|
||||
return 'Status Unknown';
|
||||
return 'Status Unknown'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const OpenAIStatusChecker: React.FC = () => {
|
||||
const [statusData, setStatusData] = useState<StatusData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [lastRefresh, setLastRefresh] = useState<Date>(new Date());
|
||||
const [statusData, setStatusData] = useState<StatusData | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [lastRefresh, setLastRefresh] = useState<Date>(new Date())
|
||||
|
||||
const fetchStatus = useCallback(async () => {
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
|
||||
const fetchStatus = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
console.log('Fetching real OpenAI status...');
|
||||
|
||||
console.log('Fetching real OpenAI status...')
|
||||
|
||||
// Use CORS proxy to fetch real OpenAI status
|
||||
const proxyUrl = 'https://api.allorigins.win/get?url=';
|
||||
const targetUrl = 'https://status.openai.com/api/v2/status.json';
|
||||
|
||||
const response = await fetch(proxyUrl + encodeURIComponent(targetUrl));
|
||||
|
||||
const proxyUrl = 'https://api.allorigins.win/get?url='
|
||||
const targetUrl = 'https://status.openai.com/api/v2/status.json'
|
||||
|
||||
const response = await fetch(proxyUrl + encodeURIComponent(targetUrl))
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Proxy returned ${response.status}`);
|
||||
throw new Error(`Proxy returned ${response.status}`)
|
||||
}
|
||||
|
||||
const proxyData = await response.json();
|
||||
const openaiData = JSON.parse(proxyData.contents);
|
||||
|
||||
console.log('Real OpenAI data received:', openaiData);
|
||||
|
||||
|
||||
const proxyData = await response.json()
|
||||
const openaiData = JSON.parse(proxyData.contents)
|
||||
|
||||
console.log('Real OpenAI data received:', openaiData)
|
||||
|
||||
// Transform real OpenAI data to our format
|
||||
const transformedData = {
|
||||
status: mapOpenAIStatusClient(openaiData.status?.indicator || 'operational'),
|
||||
const transformedData: StatusData = {
|
||||
status: mapOpenAIStatusClient(
|
||||
openaiData.status?.indicator || 'operational'
|
||||
),
|
||||
lastUpdated: openaiData.page?.updated_at || new Date().toISOString(),
|
||||
incidents: (openaiData.incidents || []).slice(0, 3),
|
||||
components: (openaiData.components || []).filter(component =>
|
||||
['ChatGPT', 'API', 'Playground'].some(name =>
|
||||
(component.name || '').toLowerCase().includes(name.toLowerCase())
|
||||
)
|
||||
)
|
||||
};
|
||||
|
||||
setStatusData(transformedData);
|
||||
setLastRefresh(new Date());
|
||||
console.log('✅ Real OpenAI status loaded successfully!');
|
||||
|
||||
}
|
||||
|
||||
setStatusData(transformedData)
|
||||
setLastRefresh(new Date())
|
||||
console.log('✅ Real OpenAI status loaded successfully!')
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch real status:', err);
|
||||
|
||||
console.error('Failed to fetch real status:', err)
|
||||
|
||||
// Fallback: try alternative proxy
|
||||
try {
|
||||
console.log('Trying alternative proxy...');
|
||||
const altResponse = await fetch(`https://cors-anywhere.herokuapp.com/https://status.openai.com/api/v2/summary.json`);
|
||||
|
||||
console.log('Trying alternative proxy...')
|
||||
const altResponse = await fetch(
|
||||
`https://cors-anywhere.herokuapp.com/https://status.openai.com/api/v2/summary.json`
|
||||
)
|
||||
|
||||
if (altResponse.ok) {
|
||||
const altData = await altResponse.json();
|
||||
const altData = await altResponse.json()
|
||||
setStatusData({
|
||||
status: mapOpenAIStatusClient(altData.status?.indicator || 'operational'),
|
||||
status: mapOpenAIStatusClient(
|
||||
altData.status?.indicator || 'operational'
|
||||
),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
incidents: []
|
||||
});
|
||||
setLastRefresh(new Date());
|
||||
console.log('✅ Alternative proxy worked!');
|
||||
return;
|
||||
incidents: [],
|
||||
})
|
||||
setLastRefresh(new Date())
|
||||
console.log('✅ Alternative proxy worked!')
|
||||
return
|
||||
}
|
||||
} catch (altErr) {
|
||||
console.log('Alternative proxy also failed');
|
||||
console.log('Alternative proxy also failed')
|
||||
}
|
||||
|
||||
|
||||
// Final fallback
|
||||
setError('Unable to fetch real-time status');
|
||||
setError('Unable to fetch real-time status')
|
||||
setStatusData({
|
||||
status: 'operational',
|
||||
status: 'operational' as const,
|
||||
lastUpdated: new Date().toISOString(),
|
||||
incidents: []
|
||||
});
|
||||
setLastRefresh(new Date());
|
||||
console.log('Using fallback status');
|
||||
|
||||
incidents: [],
|
||||
})
|
||||
setLastRefresh(new Date())
|
||||
console.log('Using fallback status')
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setLoading(false)
|
||||
}
|
||||
};
|
||||
}, [])
|
||||
|
||||
// Client-side status mapping function
|
||||
const mapOpenAIStatusClient = (indicator: string) => {
|
||||
const mapOpenAIStatusClient = (indicator: string): StatusData['status'] => {
|
||||
switch (indicator.toLowerCase()) {
|
||||
case 'none':
|
||||
case 'operational':
|
||||
return 'operational';
|
||||
return 'operational'
|
||||
case 'minor':
|
||||
return 'degraded';
|
||||
return 'degraded'
|
||||
case 'major':
|
||||
return 'partial_outage';
|
||||
return 'partial_outage'
|
||||
case 'critical':
|
||||
return 'major_outage';
|
||||
return 'major_outage'
|
||||
case 'maintenance':
|
||||
return 'under_maintenance';
|
||||
return 'under_maintenance'
|
||||
default:
|
||||
return 'operational'; // Default to operational
|
||||
return 'operational' as const // Default to operational
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchStatus();
|
||||
fetchStatus()
|
||||
// Refresh every 2 minutes for more real-time updates
|
||||
const interval = setInterval(fetchStatus, 2 * 60 * 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
const interval = setInterval(fetchStatus, 2 * 60 * 1000)
|
||||
return () => clearInterval(interval)
|
||||
}, [fetchStatus])
|
||||
|
||||
const handleRefresh = () => {
|
||||
fetchStatus();
|
||||
};
|
||||
fetchStatus()
|
||||
}
|
||||
|
||||
if (loading && !statusData) {
|
||||
return (
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6 border border-gray-200 dark:border-gray-700">
|
||||
<div className="flex items-center justify-center space-x-3">
|
||||
<RefreshCw className="w-6 h-6 text-blue-500 animate-spin" />
|
||||
<span className="text-lg font-medium text-gray-700 dark:text-gray-300">Checking OpenAI Status...</span>
|
||||
<span className="text-lg font-medium text-gray-700 dark:text-gray-300">
|
||||
Checking OpenAI Status...
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
if (error) {
|
||||
@ -190,7 +197,9 @@ export const OpenAIStatusChecker: React.FC = () => {
|
||||
<div className="flex items-center space-x-3">
|
||||
<AlertCircle className="w-6 h-6 text-red-500" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-red-800 dark:text-red-300">Unable to Check Status</h3>
|
||||
<h3 className="text-lg font-semibold text-red-800 dark:text-red-300">
|
||||
Unable to Check Status
|
||||
</h3>
|
||||
<p className="text-red-600 dark:text-red-400">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -202,7 +211,7 @@ export const OpenAIStatusChecker: React.FC = () => {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
@ -211,7 +220,9 @@ export const OpenAIStatusChecker: React.FC = () => {
|
||||
<div className="flex items-center space-x-3">
|
||||
<StatusIcon status={statusData?.status || 'unknown'} />
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-gray-100">OpenAI Services</h3>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-gray-100">
|
||||
OpenAI Services
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Last updated: {new Date(lastRefresh).toLocaleTimeString()}
|
||||
</p>
|
||||
@ -222,16 +233,22 @@ export const OpenAIStatusChecker: React.FC = () => {
|
||||
disabled={loading}
|
||||
className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors disabled:opacity-50"
|
||||
>
|
||||
<RefreshCw className={`w-5 h-5 text-gray-600 dark:text-gray-400 ${loading ? 'animate-spin' : ''}`} />
|
||||
<RefreshCw
|
||||
className={`w-5 h-5 text-gray-600 dark:text-gray-400 ${loading ? 'animate-spin' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={`inline-flex items-center px-4 py-2 rounded-full text-sm font-semibold border ${getStatusColor(statusData?.status || 'unknown')}`}>
|
||||
<div
|
||||
className={`inline-flex items-center px-4 py-2 rounded-full text-sm font-semibold border ${getStatusColor(statusData?.status || 'unknown')}`}
|
||||
>
|
||||
{getStatusText(statusData?.status || 'unknown')}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
||||
<h4 className="font-semibold text-gray-900 dark:text-gray-100 mb-2">Quick Status Check</h4>
|
||||
<h4 className="font-semibold text-gray-900 dark:text-gray-100 mb-2">
|
||||
Quick Status Check
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-gray-600 dark:text-gray-400">ChatGPT</span>
|
||||
@ -249,13 +266,18 @@ export const OpenAIStatusChecker: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="mt-4 text-xs text-gray-500 dark:text-gray-400 text-center">
|
||||
{error ? 'Using fallback status • ' : '🟢 Real-time data from OpenAI • '}
|
||||
{error
|
||||
? 'Using fallback status • '
|
||||
: '🟢 Real-time data from OpenAI • '}
|
||||
Updated: {new Date(lastRefresh).toLocaleTimeString()}
|
||||
<br />
|
||||
<a href="/post/is-chatgpt-down-use-jan#-is-chatgpt-down" className="text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 underline">
|
||||
<a
|
||||
href="/post/is-chatgpt-down-use-jan#-is-chatgpt-down"
|
||||
className="text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 underline"
|
||||
>
|
||||
View detailed status guide
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user