From 31724fa88c758a14fa0cdf8b176dcd71a7f64296 Mon Sep 17 00:00:00 2001 From: AzenKain Date: Fri, 25 Jul 2025 12:17:01 +0700 Subject: [PATCH] FIX: fix bug not create avatar --- src/components/avatarBar/index.tsx | 4 ++- src/helper/converterToAvatarStore.ts | 7 +++--- src/helper/getAvatarNotExist.ts | 15 ----------- src/helper/getSkillTree.ts | 5 ++-- src/helper/index.ts | 1 - src/helper/random.ts | 6 ++--- src/hooks/useFetchAvatarData.ts | 37 +++++++++++++++++++--------- src/stores/affixStore.ts | 2 +- src/stores/copyProfile.ts | 2 +- src/stores/freesrStore.ts | 2 +- src/stores/globalStore.ts | 2 +- src/stores/mazeStore.ts | 2 +- src/stores/userDataStore.ts | 3 ++- 13 files changed, 44 insertions(+), 44 deletions(-) delete mode 100644 src/helper/getAvatarNotExist.ts diff --git a/src/components/avatarBar/index.tsx b/src/components/avatarBar/index.tsx index 84c4d02..386c278 100644 --- a/src/components/avatarBar/index.tsx +++ b/src/components/avatarBar/index.tsx @@ -7,13 +7,14 @@ import useAvatarStore from "@/stores/avatarStore" import { useTranslations } from "next-intl" import { useFetchASData, useFetchAvatarData, useFetchConfigData, useFetchLightconeData, useFetchMOCData, useFetchMonsterData, useFetchPFData, useFetchRelicData } from "@/hooks" + export default function AvatarBar() { const [listElement, setListElement] = useState>({ "fire": false, "ice": false, "imaginary": false, "physical": false, "quantum": false, "thunder": false, "wind": false }) const [listPath, setListPath] = useState>({ "knight": false, "mage": false, "priest": false, "rogue": false, "shaman": false, "warlock": false, "warrior": false, "memory": false }) const { listAvatar, setAvatarSelected, setFilter, filter } = useAvatarStore() const transI18n = useTranslations("DataPage") const { locale } = useLocaleStore() - + useFetchConfigData() useFetchAvatarData() useFetchLightconeData() @@ -28,6 +29,7 @@ export default function AvatarBar() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [locale, listElement, listPath]) + return (
diff --git a/src/helper/converterToAvatarStore.ts b/src/helper/converterToAvatarStore.ts index cbe470b..a318d18 100644 --- a/src/helper/converterToAvatarStore.ts +++ b/src/helper/converterToAvatarStore.ts @@ -1,6 +1,7 @@ -import { AvatarEnkaDetail, AvatarProfileStore, AvatarStore, CharacterDetail, EnkaResponse, FreeSRJson, RelicStore } from "@/types"; +import { AvatarEnkaDetail, AvatarProfileStore, AvatarStore, CharacterDetail, FreeSRJson, RelicStore } from "@/types"; -function safeNumber(val: any, fallback = 0): number { +function safeNumber(val: string | number | null, fallback = 0): number { + if (!val) return fallback; const num = Number(val); return Number.isFinite(num) && num !== 0 ? num : fallback; } @@ -14,7 +15,7 @@ export function converterToAvatarStore(data: Record): { avatar_id: Number(key), data: { rank: 0, - skills: Object.entries(value.SkillTrees).reduce((acc, [pointName, dataPointEntry]) => { + skills: Object.values(value.SkillTrees).reduce((acc, dataPointEntry) => { const firstEntry = Object.values(dataPointEntry)[0]; if (firstEntry) { acc[firstEntry.PointID] = firstEntry.MaxLevel; diff --git a/src/helper/getAvatarNotExist.ts b/src/helper/getAvatarNotExist.ts deleted file mode 100644 index 729954a..0000000 --- a/src/helper/getAvatarNotExist.ts +++ /dev/null @@ -1,15 +0,0 @@ - -import useUserDataStore from "@/stores/userDataStore"; -import useAvatarStore from "@/stores/avatarStore"; -import { CharacterDetail } from "@/types"; - -export function getAvatarNotExist(): Record { - const { avatars } = useUserDataStore.getState() - const { mapAvatarInfo } = useAvatarStore.getState() - const listAvatarId = Object.keys(avatars) - const listAvatarNotExist = Object.keys(mapAvatarInfo).filter((avatarId) => !listAvatarId.includes(avatarId)) - return listAvatarNotExist.reduce((acc, avatarId) => { - acc[avatarId] = mapAvatarInfo[avatarId] - return acc - }, {} as Record) -} diff --git a/src/helper/getSkillTree.ts b/src/helper/getSkillTree.ts index 82959c9..1c6d01c 100644 --- a/src/helper/getSkillTree.ts +++ b/src/helper/getSkillTree.ts @@ -1,11 +1,10 @@ import useAvatarStore from "@/stores/avatarStore" -import useUserDataStore from "@/stores/userDataStore" export function getSkillTree(enhanced: string) { const { avatarSelected, mapAvatarInfo } = useAvatarStore.getState() if (!avatarSelected) return null; - if (enhanced != "") return Object.entries(mapAvatarInfo[avatarSelected.id || ""]?.Enhanced[enhanced].SkillTrees || {}).reduce((acc, [pointName, dataPointEntry]) => { + if (enhanced != "") return Object.values(mapAvatarInfo[avatarSelected.id || ""]?.Enhanced[enhanced].SkillTrees || {}).reduce((acc, dataPointEntry) => { const firstEntry = Object.values(dataPointEntry)[0]; if (firstEntry) { acc[firstEntry.PointID] = firstEntry.MaxLevel; @@ -13,7 +12,7 @@ export function getSkillTree(enhanced: string) { return acc; }, {} as Record) - return Object.entries(mapAvatarInfo[avatarSelected.id || ""]?.SkillTrees).reduce((acc, [pointName, dataPointEntry]) => { + return Object.values(mapAvatarInfo[avatarSelected.id || ""]?.SkillTrees).reduce((acc, dataPointEntry) => { const firstEntry = Object.values(dataPointEntry)[0]; if (firstEntry) { acc[firstEntry.PointID] = firstEntry.MaxLevel; diff --git a/src/helper/index.ts b/src/helper/index.ts index d45b19f..ba8080d 100644 --- a/src/helper/index.ts +++ b/src/helper/index.ts @@ -1,7 +1,6 @@ export * from "./getName" export * from "./replaceByParam" export * from "./converterToAvatarStore" -export * from "./getAvatarNotExist" export * from "./calcData" export * from "./random" export * from "./json" diff --git a/src/helper/random.ts b/src/helper/random.ts index b098937..206575a 100644 --- a/src/helper/random.ts +++ b/src/helper/random.ts @@ -1,7 +1,7 @@ export function randomPartition(sum: number, parts: number): number[] { - let raw = Array.from({ length: parts }, () => Math.random()); - let total = raw.reduce((a, b) => a + b, 0); - let result = raw.map(r => Math.floor((r / total) * (sum - parts)) + 1); + const raw = Array.from({ length: parts }, () => Math.random()); + const total = raw.reduce((a, b) => a + b, 0); + const result = raw.map(r => Math.floor((r / total) * (sum - parts)) + 1); let diff = sum - result.reduce((a, b) => a + b, 0); while (diff !== 0) { for (let i = 0; i < result.length && diff !== 0; i++) { diff --git a/src/hooks/useFetchAvatarData.ts b/src/hooks/useFetchAvatarData.ts index 9e1883c..3ddb293 100644 --- a/src/hooks/useFetchAvatarData.ts +++ b/src/hooks/useFetchAvatarData.ts @@ -6,12 +6,13 @@ import { toast } from 'react-toastify' import useAvatarStore from '@/stores/avatarStore' import { listCurrentLanguageApi } from '@/lib/constant' import useLocaleStore from '@/stores/localeStore' -import { converterToAvatarStore, getAvatarNotExist } from '@/helper' import useUserDataStore from '@/stores/userDataStore' +import { converterToAvatarStore } from '@/helper' +import { CharacterDetail } from '@/types' export const useFetchAvatarData = () => { const { setAvatars, avatars } = useUserDataStore() - const { setListAvatar, setAllMapAvatarInfo, setAvatarSelected } = useAvatarStore() + const { setListAvatar, setAllMapAvatarInfo, mapAvatarInfo, setAvatarSelected } = useAvatarStore() const { locale } = useLocaleStore() const { data: dataAvatar, error: errorAvatar } = useQuery({ queryKey: ['avatarData'], @@ -27,25 +28,37 @@ export const useFetchAvatarData = () => { staleTime: 1000 * 60 * 5, }) + + useEffect(() => { + const listAvatarId = Object.keys(avatars) + const listAvatarNotExist = Object.keys(mapAvatarInfo).filter((avatarId) => !listAvatarId.includes(avatarId)) + const avatarDiff = listAvatarNotExist.reduce((acc, avatarId) => { + acc[avatarId] = mapAvatarInfo[avatarId] + return acc + }, {} as Record) + const avatarStore = converterToAvatarStore(avatarDiff) + if (Object.keys(avatarStore).length === 0) return + + setAvatars({...avatarStore }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [mapAvatarInfo]) + const { data: dataAvatarInfo, error: errorAvatarInfo } = useQuery({ queryKey: ['avatarInfoData', locale], queryFn: () => - fetchCharactersByIdsNative( - dataAvatar!.map((item) => item.id), - listCurrentLanguageApi[locale.toLowerCase()] - ), + fetchCharactersByIdsNative( + dataAvatar!.map((item) => item.id), + listCurrentLanguageApi[locale.toLowerCase()] + ), staleTime: 1000 * 60 * 5, enabled: !!dataAvatar, - }); + }); useEffect(() => { if (dataAvatar && !errorAvatar) { setListAvatar(dataAvatar) setAvatarSelected(dataAvatar[0]) - const avatarStore = converterToAvatarStore(getAvatarNotExist()) - if (Object.keys(avatarStore).length > 0) { - setAvatars({ ...avatars, ...avatarStore }) - } + } else if (errorAvatar) { toast.error("Failed to load avatar data") } @@ -57,5 +70,5 @@ export const useFetchAvatarData = () => { } else if (errorAvatarInfo) { toast.error("Failed to load avatar info data") } - }, [dataAvatarInfo, errorAvatarInfo, setAllMapAvatarInfo]) + }, [dataAvatarInfo, errorAvatarInfo, setAllMapAvatarInfo, setAvatars]) } diff --git a/src/stores/affixStore.ts b/src/stores/affixStore.ts index cea2f4f..e9436ea 100644 --- a/src/stores/affixStore.ts +++ b/src/stores/affixStore.ts @@ -8,7 +8,7 @@ interface AffixState { setMapSubAffix: (newSubAffix: Record>) => void; } -const useAffixStore = create((set, get) => ({ +const useAffixStore = create((set) => ({ mapMainAffix: {}, mapSubAffix: {}, setMapMainAffix: (newMainAffix: Record>) => set({ mapMainAffix: newMainAffix }), diff --git a/src/stores/copyProfile.ts b/src/stores/copyProfile.ts index d601085..f890506 100644 --- a/src/stores/copyProfile.ts +++ b/src/stores/copyProfile.ts @@ -1,4 +1,4 @@ -import { AvatarDataStore, AvatarProfileCardType, CharacterBasic, CharacterInfoCardType, EnkaResponse, FilterAvatarType } from '@/types'; +import { AvatarProfileCardType, CharacterBasic, FilterAvatarType } from '@/types'; import { create } from 'zustand' interface CopyProfileState { diff --git a/src/stores/freesrStore.ts b/src/stores/freesrStore.ts index 84026ee..47bc707 100644 --- a/src/stores/freesrStore.ts +++ b/src/stores/freesrStore.ts @@ -8,7 +8,7 @@ interface FreeSRState { setFreeSRData: (newFreeSRData: FreeSRJson | null) => void; } -const useFreeSRStore = create((set, get) => ({ +const useFreeSRStore = create((set) => ({ selectedCharacters: [], freeSRData: null, setSelectedCharacters: (newListAvatar: CharacterInfoCardType[]) => set({ selectedCharacters: newListAvatar }), diff --git a/src/stores/globalStore.ts b/src/stores/globalStore.ts index 0ab05bc..df5dfd4 100644 --- a/src/stores/globalStore.ts +++ b/src/stores/globalStore.ts @@ -5,7 +5,7 @@ interface GlobalState { setIsConnectPS: (newIsConnectPS: boolean) => void; } -const useGlobalStore = create((set, get) => ({ +const useGlobalStore = create((set) => ({ isConnectPS: false, setIsConnectPS: (newIsConnectPS: boolean) => set({ isConnectPS: newIsConnectPS }), })); diff --git a/src/stores/mazeStore.ts b/src/stores/mazeStore.ts index c0d87c3..6c1538d 100644 --- a/src/stores/mazeStore.ts +++ b/src/stores/mazeStore.ts @@ -1,4 +1,4 @@ -import { AffixDetail, ASConfigMaze, AvatarConfigMaze, ConfigMaze, MOCConfigMaze, PFConfigMaze, StageConfigMaze } from '@/types'; +import { ASConfigMaze, AvatarConfigMaze, ConfigMaze, MOCConfigMaze, PFConfigMaze, StageConfigMaze } from '@/types'; import { create } from 'zustand' interface MazeState { diff --git a/src/stores/userDataStore.ts b/src/stores/userDataStore.ts index 5d04e8b..e5d32ba 100644 --- a/src/stores/userDataStore.ts +++ b/src/stores/userDataStore.ts @@ -1,6 +1,6 @@ import { ASConfigStore, AvatarStore, CEConfigStore, MOCConfigStore, PFConfigStore } from '@/types'; import { create } from 'zustand' -import { persist } from 'zustand/middleware'; +import { createJSONStorage, persist } from 'zustand/middleware'; interface UserDataState { @@ -71,6 +71,7 @@ const useUserDataStore = create()( }), { name: 'user-data-storage', + storage: createJSONStorage(() => localStorage), } ) );