React Components
Dashboard React components for partner registration and profile management — PartnerForm, PartnerRegistration, and PartnerProfileView.
React Components
The Supyagent dashboard includes React components for managing partner profiles. These components handle registration, profile editing, and API key display.
PartnerForm
The top-level component that renders either the registration form (for new partners) or the profile view (for existing partners).
import { PartnerForm } from "@/components/settings/partner-form";
<PartnerForm partner={partnerProfile} apiKeyPrefix={apiKeyPrefix} />Props
| Prop | Type | Description |
|---|---|---|
partner | PartnerProfile | null | The current partner profile, or null if not registered |
apiKeyPrefix | string | null | The first characters of the API key (e.g., sk_live_abc...) |
Behavior
- When
partnerisnull, renders the registration form - When
partneris provided, renders the profile view with edit capability
Usage in a Server Component
The partner settings page fetches data server-side and passes it to PartnerForm:
import { createAdminClient } from "@/lib/supabase/admin";
import { createClient } from "@/lib/supabase/server";
import { PartnerForm } from "@/components/settings/partner-form";
export default async function PartnerSettingsPage() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) redirect("/login");
const admin = createAdminClient();
const { data: partner } = await admin
.from("partner_profiles")
.select("*")
.eq("user_id", user.id)
.single();
const { data: apiKeyRow } = await admin
.from("api_keys")
.select("key_prefix")
.eq("user_id", user.id)
.eq("is_active", true)
.order("created_at", { ascending: false })
.limit(1)
.single();
return (
<PartnerForm
partner={partner || null}
apiKeyPrefix={apiKeyRow?.key_prefix || null}
/>
);
}Registration State
When no partner profile exists, PartnerForm renders a registration form with four fields:
| Field | Input Type | Required | Validation |
|---|---|---|---|
| Company Name | Text | Yes | 1-255 characters |
| Website | URL | Yes | Valid URL format |
| Contact Email | No | Valid email format | |
| Use Case | Text | No | Max 1000 characters |
Registration Flow
- User fills in the form and clicks Register
- The component calls
POST /api/partnerwith the form data - On success, switches to the RegistrationSuccess view
- Shows the Partner ID and API key with copy-to-clipboard buttons
┌─────────────────────────────────────────────┐
│ Become a Partner │
│ Register to use the Connected Accounts API │
│ │
│ Company Name [_______________] │
│ Website [_______________] │
│ Contact Email [_______________] (optional) │
│ Use Case [_______________] (optional) │
│ │
│ [ Register ] │
└─────────────────────────────────────────────┘Success View
After registration, the component displays the partner ID and API key:
┌─────────────────────────────────────────────┐
│ Partner Profile Created │
│ You can now use the Connected Accounts API │
│ │
│ Partner ID 550e8400-...440000 [Copy] │
│ Company Acme Inc. │
│ Status ● Active │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ API Key │
│ Save this key now — you won't see it again │
│ │
│ sk_live_abc123def456... [Copy] │
└─────────────────────────────────────────────┘The API key is only shown once, immediately after registration. The yellow border on the API key card indicates urgency.
Profile View State
When a partner profile exists, PartnerForm renders a view/edit interface.
View Mode
Displays partner details as a read-only summary:
┌──────────────────────────────────────────────┐
│ Partner Profile [Edit] │
│ Your registration for the Connected │
│ Accounts API │
│ │
│ Partner ID 550e8400-...440000 [Copy] │
│ Company Acme Inc. │
│ Website https://acme.com │
│ Email team@acme.com │
│ Use Case AI workflow platform │
│ Status ● Active │
│ Tier free │
└──────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ API Key │
│ Use this key to authenticate Connected │
│ Accounts API requests │
│ │
│ sk_live_abc... [Manage Keys] │
└──────────────────────────────────────────────┘Edit Mode
Clicking Edit switches to inline editing for all fields:
- Company Name, Website, Contact Email, and Use Case become editable inputs
- Save button (disabled until changes are detected)
- Cancel button resets all fields to their original values
- Changes are saved via
PATCH /api/partner
Status Indicators
| Status | Badge Color | Meaning |
|---|---|---|
active | Green (border-green-500/30 text-green-400) | Partner is active and can use the API |
suspended | Red (border-red-500/30 text-red-400) | Partner is suspended — API calls will return 403 |
API Key Section
- Shows the API key prefix (e.g.,
sk_live_abc...) if a key exists - Links to the Manage Keys page for full key management
- Shows a Create Key button if no active key exists
Dependencies
The PartnerForm component uses:
| Import | Package | Description |
|---|---|---|
Card, CardContent, CardHeader, CardTitle, CardDescription | @supyagent/ui | Card layout components |
Button | @supyagent/ui | Action buttons |
Input | @supyagent/ui | Text input fields |
Label | @supyagent/ui | Form labels |
Badge | @supyagent/ui | Status badges |
Loader2, Copy, Check | lucide-react | Icons for loading, copy, and success states |
PartnerProfile | @supyagent/types | TypeScript type for the partner profile |
TypeScript Types
PartnerProfile
interface PartnerProfile {
id: string;
user_id: string;
company_name: string;
website: string;
contact_email: string | null;
description: string | null;
status: "active" | "suspended";
tier: string;
created_at: string;
updated_at: string;
}ConnectedAccount
interface ConnectedAccount {
id: string;
platform_user_id: string;
external_id: string;
display_name: string | null;
metadata: Record<string, unknown>;
created_at: string;
}ConnectSession
type ConnectSessionStatus = "pending" | "completed" | "expired" | "failed";
interface ConnectSession {
id: string;
connected_account_id: string;
platform_user_id: string;
provider: IntegrationProvider;
status: ConnectSessionStatus;
redirect_url: string;
scopes: string[] | null;
state: string;
code_verifier: string | null;
error: string | null;
created_at: string;
expires_at: string;
}All types are exported from @supyagent/types in packages/types/src/database.ts.
Dashboard Navigation
The partner settings page is accessible from the dashboard sidebar:
Settings
├── General
├── API Keys
└── Partner ← /settings/partnerThe navigation item uses the Building2 icon from Lucide React.