fix ja language, instead fetch by axios
This commit is contained in:
19
bun.lock
19
bun.lock
@@ -4,6 +4,7 @@
|
||||
"": {
|
||||
"name": "firefly-analytics",
|
||||
"dependencies": {
|
||||
"axios": "^1.9.0",
|
||||
"chart.js": "^4.4.9",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"framer-motion": "^12.7.4",
|
||||
@@ -316,10 +317,14 @@
|
||||
|
||||
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
|
||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||
|
||||
"axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="],
|
||||
|
||||
"axios": ["axios@1.9.0", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg=="],
|
||||
|
||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
@@ -360,6 +365,8 @@
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
@@ -386,6 +393,8 @@
|
||||
|
||||
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||
|
||||
"diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
|
||||
@@ -476,8 +485,12 @@
|
||||
|
||||
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
||||
|
||||
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||
|
||||
"form-data": ["form-data@4.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w=="],
|
||||
|
||||
"framer-motion": ["framer-motion@12.9.4", "", { "dependencies": { "motion-dom": "^12.9.4", "motion-utils": "^12.9.4", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-yaeGDmGQ3eCQEwZ95/pRQMaSh/Q4E2CK6JYOclG/PdjyQad0MULJ+JFVV8911Fl5a6tF6o0wgW8Dpl5Qx4Adjg=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
@@ -658,6 +671,10 @@
|
||||
|
||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
@@ -728,6 +745,8 @@
|
||||
|
||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||
|
||||
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||
|
||||
108
messages/cn.json
Normal file
108
messages/cn.json
Normal file
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"TabTitle": {
|
||||
"title": "Firefly 分析器",
|
||||
"description": "Veritas 分析工具"
|
||||
},
|
||||
"DataAnalysisPage": {
|
||||
"useSkill": "使用技能",
|
||||
"totalDamage": "总伤害",
|
||||
"damagePerAV": "每行动值伤害",
|
||||
"totalAV": "总行动值",
|
||||
"skillType": "技能类型",
|
||||
"skillName": "技能名称",
|
||||
"actionValue": "行动值",
|
||||
"character": "角色",
|
||||
"id": "ID",
|
||||
"path": "命途",
|
||||
"rarity": "稀有度",
|
||||
"damageByActionValue": "此行动值的伤害",
|
||||
"element": "属性",
|
||||
"totalTurn": "总回合",
|
||||
"technique": "密技",
|
||||
"talent": "天赋",
|
||||
"basic": "普攻",
|
||||
"skill": "战技",
|
||||
"ultimate": "终结技",
|
||||
"servant": "忆灵",
|
||||
"skillDamageBreakdown": "技能类别",
|
||||
"skillUsageDistribution": "技能使用分布",
|
||||
"damageOverTime": "累计伤害",
|
||||
"damage": "伤害",
|
||||
"cumulativeDamage": "累计伤害量",
|
||||
"characterInformation": "角色信息",
|
||||
"turnDetail": "轮次详情",
|
||||
"damageDetails": "伤害详情",
|
||||
"cycleCount": "轮次",
|
||||
"chartInfo": "图表信息",
|
||||
"actionBar": "行动轴",
|
||||
"lineupInfo": "阵容信息",
|
||||
"loadData": "加载战斗数据",
|
||||
"exportData": "导出战斗数据",
|
||||
"connectSetting": "连接设置",
|
||||
"connected": "已连接",
|
||||
"unconnected": "未连接",
|
||||
"socketConnection": "socket连接",
|
||||
"connectionType": "连接类型",
|
||||
"status": "状态",
|
||||
"connect": "连接",
|
||||
"checkGameConnect": "检查游戏连接",
|
||||
"other": "其他",
|
||||
"host": "主机",
|
||||
"port": "端口",
|
||||
"hostPlaceHolder": "输入主机地址",
|
||||
"portPlaceHolder": "输入端口号",
|
||||
"noDamageDetail": "没有可用的伤害详情",
|
||||
"noCharactersInLineup": "队伍中没有角色",
|
||||
"noTurns": "尚未有回合",
|
||||
"type": "类型 ",
|
||||
"warrior": "毁灭",
|
||||
"knight": "存护",
|
||||
"mage": "智识",
|
||||
"priest": "丰饶",
|
||||
"rouge": "巡猎",
|
||||
"shaman": "同协",
|
||||
"warlock": "虚无",
|
||||
"memory": "记忆",
|
||||
"fire": "火",
|
||||
"ice": "冰",
|
||||
"imaginary": "虚数",
|
||||
"physical": "物理",
|
||||
"quantum": "量子",
|
||||
"thunder": "雷",
|
||||
"wind": "风",
|
||||
"cycle": "回合",
|
||||
"wave": "波次",
|
||||
"hp": "生命值",
|
||||
"atk": "攻击力",
|
||||
"speed": "速度",
|
||||
"critRate": "暴击率",
|
||||
"critDmg": "暴击伤害",
|
||||
"breakEffect": "击破特攻",
|
||||
"effectRes": "效果抵抗",
|
||||
"energyRegenerationRate": "能量回复效率",
|
||||
"effectHitRate": "效果命中",
|
||||
"outgoingHealingBoost": "治疗量加成",
|
||||
"fireDmgBoost": "火属性伤害提高",
|
||||
"iceDmgBoost": "冰属性伤害提高",
|
||||
"imaginaryDmgBoost": "虚数属性伤害提高",
|
||||
"physicalDmgBoost": "物理属性伤害提高",
|
||||
"quantumDmgBoost": "量子属性伤害提高",
|
||||
"thunderDmgBoost": "雷属性伤害提高",
|
||||
"windDmgBoost": "风属性伤害提高",
|
||||
"pursued": "附加伤害",
|
||||
"true damage": "真实伤害",
|
||||
"follow-up": "追加攻击",
|
||||
"elemental damage": "击破与超击破伤害",
|
||||
"dot": "持续伤害 ",
|
||||
"damagePerCycle": "每轮伤害",
|
||||
"damagePerCycleAndWave": "每轮/波伤害",
|
||||
"damagePerWave": "每波伤害",
|
||||
"lastTurn": "最后一回合",
|
||||
"qte": "QTE技能",
|
||||
"mazenormal": "普通迷宫",
|
||||
"level": "等级",
|
||||
"relics": "遗器",
|
||||
"eidolons": "星魂",
|
||||
"lightcones": "光锥"
|
||||
}
|
||||
}
|
||||
@@ -29,14 +29,7 @@ const nextConfig: NextConfig = {
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/api/hakushin',
|
||||
destination: 'https://api.hakush.in/hsr/data/character.json',
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default withNextIntl(nextConfig);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.9.0",
|
||||
"chart.js": "^4.4.9",
|
||||
"chartjs-plugin-datalabels": "^2.2.0",
|
||||
"framer-motion": "^12.7.4",
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useTranslations } from "next-intl";
|
||||
import { motion } from "framer-motion";
|
||||
import { getNameChar } from "@/helper";
|
||||
import Image from "next/image";
|
||||
import NameAvatar from "../nameAvatar";
|
||||
|
||||
export default function ActionBar() {
|
||||
const [selectTurn, setSelectTurn] = useState<SkillBattleInfo | null>(null);
|
||||
@@ -128,8 +129,11 @@ export default function ActionBar() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-base-content text-center text-sm mt-1 font-medium">{getNameChar(locale, data)}</div>
|
||||
<NameAvatar
|
||||
locale={locale}
|
||||
text={getNameChar(locale, data)}
|
||||
className="text-base-content text-center text-sm mt-1 font-medium"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 justify-center gap-2 py-2 w-full">
|
||||
<div className="bg-local text-primary text-xs max-w-full">
|
||||
@@ -180,14 +184,18 @@ export default function ActionBar() {
|
||||
<h4 className="text-lg font-semibold mb-2 text-pink-500">{transI18n("characterInformation")}</h4>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 items-center">
|
||||
<div className="flex flex-col space-y-2">
|
||||
<p className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium text-base-content/70">{transI18n("id")}:</span>
|
||||
<span className="font-bold">{selectAvatar.id}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-medium text-base-content/70">{transI18n("character")}:</span>
|
||||
<span className="font-bold">{getNameChar(locale, selectAvatar)}</span>
|
||||
</p>
|
||||
<NameAvatar
|
||||
locale={locale}
|
||||
text={getNameChar(locale, selectAvatar)}
|
||||
className="font-bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center items-center">
|
||||
<Image
|
||||
|
||||
@@ -3,16 +3,12 @@
|
||||
import { getNameChar } from '@/helper';
|
||||
import useLocaleStore from '@/stores/localeStore';
|
||||
import { AvatarHakushiType } from '@/types';
|
||||
import NameAvatar from '../nameAvatar';
|
||||
|
||||
interface CharacterCardProps {
|
||||
data: AvatarHakushiType
|
||||
}
|
||||
|
||||
export function parseRuby(text: string): string {
|
||||
return text.replace(/\{RUBY_B#(.*?)\}(.*?)\{RUBY_E#\}/g, (_, furigana, kanji) => {
|
||||
return `<ruby>${kanji}<rt>${furigana}</rt></ruby>`;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export default function CharacterCard({ data }: CharacterCardProps) {
|
||||
@@ -21,8 +17,7 @@ export default function CharacterCard({ data }: CharacterCardProps) {
|
||||
return (
|
||||
<li className="z-10 flex flex-col w-28 items-center p-1 rounded-md shadow-lg bg-gradient-to-b from-customStart to-customEnd transform transition-transform duration-300 hover:scale-105 m-1">
|
||||
<div
|
||||
className={`w-[80px] rounded-md p-[2px] bg-gradient-to-br ${
|
||||
data.rank === "CombatPowerAvatarRarityType5"
|
||||
className={`w-[80px] rounded-md p-[2px] bg-gradient-to-br ${data.rank === "CombatPowerAvatarRarityType5"
|
||||
? "from-yellow-400 via-yellow-300 to-yellow-500"
|
||||
: "from-purple-300 via-purple-200 to-purple-400"
|
||||
}`}
|
||||
@@ -50,16 +45,11 @@ export default function CharacterCard({ data }: CharacterCardProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{locale === "jp" ? (
|
||||
<div
|
||||
<NameAvatar
|
||||
locale={locale}
|
||||
text={text}
|
||||
className="mt-2 text-center text-base font-normal leading-tight"
|
||||
dangerouslySetInnerHTML={{ __html: parseRuby(text) }}
|
||||
/>
|
||||
) : (
|
||||
<div className="mt-2 text-center text-base font-normal leading-tight">
|
||||
{text}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function Header() {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
console.log(navigator.language.slice(0, 2))
|
||||
|
||||
const cookieLocale = document.cookie.split("; ")
|
||||
.find((row) => row.startsWith("MYNEXTAPP_LOCALE"))
|
||||
?.split("=")[1];
|
||||
|
||||
@@ -14,10 +14,11 @@ import { DamageLineForOne } from "../chart/damageLineForOne";
|
||||
import { DamagePerCycleForOne } from "../chart/damagePerCycleForOne";
|
||||
import { useCalcTotalDmgAvatar, useCalcTotalTurnAvatar } from "@/hooks/useCalcAvatarData";
|
||||
import Image from "next/image";
|
||||
import NameAvatar from "../nameAvatar";
|
||||
// import ShowCaseInfo from "../card/showCaseCard";
|
||||
|
||||
export default function LineupBar() {
|
||||
const [selectedCharacter, setSelectedCharacter] = useState<AvatarHakushiType | null>(null);
|
||||
const [selectedCharacter, setSelectedCharacter] = useState<AvatarHakushiType | undefined>(undefined);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
const transI18n = useTranslations("DataAnalysisPage");
|
||||
@@ -44,7 +45,7 @@ export default function LineupBar() {
|
||||
// Close modal handler
|
||||
const handleCloseModal = (modalId: string) => {
|
||||
setIsModalOpen(false);
|
||||
setSelectedCharacter(null);
|
||||
setSelectedCharacter(undefined);
|
||||
const modal = document.getElementById(modalId) as HTMLDialogElement | null;
|
||||
if (modal) {
|
||||
modal.close()
|
||||
@@ -80,7 +81,16 @@ export default function LineupBar() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>
|
||||
|
||||
<span className="text-sm truncate">{transI18n("lastTurn")}: {getNameChar(locale, listAvatar.find(it => it.id === turnHistory.findLast(i => i?.avatarId)?.avatarId?.toString()))}</span>
|
||||
<span className="text-sm truncate flex flex-row">
|
||||
<div>
|
||||
{transI18n("lastTurn")}:
|
||||
</div>
|
||||
|
||||
<NameAvatar
|
||||
locale={locale}
|
||||
text={getNameChar(locale, listAvatar.find(it => it.id === turnHistory.findLast(i => i?.avatarId)?.avatarId?.toString()))}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -132,9 +142,12 @@ export default function LineupBar() {
|
||||
</div>
|
||||
|
||||
<div className="border-b border-purple-500/30 px-6 py-4 mb-4">
|
||||
<h3 className="font-bold text-2xl text-transparent bg-clip-text bg-gradient-to-r from-pink-400 to-cyan-400">
|
||||
{selectedCharacter ? getNameChar(locale, selectedCharacter).toUpperCase() : ""}
|
||||
</h3>
|
||||
|
||||
<NameAvatar
|
||||
locale={locale}
|
||||
text={getNameChar(locale, selectedCharacter).toUpperCase()}
|
||||
className={"font-bold text-2xl text-transparent bg-clip-text bg-gradient-to-r from-pink-400 to-cyan-400"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{selectedCharacter && (
|
||||
|
||||
16
src/components/nameAvatar/index.tsx
Normal file
16
src/components/nameAvatar/index.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { parseRuby } from "@/helper";
|
||||
|
||||
|
||||
|
||||
interface TextProps {
|
||||
text: string;
|
||||
locale: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function NameAvatar({ text, locale, className }: TextProps) {
|
||||
if (locale === "ja") {
|
||||
return <div className={className} dangerouslySetInnerHTML={{ __html: parseRuby(text) }} />;
|
||||
}
|
||||
return <div className={className}>{text}</div>;
|
||||
}
|
||||
@@ -19,6 +19,12 @@ export function getNameChar(locale: string, data: AvatarHakushiType | undefined)
|
||||
} else if (Number(data.id) > 8000) {
|
||||
text = `Male ${data.damageType} MC`
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
export function parseRuby(text: string): string {
|
||||
const rubyRegex = /\{RUBY_B#(.*?)\}(.*?)\{RUBY_E#\}/gs;
|
||||
return text.replace(rubyRegex, (_match, furigana, kanji) => {
|
||||
return `<ruby>${kanji}<rt>${furigana}</rt></ruby>`;
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import useSocketStore from "@/stores/socketSettingStore";
|
||||
import { AvatarHakushiType, AvatarHakushiRawType } from "@/types/avatar";
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
export async function checkConnectTcpApi(): Promise<boolean> {
|
||||
const { host, port, connectionType } = useSocketStore.getState()
|
||||
@@ -23,22 +23,27 @@ export async function checkConnectTcpApi(): Promise<boolean> {
|
||||
}
|
||||
|
||||
export async function getCharacterListApi(): Promise<AvatarHakushiType[]> {
|
||||
const res = await fetch('/api/hakushin', {
|
||||
method: 'GET',
|
||||
try {
|
||||
const res = await axios.get<Record<string, AvatarHakushiRawType>>(
|
||||
'https://api.hakush.in/hsr/data/character.json',
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.log(`Error ${res.status}: ${res.statusText}`);
|
||||
return [];
|
||||
}
|
||||
);
|
||||
|
||||
const data: Map<string, AvatarHakushiRawType> = new Map(Object.entries(await res.json()));
|
||||
|
||||
const data = new Map(Object.entries(res.data));
|
||||
|
||||
return Array.from(data.entries()).map(([id, it]) => convertAvatar(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 [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"target": "ES2018",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
@@ -19,9 +22,19 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user