Skip to content

Commit 649208e

Browse files
Fix Claim button for all cells, hero badge unlock modal, reduce badge glow
- Claim button: use claimBySegment (creates task on-the-fly) so all available cells show the Claim button, not just ones with existing tasks - Badge unlock: centered hero overlay instead of small top-right toast, click to open profile panel - Reduce golden glow intensity on Proofreading Achievements badges Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3ae2c47 commit 649208e

File tree

4 files changed

+119
-8
lines changed

4 files changed

+119
-8
lines changed

src/components/AchievementToast.vue

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,17 @@ interface Toast {
3737
const toasts = ref<Toast[]>([]);
3838
let toastId = 0;
3939
40+
/** Hero badge — shown centered as a big celebration */
41+
const heroBadge = ref<Toast | null>(null);
42+
4043
function addToast(toast: Omit<Toast, 'id' | 'leaving'>) {
4144
const t: Toast = { ...toast, id: ++toastId, leaving: false };
45+
// Badge unlocks get hero treatment
46+
if (toast.type === 'badge') {
47+
heroBadge.value = t;
48+
setTimeout(() => dismissHero(), 8000);
49+
return;
50+
}
4251
toasts.value.push(t);
4352
// Auto-dismiss after 5s
4453
setTimeout(() => dismiss(t.id), 5000);
@@ -54,6 +63,15 @@ function dismiss(id: number) {
5463
}
5564
}
5665
66+
function dismissHero() {
67+
heroBadge.value = null;
68+
}
69+
70+
function onHeroClick() {
71+
dismissHero();
72+
document.dispatchEvent(new CustomEvent('nge:open-profile'));
73+
}
74+
5775
// ── Track previous values to detect threshold crossings ──────────────────────
5876
let prevEdits = 0;
5977
let prevCells = 0;
@@ -217,6 +235,24 @@ watch(() => queueStore.proofread.size, () => {
217235
<template>
218236
<ConfettiCelebration ref="confettiRef" />
219237
<Teleport to="body">
238+
<!-- Hero badge unlock overlay -->
239+
<Transition name="nge-hero">
240+
<div v-if="heroBadge" class="nge-hero-overlay" @click="onHeroClick">
241+
<div class="nge-hero-card">
242+
<div class="nge-hero-particles">
243+
<span v-for="i in 12" :key="i" class="nge-hero-particle" :style="{ '--i': i }"></span>
244+
</div>
245+
<div class="nge-hero-icon">
246+
<img v-if="heroBadge.isImage" :src="heroBadge.icon" class="nge-hero-badge-img" />
247+
<span v-else class="nge-hero-emoji">{{ heroBadge.icon }}</span>
248+
</div>
249+
<div class="nge-hero-title">{{ heroBadge.title }}</div>
250+
<div class="nge-hero-subtitle">{{ heroBadge.subtitle }}</div>
251+
<div class="nge-hero-hint">Click to view profile</div>
252+
</div>
253+
</div>
254+
</Transition>
255+
220256
<div class="nge-toast-container">
221257
<TransitionGroup name="nge-toast">
222258
<div
@@ -255,6 +291,78 @@ watch(() => queueStore.proofread.size, () => {
255291
</template>
256292

257293
<style scoped>
294+
/* ── Hero badge unlock (centered overlay) ── */
295+
.nge-hero-overlay {
296+
position: fixed;
297+
inset: 0;
298+
z-index: 10000;
299+
display: flex;
300+
align-items: center;
301+
justify-content: center;
302+
background: rgba(0, 0, 0, 0.6);
303+
backdrop-filter: blur(4px);
304+
cursor: pointer;
305+
}
306+
.nge-hero-card {
307+
display: flex;
308+
flex-direction: column;
309+
align-items: center;
310+
gap: 12px;
311+
padding: 40px 56px;
312+
background: rgba(18, 22, 30, 0.97);
313+
border: 1px solid rgba(255, 200, 80, 0.3);
314+
border-radius: 16px;
315+
box-shadow:
316+
0 0 80px rgba(245, 166, 35, 0.15),
317+
0 0 200px rgba(206, 147, 216, 0.08),
318+
0 24px 64px rgba(0, 0, 0, 0.6);
319+
position: relative;
320+
overflow: hidden;
321+
}
322+
.nge-hero-icon {
323+
width: 140px; height: 140px;
324+
display: flex; align-items: center; justify-content: center;
325+
filter: drop-shadow(0 0 24px rgba(255, 200, 80, 0.5));
326+
animation: nge-hero-float 3s ease-in-out infinite alternate;
327+
}
328+
.nge-hero-badge-img { width: 120px; height: 120px; object-fit: contain; }
329+
.nge-hero-emoji { font-size: 72px; }
330+
.nge-hero-title {
331+
font-size: 20px; font-weight: 700; color: #ffd08a;
332+
text-align: center; text-shadow: 0 0 20px rgba(245, 166, 35, 0.4);
333+
}
334+
.nge-hero-subtitle {
335+
font-size: 13px; color: #999; text-align: center; max-width: 280px;
336+
}
337+
.nge-hero-hint {
338+
font-size: 11px; color: rgba(255, 208, 138, 0.5); margin-top: 8px;
339+
}
340+
@keyframes nge-hero-float {
341+
from { transform: translateY(0); }
342+
to { transform: translateY(-8px); }
343+
}
344+
/* Hero particles */
345+
.nge-hero-particles { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
346+
.nge-hero-particle {
347+
position: absolute; width: 4px; height: 4px; border-radius: 50%;
348+
background: rgba(255, 200, 80, 0.6);
349+
animation: nge-hero-sparkle 2s ease-out infinite;
350+
animation-delay: calc(var(--i) * 0.15s);
351+
left: calc(5% + var(--i) * 7.5%);
352+
top: 80%;
353+
}
354+
@keyframes nge-hero-sparkle {
355+
0% { opacity: 1; transform: translateY(0) scale(1); }
356+
100% { opacity: 0; transform: translateY(-120px) scale(0); }
357+
}
358+
/* Hero transitions */
359+
.nge-hero-enter-active { transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
360+
.nge-hero-leave-active { transition: all 0.3s ease-in; }
361+
.nge-hero-enter-from { opacity: 0; }
362+
.nge-hero-enter-from .nge-hero-card { transform: scale(0.7); }
363+
.nge-hero-leave-to { opacity: 0; }
364+
.nge-hero-leave-to .nge-hero-card { transform: scale(0.9); }
365+
258366
.nge-toast-container {
259367
position: fixed;
260368
top: 52px;

src/components/CellLibraryPanel.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,10 @@ function parseCoords(s: string): [number, number, number] {
197197
}
198198
199199
async function claimCell(cell: typeof cells.value[0]) {
200-
if (!isLoggedIn.value || !cell.taskId) return;
201-
await backend.claimTask(cell.taskId);
200+
if (!isLoggedIn.value) return;
201+
// Use claimBySegment which creates the task if it doesn't exist yet
202+
const result = await backend.claimBySegment(cell.segId);
203+
if (!result.ok) { console.warn('[cellLibrary] Claim failed:', result.reason); return; }
202204
// Write claim to Google Sheet (best-effort)
203205
writeClaimToSheet(cell.segId, backend.userName);
204206
await backend.loadTasks('eyewire_ii');
@@ -562,7 +564,7 @@ const panelStyle = computed(() => ({
562564
>↗</button>
563565

564566
<button
565-
v-if="cell.status === 'pending' && isLoggedIn && cell.taskId"
567+
v-if="cell.status === 'pending' && isLoggedIn"
566568
class="nge-cl-btn nge-cl-btn--claim"
567569
@click="claimCell(cell)"
568570
>Claim</button>

src/components/ExtensionBar.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const {volumes} = useVolumesStore();
5151
5252
onMounted(() => {
5353
(document.querySelector('.ng-extend-logo > a > img')! as HTMLImageElement).src = logoImage;
54+
document.addEventListener('nge:open-profile', () => { showProfile.value = true; });
5455
});
5556
5657
const statsStore = useUserStatsStore();

src/components/UserProfilePanel.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,16 +1207,16 @@ const emit = defineEmits({hide: null, 'open-settings': null});
12071207
.nge-profile-badge--latest .nge-profile-badge-name {
12081208
color: #8ac8ff;
12091209
}
1210-
/* Building badges: golden highlight */
1210+
/* Building badges: subtle golden highlight */
12111211
.nge-profile-badge--building.nge-profile-badge--selected {
1212-
background: rgba(245, 166, 35, 0.12);
1213-
box-shadow: 0 0 0 1px rgba(245, 166, 35, 0.35) inset;
1212+
background: rgba(245, 166, 35, 0.06);
1213+
box-shadow: 0 0 0 1px rgba(245, 166, 35, 0.2) inset;
12141214
}
12151215
.nge-profile-badge--building.nge-profile-badge--selected .nge-profile-badge-img {
1216-
filter: drop-shadow(0 0 6px rgba(255, 200, 80, 0.75));
1216+
filter: drop-shadow(0 0 3px rgba(255, 200, 80, 0.35));
12171217
}
12181218
.nge-profile-badge--building.nge-profile-badge--latest .nge-profile-badge-img {
1219-
filter: drop-shadow(0 0 8px rgba(255, 200, 80, 0.6));
1219+
filter: drop-shadow(0 0 4px rgba(255, 200, 80, 0.3));
12201220
}
12211221
.nge-profile-badge--building.nge-profile-badge--latest .nge-profile-badge-name {
12221222
color: #ffd08a;

0 commit comments

Comments
 (0)