Добавлена связь задач с желаниями
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 58s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 58s
This commit is contained in:
@@ -373,7 +373,7 @@ const formatTelegramMessage = (task, rewards, subtasks, selectedSubtasks, progre
|
||||
return finalMessage
|
||||
}
|
||||
|
||||
function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted, onNavigate }) {
|
||||
const { authFetch } = useAuth()
|
||||
const [taskDetail, setTaskDetail] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -382,6 +382,7 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
const [progressionValue, setProgressionValue] = useState('')
|
||||
const [isCompleting, setIsCompleting] = useState(false)
|
||||
const [toastMessage, setToastMessage] = useState(null)
|
||||
const [wishlistInfo, setWishlistInfo] = useState(null)
|
||||
|
||||
const fetchTaskDetail = useCallback(async () => {
|
||||
try {
|
||||
@@ -393,6 +394,25 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
}
|
||||
const data = await response.json()
|
||||
setTaskDetail(data)
|
||||
|
||||
// Загружаем информацию о связанном желании, если есть
|
||||
if (data.task.wishlist_id) {
|
||||
try {
|
||||
const wishlistResponse = await authFetch(`/api/wishlist/${data.task.wishlist_id}`)
|
||||
if (wishlistResponse.ok) {
|
||||
const wishlistData = await wishlistResponse.json()
|
||||
setWishlistInfo({
|
||||
id: wishlistData.id,
|
||||
name: wishlistData.name,
|
||||
unlocked: wishlistData.unlocked || false
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error loading wishlist info:', err)
|
||||
}
|
||||
} else {
|
||||
setWishlistInfo(null)
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err.message)
|
||||
console.error('Error fetching task detail:', err)
|
||||
@@ -429,6 +449,12 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
const handleComplete = async (shouldDelete = false) => {
|
||||
if (!taskDetail) return
|
||||
|
||||
// Проверяем, что желание разблокировано (если есть связанное желание)
|
||||
if (wishlistInfo && !wishlistInfo.unlocked) {
|
||||
setToastMessage({ text: 'Невозможно выполнить задачу: желание не разблокировано', type: 'error' })
|
||||
return
|
||||
}
|
||||
|
||||
// Если прогрессия не введена, используем 0 (валидация не требуется)
|
||||
|
||||
setIsCompleting(true)
|
||||
@@ -492,8 +518,8 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
|
||||
const { task, rewards, subtasks } = taskDetail || {}
|
||||
const hasProgression = task?.progression_base != null
|
||||
// Кнопка всегда активна (если прогрессия не введена, используем 0)
|
||||
const canComplete = true
|
||||
// Кнопка активна только если желание разблокировано (или задачи нет связанного желания)
|
||||
const canComplete = !wishlistInfo || wishlistInfo.unlocked
|
||||
|
||||
// Определяем, является ли задача одноразовой
|
||||
// Одноразовая задача: когда оба поля null/undefined (из бэкенда видно, что в этом случае задача помечается как deleted)
|
||||
@@ -556,6 +582,33 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
|
||||
{!loading && !error && taskDetail && (
|
||||
<>
|
||||
{/* Информация о связанном желании */}
|
||||
{task.wishlist_id && wishlistInfo && (
|
||||
<div className="task-wishlist-link">
|
||||
<div className="task-wishlist-link-info">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<polyline points="20 12 20 22 4 22 4 12"></polyline>
|
||||
<rect x="2" y="7" width="20" height="5"></rect>
|
||||
<line x1="12" y1="22" x2="12" y2="7"></line>
|
||||
<path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"></path>
|
||||
<path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"></path>
|
||||
</svg>
|
||||
<span className="task-wishlist-link-label">Связано с желанием:</span>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (onClose) onClose()
|
||||
if (onNavigate && wishlistInfo) {
|
||||
onNavigate('wishlist-detail', { wishlistId: wishlistInfo.id })
|
||||
}
|
||||
}}
|
||||
className="task-wishlist-link-button"
|
||||
>
|
||||
{wishlistInfo.name}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Поле ввода прогрессии */}
|
||||
{hasProgression && (
|
||||
<div className="progression-section">
|
||||
@@ -619,13 +672,20 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted }) {
|
||||
onClick={() => handleComplete(false)}
|
||||
disabled={isCompleting || !canComplete}
|
||||
className="complete-button"
|
||||
title={!canComplete && wishlistInfo ? 'Желание не разблокировано' : ''}
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ marginRight: '0.5rem' }}>
|
||||
<path d="M13.5 4L6 11.5L2.5 8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
{!canComplete && wishlistInfo ? (
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: '0.5rem' }}>
|
||||
<path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM9 6c0-1.66 1.34-3 3-3s3 1.34 3 3v2H9V6zm9 14H6V10h12v10zm-6-3c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/>
|
||||
</svg>
|
||||
) : (
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ marginRight: '0.5rem' }}>
|
||||
<path d="M13.5 4L6 11.5L2.5 8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
)}
|
||||
{isCompleting ? 'Выполнение...' : 'Выполнить'}
|
||||
</button>
|
||||
{!isOneTime && (
|
||||
{!isOneTime && canComplete && (
|
||||
<button
|
||||
onClick={() => handleComplete(true)}
|
||||
disabled={isCompleting || !canComplete}
|
||||
|
||||
Reference in New Issue
Block a user