From 25baea7447b21bfb205ad24ba586f656ef13a1a7 Mon Sep 17 00:00:00 2001 From: Primakov Alexandr Alexandrovich Date: Tue, 4 Nov 2025 12:25:27 +0300 Subject: [PATCH] Implement local storage management for selected chain and task in MainPage component. Add state restoration logic on component mount and ensure cleanup on task completion. This enhances user experience by preserving selections across sessions. --- src/context/ChallengeContext.tsx | 2 ++ src/pages/main/main.tsx | 35 +++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/context/ChallengeContext.tsx b/src/context/ChallengeContext.tsx index b46568f..0c3a4a6 100644 --- a/src/context/ChallengeContext.tsx +++ b/src/context/ChallengeContext.tsx @@ -177,6 +177,8 @@ export const ChallengeProvider = ({ children }: PropsWithChildren) => { if (isBrowser()) { window.localStorage.removeItem(USER_ID_KEY) window.localStorage.removeItem(USER_NICKNAME_KEY) + window.localStorage.removeItem('challengeSelectedChainId') + window.localStorage.removeItem('challengeSelectedTaskId') } }, []) diff --git a/src/pages/main/main.tsx b/src/pages/main/main.tsx index 2cc94cd..5f125b9 100644 --- a/src/pages/main/main.tsx +++ b/src/pages/main/main.tsx @@ -12,8 +12,11 @@ import { Header } from '../../components/Header' import { LoginForm } from '../../components/LoginForm' import { ChainSelector } from '../../components/ChainSelector' +const SELECTED_CHAIN_KEY = 'challengeSelectedChainId' +const SELECTED_TASK_KEY = 'challengeSelectedTaskId' + export const MainPage = () => { - const { nickname, eventEmitter } = useChallenge() + const { nickname, eventEmitter, chains } = useChallenge() const [selectedChain, setSelectedChain] = useState(null) const [selectedTask, setSelectedTask] = useState(null) const [isOffline, setIsOffline] = useState(() => @@ -21,10 +24,37 @@ export const MainPage = () => { ) const [notification, setNotification] = useState<{ status: 'success' | 'warning'; title: string; description?: string } | null>(null) const notificationTimeoutRef = useRef(null) + const hasRestoredState = useRef(false) + + // Восстановление состояния при загрузке + useEffect(() => { + if (hasRestoredState.current || !chains.length || !nickname) return + + const savedChainId = localStorage.getItem(SELECTED_CHAIN_KEY) + const savedTaskId = localStorage.getItem(SELECTED_TASK_KEY) + + if (savedChainId) { + const chain = chains.find(c => c.id === savedChainId) + if (chain) { + setSelectedChain(chain) + + if (savedTaskId) { + const task = chain.tasks.find(t => t.id === savedTaskId) + setSelectedTask(task || chain.tasks[0]) + } else { + setSelectedTask(chain.tasks[0]) + } + } + } + + hasRestoredState.current = true + }, [chains, nickname]) const handleSelectChain = (chain: ChallengeChain) => { setSelectedChain(chain) setSelectedTask(chain.tasks[0]) + localStorage.setItem(SELECTED_CHAIN_KEY, chain.id) + localStorage.setItem(SELECTED_TASK_KEY, chain.tasks[0].id) } const handleTaskComplete = () => { @@ -34,10 +64,13 @@ export const MainPage = () => { if (nextTask) { setSelectedTask(nextTask) + localStorage.setItem(SELECTED_TASK_KEY, nextTask.id) } else { // Цепочка завершена, возвращаемся к выбору setSelectedChain(null) setSelectedTask(null) + localStorage.removeItem(SELECTED_CHAIN_KEY) + localStorage.removeItem(SELECTED_TASK_KEY) } }