Spaces:
Running
Running
Upload 9 files
Browse files- src/views/StudentView.js +18 -27
src/views/StudentView.js
CHANGED
|
@@ -157,23 +157,13 @@ export async function renderStudentView() {
|
|
| 157 |
// If actual stage > potential stage, it means tasks were reset/rejected.
|
| 158 |
// We must devolve.
|
| 159 |
if (actualStage > potentialStage) {
|
| 160 |
-
//
|
| 161 |
-
//
|
| 162 |
-
// Side-effect in render is bad, but necessary for self-correction.
|
| 163 |
-
// Let's debounce or check if we haven't already corrected.
|
| 164 |
-
// console.warn("Devolving from", actualStage, "to", potentialStage);
|
| 165 |
-
// Trigger update async
|
| 166 |
updateUserMonster(userId, potentialStage, null).then(() => {
|
| 167 |
-
|
| 168 |
-
// window.location.reload(); // Might cause loop if not careful?
|
| 169 |
-
// If update succeeds, the subscription will fire?
|
| 170 |
-
// No, subscription listens to PROGRESS, not USER profile updates unless we subscribe to USER too.
|
| 171 |
-
// We currently verify profile on load.
|
| 172 |
-
// Let's just force a reload once to correct it.
|
| 173 |
-
/* setTimeout(() => window.location.reload(), 500); */
|
| 174 |
});
|
| 175 |
-
//
|
| 176 |
-
|
| 177 |
}
|
| 178 |
|
| 179 |
// 3. Display Logic
|
|
@@ -203,7 +193,7 @@ export async function renderStudentView() {
|
|
| 203 |
<div id="monster-container-fixed" class="fixed top-32 left-8 z-50 flex flex-col items-center group pointer-events-none sm:pointer-events-auto w-32 h-32">
|
| 204 |
<!-- Walking Container -->
|
| 205 |
<div class="pixel-art-container relative transform transition-transform duration-500 ease-out origin-center"
|
| 206 |
-
style="transform: scale(${currentScale}); animation: walk-
|
| 207 |
|
| 208 |
<div class="pixel-monster w-28 h-28 drop-shadow-2xl filter" style="animation: breathe 3s infinite ease-in-out;">
|
| 209 |
${generateMonsterSVG(monster)}
|
|
@@ -231,12 +221,10 @@ export async function renderStudentView() {
|
|
| 231 |
` : ''}
|
| 232 |
|
| 233 |
<!-- Stats Tooltip -->
|
| 234 |
-
<div class="opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-gray-900/90 backdrop-blur text-xs text-slate-300 p-3 rounded-xl border border-slate-700 mt-6 text-left pointer-events-auto shadow-2xl min-w-[
|
| 235 |
<div class="font-bold text-white text-sm mb-1 text-center border-b border-gray-700 pb-1">${monster.name}</div>
|
| 236 |
-
<div class="space-y-1 mt-1">
|
| 237 |
-
<div class="
|
| 238 |
-
<div class="flex justify-between"><span>🏫 人數:</span> <span class="text-cyan-400 font-bold">${classSize}</span></div>
|
| 239 |
-
<div class="flex justify-between"><span>⚔️ 任務:</span> <span class="text-yellow-400 font-bold">${totalCompleted}</span></div>
|
| 240 |
</div>
|
| 241 |
</div>
|
| 242 |
</div>
|
|
@@ -246,10 +234,12 @@ export async function renderStudentView() {
|
|
| 246 |
0%, 100% { transform: translateY(0); filter: brightness(1); }
|
| 247 |
50% { transform: translateY(-3px); filter: brightness(1.1); }
|
| 248 |
}
|
| 249 |
-
@keyframes walk-
|
| 250 |
-
0%
|
| 251 |
-
|
| 252 |
-
|
|
|
|
|
|
|
| 253 |
}
|
| 254 |
</style>
|
| 255 |
`;
|
|
@@ -354,11 +344,12 @@ export async function renderStudentView() {
|
|
| 354 |
</div>
|
| 355 |
|
| 356 |
<!-- Peer Learning FAB -->
|
| 357 |
-
<button onclick="window.openPeerModal()" class="fixed bottom-
|
| 358 |
title="查看同學作業">
|
| 359 |
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-
|
| 360 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0z" />
|
| 361 |
</svg>
|
|
|
|
| 362 |
</button>
|
| 363 |
</div>
|
| 364 |
`;
|
|
|
|
| 157 |
// If actual stage > potential stage, it means tasks were reset/rejected.
|
| 158 |
// We must devolve.
|
| 159 |
if (actualStage > potentialStage) {
|
| 160 |
+
// Regression Logic
|
| 161 |
+
// Call DB update and then force reload to reflect changes
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
updateUserMonster(userId, potentialStage, null).then(() => {
|
| 163 |
+
setTimeout(() => window.location.reload(), 500);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
});
|
| 165 |
+
// Show potential stage temporarily to avoid glitch
|
| 166 |
+
return renderMonsterSection(currentUserProgress, classSize, { ...userProfile, monster_stage: potentialStage });
|
| 167 |
}
|
| 168 |
|
| 169 |
// 3. Display Logic
|
|
|
|
| 193 |
<div id="monster-container-fixed" class="fixed top-32 left-8 z-50 flex flex-col items-center group pointer-events-none sm:pointer-events-auto w-32 h-32">
|
| 194 |
<!-- Walking Container -->
|
| 195 |
<div class="pixel-art-container relative transform transition-transform duration-500 ease-out origin-center"
|
| 196 |
+
style="transform: scale(${currentScale}); animation: walk-patrol 15s linear infinite;">
|
| 197 |
|
| 198 |
<div class="pixel-monster w-28 h-28 drop-shadow-2xl filter" style="animation: breathe 3s infinite ease-in-out;">
|
| 199 |
${generateMonsterSVG(monster)}
|
|
|
|
| 221 |
` : ''}
|
| 222 |
|
| 223 |
<!-- Stats Tooltip -->
|
| 224 |
+
<div class="opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-gray-900/90 backdrop-blur text-xs text-slate-300 p-3 rounded-xl border border-slate-700 mt-6 text-left pointer-events-auto shadow-2xl min-w-[100px]">
|
| 225 |
<div class="font-bold text-white text-sm mb-1 text-center border-b border-gray-700 pb-1">${monster.name}</div>
|
| 226 |
+
<div class="space-y-1 mt-1 text-center">
|
| 227 |
+
<div class=""><span>💖</span> <span class="text-pink-400 font-bold ml-1">${totalLikes}</span></div>
|
|
|
|
|
|
|
| 228 |
</div>
|
| 229 |
</div>
|
| 230 |
</div>
|
|
|
|
| 234 |
0%, 100% { transform: translateY(0); filter: brightness(1); }
|
| 235 |
50% { transform: translateY(-3px); filter: brightness(1.1); }
|
| 236 |
}
|
| 237 |
+
@keyframes walk-patrol {
|
| 238 |
+
0% { transform: translateX(0) scaleX(1) scale(${currentScale}); }
|
| 239 |
+
45% { transform: translateX(120px) scaleX(1) scale(${currentScale}); }
|
| 240 |
+
50% { transform: translateX(120px) scaleX(-1) scale(${currentScale}); }
|
| 241 |
+
95% { transform: translateX(0) scaleX(-1) scale(${currentScale}); }
|
| 242 |
+
100% { transform: translateX(0) scaleX(1) scale(${currentScale}); }
|
| 243 |
}
|
| 244 |
</style>
|
| 245 |
`;
|
|
|
|
| 344 |
</div>
|
| 345 |
|
| 346 |
<!-- Peer Learning FAB -->
|
| 347 |
+
<button onclick="window.openPeerModal()" class="fixed bottom-8 left-1/2 -translate-x-1/2 bg-purple-600 hover:bg-purple-500 text-white rounded-full p-5 shadow-[0_0_20px_rgba(147,51,234,0.6)] transition-transform hover:scale-110 active:scale-90 z-40 flex items-center space-x-2"
|
| 348 |
title="查看同學作業">
|
| 349 |
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
| 350 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0z" />
|
| 351 |
</svg>
|
| 352 |
+
<span class="font-bold text-lg hidden sm:inline">查看同學提示詞</span>
|
| 353 |
</button>
|
| 354 |
</div>
|
| 355 |
`;
|