FIX: fix bug not create avatar
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m33s

This commit is contained in:
2025-07-25 12:17:01 +07:00
parent 01bdafcf10
commit 31724fa88c
13 changed files with 44 additions and 44 deletions

View File

@@ -7,6 +7,7 @@ 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<Record<string, boolean>>({ "fire": false, "ice": false, "imaginary": false, "physical": false, "quantum": false, "thunder": false, "wind": false })
const [listPath, setListPath] = useState<Record<string, boolean>>({ "knight": false, "mage": false, "priest": false, "rogue": false, "shaman": false, "warlock": false, "warrior": false, "memory": false })
@@ -28,6 +29,7 @@ export default function AvatarBar() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [locale, listElement, listPath])
return (
<div className="grid grid-flow-row h-full auto-rows-max w-full">
<div className="h-full rounded-lg mx-2 py-2">

View File

@@ -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<string, CharacterDetail>): {
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;

View File

@@ -1,15 +0,0 @@
import useUserDataStore from "@/stores/userDataStore";
import useAvatarStore from "@/stores/avatarStore";
import { CharacterDetail } from "@/types";
export function getAvatarNotExist(): Record<string, CharacterDetail> {
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<string, CharacterDetail>)
}

View File

@@ -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<string, number>)
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;

View File

@@ -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"

View File

@@ -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++) {

View File

@@ -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<string, CharacterDetail>)
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])
}

View File

@@ -8,7 +8,7 @@ interface AffixState {
setMapSubAffix: (newSubAffix: Record<string, Record<string, AffixDetail>>) => void;
}
const useAffixStore = create<AffixState>((set, get) => ({
const useAffixStore = create<AffixState>((set) => ({
mapMainAffix: {},
mapSubAffix: {},
setMapMainAffix: (newMainAffix: Record<string, Record<string, AffixDetail>>) => set({ mapMainAffix: newMainAffix }),

View File

@@ -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 {

View File

@@ -8,7 +8,7 @@ interface FreeSRState {
setFreeSRData: (newFreeSRData: FreeSRJson | null) => void;
}
const useFreeSRStore = create<FreeSRState>((set, get) => ({
const useFreeSRStore = create<FreeSRState>((set) => ({
selectedCharacters: [],
freeSRData: null,
setSelectedCharacters: (newListAvatar: CharacterInfoCardType[]) => set({ selectedCharacters: newListAvatar }),

View File

@@ -5,7 +5,7 @@ interface GlobalState {
setIsConnectPS: (newIsConnectPS: boolean) => void;
}
const useGlobalStore = create<GlobalState>((set, get) => ({
const useGlobalStore = create<GlobalState>((set) => ({
isConnectPS: false,
setIsConnectPS: (newIsConnectPS: boolean) => set({ isConnectPS: newIsConnectPS }),
}));

View File

@@ -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 {

View File

@@ -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<UserDataState>()(
}),
{
name: 'user-data-storage',
storage: createJSONStorage(() => localStorage),
}
)
);