FIX: fix bug not create avatar
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m33s
All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m33s
This commit is contained in:
@@ -7,13 +7,14 @@ import useAvatarStore from "@/stores/avatarStore"
|
|||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import { useFetchASData, useFetchAvatarData, useFetchConfigData, useFetchLightconeData, useFetchMOCData, useFetchMonsterData, useFetchPFData, useFetchRelicData } from "@/hooks"
|
import { useFetchASData, useFetchAvatarData, useFetchConfigData, useFetchLightconeData, useFetchMOCData, useFetchMonsterData, useFetchPFData, useFetchRelicData } from "@/hooks"
|
||||||
|
|
||||||
|
|
||||||
export default function AvatarBar() {
|
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 [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 })
|
const [listPath, setListPath] = useState<Record<string, boolean>>({ "knight": false, "mage": false, "priest": false, "rogue": false, "shaman": false, "warlock": false, "warrior": false, "memory": false })
|
||||||
const { listAvatar, setAvatarSelected, setFilter, filter } = useAvatarStore()
|
const { listAvatar, setAvatarSelected, setFilter, filter } = useAvatarStore()
|
||||||
const transI18n = useTranslations("DataPage")
|
const transI18n = useTranslations("DataPage")
|
||||||
const { locale } = useLocaleStore()
|
const { locale } = useLocaleStore()
|
||||||
|
|
||||||
useFetchConfigData()
|
useFetchConfigData()
|
||||||
useFetchAvatarData()
|
useFetchAvatarData()
|
||||||
useFetchLightconeData()
|
useFetchLightconeData()
|
||||||
@@ -28,6 +29,7 @@ export default function AvatarBar() {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [locale, listElement, listPath])
|
}, [locale, listElement, listPath])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-flow-row h-full auto-rows-max w-full">
|
<div className="grid grid-flow-row h-full auto-rows-max w-full">
|
||||||
<div className="h-full rounded-lg mx-2 py-2">
|
<div className="h-full rounded-lg mx-2 py-2">
|
||||||
|
|||||||
@@ -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);
|
const num = Number(val);
|
||||||
return Number.isFinite(num) && num !== 0 ? num : fallback;
|
return Number.isFinite(num) && num !== 0 ? num : fallback;
|
||||||
}
|
}
|
||||||
@@ -14,7 +15,7 @@ export function converterToAvatarStore(data: Record<string, CharacterDetail>): {
|
|||||||
avatar_id: Number(key),
|
avatar_id: Number(key),
|
||||||
data: {
|
data: {
|
||||||
rank: 0,
|
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];
|
const firstEntry = Object.values(dataPointEntry)[0];
|
||||||
if (firstEntry) {
|
if (firstEntry) {
|
||||||
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
||||||
|
|||||||
@@ -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>)
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import useAvatarStore from "@/stores/avatarStore"
|
import useAvatarStore from "@/stores/avatarStore"
|
||||||
import useUserDataStore from "@/stores/userDataStore"
|
|
||||||
|
|
||||||
export function getSkillTree(enhanced: string) {
|
export function getSkillTree(enhanced: string) {
|
||||||
const { avatarSelected, mapAvatarInfo } = useAvatarStore.getState()
|
const { avatarSelected, mapAvatarInfo } = useAvatarStore.getState()
|
||||||
|
|
||||||
if (!avatarSelected) return null;
|
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];
|
const firstEntry = Object.values(dataPointEntry)[0];
|
||||||
if (firstEntry) {
|
if (firstEntry) {
|
||||||
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
||||||
@@ -13,7 +12,7 @@ export function getSkillTree(enhanced: string) {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string, number>)
|
}, {} 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];
|
const firstEntry = Object.values(dataPointEntry)[0];
|
||||||
if (firstEntry) {
|
if (firstEntry) {
|
||||||
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
acc[firstEntry.PointID] = firstEntry.MaxLevel;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
export * from "./getName"
|
export * from "./getName"
|
||||||
export * from "./replaceByParam"
|
export * from "./replaceByParam"
|
||||||
export * from "./converterToAvatarStore"
|
export * from "./converterToAvatarStore"
|
||||||
export * from "./getAvatarNotExist"
|
|
||||||
export * from "./calcData"
|
export * from "./calcData"
|
||||||
export * from "./random"
|
export * from "./random"
|
||||||
export * from "./json"
|
export * from "./json"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export function randomPartition(sum: number, parts: number): number[] {
|
export function randomPartition(sum: number, parts: number): number[] {
|
||||||
let raw = Array.from({ length: parts }, () => Math.random());
|
const raw = Array.from({ length: parts }, () => Math.random());
|
||||||
let total = raw.reduce((a, b) => a + b, 0);
|
const total = raw.reduce((a, b) => a + b, 0);
|
||||||
let result = raw.map(r => Math.floor((r / total) * (sum - parts)) + 1);
|
const result = raw.map(r => Math.floor((r / total) * (sum - parts)) + 1);
|
||||||
let diff = sum - result.reduce((a, b) => a + b, 0);
|
let diff = sum - result.reduce((a, b) => a + b, 0);
|
||||||
while (diff !== 0) {
|
while (diff !== 0) {
|
||||||
for (let i = 0; i < result.length && diff !== 0; i++) {
|
for (let i = 0; i < result.length && diff !== 0; i++) {
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import { toast } from 'react-toastify'
|
|||||||
import useAvatarStore from '@/stores/avatarStore'
|
import useAvatarStore from '@/stores/avatarStore'
|
||||||
import { listCurrentLanguageApi } from '@/lib/constant'
|
import { listCurrentLanguageApi } from '@/lib/constant'
|
||||||
import useLocaleStore from '@/stores/localeStore'
|
import useLocaleStore from '@/stores/localeStore'
|
||||||
import { converterToAvatarStore, getAvatarNotExist } from '@/helper'
|
|
||||||
import useUserDataStore from '@/stores/userDataStore'
|
import useUserDataStore from '@/stores/userDataStore'
|
||||||
|
import { converterToAvatarStore } from '@/helper'
|
||||||
|
import { CharacterDetail } from '@/types'
|
||||||
|
|
||||||
export const useFetchAvatarData = () => {
|
export const useFetchAvatarData = () => {
|
||||||
const { setAvatars, avatars } = useUserDataStore()
|
const { setAvatars, avatars } = useUserDataStore()
|
||||||
const { setListAvatar, setAllMapAvatarInfo, setAvatarSelected } = useAvatarStore()
|
const { setListAvatar, setAllMapAvatarInfo, mapAvatarInfo, setAvatarSelected } = useAvatarStore()
|
||||||
const { locale } = useLocaleStore()
|
const { locale } = useLocaleStore()
|
||||||
const { data: dataAvatar, error: errorAvatar } = useQuery({
|
const { data: dataAvatar, error: errorAvatar } = useQuery({
|
||||||
queryKey: ['avatarData'],
|
queryKey: ['avatarData'],
|
||||||
@@ -27,25 +28,37 @@ export const useFetchAvatarData = () => {
|
|||||||
staleTime: 1000 * 60 * 5,
|
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({
|
const { data: dataAvatarInfo, error: errorAvatarInfo } = useQuery({
|
||||||
queryKey: ['avatarInfoData', locale],
|
queryKey: ['avatarInfoData', locale],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
fetchCharactersByIdsNative(
|
fetchCharactersByIdsNative(
|
||||||
dataAvatar!.map((item) => item.id),
|
dataAvatar!.map((item) => item.id),
|
||||||
listCurrentLanguageApi[locale.toLowerCase()]
|
listCurrentLanguageApi[locale.toLowerCase()]
|
||||||
),
|
),
|
||||||
staleTime: 1000 * 60 * 5,
|
staleTime: 1000 * 60 * 5,
|
||||||
enabled: !!dataAvatar,
|
enabled: !!dataAvatar,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dataAvatar && !errorAvatar) {
|
if (dataAvatar && !errorAvatar) {
|
||||||
setListAvatar(dataAvatar)
|
setListAvatar(dataAvatar)
|
||||||
setAvatarSelected(dataAvatar[0])
|
setAvatarSelected(dataAvatar[0])
|
||||||
const avatarStore = converterToAvatarStore(getAvatarNotExist())
|
|
||||||
if (Object.keys(avatarStore).length > 0) {
|
|
||||||
setAvatars({ ...avatars, ...avatarStore })
|
|
||||||
}
|
|
||||||
} else if (errorAvatar) {
|
} else if (errorAvatar) {
|
||||||
toast.error("Failed to load avatar data")
|
toast.error("Failed to load avatar data")
|
||||||
}
|
}
|
||||||
@@ -57,5 +70,5 @@ export const useFetchAvatarData = () => {
|
|||||||
} else if (errorAvatarInfo) {
|
} else if (errorAvatarInfo) {
|
||||||
toast.error("Failed to load avatar info data")
|
toast.error("Failed to load avatar info data")
|
||||||
}
|
}
|
||||||
}, [dataAvatarInfo, errorAvatarInfo, setAllMapAvatarInfo])
|
}, [dataAvatarInfo, errorAvatarInfo, setAllMapAvatarInfo, setAvatars])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface AffixState {
|
|||||||
setMapSubAffix: (newSubAffix: Record<string, Record<string, AffixDetail>>) => void;
|
setMapSubAffix: (newSubAffix: Record<string, Record<string, AffixDetail>>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useAffixStore = create<AffixState>((set, get) => ({
|
const useAffixStore = create<AffixState>((set) => ({
|
||||||
mapMainAffix: {},
|
mapMainAffix: {},
|
||||||
mapSubAffix: {},
|
mapSubAffix: {},
|
||||||
setMapMainAffix: (newMainAffix: Record<string, Record<string, AffixDetail>>) => set({ mapMainAffix: newMainAffix }),
|
setMapMainAffix: (newMainAffix: Record<string, Record<string, AffixDetail>>) => set({ mapMainAffix: newMainAffix }),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AvatarDataStore, AvatarProfileCardType, CharacterBasic, CharacterInfoCardType, EnkaResponse, FilterAvatarType } from '@/types';
|
import { AvatarProfileCardType, CharacterBasic, FilterAvatarType } from '@/types';
|
||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
|
|
||||||
interface CopyProfileState {
|
interface CopyProfileState {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface FreeSRState {
|
|||||||
setFreeSRData: (newFreeSRData: FreeSRJson | null) => void;
|
setFreeSRData: (newFreeSRData: FreeSRJson | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useFreeSRStore = create<FreeSRState>((set, get) => ({
|
const useFreeSRStore = create<FreeSRState>((set) => ({
|
||||||
selectedCharacters: [],
|
selectedCharacters: [],
|
||||||
freeSRData: null,
|
freeSRData: null,
|
||||||
setSelectedCharacters: (newListAvatar: CharacterInfoCardType[]) => set({ selectedCharacters: newListAvatar }),
|
setSelectedCharacters: (newListAvatar: CharacterInfoCardType[]) => set({ selectedCharacters: newListAvatar }),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ interface GlobalState {
|
|||||||
setIsConnectPS: (newIsConnectPS: boolean) => void;
|
setIsConnectPS: (newIsConnectPS: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useGlobalStore = create<GlobalState>((set, get) => ({
|
const useGlobalStore = create<GlobalState>((set) => ({
|
||||||
isConnectPS: false,
|
isConnectPS: false,
|
||||||
setIsConnectPS: (newIsConnectPS: boolean) => set({ isConnectPS: newIsConnectPS }),
|
setIsConnectPS: (newIsConnectPS: boolean) => set({ isConnectPS: newIsConnectPS }),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -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'
|
import { create } from 'zustand'
|
||||||
|
|
||||||
interface MazeState {
|
interface MazeState {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ASConfigStore, AvatarStore, CEConfigStore, MOCConfigStore, PFConfigStore } from '@/types';
|
import { ASConfigStore, AvatarStore, CEConfigStore, MOCConfigStore, PFConfigStore } from '@/types';
|
||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
import { persist } from 'zustand/middleware';
|
import { createJSONStorage, persist } from 'zustand/middleware';
|
||||||
|
|
||||||
|
|
||||||
interface UserDataState {
|
interface UserDataState {
|
||||||
@@ -71,6 +71,7 @@ const useUserDataStore = create<UserDataState>()(
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: 'user-data-storage',
|
name: 'user-data-storage',
|
||||||
|
storage: createJSONStorage(() => localStorage),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user