156
play-life-web/src/components/BoardJoinPreview.jsx
Normal file
156
play-life-web/src/components/BoardJoinPreview.jsx
Normal file
@@ -0,0 +1,156 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { useAuth } from './auth/AuthContext'
|
||||
import './BoardJoinPreview.css'
|
||||
|
||||
function BoardJoinPreview({ inviteToken, onNavigate }) {
|
||||
const { authFetch, user } = useAuth()
|
||||
const [board, setBoard] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [joining, setJoining] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (inviteToken) {
|
||||
fetchBoardInfo()
|
||||
}
|
||||
}, [inviteToken])
|
||||
|
||||
const fetchBoardInfo = async () => {
|
||||
try {
|
||||
const res = await authFetch(`/api/wishlist/invite/${inviteToken}`)
|
||||
|
||||
if (res.ok) {
|
||||
setBoard(await res.json())
|
||||
} else {
|
||||
const err = await res.json()
|
||||
setError(err.error || 'Ссылка недействительна или устарела')
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Ошибка загрузки')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleJoin = async () => {
|
||||
if (!user) {
|
||||
// Сохраняем токен для возврата после логина
|
||||
sessionStorage.setItem('pendingInviteToken', inviteToken)
|
||||
onNavigate('login')
|
||||
return
|
||||
}
|
||||
|
||||
setJoining(true)
|
||||
setError('')
|
||||
|
||||
try {
|
||||
const res = await authFetch(`/api/wishlist/invite/${inviteToken}/join`, {
|
||||
method: 'POST'
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
// Переходим на доску
|
||||
onNavigate('wishlist', { boardId: data.board.id })
|
||||
} else {
|
||||
const err = await res.json()
|
||||
setError(err.error || 'Ошибка при присоединении')
|
||||
}
|
||||
} catch (err) {
|
||||
setError('Ошибка при присоединении')
|
||||
} finally {
|
||||
setJoining(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleGoBack = () => {
|
||||
onNavigate('wishlist')
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="board-join-preview">
|
||||
<div className="preview-loading">
|
||||
<div className="w-12 h-12 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin"></div>
|
||||
<p>Загрузка...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (error && !board) {
|
||||
return (
|
||||
<div className="board-join-preview">
|
||||
<div className="preview-card error-card">
|
||||
<div className="error-icon">❌</div>
|
||||
<h2>Ошибка</h2>
|
||||
<p className="error-text">{error}</p>
|
||||
<button className="back-btn" onClick={handleGoBack}>
|
||||
Вернуться к желаниям
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="board-join-preview">
|
||||
<div className="preview-card">
|
||||
<div className="invite-icon">✨</div>
|
||||
<h2>Приглашение на доску</h2>
|
||||
|
||||
<div className="board-info">
|
||||
<div className="board-name">{board.name}</div>
|
||||
<div className="board-owner">
|
||||
<span className="label">Владелец:</span>
|
||||
<span className="value">{board.owner_name}</span>
|
||||
</div>
|
||||
{board.member_count > 0 && (
|
||||
<div className="board-members">
|
||||
<span className="label">Участников:</span>
|
||||
<span className="value">{board.member_count}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="join-error">{error}</div>
|
||||
)}
|
||||
|
||||
{user ? (
|
||||
<button
|
||||
className="join-btn"
|
||||
onClick={handleJoin}
|
||||
disabled={joining}
|
||||
>
|
||||
{joining ? (
|
||||
<>
|
||||
<span className="spinner-small"></span>
|
||||
<span>Присоединение...</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>🎉</span>
|
||||
<span>Присоединиться</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
) : (
|
||||
<div className="login-prompt">
|
||||
<p>Для присоединения необходимо войти в аккаунт</p>
|
||||
<button className="login-btn" onClick={() => onNavigate('login')}>
|
||||
Войти
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button className="cancel-link" onClick={handleGoBack}>
|
||||
Отмена
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BoardJoinPreview
|
||||
|
||||
Reference in New Issue
Block a user