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.
Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit

This commit is contained in:
Primakov Alexandr Alexandrovich 2025-11-04 12:25:27 +03:00
parent 79e3dc9864
commit 25baea7447
2 changed files with 36 additions and 1 deletions

View File

@ -177,6 +177,8 @@ export const ChallengeProvider = ({ children }: PropsWithChildren) => {
if (isBrowser()) { if (isBrowser()) {
window.localStorage.removeItem(USER_ID_KEY) window.localStorage.removeItem(USER_ID_KEY)
window.localStorage.removeItem(USER_NICKNAME_KEY) window.localStorage.removeItem(USER_NICKNAME_KEY)
window.localStorage.removeItem('challengeSelectedChainId')
window.localStorage.removeItem('challengeSelectedTaskId')
} }
}, []) }, [])

View File

@ -12,8 +12,11 @@ import { Header } from '../../components/Header'
import { LoginForm } from '../../components/LoginForm' import { LoginForm } from '../../components/LoginForm'
import { ChainSelector } from '../../components/ChainSelector' import { ChainSelector } from '../../components/ChainSelector'
const SELECTED_CHAIN_KEY = 'challengeSelectedChainId'
const SELECTED_TASK_KEY = 'challengeSelectedTaskId'
export const MainPage = () => { export const MainPage = () => {
const { nickname, eventEmitter } = useChallenge() const { nickname, eventEmitter, chains } = useChallenge()
const [selectedChain, setSelectedChain] = useState<ChallengeChain | null>(null) const [selectedChain, setSelectedChain] = useState<ChallengeChain | null>(null)
const [selectedTask, setSelectedTask] = useState<ChallengeTask | null>(null) const [selectedTask, setSelectedTask] = useState<ChallengeTask | null>(null)
const [isOffline, setIsOffline] = useState(() => 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 [notification, setNotification] = useState<{ status: 'success' | 'warning'; title: string; description?: string } | null>(null)
const notificationTimeoutRef = useRef<number | null>(null) const notificationTimeoutRef = useRef<number | null>(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) => { const handleSelectChain = (chain: ChallengeChain) => {
setSelectedChain(chain) setSelectedChain(chain)
setSelectedTask(chain.tasks[0]) setSelectedTask(chain.tasks[0])
localStorage.setItem(SELECTED_CHAIN_KEY, chain.id)
localStorage.setItem(SELECTED_TASK_KEY, chain.tasks[0].id)
} }
const handleTaskComplete = () => { const handleTaskComplete = () => {
@ -34,10 +64,13 @@ export const MainPage = () => {
if (nextTask) { if (nextTask) {
setSelectedTask(nextTask) setSelectedTask(nextTask)
localStorage.setItem(SELECTED_TASK_KEY, nextTask.id)
} else { } else {
// Цепочка завершена, возвращаемся к выбору // Цепочка завершена, возвращаемся к выбору
setSelectedChain(null) setSelectedChain(null)
setSelectedTask(null) setSelectedTask(null)
localStorage.removeItem(SELECTED_CHAIN_KEY)
localStorage.removeItem(SELECTED_TASK_KEY)
} }
} }