126 lines
4.9 KiB
TypeScript
126 lines
4.9 KiB
TypeScript
'use client'
|
|
|
|
|
|
|
|
import { useTranslation } from '../i18n/useTranslation';
|
|
import { useState, useEffect } from 'react'
|
|
import useAuthStore from '../store/authStore'
|
|
|
|
// Helper to decode JWT and get expiry
|
|
function getTokenExpiry(token: string | null): Date | null {
|
|
if (!token) return null;
|
|
try {
|
|
const [, payload] = token.split(".");
|
|
const { exp } = JSON.parse(atob(payload));
|
|
return exp ? new Date(exp * 1000) : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export default function TestRefreshPage() {
|
|
const { t } = useTranslation();
|
|
const { accessToken, refreshAuthToken, user } = useAuthStore()
|
|
const [tokenInfo, setTokenInfo] = useState<any>({})
|
|
const [refreshStatus, setRefreshStatus] = useState<string>('')
|
|
|
|
// Update token info every second
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
if (accessToken) {
|
|
const expiry = getTokenExpiry(accessToken)
|
|
const now = Date.now()
|
|
const timeLeft = expiry ? expiry.getTime() - now : 0
|
|
|
|
setTokenInfo({
|
|
hasToken: !!accessToken,
|
|
tokenPrefix: accessToken ? `${accessToken.substring(0, 20)}...` : null,
|
|
expiresAt: expiry ? expiry.toLocaleTimeString() : 'Unknown',
|
|
timeLeftMs: timeLeft,
|
|
timeLeftMin: Math.round(timeLeft / 60000),
|
|
timeLeftSec: Math.round(timeLeft / 1000),
|
|
isExpired: timeLeft <= 0
|
|
})
|
|
} else {
|
|
setTokenInfo({ hasToken: false })
|
|
}
|
|
}, 1000)
|
|
|
|
return () => clearInterval(interval)
|
|
}, [accessToken])
|
|
|
|
const handleManualRefresh = async () => {
|
|
setRefreshStatus('Refreshing...')
|
|
try {
|
|
const success = await refreshAuthToken()
|
|
setRefreshStatus(success ? '✅ Success' : '❌ Failed')
|
|
} catch (error) {
|
|
setRefreshStatus(`❌ Error: ${error}`)
|
|
}
|
|
setTimeout(() => setRefreshStatus(''), 3000)
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 p-8 text-black">
|
|
<div className="max-w-4xl mx-auto">
|
|
<h1 className="text-3xl font-bold mb-8 text-black">{t('autofix.k00016501')}</h1>
|
|
|
|
<div className="grid gap-6">
|
|
{/* Token Status */}
|
|
<div className="bg-white p-6 rounded-lg shadow text-black">
|
|
<h2 className="text-xl font-semibold mb-4 text-black">{t('autofix.kee28b8c6')}</h2>
|
|
<div className="space-y-2 font-mono text-sm text-black">
|
|
<div>{t('autofix.k47b952de')}<span className={tokenInfo.hasToken ? 'text-green-600' : 'text-red-600'}>{tokenInfo.hasToken ? t('autofix.k8e3ac56f') : t('autofix.k69519588')}</span></div>
|
|
|
|
{tokenInfo.hasToken && (
|
|
<>
|
|
<div>{t('autofix.k61f6cd4e')}<span className="text-blue-600">{tokenInfo.tokenPrefix}</span></div>
|
|
<div>{t('autofix.k3d5fe74a')}<span className="text-purple-600">{tokenInfo.expiresAt}</span></div>
|
|
<div>{t('autofix.k4ed7f4d1')}<span className={tokenInfo.timeLeftSec <= 180 ? 'text-red-600' : 'text-green-600'}>
|
|
{tokenInfo.timeLeftMin}m {tokenInfo.timeLeftSec % 60}s
|
|
</span></div>
|
|
<div>{t('autofix.k81c0b74b')}<span className={tokenInfo.isExpired ? 'text-red-600' : 'text-green-600'}>{tokenInfo.isExpired ? t('autofix.kb2f958ef') : t('autofix.k0831f6d6')}</span></div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* User Info */}
|
|
<div className="bg-white p-6 rounded-lg shadow text-black">
|
|
<h2 className="text-xl font-semibold mb-4 text-black">{t('autofix.k0d6626e3')}</h2>
|
|
<pre className="text-sm bg-gray-100 p-4 rounded overflow-auto text-black">
|
|
{JSON.stringify(user, null, 2)}
|
|
</pre>
|
|
</div>
|
|
|
|
{/* Manual Controls */}
|
|
<div className="bg-white p-6 rounded-lg shadow text-black">
|
|
<h2 className="text-xl font-semibold mb-4 text-black">{t('autofix.kb74d7c51')}</h2>
|
|
<div className="space-y-4">
|
|
<button
|
|
onClick={handleManualRefresh}
|
|
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
|
|
>{t('autofix.kf7189e80')}</button>
|
|
{refreshStatus && (
|
|
<div className="text-sm font-mono text-black">{refreshStatus}</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Instructions */}
|
|
<div className="bg-yellow-50 border border-yellow-200 p-6 rounded-lg text-black">
|
|
<h2 className="text-xl font-semibold mb-4 text-black">{t('autofix.k9213db6e')}</h2>
|
|
<ol className="list-decimal list-inside space-y-2 text-sm text-black">
|
|
<li>{t('autofix.k0778fa87')}</li>
|
|
<li>{t('autofix.k1405afab')}</li>
|
|
<li>{t('autofix.kb6b367b7')}</li>
|
|
<li>{t('autofix.kf0d33884')}</li>
|
|
<li>{t('autofix.k73d4a156')}</li>
|
|
<li>{t('autofix.kb01addda')}</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
} |