/* eslint-disable react-hooks/exhaustive-deps */ "use client" import { downloadJson } from "@/helper"; import { converterToFreeSRJson } from "@/helper/converterToFreeSRJson"; import { useChangeTheme } from "@/hooks/useChangeTheme"; import { listCurrentLanguage } from "@/constant/constant"; import useLocaleStore from "@/stores/localeStore"; import useUserDataStore from "@/stores/userDataStore"; import { motion } from "framer-motion"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import EnkaImport from "../importBar/enka"; import useModelStore from "@/stores/modelStore"; import FreeSRImport from "../importBar/freesr"; import { toast } from "react-toastify"; import { micsSchema } from "@/zod"; import useGlobalStore from "@/stores/globalStore"; import MonsterBar from "../monsterBar"; import Image from "next/image"; import ConnectBar from "../connectBar"; import ExtraSettingBar from "../extraSettingBar"; import ChangelogBar from "../changelog"; import { ModalConfig } from "@/types"; import { ScrollText } from "lucide-react"; const themes = [ { label: "Winter" }, { label: "Night" }, { label: "Cupcake" }, { label: "Coffee" }, ]; export default function Header() { const { changeTheme } = useChangeTheme() const { locale, setLocale } = useLocaleStore() const { avatars, battle_type, setAvatars, setBattleType, moc_config, pf_config, as_config, ce_config, peak_config, setMocConfig, setPfConfig, setAsConfig, setCeConfig, setPeakConfig, } = useUserDataStore() const router = useRouter() const transI18n = useTranslations("DataPage") const { setIsOpenImport, isOpenImport, setIsOpenMonster, isOpenMonster, setIsOpenConnect, isOpenConnect, setIsOpenExtra, isOpenExtra, setIsChangelog, isChangelog } = useModelStore() const [importModal, setImportModal] = useState("enka"); const { isConnectPS, extraData } = useGlobalStore() useEffect(() => { const cookieLocale = document.cookie.split("; ") .find((row) => row.startsWith("MYNEXTAPP_LOCALE")) ?.split("=")[1]; if (cookieLocale) { if (!listCurrentLanguage.hasOwnProperty(cookieLocale)) { setLocale("en") } else { setLocale(cookieLocale) } } else { let browserLocale = navigator.language.slice(0, 2); if (!listCurrentLanguage.hasOwnProperty(browserLocale)) { browserLocale = "en" } setLocale(browserLocale); document.cookie = `MYNEXTAPP_LOCALE=${browserLocale};` router.refresh() } }, [router, setLocale]) const changeLocale = (newLocale: string) => { setLocale(newLocale) document.cookie = `MYNEXTAPP_LOCALE=${newLocale};` router.refresh() } const handleShow = (modalId: string) => { const modal = document.getElementById(modalId) as HTMLDialogElement | null; if (modal) { modal.showModal(); } }; // Close modal handler const handleCloseModal = (modalId: string) => { const modal = document.getElementById(modalId) as HTMLDialogElement | null; if (modal) { modal.close() } }; const modalConfigs: ModalConfig[] = [ { id: "connect_modal", title: transI18n("psConnection"), isOpen: isOpenConnect, onClose: () => { setIsOpenConnect(false) handleCloseModal("connect_modal") }, content: }, { id: "import_modal", title: transI18n("importSetting"), isOpen: isOpenImport, onClose: () => { setIsOpenImport(false) handleCloseModal("import_modal") }, content: ( <> {importModal === "enka" && } {importModal === "freesr" && } > ) }, { id: "monster_modal", title: transI18n("monsterSetting"), isOpen: isOpenMonster, onClose: () => { setIsOpenMonster(false) handleCloseModal("monster_modal") }, content: }, { id: "extra_modal", title: transI18n("extraSetting"), isOpen: isOpenExtra, onClose: () => { setIsOpenExtra(false) handleCloseModal("extra_modal") }, content: }, { id: "changelog_modal", title: "Changelog", isOpen: isChangelog, onClose: () => { setIsChangelog(false) handleCloseModal("changelog_modal") }, content: } ] // Handle ESC key to close modal useEffect(() => { for (const item of modalConfigs) { if (!item?.isOpen) { handleCloseModal(item?.id || "") } else { handleShow(item?.id || "") } } const handleEscKey = (event: KeyboardEvent) => { if (event.key === 'Escape') { for (const item of modalConfigs) { handleCloseModal(item?.id || "") } } }; window.addEventListener('keydown', handleEscKey); return () => window.removeEventListener('keydown', handleEscKey); }, [isOpenImport, isOpenMonster, isOpenConnect, isOpenExtra, isChangelog]); const handleImportDatabase = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) { toast.error(transI18n("pleaseSelectAFile")) return } if (!file.name.endsWith(".json") || file.type !== "application/json") { toast.error(transI18n("fileMustBeAValidJsonFile")) return } if (file) { const reader = new FileReader(); reader.onload = (e) => { try { const data = JSON.parse(e.target?.result as string); const parsed = micsSchema.parse(data) setAvatars(parsed.avatars) setBattleType(parsed.battle_type) setMocConfig(parsed.moc_config) setPfConfig(parsed.pf_config) setAsConfig(parsed.as_config) setCeConfig(parsed.ce_config) setPeakConfig(parsed.peak_config) toast.success(transI18n("importDatabaseSuccess")) } catch { toast.error(transI18n("fileMustBeAValidJsonFile")) } }; reader.readAsText(file); } }; return ( {/* Mobile menu dropdown */} {transI18n("loadData")} { setImportModal("freesr") setIsOpenImport(true) }}>{transI18n("freeSr")} <> document.getElementById('database-data-upload')?.click()} > {transI18n("database")} > { setImportModal("enka") setIsOpenImport(true) }}>{transI18n("enka")} {transI18n("exportData")} downloadJson("freesr-data", converterToFreeSRJson( avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config ) )}>{transI18n("freeSr")} downloadJson("database-data", { avatars: avatars, battle_type: battle_type, moc_config: moc_config, pf_config: pf_config, as_config: as_config, ce_config: ce_config, peak_config: peak_config })}>{transI18n("database")} { setIsOpenConnect(true) }} > {transI18n("connectSetting")} { setIsOpenMonster(true) }} className="disabled px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium" > {transI18n("monsterSetting")} {extraData && ( { setIsOpenExtra(true) }} className="disabled px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium" > {transI18n("extraSetting")} )} {/* Logo */} Firefly Sr Tools By Kain {/* Desktop navigation */} {transI18n("loadData")} { setImportModal("freesr") setIsOpenImport(true) }}>{transI18n("freeSr")} <> document.getElementById('database-data-upload')?.click()} > {transI18n("database")} > { setImportModal("enka") setIsOpenImport(true) }}>{transI18n("enka")} {transI18n("exportData")} downloadJson("freesr-data", converterToFreeSRJson( avatars, battle_type, moc_config, pf_config, as_config, ce_config, peak_config ) )}>{transI18n("freeSr")} downloadJson("database-data", { avatars: avatars, battle_type: battle_type, moc_config: moc_config, pf_config: pf_config, as_config: as_config, ce_config: ce_config, peak_config: peak_config })}>{transI18n("database")} { setIsOpenConnect(true) }} > {transI18n("connectSetting")} { setIsOpenMonster(true) }} className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium" > {transI18n("monsterSetting")} {extraData && ( { setIsOpenExtra(true) }} className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium" > {transI18n("extraSetting")} )} {/* Right side items */} {isConnectPS ? transI18n("connected") : transI18n("unconnected")} { setIsChangelog(true) }} > {/* Language selector - REFINED */} changeLocale(e.target.value)} > {Object.entries(listCurrentLanguage).map(([key, value]) => ( {value} ))} {themes.map((theme) => ( { if (changeTheme) changeTheme(theme.label.toLowerCase()); }} > {theme.label} ))} {/* GitHub Link */} {modalConfigs?.map(({ id, title, onClose, content }) => ( ✕ {title} {content} ))} ) }
By Kain