"use client" import { useTranslations } from "next-intl"; import useAvatarStore from "@/stores/avatarStore"; import { useCallback, useMemo } from "react"; import { traceButtonsInfo, traceLink } from "@/constant/traceConstant"; import useUserDataStore from "@/stores/userDataStore"; import useLocaleStore from "@/stores/localeStore"; import Image from "next/image"; import { replaceByParam } from "@/helper"; import { mappingStats } from "@/constant/constant"; import { StatusAddType } from "@/types"; import cloneDeep from "lodash/cloneDeep"; import { toast } from "react-toastify"; export default function SkillsInfo() { const transI18n = useTranslations("DataPage") const { theme } = useLocaleStore() const { avatarSelected, mapAvatarInfo, skillSelected, setSkillSelected } = useAvatarStore() const { avatars, setAvatar } = useUserDataStore() const traceButtons = useMemo(() => { if (!avatarSelected) return return traceButtonsInfo[avatarSelected.baseType] }, [avatarSelected]) const avatarInfo = useMemo(() => { if (!avatarSelected) return return mapAvatarInfo[avatarSelected.id] }, [avatarSelected, mapAvatarInfo]) const avatarData = useMemo(() => { if (!avatarSelected) return return avatars[avatarSelected.id] }, [avatarSelected, avatars]) const avatarSkillTree = useMemo(() => { if (!avatarSelected || !avatars[avatarSelected.id]) return {} if (avatars[avatarSelected.id].enhanced) { return avatarInfo?.Enhanced[avatars[avatarSelected.id].enhanced.toString()].SkillTrees || {} } return avatarInfo?.SkillTrees || {} }, [avatarSelected, avatarInfo, avatars]) const skillInfo = useMemo(() => { if (!avatarSelected || !skillSelected) return return avatarSkillTree?.[skillSelected || ""]?.["1"] }, [avatarSelected, avatarSkillTree, skillSelected]) const getImageSkill = useCallback((icon: string | undefined, status: StatusAddType | undefined, provider: string = "hakushin") => { if (!icon) return let urlPrefix = "https://homdgcat.wiki/images/skillicons/avatar/"; if (provider === "hakushin") { urlPrefix = "https://api.hakush.in/hsr/UI/skillicons/" } if (icon.startsWith("SkillIcon")) { if (provider === "homdgcat") { return `${urlPrefix}${avatarSelected?.id}/${icon}` } else if (provider === "hakushin") { return `${urlPrefix}${icon.replace(".png", ".webp")}` } } else if (status && mappingStats[status.PropertyType]) { return mappingStats[status.PropertyType].icon } else if (icon.startsWith("Icon")) { return `https://api.hakush.in/hsr/UI/trace/${icon.replace(".png", ".webp")}` } }, [avatarSelected]) const getTraceBuffDisplay = useCallback((status: StatusAddType) => { const dataDisplay = mappingStats[status.PropertyType] if (!dataDisplay) return "" if (dataDisplay.unit === "%") { return `${(status.Value * 100).toFixed(1)}${dataDisplay.unit}` } if (dataDisplay.name === "SPD") { return `${status.Value.toFixed(1)}${dataDisplay.unit}` } return `${status.Value.toFixed(0)}${dataDisplay.unit}` }, []) const dataLevelUpSkill = useMemo(() => { const skillIds: number[] = skillInfo?.LevelUpSkillID || [] if (!avatarSelected || !avatarInfo || !avatarData) return let result = Object.values(avatarInfo.Skills || {})?.filter((skill) => skillIds.includes(skill.Id)) if (avatarData.enhanced) { result = Object.values(avatarInfo.Enhanced[avatarData.enhanced.toString()].Skills || {})?.filter((skill) => skillIds.includes(skill.Id)) } if (result && result.length > 0) { return { isServant: false, data: result, servantData: null, } } const resultServant = Object.entries(avatarInfo.Memosprite?.Skills || {}) ?.filter(([skillId]) => skillIds.includes(Number(skillId))) ?.map(([skillId, skillData]) => ({ Id: Number(skillId), ...skillData, })) if (resultServant && resultServant.length > 0) { return { isServant: true, data: resultServant, servantData: avatarInfo.Memosprite, } } return undefined }, [skillInfo?.LevelUpSkillID, avatarSelected, avatarInfo, avatarData]) const handlerMaxAll = () => { if (!avatarInfo || !avatarData || !avatarSkillTree) { toast.error(transI18n("maxAllFailed")) return } const newData = cloneDeep(avatarData) newData.data.skills = Object.values(avatarSkillTree).reduce((acc, dataPointEntry) => { const firstEntry = Object.values(dataPointEntry)[0]; if (firstEntry) { acc[firstEntry.PointID] = firstEntry.MaxLevel; } return acc; }, {} as Record) toast.success(transI18n("maxAllSuccess")) setAvatar(newData) } const handlerChangeStatusTrace = (status: boolean) => { if (!avatarData || !skillInfo) return const newData = cloneDeep(avatarData) newData.data.skills[skillInfo?.PointID] = status ? 1 : 0 if (!status && traceLink?.[avatarSelected?.baseType || ""]?.[skillSelected || ""]) { traceLink[avatarSelected?.baseType || ""][skillSelected || ""].forEach((pointId) => { if (avatarSkillTree?.[pointId]?.["1"]) { newData.data.skills[avatarSkillTree?.[pointId]?.["1"].PointID] = 0 } }) } setAvatar(newData) } return (

{transI18n("skills")}

{traceButtons && avatarInfo && (
{traceButtons.map((btn, index) => { if (!avatarInfo?.SkillTrees?.[btn.id]) { return null } return (
{ setSkillSelected(btn.id === skillSelected ? null : btn.id) }} style={{ left: `calc(${btn.left} - var(--size-${btn.size}) / 2)`, top: `calc(${btn.top} - var(--size-${btn.size}) / 2)`, }} > {btn.id.replaceAll("Point", { e.currentTarget.onerror = null; // trĂ¡nh loop e.currentTarget.src = getImageSkill(avatarInfo?.SkillTrees?.[btn.id]?.["1"]?.Icon, avatarSkillTree?.[btn.id]?.["1"]?.StatusAddList[0], "homdgcat") || ""; }} /> {btn.size === "big" && (

{`${avatarData?.data.skills?.[avatarSkillTree?.[btn.id]?.["1"]?.PointID] || 0}/${avatarSkillTree?.[btn.id]?.["1"]?.MaxLevel}`}

)}
)})}
)}

{transI18n("details")}

{skillSelected && avatarInfo?.SkillTrees && avatarData && (
{skillInfo?.MaxLevel && skillInfo?.MaxLevel > 1 ? (
{transI18n("level")}
{ const newData = cloneDeep(avatarData) newData.data.skills[skillInfo?.PointID] = parseInt(e.target.value) setAvatar(newData) }} className="range range-success" step="1" />
{Array.from({ length: skillInfo?.MaxLevel }, (_, index) => index + 1).map((index) => ( {index} ))}
) : skillInfo?.MaxLevel && skillInfo?.MaxLevel === 1 && traceButtons?.find((btn) => btn.id === skillSelected)?.size !== "big" ? (
{ handlerChangeStatusTrace(e.target.checked) }} />
{avatarData?.data.skills?.[skillInfo?.PointID] === 1 ? transI18n("active") : transI18n("inactive")}
) : ( null )} {((skillInfo?.PointName && skillInfo?.PointDesc) || (skillInfo?.PointName && skillInfo?.StatusAddList.length > 0)) && (
{skillInfo.PointName} {skillInfo.StatusAddList.length > 0 && (
{skillInfo.StatusAddList.map((status, index) => (
{getTraceBuffDisplay(status)}
))}
)}
)} {skillInfo?.PointDesc && (
)} {skillInfo?.LevelUpSkillID && skillInfo?.LevelUpSkillID.length > 0 && dataLevelUpSkill && (
{dataLevelUpSkill?.data?.map((skill, index) => (
{transI18n(dataLevelUpSkill.isServant ? `${skill?.Type ? "severaltalent" : "servantskill"}` : `${skill?.Type ? skill?.Type.toLowerCase() : "talent"}`)} {` (${transI18n(skill.Tag.toLowerCase())})`}
))}
)}
)}
); }