← back to Professional Directory

agents/web-agent/app/account/page.tsx

119 lines

// /account — login + role + subscription state, all proxied via /api/* to pd-api.
'use client';
import { useEffect, useState } from 'react';

type WhoAmI = {
  user: null | {
    id: number; email: string; role: string; tier: string;
    display_name?: string; claimed_professional_id?: number; claimed_organization_id?: number;
    synthetic?: boolean;
  };
};

export default function AccountPage() {
  const [me, setMe] = useState<WhoAmI | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('/api/auth/whoami', { credentials: 'include' })
      .then(r => r.ok ? r.json() : { user: null })
      .then(setMe)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <section className="section"><h2>Loading…</h2></section>;

  if (!me?.user) {
    return (
      <section className="section">
        <div className="eyebrow">Account</div>
        <h2>Sign in to drvouch</h2>
        <p style={{ maxWidth: 540, color: 'var(--ink-soft)' }}>
          Patients: Google sign-in, free, leave reviews, get personalized matches.
          Doctors / office managers: claim your practice in 60 seconds (NPI + practice email).
        </p>
        <a className="card" href="/api/auth/google?returnTo=/account"
           style={{ display: 'inline-block', marginTop: 16, padding: '12px 22px', background: 'var(--moss)', color: '#fff', borderRadius: 999, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', fontSize: 14 }}>
          Continue with Google →
        </a>
        <p style={{ marginTop: 22, color: 'var(--ink-soft)', fontSize: 13 }}>
          By signing in, you agree drvouch is non-clinical: reviews and messages are about service / scheduling / billing — not medical advice.
        </p>
      </section>
    );
  }

  const u = me.user;
  return (
    <section className="section">
      <div className="eyebrow">Account</div>
      <h2>Welcome, {u.display_name || u.email}</h2>
      <p style={{ color: 'var(--ink-soft)' }}>
        {u.synthetic ? 'Loopback synthetic-admin (Steve).' : `Signed in as ${u.email}.`}
      </p>

      <div className="card-grid" style={{ marginTop: 32 }}>
        <div className="card">
          <span className="badge">Role</span>
          <span className="name">{u.role}</span>
          <span className="meta">
            {u.role === 'patient' && 'Browse, leave reviews, suppress comments on your own page.'}
            {u.role === 'doctor'  && 'Respond to reviews, edit page, DM patients (paid tier).'}
            {u.role === 'admin'   && 'You see everything. Approve claims at /admin/doctor-claims.'}
            {u.role === 'guest'   && 'Read-only.'}
          </span>
        </div>
        <div className="card">
          <span className="badge">Tier</span>
          <span className="name">{u.tier === 'paid' ? '★ Paid' : 'Free'}</span>
          <span className="meta">
            {u.tier === 'paid'
              ? 'DMs + threads + responses unlocked.'
              : 'Free reads. Upgrade to participate.'}
          </span>
          {u.tier !== 'paid' && (
            <SubscribeButton role={u.role} />
          )}
        </div>
        {(u.claimed_professional_id || u.claimed_organization_id) && (
          <div className="card">
            <span className="badge">Claimed</span>
            <span className="name">
              {u.claimed_professional_id ? `Professional #${u.claimed_professional_id}` :
               u.claimed_organization_id  ? `Organization #${u.claimed_organization_id}` : ''}
            </span>
            <span className="meta">Edit your page content from this dashboard.</span>
          </div>
        )}
      </div>

      <form action="/api/auth/logout" method="POST" style={{ marginTop: 32 }}>
        <button type="submit" style={{ background: 'transparent', border: '1px solid var(--ink)', color: 'var(--ink)', padding: '10px 18px', borderRadius: 999, fontWeight: 600, fontSize: 13, letterSpacing: '0.04em', textTransform: 'uppercase', cursor: 'pointer' }}>
          Sign out
        </button>
      </form>
    </section>
  );
}

function SubscribeButton({ role }: { role: string }) {
  const plan = role === 'doctor' ? 'doctor_pro_monthly' : 'patient_plus_monthly';
  const onClick = async () => {
    const r = await fetch('/api/subscriptions/checkout', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      body: JSON.stringify({ plan }),
    });
    const j = await r.json();
    if (j.url) window.location.href = j.url;
    else alert(j.error || 'Checkout failed');
  };
  return (
    <button onClick={onClick}
            style={{ marginTop: 12, background: 'var(--moss)', color: '#fff', border: 0, padding: '10px 18px', borderRadius: 999, fontWeight: 600, fontSize: 13, letterSpacing: '0.04em', textTransform: 'uppercase', cursor: 'pointer', alignSelf: 'flex-start' }}>
      Upgrade →
    </button>
  );
}