4.27.2: Улучшение отладки OAuth Fitbit
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m24s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m24s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "4.27.1",
|
||||
"version": "4.27.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -10,6 +10,7 @@ function FitbitIntegration({ onNavigate }) {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState('')
|
||||
const [message, setMessage] = useState('')
|
||||
const [oauthError, setOauthError] = useState('')
|
||||
const [toastMessage, setToastMessage] = useState(null)
|
||||
const [isLoadingError, setIsLoadingError] = useState(false)
|
||||
const [goals, setGoals] = useState({
|
||||
@@ -26,23 +27,35 @@ function FitbitIntegration({ onNavigate }) {
|
||||
const [editedGoals, setEditedGoals] = useState(goals)
|
||||
const [syncing, setSyncing] = useState(false)
|
||||
|
||||
// Сохраняем OAuth статус из URL в ref, чтобы проверить после checkStatus
|
||||
const oauthStatusRef = React.useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
checkStatus()
|
||||
// Проверяем URL параметры для сообщений
|
||||
// Проверяем URL параметры для сообщений ДО вызова checkStatus
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const integration = params.get('integration')
|
||||
const status = params.get('status')
|
||||
if (integration === 'fitbit') {
|
||||
oauthStatusRef.current = status
|
||||
if (status === 'connected') {
|
||||
setMessage('✅ Fitbit успешно подключен!')
|
||||
// Очищаем URL параметры
|
||||
window.history.replaceState({}, '', window.location.pathname)
|
||||
setMessage('Fitbit успешно подключен!')
|
||||
} else if (status === 'error') {
|
||||
const errorMsg = params.get('message') || 'Произошла ошибка'
|
||||
setToastMessage({ text: errorMsg, type: 'error' })
|
||||
window.history.replaceState({}, '', window.location.pathname)
|
||||
const errorMsg = params.get('message') || 'unknown_error'
|
||||
const errorMessages = {
|
||||
'config_error': 'Ошибка конфигурации сервера. Обратитесь к администратору.',
|
||||
'invalid_state': 'Недействительный токен авторизации. Попробуйте ещё раз.',
|
||||
'no_code': 'Не получен код авторизации от Fitbit. Попробуйте ещё раз.',
|
||||
'token_exchange_failed': 'Не удалось обменять код на токен. Проверьте настройки Fitbit приложения.',
|
||||
'user_info_failed': 'Не удалось получить информацию о пользователе Fitbit.',
|
||||
'db_error': 'Ошибка сохранения данных. Попробуйте ещё раз.',
|
||||
'unknown_error': 'Произошла неизвестная ошибка при подключении Fitbit.'
|
||||
}
|
||||
setOauthError(errorMessages[errorMsg] || `Ошибка: ${errorMsg}`)
|
||||
}
|
||||
// Очищаем URL параметры
|
||||
window.history.replaceState({}, '', window.location.pathname)
|
||||
}
|
||||
checkStatus()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -65,6 +78,12 @@ function FitbitIntegration({ onNavigate }) {
|
||||
setGoals(data.goals)
|
||||
setEditedGoals(data.goals)
|
||||
}
|
||||
// Если OAuth вернул status=connected, но бэкенд не подтвердил подключение
|
||||
if (oauthStatusRef.current === 'connected' && !data.connected) {
|
||||
setOauthError('Авторизация в Fitbit прошла, но подключение не сохранилось. Попробуйте ещё раз или обратитесь к администратору.')
|
||||
setMessage('')
|
||||
}
|
||||
oauthStatusRef.current = null
|
||||
} catch (error) {
|
||||
console.error('Error checking status:', error)
|
||||
setError(error.message || 'Не удалось проверить статус')
|
||||
@@ -250,6 +269,12 @@ function FitbitIntegration({ onNavigate }) {
|
||||
<p className="text-green-800">{message}</p>
|
||||
</div>
|
||||
)}
|
||||
{oauthError && (
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
|
||||
<p className="text-red-800">{oauthError}</p>
|
||||
<button onClick={() => setOauthError('')} className="text-red-600 text-sm underline mt-1">Скрыть</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Статистика */}
|
||||
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
|
||||
@@ -440,6 +465,13 @@ function FitbitIntegration({ onNavigate }) {
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
{oauthError && (
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-6">
|
||||
<p className="text-red-800 font-medium">Ошибка подключения Fitbit</p>
|
||||
<p className="text-red-700 mt-1">{oauthError}</p>
|
||||
<button onClick={() => setOauthError('')} className="text-red-600 text-sm underline mt-2">Скрыть</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
|
||||
<h2 className="text-lg font-semibold mb-4">Подключение Fitbit</h2>
|
||||
<p className="text-gray-700 mb-4">
|
||||
|
||||
Reference in New Issue
Block a user