feat: timezone auto-detection, branding fix, frontend rebuild

Timezone:
- Add diligence/utils/dates.py with today_for_user(), now_for_user(), day_start_utc()
- Replace all 20 date.today() calls across 10 files with timezone-aware helpers
- Remove hardcoded Asia/Bangkok offset hack in nutrition router
- Change defaults from Asia/Bangkok to UTC in user model, nutrition model, config
- Add timezone field to RegisterRequest schema
- Set user.timezone from browser detection during registration
- Frontend sends Intl.DateTimeFormat().resolvedOptions().timeZone on register

Branding:
- Login page: Fitness Rewards -> Diligence, updated tagline and emoji
- index.html title: Fitness Rewards -> Diligence

Frontend rebuild:
- Fresh Vite build with all changes (index-CsKoBN0D.js)
- Nav bar, timezone detection, and branding all verified in built bundle
This commit is contained in:
Claude 2026-07-04 07:16:23 +00:00
parent 40c8485aa7
commit c37543b009
21 changed files with 1961 additions and 64 deletions

View file

@ -6,7 +6,7 @@
<meta name="theme-color" content="#1a1a2e" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<title>Fitness Rewards</title>
<title>Diligence</title>
</head>
<body>
<div id="root"></div>

1865
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@ export const api = {
login: (username, password) =>
request('/auth/login', { method: 'POST', body: JSON.stringify({ username, password }) }),
register: (username, password, display_name) =>
request('/auth/register', { method: 'POST', body: JSON.stringify({ username, password, display_name }) }),
request('/auth/register', { method: 'POST', body: JSON.stringify({ username, password, display_name, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone }) }),
me: () => request('/auth/me'),
// Onboarding

View file

@ -36,12 +36,12 @@ export default function Login() {
<div style={{ width: '100%', maxWidth: '380px' }}>
{/* Brand */}
<div style={{ textAlign: 'center', marginBottom: '32px', color: '#fff' }}>
<div style={{ fontSize: '3.2rem', marginBottom: '8px', filter: 'drop-shadow(0 4px 12px rgba(0,0,0,0.2))' }}>🔥</div>
<div style={{ fontSize: '3.2rem', marginBottom: '8px', filter: 'drop-shadow(0 4px 12px rgba(0,0,0,0.2))' }}>💪</div>
<h1 style={{ fontFamily: 'var(--font-display)', fontSize: '2.2rem', fontWeight: 900, letterSpacing: '-0.03em' }}>
Fitness Rewards
Diligence
</h1>
<p style={{ opacity: 0.8, marginTop: '4px', fontSize: '0.95rem', fontWeight: 500 }}>
Earn your rewards. Every single day.
Your fitness. Your data. Your rewards.
</p>
</div>