handleShow("action_detail_modal", data, turn)}
- className="h-full grid grid-cols-2 gap-2 border bg-base-100 w-full hover:bg-base-200 transition-colors duration-200 border-cyan-400 border-l-4 cursor-pointer min-w-[200px] sm:min-w-[250px] md:min-w-0"
+ className="h-full grid grid-cols-2 gap-2 border bg-base-100 w-full hover:bg-base-200 transition-colors duration-200 border-cyan-400 border-l-4 cursor-pointer min-w-50 sm:min-w-62.5 md:min-w-0"
>
@@ -195,15 +197,17 @@ export default function ActionBar() {
{transI18n("character")}:
@@ -31,21 +31,27 @@ export default function CharacterCard({ data }: CharacterCardProps) {
diff --git a/src/components/chart/damageLineForAll.tsx b/src/components/chart/damageLineForAll.tsx
index 52b5944..6a3593f 100644
--- a/src/components/chart/damageLineForAll.tsx
+++ b/src/components/chart/damageLineForAll.tsx
@@ -24,14 +24,13 @@ export default function MultiCharLineChart() {
const [mode, setMode] = useState<1 | 2>(2);
const dataByAvatar = useDamageLinesForAll(mode);
const avatarIds = Object.keys(dataByAvatar).map(Number);
- const { listAvatar } = useAvatarDataStore()
+ const { mapAvatar } = useAvatarDataStore()
const { locale } = useLocaleStore();
const transI18n = useTranslations("DataAnalysisPage")
-
const data = {
datasets: avatarIds.map((id, idx) => ({
- label: getNameChar(locale, listAvatar.find(it => it.id == id.toString())),
+ label: getNameChar(locale, transI18n, mapAvatar?.[id.toString()]),
data: dataByAvatar[id].map(({ x, y }: { x: number; y: number }) => {
return {
x: x.toFixed(2),
diff --git a/src/components/chart/damagePerAvatarForAll.tsx b/src/components/chart/damagePerAvatarForAll.tsx
index 755888f..84c4d4f 100644
--- a/src/components/chart/damagePerAvatarForAll.tsx
+++ b/src/components/chart/damagePerAvatarForAll.tsx
@@ -48,17 +48,16 @@ const borderPalette = colorPalette.map((c) => c.replace('0.6', '1'));
export default function DamagePerAvatarForAll() {
const transI18n = useTranslations("DataAnalysisPage");
const { lineup, skillHistory } = useBattleDataStore();
- const { listAvatar } = useAvatarDataStore();
+ const { mapAvatar } = useAvatarDataStore();
const { locale } = useLocaleStore();
const [mode, setMode] = useState(2);
const avatarMap = lineup.map((avatar) => {
- const char = listAvatar.find(it => it.id === avatar.avatarId.toString());
- if (!char) return undefined;
+ if (!mapAvatar?.[avatar.avatarId.toString()]) return undefined;
return {
avatarId: avatar.avatarId,
- avatarName: getNameChar(locale, char)
+ avatarName: getNameChar(locale, transI18n, mapAvatar?.[avatar.avatarId.toString()])
};
}).filter(Boolean) as { avatarId: number, avatarName: string }[];
diff --git a/src/components/chart/damagePercentForAll.tsx b/src/components/chart/damagePercentForAll.tsx
index 38bbb80..d6f6572 100644
--- a/src/components/chart/damagePercentForAll.tsx
+++ b/src/components/chart/damagePercentForAll.tsx
@@ -27,14 +27,14 @@ export default function DamagePercentChartForAll() {
const [mode, setMode] = useState<1 | 2>(1);
const damageByAvatar = useDamagePercentPerAvatar();
const damageByType = useDamagePercentByType();
- const { listAvatar } = useAvatarDataStore();
+ const { mapAvatar } = useAvatarDataStore();
const { locale } = useLocaleStore();
const transI18n = useTranslations("DataAnalysisPage");
const chartData = {
labels: (mode === 1
? damageByAvatar.map(d =>
- getNameChar(locale, listAvatar.find(it => it.id == d.avatarId.toString()))
+ getNameChar(locale, transI18n, mapAvatar?.[d.avatarId.toString()])
)
: damageByType.map(d => transI18n(d.type.toLowerCase()))
),
diff --git a/src/components/enemybar/index.tsx b/src/components/enemybar/index.tsx
index 673f91b..1ca45da 100644
--- a/src/components/enemybar/index.tsx
+++ b/src/components/enemybar/index.tsx
@@ -10,7 +10,7 @@ import NameAvatar from "../nameAvatar";
export default function EnemyBar() {
const { enemyDetail } = useBattleDataStore()
- const { listEnemy } = useAvatarDataStore()
+ const { mapEnemy } = useAvatarDataStore()
const { locale } = useLocaleStore()
return (
@@ -21,10 +21,12 @@ export default function EnemyBar() {
- {listEnemy.find((monster) => monster.child.includes(enemy.id))?.icon?.split("/")?.pop()?.replace(".png", "") && (
+ {mapEnemy?.[enemy.id.toString()]?.icon && (
monster.child.includes(enemy.id))?.icon?.split("/")?.pop()?.replace(".png", "")}.webp`}
+ src={`${process.env.CDN_URL}/${mapEnemy?.[enemy.id.toString()]?.icon}`}
alt={enemy.name}
+ unoptimized
+ crossOrigin="anonymous"
width={40}
height={40}
className="object-cover w-10 h-10 rounded-lg"
@@ -33,7 +35,7 @@ export default function EnemyBar() {
monster.child.includes(enemy.id)))}
+ text={getNameEnemy(locale, mapEnemy?.[enemy.id.toString()])}
locale={locale}
className="text-base font-semibold leading-tight truncate overflow-hidden"
/>
diff --git a/src/components/lineupbar/index.tsx b/src/components/lineupbar/index.tsx
index 301ac98..81bb963 100644
--- a/src/components/lineupbar/index.tsx
+++ b/src/components/lineupbar/index.tsx
@@ -4,7 +4,7 @@ import useBattleDataStore from "@/stores/battleDataStore";
import CharacterCard from "../card/characterCard";
import { useTranslations } from "next-intl";
import { useState, useEffect } from "react";
-import { AvatarHakushiType } from "@/types";
+import { CharacterBasic } from "@/types";
import useLocaleStore from "@/stores/localeStore";
import { getNameChar } from '@/helper/getNameChar';
import SkillBarChart from "../chart/skillBarChart";
@@ -18,12 +18,12 @@ import NameAvatar from "../nameAvatar";
// import ShowCaseInfo from "../card/showCaseCard";
export default function LineupBar() {
- const [selectedCharacter, setSelectedCharacter] = useState(undefined);
+ const [selectedCharacter, setSelectedCharacter] = useState(undefined);
const [isModalOpen, setIsModalOpen] = useState(false);
const transI18n = useTranslations("DataAnalysisPage");
const { lineup, turnHistory, dataAvatar } = useBattleDataStore();
- const { listAvatar } = useAvatarDataStore();
+ const { listAvatar, mapAvatar } = useAvatarDataStore();
const { locale } = useLocaleStore();
const totalDamage = useCalcTotalDmgAvatar(selectedCharacter ? Number(selectedCharacter.id) : 0);
const totalTurn = useCalcTotalTurnAvatar(selectedCharacter ? Number(selectedCharacter.id) : 0)
@@ -33,7 +33,7 @@ export default function LineupBar() {
lineup.some(av => av.avatarId.toString() === item.id)
);
- const handleShow = (modalId: string, item: AvatarHakushiType) => {
+ const handleShow = (modalId: string, item: CharacterBasic) => {
const modal = document.getElementById(modalId) as HTMLDialogElement | null;
if (modal) {
setSelectedCharacter(item);
@@ -81,16 +81,16 @@ export default function LineupBar() {
-
-
- {transI18n("lastTurn")}:
-
-
- it.id === turnHistory.findLast(i => i?.avatarId)?.avatarId?.toString()))}
- />
-
+
+
+ {transI18n("lastTurn")}:
+
+
+ i?.avatarId)?.avatarId?.toString() || ""])}
+ />
+
@@ -142,10 +142,10 @@ export default function LineupBar() {
-
+
@@ -170,8 +170,9 @@ export default function LineupBar() {
{transI18n(selectedCharacter.baseType.toLowerCase())}
{selectedCharacter.baseType && (
{transI18n("element")}:
{transI18n("lightcones")}:
{relicIds.map(it => (
({});
export const ThemeProvider = ({ children }: PropsWithChildren) => {
- const [theme, setTheme] = useState("light");
+ const { theme, setTheme } = useLocaleStore()
useEffect(() => {
if (typeof window !== "undefined") {
@@ -19,14 +20,13 @@ export const ThemeProvider = ({ children }: PropsWithChildren) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const changeTheme = (nextTheme: string | null) => {
- console.log(nextTheme)
if (nextTheme) {
setTheme(nextTheme);
if (typeof window !== "undefined") {
localStorage.setItem("theme", nextTheme);
}
} else {
- setTheme((prev) => (prev === "light" ? "night" : "light"));
+ setTheme(theme === "winter" ? "night" : "winter");
if (typeof window !== "undefined") {
localStorage.setItem("theme", theme);
}
diff --git a/src/helper/getNameChar.ts b/src/helper/getNameChar.ts
index 3cf0789..51cda11 100644
--- a/src/helper/getNameChar.ts
+++ b/src/helper/getNameChar.ts
@@ -1,38 +1,51 @@
import { listCurrentLanguage } from "@/lib/constant";
-import { AvatarHakushiType, EnemyHakushiType } from "@/types";
+import { CharacterBasic, MonsterBasic } from "@/types";
+import { useTranslations } from "next-intl";
-export function getNameChar(locale: string, data: AvatarHakushiType | undefined): string {
- if (!data) {
- return ""
- }
- if (!listCurrentLanguage.hasOwnProperty(locale)) {
- return ""
- }
+type TFunc = ReturnType
- let text = data.lang.get(listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase()) ?? "";
- if (!text) {
- text = data.lang.get("en") ?? "";
- }
- if (Number(data.id) % 2 === 0 && Number(data.id) > 8000) {
- text = `Female ${data.damageType} MC`
- } else if (Number(data.id) > 8000) {
- text = `Male ${data.damageType} MC`
- }
- return text
+export function getNameChar(
+ locale: string,
+ t: TFunc,
+ data: CharacterBasic | undefined
+): string {
+ if (!data) return "";
+
+ if (!Object.prototype.hasOwnProperty.call(listCurrentLanguage, locale)) {
+ return "";
+ }
+
+ const langKey = listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase();
+
+ let text = data.lang[langKey] ?? "";
+
+ if (!text) {
+ text = data.lang["en"] ?? "";
+ }
+
+ if (Number(data.id) > 8000) {
+ text = `${t("trailblazer")} • ${t(data?.baseType?.toLowerCase() ?? "")}`;
+ }
+
+ return text;
}
-export function getNameEnemy(locale: string, data: EnemyHakushiType | undefined): string {
+export function getNameEnemy(locale: string, data: MonsterBasic | undefined): string {
if (!data) {
return ""
}
- if (!listCurrentLanguage.hasOwnProperty(locale)) {
+ if (!Object.prototype.hasOwnProperty.call(listCurrentLanguage, locale)) {
return ""
}
- let text = data.lang.get(listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase()) ?? "";
+ const langKey = listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase();
+
+
+ let text = data.lang[langKey] ?? "";
+
if (!text) {
- text = data.lang.get("en") ?? "";
+ text = data.lang["en"] ?? "";
}
return text
}
diff --git a/src/lib/api.ts b/src/lib/api.ts
index eb4baab..5591247 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,6 +1,5 @@
import useSocketStore from "@/stores/socketSettingStore";
-import { EnemyHakushiRawType, EnemyHakushiType } from "@/types";
-import { AvatarHakushiType, AvatarHakushiRawType } from "@/types/avatar";
+import { CharacterBasic, MonsterBasic } from "@/types";
import axios from 'axios';
export async function checkConnectTcpApi(): Promise {
@@ -23,20 +22,10 @@ export async function checkConnectTcpApi(): Promise {
return false
}
-export async function getCharacterListApi(): Promise {
+export async function getCharacterListApi(): Promise {
try {
- const res = await axios.get>(
- 'https://api.hakush.in/hsr/data/character.json',
- {
- headers: {
- 'Content-Type': 'application/json',
- },
- }
- );
-
- const data = new Map(Object.entries(res.data));
-
- return Array.from(data.entries()).map(([id, it]) => convertAvatar(id, it));
+ const res = await axios.get("/data/character.json");
+ return res.data
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
console.log(`Error: ${error.response?.status} - ${error.message}`);
@@ -47,20 +36,10 @@ export async function getCharacterListApi(): Promise {
}
}
-export async function getEnemyListApi(): Promise {
+export async function getEnemyListApi(): Promise {
try {
- const res = await axios.get>(
- 'https://api.hakush.in/hsr/data/monster.json',
- {
- headers: {
- 'Content-Type': 'application/json',
- },
- }
- );
-
- const data = new Map(Object.entries(res.data));
-
- return Array.from(data.entries()).map(([id, it]) => convertMonster(id, it));
+ const res = await axios.get("/data/monster.json");
+ return res.data
} catch (error: unknown) {
if (axios.isAxiosError(error)) {
console.log(`Error: ${error.response?.status} - ${error.message}`);
@@ -70,46 +49,3 @@ export async function getEnemyListApi(): Promise {
return [];
}
}
-
-function convertAvatar(id: string, item: AvatarHakushiRawType): AvatarHakushiType {
- const lang = new Map([
- ['en', item.en],
- ['kr', item.kr],
- ['cn', item.cn],
- ['jp', item.jp]
- ]);
-
- const result: AvatarHakushiType = {
- release: item.release,
- icon: item.icon,
- rank: item.rank,
- baseType: item.baseType,
- damageType: item.damageType,
- desc: item.desc,
- lang: lang,
- id: id
- };
-
- return result;
-}
-
-export function convertMonster(id: string, item: EnemyHakushiRawType): EnemyHakushiType {
- const lang = new Map([
- ['en', item.en],
- ['kr', item.kr],
- ['cn', item.cn],
- ['jp', item.jp]
- ]);
- const result: EnemyHakushiType = {
- id: id,
- rank: item.rank,
- camp: item.camp,
- icon: item.icon,
- child: item.child,
- weak: item.weak,
- desc: item.desc,
- lang: lang
- };
-
- return result;
-}
\ No newline at end of file
diff --git a/src/stores/avatarDataStore.ts b/src/stores/avatarDataStore.ts
index c643557..ac453e1 100644
--- a/src/stores/avatarDataStore.ts
+++ b/src/stores/avatarDataStore.ts
@@ -1,19 +1,30 @@
-import { AvatarHakushiType, EnemyHakushiType } from '@/types';
+import { CharacterBasic, MonsterBasic } from '@/types';
import { create } from 'zustand'
interface AvatarDataState {
- listAvatar: AvatarHakushiType[];
- listEnemy: EnemyHakushiType[];
- setListAvatar: (list: AvatarHakushiType[]) => void;
- setListEnemy: (list: EnemyHakushiType[]) => void;
+ listAvatar: CharacterBasic[];
+ mapAvatar: Record;
+ listEnemy: MonsterBasic[];
+ mapEnemy: Record;
+ setListAvatar: (list: CharacterBasic[]) => void;
+ setMapAvatar: (data: Record) => void;
+ setListEnemy: (list: MonsterBasic[]) => void;
+ setMapEnemy: (data: Record) => void;
+
+
}
const useAvatarDataStore = create((set) => ({
listAvatar: [],
listEnemy: [],
- setListAvatar: (list: AvatarHakushiType[]) => set({ listAvatar: list }),
- setListEnemy: (list: EnemyHakushiType[]) => set({ listEnemy: list }),
+ mapAvatar: {},
+ mapEnemy: {},
+ setListAvatar: (list: CharacterBasic[]) => set({ listAvatar: list }),
+ setMapAvatar: (data: Record) => set({ mapAvatar: data }),
+ setListEnemy: (list: MonsterBasic[]) => set({ listEnemy: list }),
+ setMapEnemy: (data: Record) => set({ mapEnemy: data })
+
}));
export default useAvatarDataStore;
\ No newline at end of file
diff --git a/src/stores/localeStore.ts b/src/stores/localeStore.ts
index fe1a742..75183a7 100644
--- a/src/stores/localeStore.ts
+++ b/src/stores/localeStore.ts
@@ -1,15 +1,25 @@
import { create } from 'zustand'
+import { createJSONStorage, persist } from 'zustand/middleware';
interface LocaleState {
locale: string;
+ theme: string
+ setTheme: (newTheme: string) => void;
setLocale: (newLocale: string) => void;
}
-const useLocaleStore = create((set) => ({
- locale: "en",
- setLocale: (newLocale: string) => set({ locale: newLocale }),
-
-}));
+const useLocaleStore = create()(persist(
+ (set) => ({
+ locale: "en",
+ theme: "night",
+ setTheme: (newTheme: string) => set({ theme: newTheme }),
+ setLocale: (newLocale: string) => set({ locale: newLocale }),
+ }),
+ {
+ name: 'locale-storage',
+ storage: createJSONStorage(() => localStorage),
+ }
+));
export default useLocaleStore;
\ No newline at end of file
diff --git a/src/types/avatar.ts b/src/types/avatar.ts
index 2cb08dd..32503a0 100644
--- a/src/types/avatar.ts
+++ b/src/types/avatar.ts
@@ -1,23 +1,8 @@
-export interface AvatarHakushiRawType {
- release: number;
- icon: string;
- rank: string;
- baseType: string;
- damageType: string;
- en: string;
- desc: string;
- kr: string;
- cn: string;
- jp: string;
-}
-
-export interface AvatarHakushiType {
+export interface CharacterBasic {
id: string;
- release: number;
icon: string;
rank: string;
baseType: string;
damageType: string;
- desc: string;
- lang: Map;
+ lang: Record;
}
diff --git a/src/types/enemy.ts b/src/types/enemy.ts
index 49383bb..9acb09b 100644
--- a/src/types/enemy.ts
+++ b/src/types/enemy.ts
@@ -11,26 +11,12 @@ export interface InitializeEnemyType {
enemy: EnemyType
}
-export interface EnemyHakushiRawType {
- rank: string;
- camp: string | null;
- icon: string;
- child: number[];
- weak: string[];
- en: string;
- desc: string;
- kr: string;
- cn: string;
- jp: string;
-}
-
-export interface EnemyHakushiType {
+export interface MonsterBasic {
id: string;
rank: string;
- camp: string | null;
icon: string;
- child: number[];
+ image: string;
weak: string[];
- desc: string;
- lang: Map;
+ desc: Record;
+ lang: Record;
}