update for v4
This commit is contained in:
@@ -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": "风"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"noDamageDetail": "No damage details available",
|
"noDamageDetail": "No damage details available",
|
||||||
"noCharactersInLineup": "No characters in lineup",
|
"noCharactersInLineup": "No characters in lineup",
|
||||||
"noTurns": "No turns yet",
|
"noTurns": "No turns yet",
|
||||||
"style": "Style",
|
"type": "Type",
|
||||||
"warrior": "Destruction",
|
"warrior": "Destruction",
|
||||||
"knight": "Preservation",
|
"knight": "Preservation",
|
||||||
"mage": "Erudition",
|
"mage": "Erudition",
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
"noDamageDetail": "ダメージの詳細は利用できません",
|
"noDamageDetail": "ダメージの詳細は利用できません",
|
||||||
"noCharactersInLineup": "編成にキャラクターがいません",
|
"noCharactersInLineup": "編成にキャラクターがいません",
|
||||||
"noTurns": "まだターンがありません",
|
"noTurns": "まだターンがありません",
|
||||||
"style": "スタイル",
|
"type": "タイプ",
|
||||||
"warrior": "破壊",
|
"warrior": "破壊",
|
||||||
"knight": "保護",
|
"knight": "保護",
|
||||||
"mage": "博識",
|
"mage": "博識",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"noDamageDetail": "데미지 세부 정보가 없습니다",
|
"noDamageDetail": "데미지 세부 정보가 없습니다",
|
||||||
"noCharactersInLineup": "라인업에 캐릭터가 없습니다",
|
"noCharactersInLineup": "라인업에 캐릭터가 없습니다",
|
||||||
"noTurns": "아직 턴이 없습니다",
|
"noTurns": "아직 턴이 없습니다",
|
||||||
"style": "스타일",
|
"type": "타입 ",
|
||||||
"warrior": "파괴",
|
"warrior": "파괴",
|
||||||
"knight": "보존",
|
"knight": "보존",
|
||||||
"mage": "지식",
|
"mage": "지식",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"noDamageDetail": "Không có chi tiết sát thương",
|
"noDamageDetail": "Không có chi tiết sát thương",
|
||||||
"noCharactersInLineup": "Không có nhân vật trong đội hình",
|
"noCharactersInLineup": "Không có nhân vật trong đội hình",
|
||||||
"noTurns": "Chưa có lượt hành động",
|
"noTurns": "Chưa có lượt hành động",
|
||||||
"style": "Kiểu",
|
"type": "Loại",
|
||||||
"warrior": "Hủy Diệt",
|
"warrior": "Hủy Diệt",
|
||||||
"knight": "Bảo Hộ",
|
"knight": "Bảo Hộ",
|
||||||
"mage": "Tri Thức",
|
"mage": "Tri Thức",
|
||||||
|
|||||||
@@ -18,14 +18,14 @@
|
|||||||
"rarity": "稀有度",
|
"rarity": "稀有度",
|
||||||
"damageByActionValue": "此行动值的伤害",
|
"damageByActionValue": "此行动值的伤害",
|
||||||
"element": "属性",
|
"element": "属性",
|
||||||
"totalTurn": "总轮次",
|
"totalTurn": "总回合",
|
||||||
"technique": "密技",
|
"technique": "密技",
|
||||||
"talent": "天赋",
|
"talent": "天赋",
|
||||||
"basic": "普攻",
|
"basic": "普攻",
|
||||||
"skill": "战技",
|
"skill": "战技",
|
||||||
"ultimate": "终结技",
|
"ultimate": "终结技",
|
||||||
"servant": "忆灵",
|
"servant": "忆灵",
|
||||||
"skillDamageBreakdown": "技能伤害细分",
|
"skillDamageBreakdown": "技能类别",
|
||||||
"skillUsageDistribution": "技能使用分布",
|
"skillUsageDistribution": "技能使用分布",
|
||||||
"damageOverTime": "累计伤害",
|
"damageOverTime": "累计伤害",
|
||||||
"damage": "伤害",
|
"damage": "伤害",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"noDamageDetail": "没有可用的伤害详情",
|
"noDamageDetail": "没有可用的伤害详情",
|
||||||
"noCharactersInLineup": "队伍中没有角色",
|
"noCharactersInLineup": "队伍中没有角色",
|
||||||
"noTurns": "尚未有回合",
|
"noTurns": "尚未有回合",
|
||||||
"style": "风格",
|
"type": "类型 ",
|
||||||
"warrior": "毁灭",
|
"warrior": "毁灭",
|
||||||
"knight": "存护",
|
"knight": "存护",
|
||||||
"mage": "智识",
|
"mage": "智识",
|
||||||
|
|||||||
331
package-lock.json
generated
331
package-lock.json
generated
@@ -24,6 +24,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
@@ -47,6 +48,31 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"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": {
|
"node_modules/@emnapi/core": {
|
||||||
"version": "1.4.3",
|
"version": "1.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz",
|
||||||
@@ -759,6 +785,50 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"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": {
|
"node_modules/@kurkle/color": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
||||||
@@ -1399,6 +1469,13 @@
|
|||||||
"integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==",
|
"integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@socket.io/component-emitter": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||||
@@ -1706,6 +1783,44 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@@ -1750,6 +1865,30 @@
|
|||||||
"@types/react": "^19.0.0"
|
"@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": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.30.1",
|
"version": "8.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz",
|
||||||
@@ -2657,6 +2796,22 @@
|
|||||||
"chart.js": ">=3.0.0"
|
"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": {
|
"node_modules/client-only": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
@@ -2894,6 +3049,16 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/doctrine": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||||
@@ -3595,6 +3760,23 @@
|
|||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@@ -4529,6 +4711,87 @@
|
|||||||
"node": ">= 0.4"
|
"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": {
|
"node_modules/jiti": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
||||||
@@ -5467,6 +5730,41 @@
|
|||||||
"node": ">= 0.8.0"
|
"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": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@@ -5954,6 +6252,16 @@
|
|||||||
"is-arrayish": "^0.3.1"
|
"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": {
|
"node_modules/socket.io-client": {
|
||||||
"version": "4.8.1",
|
"version": "4.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
|
||||||
@@ -6032,6 +6340,29 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/streamsearch": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ export default function Home() {
|
|||||||
}, [expandedCharts]);
|
}, [expandedCharts]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full w-full mt-5 min-h-[74vh] bg-base-100 font-[family-name:var(--font-geist-sans)]">
|
<div className="flex flex-col px-2 h-full w-full mt-5 min-h-[74vh] bg-base-100 font-[family-name:var(--font-geist-sans)]">
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
<div className="grid grid-cols-12 gap-2 lg:gap-3 h-full min-h-full">
|
<div className="grid grid-cols-12 gap-2 lg:gap-3 h-full min-h-full">
|
||||||
<div className="col-span-12 md:col-span-3 lg:col-span-2 xl:col-span-2 h-full">
|
<div className="col-span-12 md:col-span-3 lg:col-span-2 xl:col-span-2 h-full">
|
||||||
<ActionBar />
|
<ActionBar />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-span-12 md:col-span-6 lg:col-span-8 xl:col-span-8 flex flex-col h-full">
|
<div className="col-span-12 md:col-span-6 lg:col-span-8 xl:col-span-8 max-h-[90vh] flex flex-col h-full overflow-auto">
|
||||||
<div className="grid grid-cols-3 gap-2 mb-3">
|
<div className="grid grid-cols-3 gap-2 mb-3">
|
||||||
<div className="p-2 text-base lg:text-lg xl:text-xl rounded bg-primary text-primary-content text-center shadow-md">
|
<div className="p-2 text-base lg:text-lg xl:text-xl rounded bg-primary text-primary-content text-center shadow-md">
|
||||||
{transI18n("totalDamage")}: {Number(totalDamage).toFixed(2)}
|
{transI18n("totalDamage")}: {Number(totalDamage).toFixed(2)}
|
||||||
@@ -64,7 +64,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-base-200 rounded-lg p-2 shadow-md flex-grow">
|
<div className="rounded-lg p-2 shadow-md flex-grow">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
|
||||||
{expandedCharts.includes('chart1') ? (
|
{expandedCharts.includes('chart1') ? (
|
||||||
@@ -112,7 +112,7 @@ export default function Home() {
|
|||||||
onClick={() => setModeLine(m as 0 | 1)}
|
onClick={() => setModeLine(m as 0 | 1)}
|
||||||
className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`}
|
className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`}
|
||||||
>
|
>
|
||||||
{transI18n("style")} {m}
|
{transI18n("type")} {m}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -120,7 +120,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{expandedCharts.includes('chart3') ? (
|
{expandedCharts.includes('chart3') ? (
|
||||||
<div key="chart3-expanded" className="lg:col-span-2 bg-base-200 rounded-lg p-2 shadow-md relative">
|
<div key="chart3-expanded" className="lg:col-span-2 max-h-[70vh] bg-base-200 rounded-lg p-2 shadow-md relative">
|
||||||
<div className="absolute top-2 left-2 z-10">
|
<div className="absolute top-2 left-2 z-10">
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-circle btn-ghost"
|
className="btn btn-sm btn-circle btn-ghost"
|
||||||
@@ -132,7 +132,7 @@ export default function Home() {
|
|||||||
<DamagePercentChartForAll />
|
<DamagePercentChartForAll />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div key="chart3-normal" className="bg-base-200 rounded-lg p-2 shadow-md relative">
|
<div key="chart3-normal" className="bg-base-200 max-h-[40vh] rounded-lg p-2 shadow-md relative">
|
||||||
<div className="absolute top-2 left-2 z-10">
|
<div className="absolute top-2 left-2 z-10">
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-circle btn-ghost"
|
className="btn btn-sm btn-circle btn-ghost"
|
||||||
@@ -164,7 +164,7 @@ export default function Home() {
|
|||||||
onClick={() => setModeBar(m as 0 | 1 | 2)}
|
onClick={() => setModeBar(m as 0 | 1 | 2)}
|
||||||
className={`btn btn-sm ${modeBar === m ? "btn-accent" : "btn-ghost"}`}
|
className={`btn btn-sm ${modeBar === m ? "btn-accent" : "btn-ghost"}`}
|
||||||
>
|
>
|
||||||
{transI18n("style")} {m}
|
{transI18n("type")} {m}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,13 +19,9 @@ export default function ActionBar() {
|
|||||||
const transI18n = useTranslations("DataAnalysisPage");
|
const transI18n = useTranslations("DataAnalysisPage");
|
||||||
const turnListRef = useRef<HTMLDivElement>(null);
|
const turnListRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const parallelogramStyle: React.CSSProperties = {
|
|
||||||
transform: 'skew(-9deg)',
|
|
||||||
overflow: 'hidden',
|
|
||||||
};
|
|
||||||
|
|
||||||
const contentStyle: React.CSSProperties = {
|
const contentStyle: React.CSSProperties = {
|
||||||
transform: 'skew(9deg)',
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@@ -71,7 +67,7 @@ export default function ActionBar() {
|
|||||||
}, [turnHistory.length]);
|
}, [turnHistory.length]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 rounded-lg shadow-lg w-full h-full min-h-[74vh]">
|
<div className="p-4 md:p-1 rounded-lg shadow-lg w-full h-full">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
className="text-center text-xl lg:text-2xl mb-2 font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-purple-500 to-cyan-500"
|
className="text-center text-xl lg:text-2xl mb-2 font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-purple-500 to-cyan-500"
|
||||||
initial={{ opacity: 0, y: -20 }}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
@@ -82,7 +78,7 @@ export default function ActionBar() {
|
|||||||
</motion.h2>
|
</motion.h2>
|
||||||
<div
|
<div
|
||||||
ref={turnListRef}
|
ref={turnListRef}
|
||||||
className="flex px-2 w-full max-h-[90vh] pt-2 border-t-2 border-accent overflow-y-auto custom-scrollbar overflow-x-hidden"
|
className="flex md:block px-2 md:px-0 w-full pt-2 border-t-2 border-accent overflow-x-auto md:overflow-x-hidden md:overflow-y-auto max-h-[90vh] custom-scrollbar"
|
||||||
>
|
>
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.custom-scrollbar {
|
.custom-scrollbar {
|
||||||
@@ -116,9 +112,9 @@ export default function ActionBar() {
|
|||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
|
|
||||||
<div className="w-full h-fit grid grid-cols-1 gap-1 ">
|
<div className="flex flex-nowrap md:grid md:grid-cols-1 gap-2 w-fit md:w-full">
|
||||||
{turnHistory.length === 0 ? (
|
{turnHistory.length === 0 ? (
|
||||||
<div className="flex items-center justify-center h-full">
|
<div className="flex items-center justify-center h-full w-full">
|
||||||
<p className="text-base-content opacity-50">{transI18n("noTurns")}</p>
|
<p className="text-base-content opacity-50">{transI18n("noTurns")}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -128,45 +124,48 @@ export default function ActionBar() {
|
|||||||
const text = getNameChar(locale, data);
|
const text = getNameChar(locale, data);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index}>
|
<div key={index} className="h-full md:w-full">
|
||||||
<div
|
<div
|
||||||
onClick={() => handleShow("action_detail_modal", data, turn)}
|
onClick={() => handleShow("action_detail_modal", data, turn)}
|
||||||
style={parallelogramStyle}
|
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="flex border bg-base-100 w-full hover:bg-base-200 transition-colors duration-200 border-cyan-400 border-l-4 cursor-pointer"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={contentStyle}
|
style={contentStyle}
|
||||||
className="flex flex-col items-center justify-center py-2 px-3"
|
className="lg:col-span-1 grid grid-cols-1 items-center justify-center py-2"
|
||||||
>
|
>
|
||||||
<div className="avatar">
|
<div className="avatar">
|
||||||
<div className="w-12 h-12 rounded-full border-2 flex items-center justify-center bg-base-300 border-cyan-400 border-l-4">
|
<div className="w-12 h-12 rounded-full border-2 flex items-center justify-center bg-base-300 border-cyan-400 border-l-4">
|
||||||
<img
|
<img
|
||||||
src={`https://api.hakush.in/hsr/UI/avatarshopicon/${data.id}.webp`}
|
src={`https://api.hakush.in/hsr/UI/avatarshopicon/${data.id}.webp`}
|
||||||
alt={text}
|
alt={text}
|
||||||
|
loading="lazy"
|
||||||
className="w-8 h-8 object-contain"
|
className="w-8 h-8 object-contain"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-base-content text-sm mt-1 font-medium">{text}</div>
|
|
||||||
|
<div className="text-base-content text-center text-sm mt-1 font-medium">{getNameChar(locale, data)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center gap-2 px-3 py-2">
|
<div className="grid grid-cols-1 justify-center gap-2 py-2 w-full">
|
||||||
<div className="text-primary text-xs">
|
<div className="bg-local text-primary text-xs max-w-full">
|
||||||
{`${transI18n("useSkill")}: ${turn.skillType}`}
|
{`${transI18n("useSkill")}: ${transI18n(turn.skillType.toLowerCase())}`}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-primary text-xs">
|
<div className="text-primary text-xs max-w-full">
|
||||||
{`${transI18n("totalDamage")}: ${turn.totalDamage.toFixed(2)}`}
|
{`${transI18n("totalDamage")}: ${turn.totalDamage.toFixed(2)}`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/* Character Detail Modal */}
|
{/* Character Detail Modal */}
|
||||||
<dialog id="action_detail_modal" className="modal modal-bottom sm:modal-middle backdrop-blur-sm">
|
<dialog id="action_detail_modal" className="modal sm:modal-middle backdrop-blur-sm">
|
||||||
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
<div className="modal-box w-11/12 max-w-7xl bg-base-100 text-base-content border border-purple-500/50 shadow-lg shadow-purple-500/20">
|
||||||
<div className="sticky top-0 z-10">
|
<div className="sticky top-0 z-10">
|
||||||
<motion.button
|
<motion.button
|
||||||
@@ -207,6 +206,7 @@ export default function ActionBar() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
<img
|
<img
|
||||||
|
loading="lazy"
|
||||||
src={`https://api.hakush.in/hsr/UI/avatarshopicon/${selectAvatar.id}.webp`}
|
src={`https://api.hakush.in/hsr/UI/avatarshopicon/${selectAvatar.id}.webp`}
|
||||||
alt={getNameChar(locale, selectAvatar)}
|
alt={getNameChar(locale, selectAvatar)}
|
||||||
className="h-20 w-20 object-cover rounded-full border-2 border-purple-500 shadow-lg shadow-purple-500/20"
|
className="h-20 w-20 object-cover rounded-full border-2 border-purple-500 shadow-lg shadow-purple-500/20"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { exportBattleData, importBattleData } from "@/helper";
|
import { exportBattleData, importBattleData } from "@/helper";
|
||||||
import { useChangeTheme } from "@/hooks/useChangeTheme";
|
import { useChangeTheme } from "@/hooks/useChangeTheme";
|
||||||
import { checkConnectTcpApi } from "@/lib/api";
|
import { checkConnectTcpApi } from "@/lib/api";
|
||||||
|
import { listCurrentLanguage } from "@/lib/constant";
|
||||||
import { connectSocket, disconnectSocket, getSocket, isSocketConnected } from "@/lib/socket";
|
import { connectSocket, disconnectSocket, getSocket, isSocketConnected } from "@/lib/socket";
|
||||||
import useBattleDataStore from "@/stores/battleDataStore";
|
import useBattleDataStore from "@/stores/battleDataStore";
|
||||||
import useLocaleStore from "@/stores/localeStore";
|
import useLocaleStore from "@/stores/localeStore";
|
||||||
@@ -38,7 +39,9 @@ export default function Header() {
|
|||||||
const [message, setMessage] = useState({ text: '', type: '' });
|
const [message, setMessage] = useState({ text: '', type: '' });
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(navigator.language.slice(0, 2))
|
||||||
const cookieLocale = document.cookie.split("; ")
|
const cookieLocale = document.cookie.split("; ")
|
||||||
.find((row) => row.startsWith("MYNEXTAPP_LOCALE"))
|
.find((row) => row.startsWith("MYNEXTAPP_LOCALE"))
|
||||||
?.split("=")[1];
|
?.split("=")[1];
|
||||||
@@ -47,8 +50,8 @@ export default function Header() {
|
|||||||
setLocale(cookieLocale)
|
setLocale(cookieLocale)
|
||||||
} else {
|
} else {
|
||||||
let browserLocale = navigator.language.slice(0, 2);
|
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"
|
browserLocale = "en"
|
||||||
}
|
}
|
||||||
setLocale(browserLocale);
|
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"
|
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"
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="application/json"
|
||||||
|
id="battle-data-upload"
|
||||||
|
className="hidden"
|
||||||
|
onChange={(e) => {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium"
|
className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium"
|
||||||
|
onClick={() => document.getElementById('battle-data-upload')?.click()}
|
||||||
>
|
>
|
||||||
{transI18n("loadData")}
|
{transI18n("loadData")}
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium"
|
className="px-3 py-2 hover:bg-base-200 rounded-md transition-all duration-200 font-medium"
|
||||||
|
onClick={() => exportBattleData({ totalAV, totalDamage, turnHistory, damagePerAV, lineup } as BattleDataStateJson)}
|
||||||
>
|
>
|
||||||
{transI18n("exportData")}
|
{transI18n("exportData")}
|
||||||
</button>
|
</button>
|
||||||
@@ -193,7 +214,7 @@ export default function Header() {
|
|||||||
|
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
|
|
||||||
<a className=" flex flex-col items-start text-left gap-0 hover:scale-105 px-2">
|
<a className="hidden sm:grid sm:grid-cols-1 items-start text-left gap-0 hover:scale-105 px-2">
|
||||||
<h1 className="text-xl font-bold">
|
<h1 className="text-xl font-bold">
|
||||||
<span className="text-emerald-500">Firefly Analy</span>
|
<span className="text-emerald-500">Firefly Analy</span>
|
||||||
<span className="bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 via-orange-500 to-red-500">
|
<span className="bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 via-orange-500 to-red-500">
|
||||||
@@ -256,12 +277,13 @@ export default function Header() {
|
|||||||
<div className="navbar-end gap-2">
|
<div className="navbar-end gap-2">
|
||||||
<div className="px-2">
|
<div className="px-2">
|
||||||
<div className="flex items-center space-x-2 p-1.5 rounded-full shadow-md">
|
<div className="flex items-center space-x-2 p-1.5 rounded-full shadow-md">
|
||||||
<div className={`text-sm italic ${status ? 'text-green-500' : 'text-red-500'}`}>
|
<div className={`hidden lg:block text-sm italic ${status ? 'text-green-500' : 'text-red-500'}`}>
|
||||||
{status ? transI18n("connected") : transI18n("unconnected")}
|
{status ? transI18n("connected") : transI18n("unconnected")}
|
||||||
</div>
|
</div>
|
||||||
<div className={`w-3 h-3 rounded-full ${status ? 'bg-green-500' : 'bg-red-500'}`}></div>
|
<div className={`w-3 h-3 rounded-full ${status ? 'bg-green-500' : 'bg-red-500'}`}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Language selector - REFINED */}
|
{/* Language selector - REFINED */}
|
||||||
<div className="dropdown dropdown-end">
|
<div className="dropdown dropdown-end">
|
||||||
<div className="flex items-center gap-1 border border-base-300 rounded text-sm px-1.5 py-0.5 hover:bg-base-200 cursor-pointer transition-all duration-200">
|
<div className="flex items-center gap-1 border border-base-300 rounded text-sm px-1.5 py-0.5 hover:bg-base-200 cursor-pointer transition-all duration-200">
|
||||||
@@ -274,11 +296,10 @@ export default function Header() {
|
|||||||
value={locale}
|
value={locale}
|
||||||
onChange={(e) => changeLocale(e.target.value)}
|
onChange={(e) => changeLocale(e.target.value)}
|
||||||
>
|
>
|
||||||
<option value="vi">VI</option>
|
{Object.entries(listCurrentLanguage).map(([key, value]) => (
|
||||||
<option value="en">EN</option>
|
<option key={key} value={key}>{value}</option>
|
||||||
<option value="cn">CN</option>
|
))}
|
||||||
<option value="jp">JP</option>
|
|
||||||
<option value="kr">KR</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -347,7 +368,7 @@ export default function Header() {
|
|||||||
|
|
||||||
{/* GitHub Link */}
|
{/* GitHub Link */}
|
||||||
<Link
|
<Link
|
||||||
className='btn btn-ghost btn-sm btn-circle hover:bg-base-200 transition-all duration-200'
|
className='hidden sm:block btn btn-ghost btn-sm btn-circle hover:bg-base-200 transition-all duration-200'
|
||||||
href={"https://github.com/AzenKain/SR-Analysis"}
|
href={"https://github.com/AzenKain/SR-Analysis"}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default function LineupBar() {
|
|||||||
}, [isModalOpen]);
|
}, [isModalOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4 rounded-lg shadow-lg w-full h-full min-h-[74vh]">
|
<div className="p-4 md:p-1 rounded-lg shadow-lg w-full h-full">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
className="text-center text-xl lg:text-2xl pb-2 font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-purple-500 to-cyan-500"
|
className="text-center text-xl lg:text-2xl pb-2 font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 via-purple-500 to-cyan-500"
|
||||||
initial={{ opacity: 0, y: -20 }}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
@@ -82,7 +82,7 @@ export default function LineupBar() {
|
|||||||
<p className="text-base-content opacity-50">{transI18n("noCharactersInLineup")}</p>
|
<p className="text-base-content opacity-50">{transI18n("noCharactersInLineup")}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-full w-full overflow-y-auto overflow-x-hidden custom-scrollbar rounded-lg">
|
<div className="h-full w-full overflow-x-auto md:overflow-x-hidden md:overflow-y-auto custom-scrollbar rounded-lg">
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.custom-scrollbar {
|
.custom-scrollbar {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
@@ -114,7 +114,8 @@ export default function LineupBar() {
|
|||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
<div className="grid grid-cols-1 w-full justify-items-center items-start">
|
|
||||||
|
<div className="flex flex-nowrap md:grid md:grid-cols-1 w-fit md:w-full justify-items-center items-start gap-2">
|
||||||
{lineupAvatars.map((item, index) => (
|
{lineupAvatars.map((item, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
@@ -122,7 +123,7 @@ export default function LineupBar() {
|
|||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
transition={{ duration: 0.3, delay: index * 0.1 }}
|
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer flex-shrink-0 md:w-full justify-items-center"
|
||||||
onClick={() => handleShow("character_detail_modal", item)}
|
onClick={() => handleShow("character_detail_modal", item)}
|
||||||
>
|
>
|
||||||
<CharacterCard data={item} />
|
<CharacterCard data={item} />
|
||||||
@@ -130,6 +131,7 @@ export default function LineupBar() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Character Detail Modal */}
|
{/* Character Detail Modal */}
|
||||||
@@ -232,7 +234,7 @@ export default function LineupBar() {
|
|||||||
onClick={() => setModeLine(m as 0 | 1)}
|
onClick={() => setModeLine(m as 0 | 1)}
|
||||||
className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`}
|
className={`btn btn-sm ${modeLine === m ? "btn-accent" : "btn-ghost"}`}
|
||||||
>
|
>
|
||||||
{transI18n("style")} {m}
|
{transI18n("type")} {m}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -256,7 +258,7 @@ export default function LineupBar() {
|
|||||||
onClick={() => setModeBar(m as 0 | 1 | 2)}
|
onClick={() => setModeBar(m as 0 | 1 | 2)}
|
||||||
className={`btn btn-sm ${modeBar === m ? "btn-accent" : "btn-ghost"}`}
|
className={`btn btn-sm ${modeBar === m ? "btn-accent" : "btn-ghost"}`}
|
||||||
>
|
>
|
||||||
{transI18n("style")} {m}
|
{transI18n("type")} {m}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { listCurrentLanguage } from "@/lib/constant";
|
||||||
import { AvatarType } from "@/types";
|
import { AvatarType } from "@/types";
|
||||||
|
|
||||||
|
|
||||||
@@ -5,7 +6,11 @@ export function getNameChar(locale: string, data: AvatarType | undefined): strin
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return ""
|
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) {
|
if (!text) {
|
||||||
text = data.lang.get("en") ?? "";
|
text = data.lang.get("en") ?? "";
|
||||||
}
|
}
|
||||||
|
|||||||
7
src/lib/constant.ts
Normal file
7
src/lib/constant.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const listCurrentLanguage = {
|
||||||
|
ja: "JP",
|
||||||
|
ko: "KR",
|
||||||
|
en: "US",
|
||||||
|
vi: "VN",
|
||||||
|
zh: "CN"
|
||||||
|
};
|
||||||
@@ -77,12 +77,16 @@ export const connectSocket = (): Socket => {
|
|||||||
|
|
||||||
socket.on("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json)));
|
socket.on("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json)));
|
||||||
socket.on("TurnEnd", (json) => onTurnEndService(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("OnUseSkill", (json) => onUseSkillService(JSON.parse(json)));
|
||||||
socket.on("OnKill", (json) => onKillService(JSON.parse(json)));
|
socket.on("OnKill", (json) => onKillService(JSON.parse(json)));
|
||||||
socket.on("OnDamage", (json) => onDamageService(JSON.parse(json)));
|
socket.on("OnDamage", (json) => onDamageService(JSON.parse(json)));
|
||||||
socket.on('BattleBegin', () => onBattleBegin());
|
socket.on('BattleBegin', () => onBattleBegin());
|
||||||
|
socket.on('OnBattleBegin', () => onBattleBegin());
|
||||||
socket.on('TurnBegin', (json) => onTurnBeginService(JSON.parse(json)));
|
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('BattleEnd', (json) => onBattleEndService(JSON.parse(json)));
|
||||||
|
socket.on('OnBattleEnd', (json) => onBattleEndService(JSON.parse(json)));
|
||||||
|
|
||||||
socket.on("Error", (msg: string) => {
|
socket.on("Error", (msg: string) => {
|
||||||
console.error("Server Error:", msg);
|
console.error("Server Error:", msg);
|
||||||
@@ -104,12 +108,16 @@ export const disconnectSocket = (): void => {
|
|||||||
if (socket) {
|
if (socket) {
|
||||||
socket.off("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json)));
|
socket.off("SetBattleLineup", (json) => onSetBattleLineupService(JSON.parse(json)));
|
||||||
socket.off("TurnEnd", (json) => onTurnEndService(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("OnUseSkill", (json) => onUseSkillService(JSON.parse(json)));
|
||||||
socket.off("OnKill", (json) => onKillService(JSON.parse(json)));
|
socket.off("OnKill", (json) => onKillService(JSON.parse(json)));
|
||||||
socket.off("OnDamage", (json) => onDamageService(JSON.parse(json)));
|
socket.off("OnDamage", (json) => onDamageService(JSON.parse(json)));
|
||||||
socket.off('BattleBegin', () => onBattleBegin());
|
socket.off('BattleBegin', () => onBattleBegin());
|
||||||
|
socket.off('OnBattleBegin', () => onBattleBegin());
|
||||||
socket.off('TurnBegin', (json) => onTurnBeginService(JSON.parse(json)));
|
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('BattleEnd', (json) => onBattleEndService(JSON.parse(json)));
|
||||||
|
socket.off('OnBattleEnd', (json) => onBattleEndService(JSON.parse(json)));
|
||||||
socket.offAny();
|
socket.offAny();
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
useSocketStore.getState().setStatus(false);
|
useSocketStore.getState().setStatus(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user