Исправления задач-желаний и версия 3.22.0
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 50s

This commit is contained in:
poignatov
2026-01-20 20:48:40 +03:00
parent 08d86eb5f5
commit eb708b057d
5 changed files with 41 additions and 78 deletions

View File

@@ -1 +1 @@
3.21.0 3.22.0

View File

@@ -1,6 +1,6 @@
{ {
"name": "play-life-web", "name": "play-life-web",
"version": "3.21.0", "version": "3.22.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -643,8 +643,8 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
// При создании: отправляем currentWishlistId если указан (уже число) // При создании: отправляем currentWishlistId если указан (уже число)
// При редактировании: отправляем null только если была привязка (currentWishlistId) и пользователь отвязал (!wishlistInfo) // При редактировании: отправляем null только если была привязка (currentWishlistId) и пользователь отвязал (!wishlistInfo)
// Если не было привязки или привязка осталась - не отправляем поле (undefined) // Если не было привязки или привязка осталась - не отправляем поле (undefined)
wishlist_id: taskId wishlist_id: taskId
? (currentWishlistId && !wishlistInfo ? null : undefined) ? currentWishlistId // При редактировании сохраняем текущую привязку к желанию
: (currentWishlistId || undefined), : (currentWishlistId || undefined),
reward_policy: (wishlistInfo || currentWishlistId) ? rewardPolicy : undefined, reward_policy: (wishlistInfo || currentWishlistId) ? rewardPolicy : undefined,
rewards: rewards.map(r => ({ rewards: rewards.map(r => ({
@@ -806,16 +806,6 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
<span className="wishlist-link-text"> <span className="wishlist-link-text">
Связана с желанием: <strong>{wishlistInfo.name}</strong> Связана с желанием: <strong>{wishlistInfo.name}</strong>
</span> </span>
{taskId && currentWishlistId && (
<button
type="button"
onClick={handleUnlinkWishlist}
className="wishlist-unlink-x"
title="Отвязать от желания"
>
</button>
)}
</div> </div>
<div className="form-group" style={{ marginTop: '12px' }}> <div className="form-group" style={{ marginTop: '12px' }}>
<label htmlFor="reward_policy">Политика награждения:</label> <label htmlFor="reward_policy">Политика награждения:</label>
@@ -837,7 +827,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
</div> </div>
)} )}
{!isTest && ( {!isTest && !wishlistInfo && (
<div className="form-group"> <div className="form-group">
<label htmlFor="progression_base">Прогрессия</label> <label htmlFor="progression_base">Прогрессия</label>
<input <input
@@ -920,6 +910,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
</div> </div>
)} )}
{!wishlistInfo && (
<div className="form-group"> <div className="form-group">
<label htmlFor="repetition_period">Повторения</label> <label htmlFor="repetition_period">Повторения</label>
{(() => { {(() => {
@@ -1007,6 +998,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
) )
})()} })()}
</div> </div>
)}
<div className="form-group"> <div className="form-group">
<label htmlFor="reward_message">Сообщение награды</label> <label htmlFor="reward_message">Сообщение награды</label>

View File

@@ -636,16 +636,16 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
<path d="M12 12c0 2.5 1.5 4.5 3.5 4.5S19 14.5 19 12s-1.5-4.5-3.5-4.5S12 9.5 12 12z"/> <path d="M12 12c0 2.5 1.5 4.5 3.5 4.5S19 14.5 19 12s-1.5-4.5-3.5-4.5S12 9.5 12 12z"/>
</svg> </svg>
)} )}
{isOneTime && ( {isOneTime && !isWishlist && (
<svg <svg
className="task-onetime-icon" className="task-onetime-icon"
width="16" width="16"
height="16" height="16"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none" fill="none"
stroke="currentColor" stroke="currentColor"
strokeWidth="2" strokeWidth="2"
strokeLinecap="round" strokeLinecap="round"
strokeLinejoin="round" strokeLinejoin="round"
title="Одноразовая задача" title="Одноразовая задача"
> >

View File

@@ -170,69 +170,34 @@ function WishlistDetail({ wishlistId, onNavigate, onRefresh, boardId }) {
} }
} }
const handleUnlinkTask = async (e) => { const handleDeleteTask = async (e) => {
e.stopPropagation() e.stopPropagation()
if (!wishlistItem?.linked_task) return if (!wishlistItem?.linked_task) return
if (!window.confirm('Удалить задачу, связанную с желанием?')) {
return
}
try { try {
// Загружаем текущую задачу // Удаляем задачу (помечаем как удалённую)
const taskResponse = await authFetch(`/api/tasks/${wishlistItem.linked_task.id}`) const deleteResponse = await authFetch(`/api/tasks/${wishlistItem.linked_task.id}`, {
if (!taskResponse.ok) { method: 'DELETE',
throw new Error('Ошибка при загрузке задачи')
}
const taskData = await taskResponse.json()
const task = taskData.task
// Формируем payload для обновления задачи
const payload = {
name: task.name,
reward_message: task.reward_message || null,
progression_base: task.progression_base || null,
repetition_period: task.repetition_period || null,
repetition_date: task.repetition_date || null,
wishlist_id: null, // Отвязываем от желания
rewards: (task.rewards || []).map(r => ({
position: r.position,
project_name: r.project_name,
value: r.value,
use_progression: r.use_progression || false
})),
subtasks: (task.subtasks || []).map(st => ({
id: st.id,
name: st.name || null,
reward_message: st.reward_message || null,
rewards: (st.rewards || []).map(r => ({
position: r.position,
project_name: r.project_name,
value: r.value,
use_progression: r.use_progression || false
}))
}))
}
// Обновляем задачу, отвязывая от желания
const updateResponse = await authFetch(`/api/tasks/${wishlistItem.linked_task.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
}) })
if (!updateResponse.ok) { if (!deleteResponse.ok) {
const errorData = await updateResponse.json().catch(() => ({})) const errorData = await deleteResponse.json().catch(() => ({}))
throw new Error(errorData.message || errorData.error || 'Ошибка при отвязке задачи') throw new Error(errorData.message || errorData.error || 'Ошибка при удалении задачи')
} }
setToastMessage({ text: 'Задача отвязана от желания', type: 'success' }) setToastMessage({ text: 'Задача удалена', type: 'success' })
// Обновляем данные желания // Обновляем данные желания
fetchWishlistDetail() fetchWishlistDetail()
if (onRefresh) { if (onRefresh) {
onRefresh() onRefresh()
} }
} catch (err) { } catch (err) {
console.error('Error unlinking task:', err) console.error('Error deleting task:', err)
setToastMessage({ text: err.message || 'Ошибка при отвязке задачи', type: 'error' }) setToastMessage({ text: err.message || 'Ошибка при удалении задачи', type: 'error' })
} }
} }
@@ -461,11 +426,17 @@ function WishlistDetail({ wishlistId, onNavigate, onRefresh, boardId }) {
</div> </div>
<div className="task-actions"> <div className="task-actions">
<button <button
className="task-unlink-button" className="task-delete-button"
onClick={handleUnlinkTask} onClick={handleDeleteTask}
title="Отвязать от желания" title="Удалить задачу"
> >
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M3 6h18"></path>
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
</button> </button>
</div> </div>
</div> </div>