diff --git a/public/ff-sranalysis.ico b/public/ff-sranalysis.ico
new file mode 100644
index 0000000..ba78eb0
Binary files /dev/null and b/public/ff-sranalysis.ico differ
diff --git a/public/ff-sranalysis.png b/public/ff-sranalysis.png
new file mode 100644
index 0000000..2fd9142
Binary files /dev/null and b/public/ff-sranalysis.png differ
diff --git a/public/file.svg b/public/file.svg
deleted file mode 100644
index 004145c..0000000
--- a/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/globe.svg b/public/globe.svg
deleted file mode 100644
index 567f17b..0000000
--- a/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index 7705396..0000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/window.svg b/public/window.svg
deleted file mode 100644
index b2b2a44..0000000
--- a/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
deleted file mode 100644
index b8133f5..0000000
Binary files a/src/app/favicon.ico and /dev/null differ
diff --git a/src/app/icon.png b/src/app/icon.png
deleted file mode 100644
index 02ef1c8..0000000
Binary files a/src/app/icon.png and /dev/null differ
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 0af71de..cd71a6f 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -21,7 +21,34 @@ const geistMono = Geist_Mono({
export const metadata: Metadata = {
title: "Firefly Analytics",
description: "Analytics tool for Veritas",
-};
+ icons: {
+ icon: "/ff-sranalysis.png",
+ shortcut: "/ff-sranalysis.ico",
+ apple: "/ff-sranalysis.png",
+ },
+ openGraph: {
+ title: "Firefly Analytics",
+ description: "Analytics tool for Veritas",
+ url: "https://sranalysis.kain.id.vn",
+ siteName: "Firefly Analytics",
+ images: [
+ {
+ url: "https://sranalysis.kain.id.vn/ff-sranalysis.png",
+ width: 1200,
+ height: 630,
+ alt: "Firefly Analytics Logo",
+ },
+ ],
+ locale: "en_US",
+ type: "website",
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: "Firefly Analytics",
+ description: "Analytics tool for Veritas",
+ images: ["https://sranalysis.kain.id.vn/ff-sranalysis.png"],
+ },
+ };
export default async function RootLayout({
children,
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 4e71dfd..2af7d74 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -3,7 +3,7 @@ import { useTranslations } from "next-intl";
import { useEffect, useState } from "react";
import ActionBar from "@/components/actionbar";
import useAvatarDataStore from "@/stores/avatarDataStore";
-import { getCharacterListApi } from "@/lib/api";
+import { getCharacterListApi, getEnemyListApi } from "@/lib/api";
import LineupBar from "@/components/lineupbar";
import useBattleDataStore from "@/stores/battleDataStore";
import DamagePerAvatarForAll from "@/components/chart/damagePerAvatarForAll";
@@ -14,7 +14,7 @@ import EnemyBar from "@/components/enemybar";
export default function Home() {
const transI18n = useTranslations("DataAnalysisPage");
- const { setListAvatar } = useAvatarDataStore();
+ const { setListAvatar, setListEnemy } = useAvatarDataStore();
const {
totalAV,
totalDamage,
@@ -36,9 +36,11 @@ export default function Home() {
const fetchData = async () => {
const data = await getCharacterListApi();
setListAvatar(data);
+ const enemyData = await getEnemyListApi();
+ setListEnemy(enemyData);
};
fetchData();
- }, [setListAvatar]);
+ }, [setListAvatar, setListEnemy]);
useEffect(() => {
window.dispatchEvent(new Event('resize'));
diff --git a/src/components/enemybar/index.tsx b/src/components/enemybar/index.tsx
index 61c6ea9..4945eae 100644
--- a/src/components/enemybar/index.tsx
+++ b/src/components/enemybar/index.tsx
@@ -2,15 +2,16 @@
import useBattleDataStore from "@/stores/battleDataStore";
import Image from "next/image";
+import useAvatarDataStore from "@/stores/avatarDataStore";
+import { getNameEnemy } from "@/helper/getNameChar";
-function formatEnemyIdForURL(id?: number): string {
- const n = id ?? 0;
- const adjusted = n.toString().length === 9 ? n / 100 : n;
- return adjusted.toFixed(0);
-}
+import useLocaleStore from "@/stores/localeStore";
+import NameAvatar from "../nameAvatar";
export default function EnemyBar() {
const { enemyDetail } = useBattleDataStore()
+ const { listEnemy } = useAvatarDataStore()
+ const { locale } = useLocaleStore()
return (
@@ -21,16 +22,18 @@ export default function EnemyBar() {
monster.child.includes(enemy.id))?.icon?.split("/")?.pop()?.replace(".png", "")}.webp`}
alt={enemy.name}
width={40}
height={40}
className="object-cover w-10 h-10 rounded-lg"
/>
-
- {enemy.name}
-
+
monster.child.includes(enemy.id)))}
+ locale={locale}
+ className="text-base font-semibold leading-tight truncate overflow-hidden"
+ />
Level {enemy.level || 1}
diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx
index c3d877e..3d43936 100644
--- a/src/components/header/index.tsx
+++ b/src/components/header/index.tsx
@@ -12,6 +12,7 @@ import { useTranslations } from "next-intl";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
+import Image from "next/image";
const themes = [
{ label: "Winter" },
@@ -211,23 +212,28 @@ export default function Header() {
{/* Logo */}
-
- Firefly Analy
-
- sis
-
-
- For Veritas
+
+
+
+
+ Firefly Analy
+
+ sis
+
+
+
For Veritas
+
+
{version && (
-
+
)}
diff --git a/src/helper/getNameChar.ts b/src/helper/getNameChar.ts
index 843038a..3cf0789 100644
--- a/src/helper/getNameChar.ts
+++ b/src/helper/getNameChar.ts
@@ -1,5 +1,5 @@
import { listCurrentLanguage } from "@/lib/constant";
-import { AvatarHakushiType } from "@/types";
+import { AvatarHakushiType, EnemyHakushiType } from "@/types";
export function getNameChar(locale: string, data: AvatarHakushiType | undefined): string {
@@ -22,6 +22,21 @@ export function getNameChar(locale: string, data: AvatarHakushiType | undefined)
return text
}
+export function getNameEnemy(locale: string, data: EnemyHakushiType | undefined): string {
+ if (!data) {
+ return ""
+ }
+ if (!listCurrentLanguage.hasOwnProperty(locale)) {
+ return ""
+ }
+
+ let text = data.lang.get(listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase()) ?? "";
+ if (!text) {
+ text = data.lang.get("en") ?? "";
+ }
+ return text
+}
+
export function parseRuby(text: string): string {
const rubyRegex = /\{RUBY_B#(.*?)\}(.*?)\{RUBY_E#\}/gs;
return text.replace(rubyRegex, (_match, furigana, kanji) => {
diff --git a/src/lib/api.ts b/src/lib/api.ts
index b854297..eb4baab 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,4 +1,5 @@
import useSocketStore from "@/stores/socketSettingStore";
+import { EnemyHakushiRawType, EnemyHakushiType } from "@/types";
import { AvatarHakushiType, AvatarHakushiRawType } from "@/types/avatar";
import axios from 'axios';
@@ -46,6 +47,29 @@ export async function getCharacterListApi(): 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));
+ } catch (error: unknown) {
+ if (axios.isAxiosError(error)) {
+ console.log(`Error: ${error.response?.status} - ${error.message}`);
+ } else {
+ console.log(`Unexpected error: ${String(error)}`);
+ }
+ return [];
+ }
+}
function convertAvatar(id: string, item: AvatarHakushiRawType): AvatarHakushiType {
const lang = new Map([
@@ -66,5 +90,26 @@ function convertAvatar(id: string, item: AvatarHakushiRawType): AvatarHakushiTyp
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 d5711e7..c643557 100644
--- a/src/stores/avatarDataStore.ts
+++ b/src/stores/avatarDataStore.ts
@@ -1,16 +1,19 @@
-import { AvatarHakushiType } from '@/types';
+import { AvatarHakushiType, EnemyHakushiType } from '@/types';
import { create } from 'zustand'
interface AvatarDataState {
listAvatar: AvatarHakushiType[];
+ listEnemy: EnemyHakushiType[];
setListAvatar: (list: AvatarHakushiType[]) => void;
+ setListEnemy: (list: EnemyHakushiType[]) => void;
}
const useAvatarDataStore = create((set) => ({
listAvatar: [],
+ listEnemy: [],
setListAvatar: (list: AvatarHakushiType[]) => set({ listAvatar: list }),
-
+ setListEnemy: (list: EnemyHakushiType[]) => set({ listEnemy: list }),
}));
export default useAvatarDataStore;
\ No newline at end of file
diff --git a/src/stores/battleDataStore.ts b/src/stores/battleDataStore.ts
index 56e9256..6bb4923 100644
--- a/src/stores/battleDataStore.ts
+++ b/src/stores/battleDataStore.ts
@@ -1,4 +1,4 @@
-import { DamageType, AvatarAnalysisJson, UseSkillType, BattleBeginType, BattleEndType, DamageDetailType, EntityDefeatedType, SetBattleLineupType, TurnBeginType, TurnEndType, UpdateCycleType, UpdateWaveType, VersionType, StatType, StatChangeType, UpdateTeamFormationType } from '@/types';
+import { DamageType, AvatarAnalysisJson, UseSkillType, BattleBeginType, BattleEndType, DamageDetailType, EntityDefeatedType, SetBattleLineupType, TurnBeginType, TurnEndType, UpdateCycleType, UpdateWaveType, VersionType, StatChangeType, UpdateTeamFormationType } from '@/types';
import { InitializeEnemyType } from '@/types/enemy';
import { AvatarBattleInfo, AvatarInfo, BattleDataStateJson, EnemyInfo, SkillBattleInfo, TurnBattleInfo } from '@/types/mics';
import { create } from 'zustand'
diff --git a/src/types/enemy.ts b/src/types/enemy.ts
index 785d2a5..49383bb 100644
--- a/src/types/enemy.ts
+++ b/src/types/enemy.ts
@@ -9,4 +9,28 @@ export interface EnemyType {
export interface InitializeEnemyType {
enemy: EnemyType
-}
\ No newline at end of file
+}
+
+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 {
+ id: string;
+ rank: string;
+ camp: string | null;
+ icon: string;
+ child: number[];
+ weak: string[];
+ desc: string;
+ lang: Map;
+}
diff --git a/src/types/index.ts b/src/types/index.ts
index dbc8c09..f8674a5 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -9,3 +9,4 @@ export * from "./srtools"
export * from "./version"
export * from "./entity"
export * from "./stat"
+export * from "./enemy"