From 6a9731b882be406ba52d1621b27e19d85a40c78b Mon Sep 17 00:00:00 2001 From: AzenKain Date: Sun, 27 Apr 2025 13:53:19 +0700 Subject: [PATCH] update for v4 --- messages/cn.json | 75 ------- messages/en.json | 2 +- messages/{jp.json => ja.json} | 2 +- messages/{kr.json => ko.json} | 2 +- messages/vi.json | 2 +- messages/zh.json | 6 +- package-lock.json | 331 +++++++++++++++++++++++++++++ package.json | 1 + src/app/page.tsx | 14 +- src/components/actionbar/index.tsx | 64 +++--- src/components/header/index.tsx | 51 +++-- src/components/lineupbar/index.tsx | 68 +++--- src/helper/getNameChar.ts | 7 +- src/lib/constant.ts | 7 + src/lib/socket.ts | 8 + 15 files changed, 470 insertions(+), 170 deletions(-) delete mode 100644 messages/cn.json rename messages/{jp.json => ja.json} (98%) rename messages/{kr.json => ko.json} (98%) create mode 100644 src/lib/constant.ts diff --git a/messages/cn.json b/messages/cn.json deleted file mode 100644 index 25d39c1..0000000 --- a/messages/cn.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "TabTitle": { - "title": "Firefly 分析器", - "description": "Veritas 分析工具" - }, - "DataAnalysisPage": { - "useSkill": "使用技能", - "totalDamage": "总伤害", - "damagePerAV": "每行动值伤害", - "totalAV": "总行动值", - "damagerPerCycle": "每轮伤害", - "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": "尚未有回合", - "style": "风格", - "warrior": "毁灭", - "knight": "存护", - "mage": "智识", - "priest": "丰饶", - "rouge": "巡猎", - "shaman": "同协", - "warlock": "虚无", - "memory": "记忆", - "fire": "火", - "ice": "冰", - "imaginary": "虚数", - "physical": "物理", - "quantum": "量子", - "thunder": "雷", - "wind": "风" - } -} diff --git a/messages/en.json b/messages/en.json index 7e48e06..2c32730 100644 --- a/messages/en.json +++ b/messages/en.json @@ -55,7 +55,7 @@ "noDamageDetail": "No damage details available", "noCharactersInLineup": "No characters in lineup", "noTurns": "No turns yet", - "style": "Style", + "type": "Type", "warrior": "Destruction", "knight": "Preservation", "mage": "Erudition", diff --git a/messages/jp.json b/messages/ja.json similarity index 98% rename from messages/jp.json rename to messages/ja.json index 7a5a76e..0db06cf 100644 --- a/messages/jp.json +++ b/messages/ja.json @@ -55,7 +55,7 @@ "noDamageDetail": "ダメージの詳細は利用できません", "noCharactersInLineup": "編成にキャラクターがいません", "noTurns": "まだターンがありません", - "style": "スタイル", + "type": "タイプ", "warrior": "破壊", "knight": "保護", "mage": "博識", diff --git a/messages/kr.json b/messages/ko.json similarity index 98% rename from messages/kr.json rename to messages/ko.json index 6ded2af..d3ebeda 100644 --- a/messages/kr.json +++ b/messages/ko.json @@ -55,7 +55,7 @@ "noDamageDetail": "데미지 세부 정보가 없습니다", "noCharactersInLineup": "라인업에 캐릭터가 없습니다", "noTurns": "아직 턴이 없습니다", - "style": "스타일", + "type": "타입 ", "warrior": "파괴", "knight": "보존", "mage": "지식", diff --git a/messages/vi.json b/messages/vi.json index d00d4d6..26ab286 100644 --- a/messages/vi.json +++ b/messages/vi.json @@ -55,7 +55,7 @@ "noDamageDetail": "Không có chi tiết sát thương", "noCharactersInLineup": "Không có nhân vật trong đội hình", "noTurns": "Chưa có lượt hành động", - "style": "Kiểu", + "type": "Loại", "warrior": "Hủy Diệt", "knight": "Bảo Hộ", "mage": "Tri Thức", diff --git a/messages/zh.json b/messages/zh.json index 25d39c1..6a6ab73 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -18,14 +18,14 @@ "rarity": "稀有度", "damageByActionValue": "此行动值的伤害", "element": "属性", - "totalTurn": "总轮次", + "totalTurn": "总回合", "technique": "密技", "talent": "天赋", "basic": "普攻", "skill": "战技", "ultimate": "终结技", "servant": "忆灵", - "skillDamageBreakdown": "技能伤害细分", + "skillDamageBreakdown": "技能类别", "skillUsageDistribution": "技能使用分布", "damageOverTime": "累计伤害", "damage": "伤害", @@ -55,7 +55,7 @@ "noDamageDetail": "没有可用的伤害详情", "noCharactersInLineup": "队伍中没有角色", "noTurns": "尚未有回合", - "style": "风格", + "type": "类型 ", "warrior": "毁灭", "knight": "存护", "mage": "智识", diff --git a/package-lock.json b/package-lock.json index b8ce99a..c6f4b06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "devDependencies": { "@eslint/eslintrc": "^3", "@tailwindcss/postcss": "^4", + "@types/jest": "^29.5.14", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -47,6 +48,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@emnapi/core": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", @@ -759,6 +785,50 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@kurkle/color": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", @@ -1399,6 +1469,13 @@ "integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==", "license": "MIT" }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -1706,6 +1783,44 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1750,6 +1865,30 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.30.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", @@ -2657,6 +2796,22 @@ "chart.js": ">=3.0.0" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -2894,6 +3049,16 @@ "node": ">=8" } }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -3595,6 +3760,23 @@ "node": ">=0.10.0" } }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4529,6 +4711,87 @@ "node": ">= 0.4" } }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jiti": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", @@ -5467,6 +5730,41 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5954,6 +6252,16 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/socket.io-client": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", @@ -6032,6 +6340,29 @@ "dev": true, "license": "MIT" }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", diff --git a/package.json b/package.json index 2565e55..3e480b1 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "devDependencies": { "@eslint/eslintrc": "^3", "@tailwindcss/postcss": "^4", + "@types/jest": "^29.5.14", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", diff --git a/src/app/page.tsx b/src/app/page.tsx index d7af526..c233fba 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -44,14 +44,14 @@ export default function Home() { }, [expandedCharts]); return ( -
+
-
+
{transI18n("totalDamage")}: {Number(totalDamage).toFixed(2)} @@ -64,7 +64,7 @@ export default function Home() {
-
+
{expandedCharts.includes('chart1') ? ( @@ -112,7 +112,7 @@ export default function Home() { onClick={() => setModeLine(m as 0 | 1)} className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`} > - {transI18n("style")} {m} + {transI18n("type")} {m} ))}
@@ -120,7 +120,7 @@ export default function Home() {
{expandedCharts.includes('chart3') ? ( -
+
) : ( -
+
))}
diff --git a/src/components/actionbar/index.tsx b/src/components/actionbar/index.tsx index 356d434..88b3d10 100644 --- a/src/components/actionbar/index.tsx +++ b/src/components/actionbar/index.tsx @@ -19,13 +19,9 @@ export default function ActionBar() { const transI18n = useTranslations("DataAnalysisPage"); const turnListRef = useRef(null); - const parallelogramStyle: React.CSSProperties = { - transform: 'skew(-9deg)', - overflow: 'hidden', - }; const contentStyle: React.CSSProperties = { - transform: 'skew(9deg)', + display: 'flex', flexDirection: 'column', alignItems: 'center', @@ -71,7 +67,7 @@ export default function ActionBar() { }, [turnHistory.length]); return ( -
+
-
+
{turnHistory.length === 0 ? ( -
+

{transI18n("noTurns")}

) : ( @@ -128,45 +124,48 @@ export default function ActionBar() { const text = getNameChar(locale, data); return ( -
+
handleShow("action_detail_modal", data, turn)} - style={parallelogramStyle} - className="flex border bg-base-100 w-full hover:bg-base-200 transition-colors duration-200 border-cyan-400 border-l-4 cursor-pointer" + 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" >
{text}
-
{text}
+ +
{getNameChar(locale, data)}
-
-
- {`${transI18n("useSkill")}: ${turn.skillType}`} +
+
+ {`${transI18n("useSkill")}: ${transI18n(turn.skillType.toLowerCase())}`}
-
+
{`${transI18n("totalDamage")}: ${turn.totalDamage.toFixed(2)}`}
); + }) )}
+ {/* Character Detail Modal */} - +

- {transI18n("turnDetail").toUpperCase()} + {transI18n("turnDetail").toUpperCase()}

@@ -207,6 +206,7 @@ export default function ActionBar() {
{getNameChar(locale, { + console.log(navigator.language.slice(0, 2)) const cookieLocale = document.cookie.split("; ") .find((row) => row.startsWith("MYNEXTAPP_LOCALE")) ?.split("=")[1]; @@ -47,8 +50,8 @@ export default function Header() { setLocale(cookieLocale) } else { let browserLocale = navigator.language.slice(0, 2); - const listCurrentLanguage = ["jp", "kr", "en", "vi", "zh", "cn"] - if(!listCurrentLanguage.includes(browserLocale)) { + + if (!listCurrentLanguage.hasOwnProperty(browserLocale)) { browserLocale = "en" } setLocale(browserLocale); @@ -167,15 +170,33 @@ export default function Header() { className="menu menu-sm dropdown-content bg-base-100 rounded-box z-10 mt-3 w-52 p-2 shadow-md border border-base-200" >
  • - + <> + { + const file = e.target.files?.[0]; + if (file) { + importBattleData(file, loadBattleDataFromJSON) + .then(() => console.log('Data loaded')) + .catch(err => alert('Failed to load data: ' + err.message)); + } + }} + /> + +
  • @@ -193,7 +214,7 @@ export default function Header() { {/* Logo */} - +

    Firefly Analy @@ -256,12 +277,13 @@ export default function Header() {
    -
    +
    {status ? transI18n("connected") : transI18n("unconnected")}
    + {/* Language selector - REFINED */}
    @@ -274,11 +296,10 @@ export default function Header() { value={locale} onChange={(e) => changeLocale(e.target.value)} > - - - - - + {Object.entries(listCurrentLanguage).map(([key, value]) => ( + + ))} +
    @@ -347,7 +368,7 @@ export default function Header() { {/* GitHub Link */} +
    {transI18n("noCharactersInLineup")}

    ) : ( -
    +
    -
    + .custom-scrollbar::-webkit-scrollbar-button { + display: none; + height: 0; + width: 0; + } + `} + +
    {lineupAvatars.map((item, index) => ( handleShow("character_detail_modal", item)} > @@ -130,6 +131,7 @@ export default function LineupBar() { ))}
    + )} {/* Character Detail Modal */} @@ -165,7 +167,7 @@ export default function LineupBar() {

    - {transI18n("id")}: {selectedCharacter.id} + {transI18n("id")}: {selectedCharacter.id}

    {transI18n("path")}: @@ -180,7 +182,7 @@ export default function LineupBar() { )}

    - {transI18n("rarity")}: {selectedCharacter.rank === "CombatPowerAvatarRarityType5" ? "5*" : "4*"} + {transI18n("rarity")}: {selectedCharacter.rank === "CombatPowerAvatarRarityType5" ? "5*" : "4*"}

    {transI18n("element")}: @@ -232,7 +234,7 @@ export default function LineupBar() { onClick={() => setModeLine(m as 0 | 1)} className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`} > - {transI18n("style")} {m} + {transI18n("type")} {m} ))}

    @@ -256,7 +258,7 @@ export default function LineupBar() { onClick={() => setModeBar(m as 0 | 1 | 2)} className={`btn btn-sm ${modeBar === m ? "btn-accent" : "btn-ghost"}`} > - {transI18n("style")} {m} + {transI18n("type")} {m} ))}
    diff --git a/src/helper/getNameChar.ts b/src/helper/getNameChar.ts index b71cff9..0d52d1b 100644 --- a/src/helper/getNameChar.ts +++ b/src/helper/getNameChar.ts @@ -1,3 +1,4 @@ +import { listCurrentLanguage } from "@/lib/constant"; import { AvatarType } from "@/types"; @@ -5,7 +6,11 @@ export function getNameChar(locale: string, data: AvatarType | undefined): strin if (!data) { return "" } - let text = data.lang.get(locale) ?? ""; + if (!listCurrentLanguage.hasOwnProperty(locale)) { + return "" + } + + let text = data.lang.get(listCurrentLanguage[locale as keyof typeof listCurrentLanguage].toLowerCase()) ?? ""; if (!text) { text = data.lang.get("en") ?? ""; } diff --git a/src/lib/constant.ts b/src/lib/constant.ts new file mode 100644 index 0000000..071fb5d --- /dev/null +++ b/src/lib/constant.ts @@ -0,0 +1,7 @@ +export const listCurrentLanguage = { + ja: "JP", + ko: "KR", + en: "US", + vi: "VN", + zh: "CN" +}; \ No newline at end of file diff --git a/src/lib/socket.ts b/src/lib/socket.ts index 7b3bbcb..6de662c 100644 --- a/src/lib/socket.ts +++ b/src/lib/socket.ts @@ -77,12 +77,16 @@ export const connectSocket = (): Socket => { socket.on("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json))); socket.on("TurnEnd", (json) => onTurnEndService(JSON.parse(json))); + socket.on("OnTurnEnd", (json) => onTurnEndService(JSON.parse(json))); socket.on("OnUseSkill", (json) => onUseSkillService(JSON.parse(json))); socket.on("OnKill", (json) => onKillService(JSON.parse(json))); socket.on("OnDamage", (json) => onDamageService(JSON.parse(json))); socket.on('BattleBegin', () => onBattleBegin()); + socket.on('OnBattleBegin', () => onBattleBegin()); socket.on('TurnBegin', (json) => onTurnBeginService(JSON.parse(json))); + socket.on('OnTurnBegin', (json) => onTurnBeginService(JSON.parse(json))); socket.on('BattleEnd', (json) => onBattleEndService(JSON.parse(json))); + socket.on('OnBattleEnd', (json) => onBattleEndService(JSON.parse(json))); socket.on("Error", (msg: string) => { console.error("Server Error:", msg); @@ -104,12 +108,16 @@ export const disconnectSocket = (): void => { if (socket) { socket.off("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json))); socket.off("TurnEnd", (json) => onTurnEndService(JSON.parse(json))); + socket.off("OnTurnEnd", (json) => onTurnEndService(JSON.parse(json))); socket.off("OnUseSkill", (json) => onUseSkillService(JSON.parse(json))); socket.off("OnKill", (json) => onKillService(JSON.parse(json))); socket.off("OnDamage", (json) => onDamageService(JSON.parse(json))); socket.off('BattleBegin', () => onBattleBegin()); + socket.off('OnBattleBegin', () => onBattleBegin()); socket.off('TurnBegin', (json) => onTurnBeginService(JSON.parse(json))); + socket.off('OnTurnBegin', (json) => onTurnBeginService(JSON.parse(json))); socket.off('BattleEnd', (json) => onBattleEndService(JSON.parse(json))); + socket.off('OnBattleEnd', (json) => onBattleEndService(JSON.parse(json))); socket.offAny(); socket.disconnect(); useSocketStore.getState().setStatus(false);