Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit
205 lines
7.1 KiB
TypeScript
205 lines
7.1 KiB
TypeScript
/**
|
||
* Централизованная работа с localStorage
|
||
* Все ключи и операции в одном месте
|
||
*/
|
||
|
||
import { clearAllFinalAnswers, listDrafts, clearDraft } from './drafts'
|
||
|
||
const isBrowser = () => typeof window !== 'undefined'
|
||
|
||
// Ключи localStorage
|
||
export const STORAGE_KEYS = {
|
||
USER_ID: 'challengeUserId',
|
||
NICKNAME: 'challengeNickname',
|
||
WORKPLACE_NUMBER: 'challengeWorkplaceNumber',
|
||
SELECTED_CHAIN_ID: 'challengeSelectedChainId',
|
||
SELECTED_TASK_ID: 'challengeSelectedTaskId',
|
||
} as const
|
||
|
||
// Вспомогательные функции для ключей
|
||
const getFurthestTaskKey = (chainId: string) => `challengeFurthestTask_${chainId}`
|
||
const getSkippedTasksKey = (chainId: string) => `challengeSkippedTasks_${chainId}`
|
||
|
||
// Получение значений
|
||
export const storage = {
|
||
getUserId: (): string | null => {
|
||
if (!isBrowser()) return null
|
||
return localStorage.getItem(STORAGE_KEYS.USER_ID)
|
||
},
|
||
|
||
getNickname: (): string | null => {
|
||
if (!isBrowser()) return null
|
||
return localStorage.getItem(STORAGE_KEYS.NICKNAME)
|
||
},
|
||
|
||
getWorkplaceNumber: (): string | null => {
|
||
if (!isBrowser()) return null
|
||
return localStorage.getItem(STORAGE_KEYS.WORKPLACE_NUMBER)
|
||
},
|
||
|
||
getSelectedChainId: (): string | null => {
|
||
if (!isBrowser()) return null
|
||
return localStorage.getItem(STORAGE_KEYS.SELECTED_CHAIN_ID)
|
||
},
|
||
|
||
getSelectedTaskId: (): string | null => {
|
||
if (!isBrowser()) return null
|
||
return localStorage.getItem(STORAGE_KEYS.SELECTED_TASK_ID)
|
||
},
|
||
|
||
// Установка значений
|
||
setUserId: (value: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.setItem(STORAGE_KEYS.USER_ID, value)
|
||
},
|
||
|
||
setNickname: (value: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.setItem(STORAGE_KEYS.NICKNAME, value)
|
||
},
|
||
|
||
setWorkplaceNumber: (value: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.setItem(STORAGE_KEYS.WORKPLACE_NUMBER, value)
|
||
},
|
||
|
||
setSelectedChainId: (value: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.setItem(STORAGE_KEYS.SELECTED_CHAIN_ID, value)
|
||
},
|
||
|
||
setSelectedTaskId: (value: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.setItem(STORAGE_KEYS.SELECTED_TASK_ID, value)
|
||
},
|
||
|
||
// Удаление значений
|
||
removeUserId: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.USER_ID)
|
||
},
|
||
|
||
removeNickname: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.NICKNAME)
|
||
},
|
||
|
||
removeWorkplaceNumber: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.WORKPLACE_NUMBER)
|
||
},
|
||
|
||
removeSelectedChainId: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_CHAIN_ID)
|
||
},
|
||
|
||
removeSelectedTaskId: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_TASK_ID)
|
||
},
|
||
|
||
// Полная очистка при выходе (кроме номера рабочего места)
|
||
clearAll: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.USER_ID)
|
||
localStorage.removeItem(STORAGE_KEYS.NICKNAME)
|
||
// Номер рабочего места НЕ удаляем
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_CHAIN_ID)
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_TASK_ID)
|
||
|
||
// Очищаем все прогрессы по цепочкам
|
||
storage.clearAllChainProgress()
|
||
|
||
// Очищаем все финальные ответы
|
||
clearAllFinalAnswers()
|
||
|
||
// Очищаем все черновики
|
||
const drafts = listDrafts()
|
||
drafts.forEach(taskId => clearDraft(taskId))
|
||
},
|
||
|
||
// Очистка всех прогрессов по цепочкам
|
||
clearAllChainProgress: (): void => {
|
||
if (!isBrowser()) return
|
||
// Перебираем все ключи localStorage и удаляем те, что начинаются с challengeFurthestTask_ или challengeSkippedTasks_
|
||
const keysToRemove: string[] = []
|
||
for (let i = 0; i < localStorage.length; i++) {
|
||
const key = localStorage.key(i)
|
||
if (key && (key.startsWith('challengeFurthestTask_') || key.startsWith('challengeSkippedTasks_'))) {
|
||
keysToRemove.push(key)
|
||
}
|
||
}
|
||
keysToRemove.forEach(key => localStorage.removeItem(key))
|
||
},
|
||
|
||
// Очистка данных сессии (цепочка, задание) без выхода
|
||
clearSessionData: (): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_CHAIN_ID)
|
||
localStorage.removeItem(STORAGE_KEYS.SELECTED_TASK_ID)
|
||
},
|
||
|
||
// Получение самого дальнего достигнутого индекса задания в цепочке
|
||
getFurthestTaskIndex: (chainId: string): number => {
|
||
if (!isBrowser()) return 0
|
||
const value = localStorage.getItem(getFurthestTaskKey(chainId))
|
||
return value ? parseInt(value, 10) : 0
|
||
},
|
||
|
||
// Установка самого дальнего достигнутого индекса задания
|
||
setFurthestTaskIndex: (chainId: string, index: number): void => {
|
||
if (!isBrowser()) return
|
||
const current = storage.getFurthestTaskIndex(chainId)
|
||
// Обновляем только если новый индекс больше текущего
|
||
if (index > current) {
|
||
localStorage.setItem(getFurthestTaskKey(chainId), index.toString())
|
||
}
|
||
},
|
||
|
||
// Очистка прогресса цепочки
|
||
clearChainProgress: (chainId: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(getFurthestTaskKey(chainId))
|
||
},
|
||
|
||
// Получение пропущенных заданий для цепочки
|
||
getSkippedTasks: (chainId: string): string[] => {
|
||
if (!isBrowser()) return []
|
||
const value = localStorage.getItem(getSkippedTasksKey(chainId))
|
||
return value ? JSON.parse(value) : []
|
||
},
|
||
|
||
// Добавление задания в список пропущенных
|
||
addSkippedTask: (chainId: string, taskId: string): void => {
|
||
if (!isBrowser()) return
|
||
const skipped = storage.getSkippedTasks(chainId)
|
||
if (!skipped.includes(taskId)) {
|
||
skipped.push(taskId)
|
||
localStorage.setItem(getSkippedTasksKey(chainId), JSON.stringify(skipped))
|
||
}
|
||
},
|
||
|
||
// Удаление задания из списка пропущенных (когда оно выполнено)
|
||
removeSkippedTask: (chainId: string, taskId: string): void => {
|
||
if (!isBrowser()) return
|
||
const skipped = storage.getSkippedTasks(chainId)
|
||
const filtered = skipped.filter(id => id !== taskId)
|
||
localStorage.setItem(getSkippedTasksKey(chainId), JSON.stringify(filtered))
|
||
},
|
||
|
||
// Проверка, пропущено ли задание
|
||
isTaskSkipped: (chainId: string, taskId: string): boolean => {
|
||
if (!isBrowser()) return false
|
||
const skipped = storage.getSkippedTasks(chainId)
|
||
return skipped.includes(taskId)
|
||
},
|
||
|
||
// Очистка всех пропущенных заданий цепочки
|
||
clearSkippedTasks: (chainId: string): void => {
|
||
if (!isBrowser()) return
|
||
localStorage.removeItem(getSkippedTasksKey(chainId))
|
||
},
|
||
}
|
||
|