6.9.0: Задачи-закупки
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m20s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m20s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import ShoppingItemForm from './components/ShoppingItemForm'
|
||||
import ShoppingBoardForm from './components/ShoppingBoardForm'
|
||||
import ShoppingBoardJoinPreview from './components/ShoppingBoardJoinPreview'
|
||||
import ShoppingItemHistory from './components/ShoppingItemHistory'
|
||||
import PurchaseScreen from './components/PurchaseScreen'
|
||||
import TodoistIntegration from './components/TodoistIntegration'
|
||||
import TelegramIntegration from './components/TelegramIntegration'
|
||||
import FitbitIntegration from './components/FitbitIntegration'
|
||||
@@ -35,7 +36,7 @@ const FULL_STATISTICS_API_URL = '/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b'
|
||||
|
||||
// Определяем основные табы (без крестика) и глубокие табы (с крестиком)
|
||||
const mainTabs = ['current', 'tasks', 'wishlist', 'shopping', 'profile']
|
||||
const deepTabs = ['add-words', 'test', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
const deepTabs = ['add-words', 'test', 'purchase', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
|
||||
/**
|
||||
* Гарантирует базовую запись истории для главного экрана перед глубоким табом.
|
||||
@@ -87,6 +88,7 @@ function AppContent() {
|
||||
'shopping-board-form': false,
|
||||
'shopping-board-join': false,
|
||||
'shopping-item-history': false,
|
||||
purchase: false,
|
||||
})
|
||||
|
||||
// Отслеживаем, какие табы уже были загружены (для предотвращения повторных загрузок)
|
||||
@@ -117,6 +119,7 @@ function AppContent() {
|
||||
'shopping-board-form': false,
|
||||
'shopping-board-join': false,
|
||||
'shopping-item-history': false,
|
||||
purchase: false,
|
||||
})
|
||||
|
||||
// Параметры для навигации между вкладками
|
||||
@@ -295,7 +298,7 @@ function AppContent() {
|
||||
|
||||
// Проверяем URL только для глубоких табов
|
||||
const tabFromUrl = urlParams.get('tab')
|
||||
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'profile', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'purchase', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'profile', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
|
||||
if (tabFromUrl && validTabs.includes(tabFromUrl) && deepTabs.includes(tabFromUrl) && window.history.length > 1) {
|
||||
// Восстанавливаем глубокий таб из URL только если есть история (не рестарт PWA)
|
||||
@@ -792,7 +795,7 @@ function AppContent() {
|
||||
return
|
||||
}
|
||||
|
||||
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'profile', 'todoist-integration', 'telegram-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'purchase', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'profile', 'todoist-integration', 'telegram-integration', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
|
||||
|
||||
// Проверяем state текущей записи истории (куда мы вернулись)
|
||||
if (event.state && event.state.tab) {
|
||||
@@ -909,7 +912,7 @@ function AppContent() {
|
||||
{
|
||||
// Для task-form и wishlist-form явно удаляем параметры, только если нет никаких параметров
|
||||
// task-form может иметь taskId (редактирование), wishlistId (создание из желания), returnTo (возврат после создания), или isTest (создание теста)
|
||||
const isTaskFormWithNoParams = tab === 'task-form' && params.taskId === undefined && params.wishlistId === undefined && params.returnTo === undefined && params.isTest === undefined
|
||||
const isTaskFormWithNoParams = tab === 'task-form' && params.taskId === undefined && params.wishlistId === undefined && params.returnTo === undefined && params.isTest === undefined && params.isPurchase === undefined
|
||||
// Проверяем, что boardId не null и не undefined (null означает "нет доски", но это валидное значение)
|
||||
const hasBoardId = params.boardId !== null && params.boardId !== undefined
|
||||
const isWishlistFormWithNoParams = tab === 'wishlist-form' && params.wishlistId === undefined && params.newTaskId === undefined && !hasBoardId
|
||||
@@ -976,7 +979,7 @@ function AppContent() {
|
||||
}
|
||||
// Обновляем список задач при возврате из экрана редактирования или теста
|
||||
// Используем фоновую загрузку, чтобы не показывать индикатор загрузки
|
||||
if ((activeTab === 'task-form' || activeTab === 'test') && tab === 'tasks') {
|
||||
if ((activeTab === 'task-form' || activeTab === 'test' || activeTab === 'purchase') && tab === 'tasks') {
|
||||
fetchTasksData(true)
|
||||
}
|
||||
// Сохраняем предыдущий таб при открытии wishlist-form или wishlist-detail
|
||||
@@ -1037,6 +1040,11 @@ function AppContent() {
|
||||
handleNavigate('task-form', { taskId: undefined, isTest: true })
|
||||
}
|
||||
|
||||
const handleAddPurchase = () => {
|
||||
setShowAddModal(false)
|
||||
handleNavigate('task-form', { taskId: undefined, isPurchase: true })
|
||||
}
|
||||
|
||||
// Обработчик навигации для компонентов
|
||||
const handleNavigate = (tab, params = {}, options = {}) => {
|
||||
handleTabChange(tab, params, options)
|
||||
@@ -1116,7 +1124,7 @@ function AppContent() {
|
||||
}
|
||||
|
||||
// Определяем, нужно ли скрывать нижнюю панель (для fullscreen экранов)
|
||||
const isFullscreenTab = activeTab === 'test' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'fitbit-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'words' || activeTab === 'dictionaries' || activeTab === 'tracking' || activeTab === 'tracking-access' || activeTab === 'tracking-invite' || activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form' || activeTab === 'shopping-board-join' || activeTab === 'shopping-item-history'
|
||||
const isFullscreenTab = activeTab === 'test' || activeTab === 'purchase' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'fitbit-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'words' || activeTab === 'dictionaries' || activeTab === 'tracking' || activeTab === 'tracking-access' || activeTab === 'tracking-invite' || activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form' || activeTab === 'shopping-board-join' || activeTab === 'shopping-item-history'
|
||||
|
||||
// Функция для получения классов скролл-контейнера для каждого таба
|
||||
// Каждый таб имеет свой изолированный скролл-контейнер для автоматического сохранения позиции скролла
|
||||
@@ -1145,7 +1153,7 @@ function AppContent() {
|
||||
if (tabName === 'current') {
|
||||
return 'max-w-7xl mx-auto p-4 md:p-6'
|
||||
}
|
||||
if (tabName === 'full' || tabName === 'priorities' || tabName === 'dictionaries' || tabName === 'words' || tabName === 'shopping-item-history') {
|
||||
if (tabName === 'full' || tabName === 'priorities' || tabName === 'dictionaries' || tabName === 'words' || tabName === 'shopping-item-history' || tabName === 'purchase') {
|
||||
return 'max-w-7xl mx-auto px-4 md:px-8 py-0'
|
||||
}
|
||||
// Fullscreen табы без отступов
|
||||
@@ -1257,7 +1265,7 @@ function AppContent() {
|
||||
{loadedTabs.test && (
|
||||
<div className={getTabContainerClasses('test')}>
|
||||
<div className={getInnerContainerClasses('test')}>
|
||||
<TestWords
|
||||
<TestWords
|
||||
onNavigate={handleNavigate}
|
||||
wordCount={tabParams.wordCount}
|
||||
configId={tabParams.configId}
|
||||
@@ -1268,6 +1276,19 @@ function AppContent() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loadedTabs.purchase && (
|
||||
<div className={getTabContainerClasses('purchase')}>
|
||||
<div className={getInnerContainerClasses('purchase')}>
|
||||
<PurchaseScreen
|
||||
onNavigate={handleNavigate}
|
||||
purchaseConfigId={tabParams.purchaseConfigId}
|
||||
taskId={tabParams.taskId}
|
||||
taskName={tabParams.taskName}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loadedTabs.tasks && (
|
||||
<div className={getTabContainerClasses('tasks')}>
|
||||
<div className={getInnerContainerClasses('tasks')}>
|
||||
@@ -1293,6 +1314,7 @@ function AppContent() {
|
||||
taskId={tabParams.taskId}
|
||||
wishlistId={tabParams.wishlistId}
|
||||
isTest={tabParams.isTest}
|
||||
isPurchase={tabParams.isPurchase}
|
||||
returnTo={tabParams.returnTo}
|
||||
returnWishlistId={tabParams.returnWishlistId}
|
||||
/>
|
||||
@@ -1787,6 +1809,17 @@ function AppContent() {
|
||||
</svg>
|
||||
Тест
|
||||
</button>
|
||||
<button
|
||||
className="task-add-modal-button task-add-modal-button-purchase"
|
||||
onClick={handleAddPurchase}
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="9" cy="21" r="1"></circle>
|
||||
<circle cx="20" cy="21" r="1"></circle>
|
||||
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
|
||||
</svg>
|
||||
Закупка
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user