6.4.13: Фикс кнопки назад для диалога цели
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m5s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
poignatov
2026-03-09 22:08:24 +03:00
parent 17e6bbf9f1
commit 3a1b836ece
5 changed files with 79 additions and 26 deletions

View File

@@ -1 +1 @@
6.4.12 6.4.13

View File

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

View File

@@ -773,9 +773,10 @@ function AppContent() {
// Проверяем, есть ли открытые модальные окна в DOM // Проверяем, есть ли открытые модальные окна в DOM
const taskDetailModal = document.querySelector('.task-detail-modal-overlay') const taskDetailModal = document.querySelector('.task-detail-modal-overlay')
const wishlistDetailModal = document.querySelector('.wishlist-detail-modal-overlay') const wishlistDetailModal = document.querySelector('.wishlist-detail-modal-overlay')
const conditionFormOverlay = document.querySelector('.condition-form-overlay')
// Если есть открытые модальные окна, не обрабатываем здесь - компоненты сами закроют их // Если есть открытые модальные окна, не обрабатываем здесь - компоненты сами закроют их
if (taskDetailModal || wishlistDetailModal) { if (taskDetailModal || wishlistDetailModal || conditionFormOverlay) {
return return
} }
@@ -922,7 +923,7 @@ function AppContent() {
if (isNewTabDeep) { if (isNewTabDeep) {
// Проверяем, была ли последняя запись в истории от модального окна // Проверяем, была ли последняя запись в истории от модального окна
const currentState = window.history.state || {} const currentState = window.history.state || {}
const isFromModal = currentState.modalOpen === true const isFromModal = currentState.modalOpen === true || currentState.conditionForm === true
const isNavigatingToForm = tab === 'task-form' || tab === 'wishlist-form' || tab === 'shopping-item-form' const isNavigatingToForm = tab === 'task-form' || tab === 'wishlist-form' || tab === 'shopping-item-form'
if (isFromModal && isNavigatingToForm) { if (isFromModal && isNavigatingToForm) {

View File

@@ -768,11 +768,11 @@ function TaskForm({ onNavigate, taskId, wishlistId, isTest: isTestFromProps = fa
// Если был returnTo, возвращаемся на форму желания с ID новой задачи // Если был returnTo, возвращаемся на форму желания с ID новой задачи
if (returnTo === 'wishlist-form') { if (returnTo === 'wishlist-form') {
console.log('[TaskForm] Navigating back to wishlist-form with newTaskId:', newTaskId) console.log('[TaskForm] Saving newTaskId to sessionStorage and going back:', newTaskId)
onNavigate?.(returnTo, { // Сохраняем newTaskId в sessionStorage, чтобы WishlistForm мог его прочитать
wishlistId: returnWishlistId, sessionStorage.setItem('wishlistFormNewTaskId', String(newTaskId))
newTaskId: newTaskId, // Используем history.back() чтобы не создавать лишнюю запись в стеке
}) window.history.back()
} else { } else {
console.log('[TaskForm] No returnTo, going back in history') console.log('[TaskForm] No returnTo, going back in history')
// Возврат назад по стеку истории (на список задач, желаний и т.д.) // Возврат назад по стеку истории (на список задач, желаний и т.д.)

View File

@@ -9,8 +9,20 @@ const TASKS_API_URL = '/api/tasks'
const PROJECTS_API_URL = '/projects' const PROJECTS_API_URL = '/projects'
const WISHLIST_FORM_STATE_KEY = 'wishlistFormPendingState' const WISHLIST_FORM_STATE_KEY = 'wishlistFormPendingState'
function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, boardId }) { function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: newTaskIdProp, boardId }) {
const { authFetch, user } = useAuth() const { authFetch, user } = useAuth()
// newTaskId может прийти из props (через onNavigate) или из sessionStorage (через history.back)
const [newTaskId] = useState(() => {
if (newTaskIdProp) return newTaskIdProp
const stored = sessionStorage.getItem('wishlistFormNewTaskId')
if (stored) {
sessionStorage.removeItem('wishlistFormNewTaskId')
return parseInt(stored, 10)
}
return undefined
})
const [name, setName] = useState('') const [name, setName] = useState('')
const [price, setPrice] = useState('') const [price, setPrice] = useState('')
const [link, setLink] = useState('') const [link, setLink] = useState('')
@@ -33,10 +45,14 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
const [toastMessage, setToastMessage] = useState(null) const [toastMessage, setToastMessage] = useState(null)
const [loadingWishlist, setLoadingWishlist] = useState(false) const [loadingWishlist, setLoadingWishlist] = useState(false)
const [fetchingMetadata, setFetchingMetadata] = useState(false) const [fetchingMetadata, setFetchingMetadata] = useState(false)
const [restoredFromSession, setRestoredFromSession] = useState(false) // Флаг восстановления из sessionStorage const [restoredFromSession, setRestoredFromSession] = useState(() => {
// Инициализируем флаг сразу, чтобы loadWishlist не запустился до восстановления
return !!(newTaskId && sessionStorage.getItem(WISHLIST_FORM_STATE_KEY))
})
const [loadedWishlistData, setLoadedWishlistData] = useState(null) // Данные желания для последующего маппинга условий const [loadedWishlistData, setLoadedWishlistData] = useState(null) // Данные желания для последующего маппинга условий
const [imageUrlInput, setImageUrlInput] = useState('') // Ссылка на картинку для загрузки по URL const [imageUrlInput, setImageUrlInput] = useState('') // Ссылка на картинку для загрузки по URL
const [loadingImageFromUrl, setLoadingImageFromUrl] = useState(false) const [loadingImageFromUrl, setLoadingImageFromUrl] = useState(false)
const [newTaskConsumed, setNewTaskConsumed] = useState(false) // Флаг что newTaskId уже добавлен как цель
const fileInputRef = useRef(null) const fileInputRef = useRef(null)
// Загрузка задач, проектов и саджестов групп // Загрузка задач, проектов и саджестов групп
@@ -139,6 +155,24 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
} }
}, [editConditionIndex, unlockConditions]) }, [editConditionIndex, unlockConditions])
// Обработка кнопки "назад" для диалога ConditionForm
const showConditionFormRef = useRef(false)
const conditionClosedByPopStateRef = useRef(false)
showConditionFormRef.current = showConditionForm
useEffect(() => {
const handlePopState = () => {
if (showConditionFormRef.current) {
// Закрываем диалог — popstate уже убрал запись из стека
conditionClosedByPopStateRef.current = true
setShowConditionForm(false)
setEditingConditionIndex(null)
}
}
window.addEventListener('popstate', handlePopState)
return () => window.removeEventListener('popstate', handlePopState)
}, [])
// Восстановление состояния при возврате с создания задачи // Восстановление состояния при возврате с создания задачи
useEffect(() => { useEffect(() => {
const savedState = sessionStorage.getItem(WISHLIST_FORM_STATE_KEY) const savedState = sessionStorage.getItem(WISHLIST_FORM_STATE_KEY)
@@ -161,6 +195,9 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
const restoredConditions = state.unlockConditions || [] const restoredConditions = state.unlockConditions || []
console.log('[WishlistForm] Restored conditions:', restoredConditions) console.log('[WishlistForm] Restored conditions:', restoredConditions)
// Устанавливаем флаг синхронно, чтобы loadWishlist не перезаписал восстановленное состояние
setRestoredFromSession(true)
// Перезагружаем задачи, чтобы новая задача была в списке // Перезагружаем задачи, чтобы новая задача была в списке
const reloadTasks = async () => { const reloadTasks = async () => {
console.log('[WishlistForm] Reloading tasks...') console.log('[WishlistForm] Reloading tasks...')
@@ -199,12 +236,10 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
console.log('[WishlistForm] Adding new condition, final conditions:', finalConditions) console.log('[WishlistForm] Adding new condition, final conditions:', finalConditions)
setUnlockConditions(finalConditions) setUnlockConditions(finalConditions)
} }
setNewTaskConsumed(true)
} else { } else {
setUnlockConditions(restoredConditions) setUnlockConditions(restoredConditions)
} }
// Устанавливаем флаг, что состояние восстановлено
setRestoredFromSession(true)
} }
} catch (err) { } catch (err) {
console.error('[WishlistForm] Error reloading tasks:', err) console.error('[WishlistForm] Error reloading tasks:', err)
@@ -543,9 +578,25 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
} }
} }
const openConditionForm = () => {
setShowConditionForm(true)
conditionClosedByPopStateRef.current = false
window.history.pushState({ conditionForm: true }, '', window.location.href)
}
const closeConditionForm = () => {
setShowConditionForm(false)
setEditingConditionIndex(null)
// Если закрытие через popstate — запись уже убрана, не делаем back
if (!conditionClosedByPopStateRef.current) {
window.history.back()
}
conditionClosedByPopStateRef.current = false
}
const handleAddCondition = () => { const handleAddCondition = () => {
setEditingConditionIndex(null) setEditingConditionIndex(null)
setShowConditionForm(true) openConditionForm()
} }
const handleEditCondition = (index) => { const handleEditCondition = (index) => {
@@ -556,7 +607,7 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
return return
} }
setEditingConditionIndex(index) setEditingConditionIndex(index)
setShowConditionForm(true) openConditionForm()
} }
const handleConditionSubmit = (condition) => { const handleConditionSubmit = (condition) => {
@@ -569,13 +620,11 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
// Добавление нового условия // Добавление нового условия
setUnlockConditions([...unlockConditions, { ...condition, display_order: unlockConditions.length }]) setUnlockConditions([...unlockConditions, { ...condition, display_order: unlockConditions.length }])
} }
setShowConditionForm(false) closeConditionForm()
setEditingConditionIndex(null)
} }
const handleConditionCancel = () => { const handleConditionCancel = () => {
setShowConditionForm(false) closeConditionForm()
setEditingConditionIndex(null)
} }
const handleRemoveCondition = (index) => { const handleRemoveCondition = (index) => {
@@ -590,6 +639,9 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
// Обработчик для создания задачи из ConditionForm // Обработчик для создания задачи из ConditionForm
const handleCreateTaskFromCondition = () => { const handleCreateTaskFromCondition = () => {
// Закрываем диалог цели перед переходом
setShowConditionForm(false)
// Сохранить текущее состояние формы // Сохранить текущее состояние формы
const stateToSave = { const stateToSave = {
name, name,
@@ -987,7 +1039,7 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId, b
onCancel={handleConditionCancel} onCancel={handleConditionCancel}
editingCondition={editingConditionIndex !== null ? unlockConditions[editingConditionIndex] : null} editingCondition={editingConditionIndex !== null ? unlockConditions[editingConditionIndex] : null}
onCreateTask={handleCreateTaskFromCondition} onCreateTask={handleCreateTaskFromCondition}
preselectedTaskId={newTaskId} preselectedTaskId={newTaskConsumed ? undefined : newTaskId}
authFetch={authFetch} authFetch={authFetch}
/> />
)} )}