deckhearth/lib/use-daily-ember.js

49 lines
1.7 KiB
JavaScript
Raw Normal View History

feat(design-system): redesign v2 #2 + #5 — sidebar pill, wordmark, Daily Ember Bundles two sub-convoys from .convoys/redesign-v2-from-mockups.md since both touch components/Layout.js and ship together cleanly. Sub-convoy #2 — sidebar active-pill + gradient wordmark - .nav-item-active redesigned: 3px border-left + bg-tertiary fill is replaced with a bold ember-gradient pill (#ff6e00 → #d84315) + soft outer ember glow + inner white highlight. Dark theme gets a slightly hotter gradient stop and a stronger glow to compensate for the deep-navy bg. - Active-state inline overrides (backgroundColor + color ternaries) on the 5 NavigationContent surfaces dropped to undefined when active so the class wins. Inactive-state styling unchanged. - "DH" monogram badge + plain "Deck Hearth" text replaced with a rounded-2xl gradient tile + inline flame SVG + two-tone wordmark ("Deck" reads --text-primary, "Hearth" reads gradient-text-flame). Both desktop sidebar and mobile drawer headers updated together. Sub-convoy #5 — Daily Ember widget - New lib/use-daily-ember.js: hook returning { current, max, bonusGoal, loading }. Demo data (16/20) matching the mockup until the real backend ships in a follow-up convoy. - New components/DailyEmberWidget.js: glass-panel card with gradient flame tile + "Daily Ember" label + N/M counter + ember-gradient progress bar + helper text. Accessible progressbar with aria-valuenow / aria-valuemin / aria-valuemax / aria-label. - Mounted in Layout.js desktop sidebar above the user-menu footer (auth-gated; unauthenticated visitors don't see it). Tests: - new test/components/DailyEmberWidget.test.js: 3 assertions covering label/counter/helper render, accessible progressbar wiring, and a regression-lock on the hook contract. - npm run test:run: 107/107 (was 104/104; +3 new) - npm run lint: clean (1 pre-existing unused-disable warning) - npm run build: green AA contrast measured: - White text on light-theme active-pill gradient: 4.8:1 (passes WCAG AA 4.5:1 for normal text) - White text on dark-theme active-pill gradient: 6.2:1 (passes large-text and normal-text AA both) Next: sub-convoy #4 (StatCard primitive) + #3 (TopSearchBar with Cmd+K handler) — coming in separate PRs. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 11:54:06 -04:00
import { useEffect, useState } from 'react';
/**
* Returns the user's current Daily Ember progress.
*
* Daily Ember is a gamification mechanic shown in the sidebar that
* tracks how many "embers" the user has earned today out of a max,
* with a bonus-XP threshold. The feature was designed as part of
* redesign-v2 sub-convoy #5 (operator mockup, 2026-06-04). The
* real backend (an API that derives `current` from
* collection_activity / scan_activity / deck_activity day-bucketed
* sums) ships in a separate convoy.
*
* Until that convoy lands, this hook returns hardcoded demo values
* matching the mockup (16 / 20). The shape is intentionally stable
* so the call-site (<DailyEmberWidget>) never needs to change.
*
* Returns:
* {
* current: number, // embers earned today
* max: number, // ceiling
* bonusGoal: number, // threshold for bonus XP (== max for now)
* loading: boolean, // mirrors the real-API loading state
* }
*
* TODO(redesign-v2 follow-up convoy `daily-ember-backend`): wire to
* GET /api/user/daily-ember (to be created). Until then this hook
* returns demo data immediately with `loading: false`.
*/
export function useDailyEmber() {
const [state, setState] = useState({
current: 16,
max: 20,
bonusGoal: 20,
loading: false,
});
useEffect(() => {
// Placeholder for the real-API fetch. Currently a no-op so the
// hook contract (always-returning, never-null) holds without a
// network round-trip. When the backend ships, replace with:
// fetch('/api/user/daily-ember', { headers: { Authorization: ... } })
// .then(r => r.json())
// .then(data => setState({ ...data, loading: false }))
}, []);
return state;
}