Add modals
This commit is contained in:
@@ -6,9 +6,13 @@ import { Button, Card, CardContent } from '@/components/ui'
|
||||
import { SpinWheel } from '@/components/SpinWheel'
|
||||
import { EventBanner } from '@/components/EventBanner'
|
||||
import { Loader2, Upload, X, Gamepad2, ArrowLeftRight, Check, XCircle, Clock, Send, Trophy, Users, ArrowLeft, AlertTriangle } from 'lucide-react'
|
||||
import { useToast } from '@/store/toast'
|
||||
import { useConfirm } from '@/store/confirm'
|
||||
|
||||
export function PlayPage() {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const toast = useToast()
|
||||
const confirm = useConfirm()
|
||||
|
||||
const [marathon, setMarathon] = useState<Marathon | null>(null)
|
||||
const [currentAssignment, setCurrentAssignment] = useState<Assignment | null>(null)
|
||||
@@ -99,7 +103,7 @@ export function PlayPage() {
|
||||
setGameChoiceChallenges(challenges)
|
||||
} catch (error) {
|
||||
console.error('Failed to load game choice challenges:', error)
|
||||
alert('Не удалось загрузить челленджи для этой игры')
|
||||
toast.error('Не удалось загрузить челленджи для этой игры')
|
||||
} finally {
|
||||
setIsLoadingChallenges(false)
|
||||
}
|
||||
@@ -181,7 +185,7 @@ export function PlayPage() {
|
||||
return result.game
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось крутить')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось крутить')
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -196,7 +200,7 @@ export function PlayPage() {
|
||||
const handleComplete = async () => {
|
||||
if (!currentAssignment) return
|
||||
if (!proofFile && !proofUrl) {
|
||||
alert('Пожалуйста, предоставьте доказательство (файл или ссылку)')
|
||||
toast.warning('Пожалуйста, предоставьте доказательство (файл или ссылку)')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -208,7 +212,7 @@ export function PlayPage() {
|
||||
comment: comment || undefined,
|
||||
})
|
||||
|
||||
alert(`Выполнено! +${result.points_earned} очков (бонус серии: +${result.streak_bonus})`)
|
||||
toast.success(`Выполнено! +${result.points_earned} очков (бонус серии: +${result.streak_bonus})`)
|
||||
|
||||
// Reset form
|
||||
setProofFile(null)
|
||||
@@ -219,7 +223,7 @@ export function PlayPage() {
|
||||
await loadData()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось выполнить')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось выполнить')
|
||||
} finally {
|
||||
setIsCompleting(false)
|
||||
}
|
||||
@@ -229,18 +233,25 @@ export function PlayPage() {
|
||||
if (!currentAssignment) return
|
||||
|
||||
const penalty = spinResult?.drop_penalty || 0
|
||||
if (!confirm(`Пропустить это задание? Вы потеряете ${penalty} очков.`)) return
|
||||
const confirmed = await confirm({
|
||||
title: 'Пропустить задание?',
|
||||
message: `Вы потеряете ${penalty} очков.`,
|
||||
confirmText: 'Пропустить',
|
||||
cancelText: 'Отмена',
|
||||
variant: 'warning',
|
||||
})
|
||||
if (!confirmed) return
|
||||
|
||||
setIsDropping(true)
|
||||
try {
|
||||
const result = await wheelApi.drop(currentAssignment.id)
|
||||
alert(`Пропущено. Штраф: -${result.penalty} очков`)
|
||||
toast.info(`Пропущено. Штраф: -${result.penalty} очков`)
|
||||
|
||||
setSpinResult(null)
|
||||
await loadData()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось пропустить')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось пропустить')
|
||||
} finally {
|
||||
setIsDropping(false)
|
||||
}
|
||||
@@ -249,7 +260,7 @@ export function PlayPage() {
|
||||
const handleEventComplete = async () => {
|
||||
if (!eventAssignment?.assignment) return
|
||||
if (!eventProofFile && !eventProofUrl) {
|
||||
alert('Пожалуйста, предоставьте доказательство (файл или ссылку)')
|
||||
toast.warning('Пожалуйста, предоставьте доказательство (файл или ссылку)')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -261,7 +272,7 @@ export function PlayPage() {
|
||||
comment: eventComment || undefined,
|
||||
})
|
||||
|
||||
alert(`Выполнено! +${result.points_earned} очков`)
|
||||
toast.success(`Выполнено! +${result.points_earned} очков`)
|
||||
|
||||
// Reset form
|
||||
setEventProofFile(null)
|
||||
@@ -271,7 +282,7 @@ export function PlayPage() {
|
||||
await loadData()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось выполнить')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось выполнить')
|
||||
} finally {
|
||||
setIsEventCompleting(false)
|
||||
}
|
||||
@@ -286,22 +297,27 @@ export function PlayPage() {
|
||||
if (!id) return
|
||||
|
||||
const hasActiveAssignment = !!currentAssignment
|
||||
const confirmMessage = hasActiveAssignment
|
||||
? 'Выбрать этот челлендж? Текущее задание будет заменено без штрафа.'
|
||||
: 'Выбрать этот челлендж?'
|
||||
|
||||
if (!confirm(confirmMessage)) return
|
||||
const confirmed = await confirm({
|
||||
title: 'Выбрать челлендж?',
|
||||
message: hasActiveAssignment
|
||||
? 'Текущее задание будет заменено без штрафа.'
|
||||
: 'Вы уверены, что хотите выбрать этот челлендж?',
|
||||
confirmText: 'Выбрать',
|
||||
cancelText: 'Отмена',
|
||||
variant: 'info',
|
||||
})
|
||||
if (!confirmed) return
|
||||
|
||||
setIsSelectingChallenge(true)
|
||||
try {
|
||||
const result = await eventsApi.selectGameChoiceChallenge(parseInt(id), challengeId)
|
||||
alert(result.message)
|
||||
toast.success(result.message)
|
||||
setSelectedGameId(null)
|
||||
setGameChoiceChallenges(null)
|
||||
await loadData()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось выбрать челлендж')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось выбрать челлендж')
|
||||
} finally {
|
||||
setIsSelectingChallenge(false)
|
||||
}
|
||||
@@ -310,17 +326,24 @@ export function PlayPage() {
|
||||
const handleSendSwapRequest = async (participantId: number, participantName: string, theirChallenge: string) => {
|
||||
if (!id) return
|
||||
|
||||
if (!confirm(`Отправить запрос на обмен с ${participantName}?\n\nВы предлагаете обменяться на: "${theirChallenge}"\n\n${participantName} должен будет подтвердить обмен.`)) return
|
||||
const confirmed = await confirm({
|
||||
title: 'Отправить запрос на обмен?',
|
||||
message: `Вы предлагаете обменяться с ${participantName} на:\n"${theirChallenge}"\n\n${participantName} должен будет подтвердить обмен.`,
|
||||
confirmText: 'Отправить',
|
||||
cancelText: 'Отмена',
|
||||
variant: 'info',
|
||||
})
|
||||
if (!confirmed) return
|
||||
|
||||
setSendingRequestTo(participantId)
|
||||
try {
|
||||
await eventsApi.createSwapRequest(parseInt(id), participantId)
|
||||
alert('Запрос на обмен отправлен! Ожидайте подтверждения.')
|
||||
toast.success('Запрос на обмен отправлен! Ожидайте подтверждения.')
|
||||
await loadSwapRequests()
|
||||
await loadSwapCandidates()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось отправить запрос')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось отправить запрос')
|
||||
} finally {
|
||||
setSendingRequestTo(null)
|
||||
}
|
||||
@@ -329,16 +352,23 @@ export function PlayPage() {
|
||||
const handleAcceptSwapRequest = async (requestId: number) => {
|
||||
if (!id) return
|
||||
|
||||
if (!confirm('Принять обмен? Задания будут обменяны сразу после подтверждения.')) return
|
||||
const confirmed = await confirm({
|
||||
title: 'Принять обмен?',
|
||||
message: 'Задания будут обменяны сразу после подтверждения.',
|
||||
confirmText: 'Принять',
|
||||
cancelText: 'Отмена',
|
||||
variant: 'info',
|
||||
})
|
||||
if (!confirmed) return
|
||||
|
||||
setProcessingRequestId(requestId)
|
||||
try {
|
||||
await eventsApi.acceptSwapRequest(parseInt(id), requestId)
|
||||
alert('Обмен выполнен!')
|
||||
toast.success('Обмен выполнен!')
|
||||
await loadData()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось выполнить обмен')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось выполнить обмен')
|
||||
} finally {
|
||||
setProcessingRequestId(null)
|
||||
}
|
||||
@@ -353,7 +383,7 @@ export function PlayPage() {
|
||||
await loadSwapRequests()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось отклонить запрос')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось отклонить запрос')
|
||||
} finally {
|
||||
setProcessingRequestId(null)
|
||||
}
|
||||
@@ -369,7 +399,7 @@ export function PlayPage() {
|
||||
await loadSwapCandidates()
|
||||
} catch (err: unknown) {
|
||||
const error = err as { response?: { data?: { detail?: string } } }
|
||||
alert(error.response?.data?.detail || 'Не удалось отменить запрос')
|
||||
toast.error(error.response?.data?.detail || 'Не удалось отменить запрос')
|
||||
} finally {
|
||||
setProcessingRequestId(null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user