Доски желаний и политика награждения
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m0s

This commit is contained in:
poignatov
2026-01-13 22:35:01 +03:00
parent 5ebb55510e
commit f9928c6470
19 changed files with 3662 additions and 198 deletions

View File

@@ -12,6 +12,8 @@ import TaskForm from './components/TaskForm.jsx'
import Wishlist from './components/Wishlist'
import WishlistForm from './components/WishlistForm'
import WishlistDetail from './components/WishlistDetail'
import BoardForm from './components/BoardForm'
import BoardJoinPreview from './components/BoardJoinPreview'
import TodoistIntegration from './components/TodoistIntegration'
import TelegramIntegration from './components/TelegramIntegration'
import { AuthProvider, useAuth } from './components/auth/AuthContext'
@@ -24,7 +26,7 @@ const FULL_STATISTICS_API_URL = '/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b'
// Определяем основные табы (без крестика) и глубокие табы (с крестиком)
const mainTabs = ['current', 'tasks', 'wishlist', 'profile']
const deepTabs = ['add-words', 'test', 'task-form', 'wishlist-form', 'wishlist-detail', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'full', 'priorities']
const deepTabs = ['add-words', 'test', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'full', 'priorities']
function AppContent() {
const { authFetch, isAuthenticated, loading: authLoading } = useAuth()
@@ -57,6 +59,8 @@ function AppContent() {
wishlist: false,
'wishlist-form': false,
'wishlist-detail': false,
'board-form': false,
'board-join': false,
profile: false,
'todoist-integration': false,
'telegram-integration': false,
@@ -76,6 +80,8 @@ function AppContent() {
wishlist: false,
'wishlist-form': false,
'wishlist-detail': false,
'board-form': false,
'board-join': false,
profile: false,
'todoist-integration': false,
'telegram-integration': false,
@@ -122,10 +128,25 @@ function AppContent() {
if (isInitialized) return
try {
// Проверяем путь /invite/:token для присоединения к доске
const path = window.location.pathname
if (path.startsWith('/invite/')) {
const token = path.replace('/invite/', '')
if (token) {
setActiveTab('board-join')
setLoadedTabs(prev => ({ ...prev, 'board-join': true }))
setTabParams({ inviteToken: token })
setIsInitialized(true)
// Очищаем путь, оставляем только параметры
window.history.replaceState({}, '', '/?tab=board-join&inviteToken=' + token)
return
}
}
// Проверяем URL только для глубоких табов
const urlParams = new URLSearchParams(window.location.search)
const tabFromUrl = urlParams.get('tab')
const validTabs = ['current', 'priorities', 'full', 'words', 'add-words', 'dictionaries', 'test', 'tasks', 'task-form', 'wishlist', 'wishlist-form', 'wishlist-detail', 'profile', 'todoist-integration', 'telegram-integration']
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']
if (tabFromUrl && validTabs.includes(tabFromUrl) && deepTabs.includes(tabFromUrl)) {
// Если в URL есть глубокий таб, восстанавливаем его
@@ -616,7 +637,7 @@ function AppContent() {
// Для task-form и wishlist-form явно удаляем параметры, только если нет никаких параметров
// task-form может иметь taskId (редактирование), wishlistId (создание из желания), или returnTo (возврат после создания)
const isTaskFormWithNoParams = tab === 'task-form' && params.taskId === undefined && params.wishlistId === undefined && params.returnTo === undefined
const isWishlistFormWithNoParams = tab === 'wishlist-form' && params.wishlistId === undefined && params.newTaskId === undefined
const isWishlistFormWithNoParams = tab === 'wishlist-form' && params.wishlistId === undefined && params.newTaskId === undefined && params.boardId === undefined
if (isTaskFormWithNoParams || isWishlistFormWithNoParams) {
setTabParams({})
if (isNewTabMain) {
@@ -655,7 +676,12 @@ function AppContent() {
}
// Обновляем список желаний при возврате из экрана редактирования
if (activeTab === 'wishlist-form' && tab === 'wishlist') {
setTabParams({}) // Очищаем параметры при закрытии формы
// Сохраняем boardId из параметров или текущих tabParams
const savedBoardId = params.boardId || tabParams.boardId
// Параметры уже установлены в строке 649, но мы можем их обновить, чтобы сохранить boardId
if (savedBoardId) {
setTabParams(prev => ({ ...prev, boardId: savedBoardId }))
}
setWishlistRefreshTrigger(prev => prev + 1)
}
// Загрузка данных произойдет в useEffect при изменении activeTab
@@ -859,6 +885,8 @@ function AppContent() {
onNavigate={handleNavigate}
refreshTrigger={wishlistRefreshTrigger}
isActive={activeTab === 'wishlist'}
initialBoardId={tabParams.boardId}
boardDeleted={tabParams.boardDeleted}
/>
</div>
)}
@@ -866,11 +894,12 @@ function AppContent() {
{loadedTabs['wishlist-form'] && (
<div className={activeTab === 'wishlist-form' ? 'block' : 'hidden'}>
<WishlistForm
key={`${tabParams.wishlistId || 'new'}-${tabParams.editConditionIndex ?? ''}-${tabParams.newTaskId ?? ''}`}
key={`${tabParams.wishlistId || 'new'}-${tabParams.editConditionIndex ?? ''}-${tabParams.newTaskId ?? ''}-${tabParams.boardId ?? ''}`}
onNavigate={handleNavigate}
wishlistId={tabParams.wishlistId}
editConditionIndex={tabParams.editConditionIndex}
newTaskId={tabParams.newTaskId}
boardId={tabParams.boardId}
/>
</div>
)}
@@ -886,6 +915,27 @@ function AppContent() {
</div>
)}
{loadedTabs['board-form'] && (
<div className={activeTab === 'board-form' ? 'block' : 'hidden'}>
<BoardForm
key={tabParams.boardId || 'new'}
onNavigate={handleNavigate}
boardId={tabParams.boardId}
onSaved={() => setWishlistRefreshTrigger(prev => prev + 1)}
/>
</div>
)}
{loadedTabs['board-join'] && (
<div className={activeTab === 'board-join' ? 'block' : 'hidden'}>
<BoardJoinPreview
key={tabParams.inviteToken}
onNavigate={handleNavigate}
inviteToken={tabParams.inviteToken}
/>
</div>
)}
{loadedTabs.profile && (
<div className={activeTab === 'profile' ? 'block' : 'hidden'}>
<Profile onNavigate={handleNavigate} />