Redesign v2: Solar Momentum — bold, bright, energetic
Design philosophy informed by skills review: - canvas-design: Named aesthetic movement, craftsmanship emphasis - frontend-design: Bold direction, distinctive typography, avoid AI slop - frontend-patterns: Component composition, proper hooks - theme-factory: Focused 4-color palettes with clear hierarchy Changes: - Palette: Deep orange (#FF5722) + vivid green (#00C853) + electric blue + purple - Typography: Outfit (display, 900 weight) + Plus Jakarta Sans (body) - Background: Warm gradient (peach → cream → light blue) - Gate banner: 2.8rem hero numbers, thick gradient progress bars - Activity checklist: Colored icon badges per category - Cards: Larger radius (20px), warm shadows, tinted section backgrounds - Login: Bold gradient hero (orange → dark), fire emoji brand - Navigation: Orange active indicator bar, frosted glass backdrop - Week view: Purple-themed hero with large stats - Buttons: More shadow depth, active press scale animation - All CSS variables renamed to semantic system (--orange, --green, --text-2) - Zero orphaned old variable references
This commit is contained in:
parent
22f5e8fae3
commit
080b7856b7
9 changed files with 566 additions and 552 deletions
|
|
@ -6,66 +6,84 @@ export default function WeekView() {
|
|||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => { load() }, [])
|
||||
|
||||
async function load() {
|
||||
try {
|
||||
const data = await api.week()
|
||||
setWeek(data)
|
||||
} catch (err) { console.error(err) }
|
||||
try { setWeek(await api.week()) }
|
||||
catch (err) { console.error(err) }
|
||||
finally { setLoading(false) }
|
||||
}
|
||||
|
||||
if (loading) return <div className="page"><div className="loading">Loading...</div></div>
|
||||
if (!week) return <div className="page"><div className="error-msg">Failed to load</div></div>
|
||||
|
||||
const dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||
const pct = week.weekly_target > 0 ? Math.min(100, Math.round((week.total_points_earned / week.weekly_target) * 100)) : 0
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
|
||||
return (
|
||||
<div className="page">
|
||||
<h1 className="page-title">📊 This Week</h1>
|
||||
<h1 className="page-title">This Week</h1>
|
||||
|
||||
{/* Week summary */}
|
||||
<div className="card" style={{ textAlign: 'center' }}>
|
||||
<div style={{ fontSize: '2rem', fontWeight: 800 }}>{week.total_points_earned}</div>
|
||||
<div style={{ color: 'var(--text-muted)', marginBottom: '8px' }}>/ {week.weekly_target} pts</div>
|
||||
<div className="progress-bar">
|
||||
<div className="progress-bar-fill" style={{ width: `${pct}%`, background: week.hit_weekly_target ? 'var(--success)' : 'var(--accent)' }} />
|
||||
{/* Summary hero */}
|
||||
<div className="card" style={{ textAlign: 'center', background: 'var(--purple-ghost)' }}>
|
||||
<div className="section-label">Weekly Total</div>
|
||||
<div style={{ fontFamily: 'var(--font-display)', fontSize: '2.6rem', fontWeight: 900, letterSpacing: '-0.03em' }}>
|
||||
{week.total_points_earned}
|
||||
</div>
|
||||
<div style={{ color: 'var(--text-3)', fontWeight: 600, fontSize: '0.88rem', marginBottom: '12px' }}>
|
||||
/ {week.weekly_target} pts
|
||||
</div>
|
||||
<div className="progress-bar" style={{ height: '12px' }}>
|
||||
<div className="progress-bar-fill" style={{
|
||||
width: `${pct}%`,
|
||||
background: week.hit_weekly_target ? 'linear-gradient(90deg, #00C853, #69F0AE)' : 'linear-gradient(90deg, #7C4DFF, #B388FF)',
|
||||
}} />
|
||||
</div>
|
||||
{week.hit_weekly_target && (
|
||||
<div style={{ marginTop: '8px', color: 'var(--success)', fontWeight: 600 }}>
|
||||
🏆 Weekly target hit! +{week.weekly_bonus_earned} bonus pts
|
||||
<div style={{ marginTop: '10px', color: 'var(--green-dark)', fontWeight: 700, fontSize: '0.9rem' }}>
|
||||
🏆 Target hit! +{week.weekly_bonus_earned} bonus
|
||||
</div>
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: '24px', marginTop: '12px', fontSize: '0.85rem' }}>
|
||||
<div><span style={{ fontWeight: 700 }}>{week.active_days}</span> <span style={{ color: 'var(--text-muted)' }}>active days</span></div>
|
||||
<div><span style={{ fontWeight: 700 }}>{week.gate_passed_days}</span> <span style={{ color: 'var(--text-muted)' }}>rewards earned</span></div>
|
||||
<div style={{ display: 'flex', justifyContent: 'center', gap: '28px', marginTop: '14px' }}>
|
||||
<div>
|
||||
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.3rem' }}>{week.active_days}</div>
|
||||
<div style={{ fontSize: '0.72rem', color: 'var(--text-3)', fontWeight: 600 }}>active days</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.3rem' }}>{week.gate_passed_days}</div>
|
||||
<div style={{ fontSize: '0.72rem', color: 'var(--text-3)', fontWeight: 600 }}>rewards earned</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Daily breakdown */}
|
||||
<div className="card">
|
||||
<div style={{ fontWeight: 700, marginBottom: '12px' }}>Daily Breakdown</div>
|
||||
<div className="section-label">Daily Breakdown</div>
|
||||
{week.daily_breakdown.map((day, i) => {
|
||||
const dayPct = day.daily_minimum > 0 ? Math.min(100, Math.round((day.points_earned / day.daily_minimum) * 100)) : 0
|
||||
const isToday = day.date === new Date().toISOString().split('T')[0]
|
||||
const isToday = day.date === today
|
||||
return (
|
||||
<div key={day.date} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '8px 0', borderBottom: i < 6 ? '1px solid var(--border)' : 'none' }}>
|
||||
<div style={{ width: '40px', fontWeight: isToday ? 700 : 400, color: isToday ? 'var(--accent)' : 'var(--text)' }}>
|
||||
{dayNames[i]}
|
||||
<div key={day.date} style={{
|
||||
display: 'flex', alignItems: 'center', gap: '10px', padding: '10px 0',
|
||||
borderBottom: i < 6 ? '1px solid var(--divider)' : 'none',
|
||||
}}>
|
||||
<div style={{
|
||||
width: '38px', fontWeight: isToday ? 800 : 600, fontSize: '0.85rem',
|
||||
color: isToday ? 'var(--orange)' : 'var(--text)',
|
||||
}}>
|
||||
{days[i]}
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<div className="progress-bar" style={{ height: '6px' }}>
|
||||
<div className="progress-bar" style={{ height: '8px' }}>
|
||||
<div className="progress-bar-fill" style={{
|
||||
width: `${dayPct}%`,
|
||||
background: day.gate_passed ? 'var(--success)' : day.points_earned > 0 ? 'var(--warning)' : 'var(--border)',
|
||||
background: day.gate_passed ? 'var(--green)' : day.points_earned > 0 ? 'var(--amber)' : 'transparent',
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ width: '50px', textAlign: 'right', fontSize: '0.85rem', fontWeight: 600 }}>
|
||||
<div style={{ width: '46px', textAlign: 'right', fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '0.9rem' }}>
|
||||
{day.points_earned}
|
||||
</div>
|
||||
<div style={{ width: '24px', textAlign: 'center' }}>
|
||||
<div style={{ width: '22px', textAlign: 'center', fontSize: '0.9rem' }}>
|
||||
{day.gate_passed ? '✅' : day.points_earned > 0 ? '🟡' : '⬜'}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue