feat(integrations): add Google Health card to connect page (#119)

The OAuth backend (signal source, /connect and /callback routes, token
refresh, consent grant) was already complete. This adds the missing UI:
a Google Health card in /connect with Connect/Disconnect actions, and
broadens the "See my tip →" CTA to appear when any integration is
connected (not only Todoist).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 10:28:14 +00:00
parent ad43a8f06a
commit 8474468614

View File

@@ -51,6 +51,8 @@ function ConnectPageInner() {
}
const todoistConnected = isConnected('todoist');
const googleHealthConnected = isConnected('google-health');
const anyConnected = todoistConnected || googleHealthConnected;
return (
<main style={{ minHeight: '100vh', padding: '4rem 2rem', maxWidth: '480px', margin: '0 auto' }}>
@@ -85,7 +87,6 @@ function ConnectPageInner() {
marginBottom: '1rem',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.875rem' }}>
{/* Todoist logomark */}
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" aria-label="Todoist">
<rect width="24" height="24" rx="6" fill="#DB4035"/>
<path d="M6 8.5L11 13l7-7" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
@@ -130,7 +131,65 @@ function ConnectPageInner() {
)}
</div>
{todoistConnected && (
{/* Google Health card */}
<div style={{
border: '1px solid rgba(255,255,255,0.1)',
borderRadius: '0.75rem',
padding: '1.25rem 1.5rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '1rem',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.875rem' }}>
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" aria-label="Google Health">
<rect width="24" height="24" rx="6" fill="#EA4335"/>
<path d="M12 6.5c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2z" fill="#fff"/>
<path d="M8 10.5c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2z" fill="#fff" opacity=".7"/>
<path d="M12 14.5c0 2.2-1.8 4-4 4s-4-1.8-4-4 1.8-4 4-4 4 1.8 4 4z" fill="#fff" opacity=".4"/>
<path d="M13 13.5c.5-1 1.5-1.7 2.5-1.7 1.7 0 3 1.3 3 3s-1.3 3-3 3c-1 0-1.9-.5-2.5-1.3" stroke="#fff" strokeWidth="1.5" strokeLinecap="round" fill="none"/>
</svg>
<div>
<div style={{ fontWeight: 500, fontSize: '0.9rem' }}>Google Health</div>
<div style={{ color: 'var(--gray)', fontSize: '0.75rem', marginTop: '0.1rem' }}>
{googleHealthConnected ? 'Connected' : 'Steps, sleep & activity'}
</div>
</div>
</div>
{googleHealthConnected ? (
<button
onClick={() => handleDisconnect('google-health')}
disabled={disconnecting === 'google-health'}
style={{
background: 'transparent',
border: '1px solid rgba(255,255,255,0.15)',
color: 'var(--gray)',
borderRadius: '0.375rem',
padding: '0.375rem 0.875rem',
fontSize: '0.8rem',
}}
>
{disconnecting === 'google-health' ? '…' : 'Disconnect'}
</button>
) : (
<a
href="/api/integrations/google-health/connect?redirectTo=/connect"
style={{
background: 'var(--white)',
color: 'var(--black)',
borderRadius: '0.375rem',
padding: '0.375rem 0.875rem',
fontSize: '0.8rem',
fontWeight: 500,
}}
>
Connect
</a>
)}
</div>
{anyConnected && (
<div style={{ marginTop: '3rem' }}>
<a
href="/tip"