@octo-cyber/sea-king 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/character.controller.d.ts +10 -0
- package/dist/controllers/character.controller.d.ts.map +1 -0
- package/dist/controllers/character.controller.js +58 -0
- package/dist/controllers/character.controller.js.map +1 -0
- package/dist/controllers/chat.controller.d.ts +13 -0
- package/dist/controllers/chat.controller.d.ts.map +1 -0
- package/dist/controllers/chat.controller.js +113 -0
- package/dist/controllers/chat.controller.js.map +1 -0
- package/dist/controllers/crisis.controller.d.ts +10 -0
- package/dist/controllers/crisis.controller.d.ts.map +1 -0
- package/dist/controllers/crisis.controller.js +69 -0
- package/dist/controllers/crisis.controller.js.map +1 -0
- package/dist/controllers/index.d.ts +10 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/index.js +24 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/controllers/leaderboard.controller.d.ts +9 -0
- package/dist/controllers/leaderboard.controller.d.ts.map +1 -0
- package/dist/controllers/leaderboard.controller.js +51 -0
- package/dist/controllers/leaderboard.controller.js.map +1 -0
- package/dist/controllers/live-chat.controller.d.ts +14 -0
- package/dist/controllers/live-chat.controller.d.ts.map +1 -0
- package/dist/controllers/live-chat.controller.js +95 -0
- package/dist/controllers/live-chat.controller.js.map +1 -0
- package/dist/controllers/matchmaking.controller.d.ts +22 -0
- package/dist/controllers/matchmaking.controller.d.ts.map +1 -0
- package/dist/controllers/matchmaking.controller.js +157 -0
- package/dist/controllers/matchmaking.controller.js.map +1 -0
- package/dist/controllers/phrase.controller.d.ts +11 -0
- package/dist/controllers/phrase.controller.d.ts.map +1 -0
- package/dist/controllers/phrase.controller.js +78 -0
- package/dist/controllers/phrase.controller.js.map +1 -0
- package/dist/controllers/profile.controller.d.ts +9 -0
- package/dist/controllers/profile.controller.d.ts.map +1 -0
- package/dist/controllers/profile.controller.js +44 -0
- package/dist/controllers/profile.controller.js.map +1 -0
- package/dist/controllers/turing.controller.d.ts +18 -0
- package/dist/controllers/turing.controller.d.ts.map +1 -0
- package/dist/controllers/turing.controller.js +103 -0
- package/dist/controllers/turing.controller.js.map +1 -0
- package/dist/entities/chat-character.entity.d.ts +34 -0
- package/dist/entities/chat-character.entity.d.ts.map +1 -0
- package/dist/entities/chat-character.entity.js +101 -0
- package/dist/entities/chat-character.entity.js.map +1 -0
- package/dist/entities/chat-message.entity.d.ts +26 -0
- package/dist/entities/chat-message.entity.d.ts.map +1 -0
- package/dist/entities/chat-message.entity.js +84 -0
- package/dist/entities/chat-message.entity.js.map +1 -0
- package/dist/entities/chat-session.entity.d.ts +31 -0
- package/dist/entities/chat-session.entity.d.ts.map +1 -0
- package/dist/entities/chat-session.entity.js +95 -0
- package/dist/entities/chat-session.entity.js.map +1 -0
- package/dist/entities/chat-thread.entity.d.ts +30 -0
- package/dist/entities/chat-thread.entity.d.ts.map +1 -0
- package/dist/entities/chat-thread.entity.js +105 -0
- package/dist/entities/chat-thread.entity.js.map +1 -0
- package/dist/entities/crisis-event.entity.d.ts +30 -0
- package/dist/entities/crisis-event.entity.d.ts.map +1 -0
- package/dist/entities/crisis-event.entity.js +90 -0
- package/dist/entities/crisis-event.entity.js.map +1 -0
- package/dist/entities/index.d.ts +38 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +62 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/leaderboard-entry.entity.d.ts +22 -0
- package/dist/entities/leaderboard-entry.entity.d.ts.map +1 -0
- package/dist/entities/leaderboard-entry.entity.js +75 -0
- package/dist/entities/leaderboard-entry.entity.js.map +1 -0
- package/dist/entities/live-message.entity.d.ts +34 -0
- package/dist/entities/live-message.entity.d.ts.map +1 -0
- package/dist/entities/live-message.entity.js +99 -0
- package/dist/entities/live-message.entity.js.map +1 -0
- package/dist/entities/live-thread.entity.d.ts +50 -0
- package/dist/entities/live-thread.entity.d.ts.map +1 -0
- package/dist/entities/live-thread.entity.js +144 -0
- package/dist/entities/live-thread.entity.js.map +1 -0
- package/dist/entities/match-room.entity.d.ts +44 -0
- package/dist/entities/match-room.entity.d.ts.map +1 -0
- package/dist/entities/match-room.entity.js +131 -0
- package/dist/entities/match-room.entity.js.map +1 -0
- package/dist/entities/phrase-template.entity.d.ts +28 -0
- package/dist/entities/phrase-template.entity.d.ts.map +1 -0
- package/dist/entities/phrase-template.entity.js +84 -0
- package/dist/entities/phrase-template.entity.js.map +1 -0
- package/dist/entities/player-profile.entity.d.ts +36 -0
- package/dist/entities/player-profile.entity.d.ts.map +1 -0
- package/dist/entities/player-profile.entity.js +112 -0
- package/dist/entities/player-profile.entity.js.map +1 -0
- package/dist/entities/player-queue.entity.d.ts +24 -0
- package/dist/entities/player-queue.entity.d.ts.map +1 -0
- package/dist/entities/player-queue.entity.js +76 -0
- package/dist/entities/player-queue.entity.js.map +1 -0
- package/dist/entities/turing-guess.entity.d.ts +29 -0
- package/dist/entities/turing-guess.entity.d.ts.map +1 -0
- package/dist/entities/turing-guess.entity.js +94 -0
- package/dist/entities/turing-guess.entity.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/sea-king.schema.d.ts +109 -0
- package/dist/schemas/sea-king.schema.d.ts.map +1 -0
- package/dist/schemas/sea-king.schema.js +103 -0
- package/dist/schemas/sea-king.schema.js.map +1 -0
- package/dist/sea-king.module.d.ts +19 -0
- package/dist/sea-king.module.d.ts.map +1 -0
- package/dist/sea-king.module.js +114 -0
- package/dist/sea-king.module.js.map +1 -0
- package/dist/services/character.service.d.ts +30 -0
- package/dist/services/character.service.d.ts.map +1 -0
- package/dist/services/character.service.js +75 -0
- package/dist/services/character.service.js.map +1 -0
- package/dist/services/chat.service.d.ts +49 -0
- package/dist/services/chat.service.d.ts.map +1 -0
- package/dist/services/chat.service.js +332 -0
- package/dist/services/chat.service.js.map +1 -0
- package/dist/services/crisis.service.d.ts +17 -0
- package/dist/services/crisis.service.d.ts.map +1 -0
- package/dist/services/crisis.service.js +177 -0
- package/dist/services/crisis.service.js.map +1 -0
- package/dist/services/index.d.ts +13 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +28 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/leaderboard.service.d.ts +29 -0
- package/dist/services/leaderboard.service.d.ts.map +1 -0
- package/dist/services/leaderboard.service.js +64 -0
- package/dist/services/leaderboard.service.js.map +1 -0
- package/dist/services/live-chat.service.d.ts +71 -0
- package/dist/services/live-chat.service.d.ts.map +1 -0
- package/dist/services/live-chat.service.js +273 -0
- package/dist/services/live-chat.service.js.map +1 -0
- package/dist/services/matchmaking.service.d.ts +60 -0
- package/dist/services/matchmaking.service.d.ts.map +1 -0
- package/dist/services/matchmaking.service.js +208 -0
- package/dist/services/matchmaking.service.js.map +1 -0
- package/dist/services/phrase.service.d.ts +27 -0
- package/dist/services/phrase.service.d.ts.map +1 -0
- package/dist/services/phrase.service.js +70 -0
- package/dist/services/phrase.service.js.map +1 -0
- package/dist/services/profile.service.d.ts +41 -0
- package/dist/services/profile.service.d.ts.map +1 -0
- package/dist/services/profile.service.js +107 -0
- package/dist/services/profile.service.js.map +1 -0
- package/dist/services/seed.service.d.ts +19 -0
- package/dist/services/seed.service.d.ts.map +1 -0
- package/dist/services/seed.service.js +550 -0
- package/dist/services/seed.service.js.map +1 -0
- package/dist/services/turing.service.d.ts +74 -0
- package/dist/services/turing.service.d.ts.map +1 -0
- package/dist/services/turing.service.js +175 -0
- package/dist/services/turing.service.js.map +1 -0
- package/dist/services/ws-hub.service.d.ts +51 -0
- package/dist/services/ws-hub.service.d.ts.map +1 -0
- package/dist/services/ws-hub.service.js +174 -0
- package/dist/services/ws-hub.service.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +69 -0
- package/web/index.ts +30 -0
- package/web/manifest.ts +40 -0
- package/web/messages/en-US.json +113 -0
- package/web/messages/zh-CN.json +113 -0
- package/web/pages/AnalysisPage.tsx +198 -0
- package/web/pages/ChatPage.tsx +482 -0
- package/web/pages/DashboardPage.tsx +281 -0
- package/web/pages/LeaderboardPage.tsx +208 -0
- package/web/pages/PhrasesPage.tsx +221 -0
- package/web/services/sea-king-service.ts +151 -0
- package/web/types/sea-king.ts +249 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"seaKing": {
|
|
3
|
+
"moduleName": "Sea King Arena",
|
|
4
|
+
"dashboard": {
|
|
5
|
+
"title": "Sea King HQ",
|
|
6
|
+
"description": "View your social skills data and training progress",
|
|
7
|
+
"welcomeTitle": "🌊 Welcome to the Sea King Arena",
|
|
8
|
+
"welcomeSubtitle": "Chat with multiple AI characters simultaneously to train your high-EQ social skills! Remember: a true Sea King never crashes and burns.",
|
|
9
|
+
"currentRank": "Current Rank",
|
|
10
|
+
"pointsToNext": "{points} points to next rank",
|
|
11
|
+
"totalFavor": "Total Favor",
|
|
12
|
+
"totalSessions": "Sessions",
|
|
13
|
+
"crisisResolved": "Crises Resolved",
|
|
14
|
+
"bestStreak": "Best Streak",
|
|
15
|
+
"skillRadar": "Social Skills Radar",
|
|
16
|
+
"quickStart": "Quick Start",
|
|
17
|
+
"startChat": "Start Chatting",
|
|
18
|
+
"startChatDesc": "Chat with multiple characters at once",
|
|
19
|
+
"learnPhrases": "Learn Phrases",
|
|
20
|
+
"learnPhrasesDesc": "Master high-EQ reply templates",
|
|
21
|
+
"viewRanking": "View Rankings",
|
|
22
|
+
"viewRankingDesc": "Who's the real Sea King?",
|
|
23
|
+
"recentSessions": "Recent Sessions",
|
|
24
|
+
"characters": "chats",
|
|
25
|
+
"score": "Score"
|
|
26
|
+
},
|
|
27
|
+
"chat": {
|
|
28
|
+
"title": "Multi-Chat Simulator",
|
|
29
|
+
"description": "Chat with multiple AI characters simultaneously to train your social adaptability",
|
|
30
|
+
"startDescription": "Choose how many characters to chat with. Are you ready for the challenge?",
|
|
31
|
+
"selectCharacterCount": "Select number of simultaneous chats",
|
|
32
|
+
"characterCountHint": "You'll chat with {count} AI characters with different personalities",
|
|
33
|
+
"matching": "Matching characters...",
|
|
34
|
+
"startTraining": "Start Challenge",
|
|
35
|
+
"chatList": "Chat List",
|
|
36
|
+
"endSession": "End Session",
|
|
37
|
+
"inputPlaceholder": "Type a message... Be warm but not cringe!",
|
|
38
|
+
"blocked": "This character has blocked you... Watch what you say next time!",
|
|
39
|
+
"crisisAlert": "🚨 Crisis Event!",
|
|
40
|
+
"crisisPlaceholder": "Quick, think of a response...",
|
|
41
|
+
"respond": "Respond",
|
|
42
|
+
"sessionComplete": "Session Complete!",
|
|
43
|
+
"playAgain": "Play Again"
|
|
44
|
+
},
|
|
45
|
+
"phrases": {
|
|
46
|
+
"title": "Phrase Library",
|
|
47
|
+
"description": "High-EQ reply templates for every social situation",
|
|
48
|
+
"subtitle": "From low-EQ to high-EQ — one reply can make all the difference",
|
|
49
|
+
"allScenes": "All",
|
|
50
|
+
"scenes": {
|
|
51
|
+
"first_meet": "First Meeting",
|
|
52
|
+
"daily_care": "Daily Care",
|
|
53
|
+
"resolve_awkward": "Resolve Awkward",
|
|
54
|
+
"elegant_reject": "Elegant Rejection",
|
|
55
|
+
"flirt": "Flirting",
|
|
56
|
+
"cool_down": "Cool Down",
|
|
57
|
+
"crisis_response": "Crisis Response",
|
|
58
|
+
"morning_night": "Good Morning/Night"
|
|
59
|
+
},
|
|
60
|
+
"practiceMode": "Practice Mode",
|
|
61
|
+
"theyAsk": "They say:",
|
|
62
|
+
"badReply": "Low-EQ Reply",
|
|
63
|
+
"goodReply": "High-EQ Reply",
|
|
64
|
+
"reveal": "Show Answer",
|
|
65
|
+
"hide": "Hide Answer",
|
|
66
|
+
"thinkFirst": "Think about how you'd reply first, then click 'Show Answer'",
|
|
67
|
+
"noPhrases": "No phrase templates yet"
|
|
68
|
+
},
|
|
69
|
+
"analysis": {
|
|
70
|
+
"title": "Social Analysis",
|
|
71
|
+
"description": "Deep analysis of your chat style with a social skills radar chart",
|
|
72
|
+
"subtitle": "Understand your social skill dimensions and improve your weaknesses",
|
|
73
|
+
"currentRank": "Current Rank",
|
|
74
|
+
"nextRank": "Next Rank",
|
|
75
|
+
"needPoints": "{points} more points needed",
|
|
76
|
+
"totalPoints": "Rank Points",
|
|
77
|
+
"socialRadar": "Five-Dimension Social Radar",
|
|
78
|
+
"excellent": "Excellent",
|
|
79
|
+
"good": "Good",
|
|
80
|
+
"average": "Average",
|
|
81
|
+
"needWork": "Needs Work",
|
|
82
|
+
"totalSessions": "Total Sessions",
|
|
83
|
+
"totalFavor": "Total Favor Earned",
|
|
84
|
+
"crisisResolved": "Crises Resolved",
|
|
85
|
+
"improvementTips": "Improvement Tips",
|
|
86
|
+
"tipFor": "Your '{dimension}' score is {score}. Practice more related scenarios to improve.",
|
|
87
|
+
"noData": "No training data yet. Go chat a few rounds first!"
|
|
88
|
+
},
|
|
89
|
+
"leaderboard": {
|
|
90
|
+
"title": "Sea King Leaderboard",
|
|
91
|
+
"description": "Total favor score rankings — who's the real king of social charm?",
|
|
92
|
+
"subtitle": "Season 1 Rankings · Monthly Reset · True Sea Kings never fear comparison",
|
|
93
|
+
"rankCol": "Rank",
|
|
94
|
+
"player": "Player",
|
|
95
|
+
"tier": "Tier",
|
|
96
|
+
"score": "Score",
|
|
97
|
+
"maxChats": "Max Chats",
|
|
98
|
+
"crisisRate": "Crisis Rate",
|
|
99
|
+
"empty": "No one on the board yet. Be the first Sea King!",
|
|
100
|
+
"prev": "Previous",
|
|
101
|
+
"next": "Next"
|
|
102
|
+
},
|
|
103
|
+
"ranks": {
|
|
104
|
+
"bronze": "🥉 Bronze Newbie",
|
|
105
|
+
"silver": "🥈 Silver Sweetheart",
|
|
106
|
+
"gold": "🥇 Gold Socialite",
|
|
107
|
+
"platinum": "💎 Platinum Charmer",
|
|
108
|
+
"diamond": "💠 Diamond Social Star",
|
|
109
|
+
"master": "👑 Master Player",
|
|
110
|
+
"king": "🔱 King of the Sea"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"seaKing": {
|
|
3
|
+
"moduleName": "海王修炼场",
|
|
4
|
+
"dashboard": {
|
|
5
|
+
"title": "海王总部",
|
|
6
|
+
"description": "查看你的社交能力数据和训练进度",
|
|
7
|
+
"welcomeTitle": "🌊 欢迎来到海王修炼场",
|
|
8
|
+
"welcomeSubtitle": "同时和多个AI角色聊天,训练你的高情商社交能力!记住,真正的海王从不翻车。",
|
|
9
|
+
"currentRank": "当前段位",
|
|
10
|
+
"pointsToNext": "距下一段位还差 {points} 分",
|
|
11
|
+
"totalFavor": "累计好感度",
|
|
12
|
+
"totalSessions": "训练场次",
|
|
13
|
+
"crisisResolved": "化解危机",
|
|
14
|
+
"bestStreak": "最佳连胜",
|
|
15
|
+
"skillRadar": "社交能力雷达",
|
|
16
|
+
"quickStart": "快速开始",
|
|
17
|
+
"startChat": "开始聊天",
|
|
18
|
+
"startChatDesc": "同时和多个角色开聊",
|
|
19
|
+
"learnPhrases": "学习话术",
|
|
20
|
+
"learnPhrasesDesc": "掌握高情商回复模板",
|
|
21
|
+
"viewRanking": "查看排行",
|
|
22
|
+
"viewRankingDesc": "谁才是真正的海王",
|
|
23
|
+
"recentSessions": "最近训练",
|
|
24
|
+
"characters": "人对话",
|
|
25
|
+
"score": "得分"
|
|
26
|
+
},
|
|
27
|
+
"chat": {
|
|
28
|
+
"title": "多线聊天模拟",
|
|
29
|
+
"description": "同时和多个AI角色聊天,训练你的社交应变能力",
|
|
30
|
+
"startDescription": "选择同时聊天的人数,准备好接受挑战了吗?",
|
|
31
|
+
"selectCharacterCount": "选择同时聊天的角色数量",
|
|
32
|
+
"characterCountHint": "将同时和 {count} 个不同性格的AI角色聊天",
|
|
33
|
+
"matching": "匹配角色中...",
|
|
34
|
+
"startTraining": "开始挑战",
|
|
35
|
+
"chatList": "聊天列表",
|
|
36
|
+
"endSession": "结束训练",
|
|
37
|
+
"inputPlaceholder": "输入消息... 记住要有温度又不油腻哦",
|
|
38
|
+
"blocked": "这个角色已经把你拉黑了... 下次注意说话方式!",
|
|
39
|
+
"crisisAlert": "🚨 紧急事件!",
|
|
40
|
+
"crisisPlaceholder": "快想想怎么应对...",
|
|
41
|
+
"respond": "回应",
|
|
42
|
+
"sessionComplete": "训练结束!",
|
|
43
|
+
"playAgain": "再来一局"
|
|
44
|
+
},
|
|
45
|
+
"phrases": {
|
|
46
|
+
"title": "话术宝典",
|
|
47
|
+
"description": "收集高情商回复模板,让你的每句话都恰到好处",
|
|
48
|
+
"subtitle": "从低情商到高情商,一个回复的差距可能决定一切",
|
|
49
|
+
"allScenes": "全部",
|
|
50
|
+
"scenes": {
|
|
51
|
+
"first_meet": "初次认识",
|
|
52
|
+
"daily_care": "日常关心",
|
|
53
|
+
"resolve_awkward": "化解尴尬",
|
|
54
|
+
"elegant_reject": "优雅拒绝",
|
|
55
|
+
"flirt": "调情升温",
|
|
56
|
+
"cool_down": "降温冷却",
|
|
57
|
+
"crisis_response": "危机应对",
|
|
58
|
+
"morning_night": "早安晚安"
|
|
59
|
+
},
|
|
60
|
+
"practiceMode": "练习模式",
|
|
61
|
+
"theyAsk": "对方说:",
|
|
62
|
+
"badReply": "低情商回复",
|
|
63
|
+
"goodReply": "高情商回复",
|
|
64
|
+
"reveal": "显示答案",
|
|
65
|
+
"hide": "隐藏答案",
|
|
66
|
+
"thinkFirst": "先想想你会怎么回复?然后点击「显示答案」",
|
|
67
|
+
"noPhrases": "暂无话术模板"
|
|
68
|
+
},
|
|
69
|
+
"analysis": {
|
|
70
|
+
"title": "社交分析",
|
|
71
|
+
"description": "深度分析你的聊天风格,给出社交能力雷达图",
|
|
72
|
+
"subtitle": "了解你的社交能力维度,精准提升短板",
|
|
73
|
+
"currentRank": "当前段位",
|
|
74
|
+
"nextRank": "下一段位",
|
|
75
|
+
"needPoints": "还需 {points} 分",
|
|
76
|
+
"totalPoints": "段位积分",
|
|
77
|
+
"socialRadar": "社交能力五维图",
|
|
78
|
+
"excellent": "优秀",
|
|
79
|
+
"good": "良好",
|
|
80
|
+
"average": "一般",
|
|
81
|
+
"needWork": "需加强",
|
|
82
|
+
"totalSessions": "总训练场次",
|
|
83
|
+
"totalFavor": "累计好感度",
|
|
84
|
+
"crisisResolved": "危机化解数",
|
|
85
|
+
"improvementTips": "提升建议",
|
|
86
|
+
"tipFor": "你的「{dimension}」得分为 {score},建议多练习相关场景来提升",
|
|
87
|
+
"noData": "还没有训练数据,先去聊几局吧!"
|
|
88
|
+
},
|
|
89
|
+
"leaderboard": {
|
|
90
|
+
"title": "海王排行榜",
|
|
91
|
+
"description": "好感度总分排行,看看谁才是真正的社交之王",
|
|
92
|
+
"subtitle": "S1赛季排行 · 每月重置 · 真正的海王从不怕比较",
|
|
93
|
+
"rankCol": "排名",
|
|
94
|
+
"player": "玩家",
|
|
95
|
+
"tier": "段位",
|
|
96
|
+
"score": "总分",
|
|
97
|
+
"maxChats": "最多同聊",
|
|
98
|
+
"crisisRate": "危机成功率",
|
|
99
|
+
"empty": "还没有人上榜,成为第一个海王吧!",
|
|
100
|
+
"prev": "上一页",
|
|
101
|
+
"next": "下一页"
|
|
102
|
+
},
|
|
103
|
+
"ranks": {
|
|
104
|
+
"bronze": "🥉 青铜直男/直女",
|
|
105
|
+
"silver": "🥈 白银暖男/暖女",
|
|
106
|
+
"gold": "🥇 黄金交际花",
|
|
107
|
+
"platinum": "💎 铂金万人迷",
|
|
108
|
+
"diamond": "💠 钻石社交达人",
|
|
109
|
+
"master": "👑 大师级海王/海后",
|
|
110
|
+
"king": "🔱 王者海王/海后"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useTranslations } from 'next-intl';
|
|
5
|
+
import { Radar, TrendingUp, Award, Target, Zap } from 'lucide-react';
|
|
6
|
+
import { getAnalysis } from '../services/sea-king-service';
|
|
7
|
+
import type { PlayerAnalysis } from '../types/sea-king';
|
|
8
|
+
|
|
9
|
+
const RANK_EMOJIS: Record<string, string> = {
|
|
10
|
+
bronze: '🥉',
|
|
11
|
+
silver: '🥈',
|
|
12
|
+
gold: '🥇',
|
|
13
|
+
platinum: '💎',
|
|
14
|
+
diamond: '💠',
|
|
15
|
+
master: '👑',
|
|
16
|
+
king: '🔱',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const DIMENSION_COLORS: Record<string, string> = {
|
|
20
|
+
humor: '#f59e0b',
|
|
21
|
+
empathy: '#ec4899',
|
|
22
|
+
topic_lead: '#3b82f6',
|
|
23
|
+
time_manage: '#10b981',
|
|
24
|
+
crisis_handle: '#ef4444',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default function AnalysisPage() {
|
|
28
|
+
const t = useTranslations('seaKing.analysis');
|
|
29
|
+
const tRanks = useTranslations('seaKing.ranks');
|
|
30
|
+
|
|
31
|
+
const [analysis, setAnalysis] = useState<PlayerAnalysis | null>(null);
|
|
32
|
+
const [loading, setLoading] = useState(true);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
getAnalysis()
|
|
36
|
+
.then(setAnalysis)
|
|
37
|
+
.catch(() => {})
|
|
38
|
+
.finally(() => setLoading(false));
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
if (loading) {
|
|
42
|
+
return (
|
|
43
|
+
<div className="flex items-center justify-center min-h-[400px]">
|
|
44
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-500" />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!analysis) {
|
|
50
|
+
return (
|
|
51
|
+
<div className="text-center py-20 text-gray-400">
|
|
52
|
+
<span className="text-6xl">📊</span>
|
|
53
|
+
<p className="mt-4 text-lg">{t('noData')}</p>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { profile, rankInfo, radarData } = analysis;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div className="space-y-6 p-6">
|
|
62
|
+
{/* Header */}
|
|
63
|
+
<div className="bg-gradient-to-r from-purple-600 via-violet-600 to-indigo-600 rounded-2xl p-8 text-white relative overflow-hidden">
|
|
64
|
+
<div className="absolute top-0 right-0 opacity-10 text-[180px] leading-none select-none">
|
|
65
|
+
📊
|
|
66
|
+
</div>
|
|
67
|
+
<div className="relative z-10">
|
|
68
|
+
<div className="flex items-center gap-3 mb-2">
|
|
69
|
+
<Radar className="h-8 w-8" />
|
|
70
|
+
<h1 className="text-3xl font-bold">{t('title')}</h1>
|
|
71
|
+
</div>
|
|
72
|
+
<p className="text-purple-200 text-lg mt-2">{t('subtitle')}</p>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{/* Rank Card */}
|
|
77
|
+
<div className="bg-white rounded-xl border p-6">
|
|
78
|
+
<div className="flex items-center gap-6">
|
|
79
|
+
<div className="text-7xl">{rankInfo.emoji}</div>
|
|
80
|
+
<div className="flex-1">
|
|
81
|
+
<div className="text-sm text-gray-400">{t('currentRank')}</div>
|
|
82
|
+
<div className="text-2xl font-bold">{rankInfo.label}</div>
|
|
83
|
+
{rankInfo.nextRank && (
|
|
84
|
+
<div className="mt-2">
|
|
85
|
+
<div className="flex items-center justify-between text-sm mb-1">
|
|
86
|
+
<span className="text-gray-500">
|
|
87
|
+
{t('nextRank')}: {rankInfo.nextRank}
|
|
88
|
+
</span>
|
|
89
|
+
<span className="text-purple-600 font-medium">
|
|
90
|
+
{t('needPoints', { points: rankInfo.pointsToNext })}
|
|
91
|
+
</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div className="h-2 bg-gray-100 rounded-full overflow-hidden">
|
|
94
|
+
<div
|
|
95
|
+
className="h-full bg-gradient-to-r from-purple-500 to-indigo-500 rounded-full transition-all duration-500"
|
|
96
|
+
style={{
|
|
97
|
+
width: `${Math.min(100, (profile.rankPoints / (profile.rankPoints + rankInfo.pointsToNext)) * 100)}%`,
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
<div className="text-right">
|
|
105
|
+
<div className="text-4xl font-bold text-purple-600">{profile.rankPoints}</div>
|
|
106
|
+
<div className="text-sm text-gray-400">{t('totalPoints')}</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{/* Radar Chart (CSS-based) */}
|
|
112
|
+
<div className="bg-white rounded-xl border p-6">
|
|
113
|
+
<h2 className="text-lg font-semibold mb-6 flex items-center gap-2">
|
|
114
|
+
<Target className="h-5 w-5 text-purple-500" />
|
|
115
|
+
{t('socialRadar')}
|
|
116
|
+
</h2>
|
|
117
|
+
<div className="grid grid-cols-1 md:grid-cols-5 gap-6">
|
|
118
|
+
{radarData.map((d) => {
|
|
119
|
+
const color = DIMENSION_COLORS[d.dimension] ?? '#6b7280';
|
|
120
|
+
const level =
|
|
121
|
+
d.score >= 80 ? t('excellent') : d.score >= 60 ? t('good') : d.score >= 40 ? t('average') : t('needWork');
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div key={d.dimension} className="text-center">
|
|
125
|
+
{/* Circular Progress */}
|
|
126
|
+
<div className="relative w-24 h-24 mx-auto mb-3">
|
|
127
|
+
<svg viewBox="0 0 36 36" className="w-24 h-24 transform -rotate-90">
|
|
128
|
+
<path
|
|
129
|
+
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
|
130
|
+
fill="none"
|
|
131
|
+
stroke="#f3f4f6"
|
|
132
|
+
strokeWidth="3"
|
|
133
|
+
/>
|
|
134
|
+
<path
|
|
135
|
+
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
|
136
|
+
fill="none"
|
|
137
|
+
stroke={color}
|
|
138
|
+
strokeWidth="3"
|
|
139
|
+
strokeDasharray={`${d.score}, 100`}
|
|
140
|
+
strokeLinecap="round"
|
|
141
|
+
/>
|
|
142
|
+
</svg>
|
|
143
|
+
<span className="absolute inset-0 flex items-center justify-center text-xl font-bold">
|
|
144
|
+
{d.score}
|
|
145
|
+
</span>
|
|
146
|
+
</div>
|
|
147
|
+
<div className="font-medium text-sm">{d.label}</div>
|
|
148
|
+
<div className="text-xs text-gray-400 mt-1">{level}</div>
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
})}
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
{/* Stats Grid */}
|
|
156
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
157
|
+
<div className="bg-gradient-to-br from-pink-50 to-rose-50 rounded-xl border border-pink-200 p-5">
|
|
158
|
+
<div className="flex items-center gap-2 mb-2">
|
|
159
|
+
<Award className="h-5 w-5 text-pink-500" />
|
|
160
|
+
<span className="text-sm text-gray-600">{t('totalSessions')}</span>
|
|
161
|
+
</div>
|
|
162
|
+
<div className="text-3xl font-bold text-pink-600">{profile.totalSessions}</div>
|
|
163
|
+
</div>
|
|
164
|
+
<div className="bg-gradient-to-br from-green-50 to-emerald-50 rounded-xl border border-green-200 p-5">
|
|
165
|
+
<div className="flex items-center gap-2 mb-2">
|
|
166
|
+
<TrendingUp className="h-5 w-5 text-green-500" />
|
|
167
|
+
<span className="text-sm text-gray-600">{t('totalFavor')}</span>
|
|
168
|
+
</div>
|
|
169
|
+
<div className="text-3xl font-bold text-green-600">{profile.totalFavorGained}</div>
|
|
170
|
+
</div>
|
|
171
|
+
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl border border-blue-200 p-5">
|
|
172
|
+
<div className="flex items-center gap-2 mb-2">
|
|
173
|
+
<Zap className="h-5 w-5 text-blue-500" />
|
|
174
|
+
<span className="text-sm text-gray-600">{t('crisisResolved')}</span>
|
|
175
|
+
</div>
|
|
176
|
+
<div className="text-3xl font-bold text-blue-600">{profile.crisisResolved}</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{/* Tips */}
|
|
181
|
+
<div className="bg-amber-50 rounded-xl border border-amber-200 p-6">
|
|
182
|
+
<h3 className="font-semibold text-amber-800 mb-3 flex items-center gap-2">
|
|
183
|
+
💡 {t('improvementTips')}
|
|
184
|
+
</h3>
|
|
185
|
+
<div className="space-y-2 text-sm text-amber-700">
|
|
186
|
+
{radarData
|
|
187
|
+
.sort((a, b) => a.score - b.score)
|
|
188
|
+
.slice(0, 2)
|
|
189
|
+
.map((d) => (
|
|
190
|
+
<p key={d.dimension}>
|
|
191
|
+
{t('tipFor', { dimension: d.label, score: d.score })}
|
|
192
|
+
</p>
|
|
193
|
+
))}
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|