'use client'; import { useEffect, useState } from 'react'; import { apiFetch } from '@/lib/api'; import { Button } from '@/components/ui/button'; interface Org { id: string; slug: string; name: string; plan: string; monthlyCallQuota: number; callsThisPeriod: number; periodStartsAt: string; createdAt: string; } interface Member { id: string; userId: string; email: string; name: string | null; role: string; createdAt: string; } export default function SettingsPage() { const [org, setOrg] = useState(null); const [members, setMembers] = useState([]); const [err, setErr] = useState(null); useEffect(() => { apiFetch<{ org: Org; members: Member[] }>('/v1/me/org') .then((r) => { setOrg(r.org); setMembers(r.members); }) .catch((e) => setErr((e as Error).message)); }, []); if (err?.includes('401')) { if (typeof window !== 'undefined') window.location.href = '/login'; return null; } return (

Settings

Organization, plan, members, billing.

{!org &&
Loading…
} {org && (
{members.map((m) => ( ))}
Email Name Role Joined
{m.email} {m.name ?? '—'} {m.role} {new Date(m.createdAt).toLocaleDateString()}

Programmatic access for the upcoming bmm CLI.

Secrets are encrypted before write to Postgres, decrypted only at the moment of container env injection. Plaintext is never logged.

)}
); } function Card({ title, children, className, }: { title: string; children: React.ReactNode; className?: string; }) { return (
{title}
{children}
); } function Row({ label, value, mono, small, }: { label: string; value: string; mono?: boolean; small?: boolean; }) { return (
{label} {value}
); }