Settings Page
Configure call preferences, integrations, notifications, and account security settings
Settings Page
The settings page allows solvers to configure their preferences and manage integrations. Located at /dashboard/settings, it provides control over call handling, notifications, payment setup, and security.
Page Sections
The settings page is organized into several cards:
- Call Preferences - How voice calls are handled
- Google Meet Integration - Video calling status
- Notifications - Browser and sound alerts
- Payment Settings - Stripe Connect status
- Security - Account security via Clerk
- Help & Support - Documentation and contact links
Call Preferences
Solvers can choose how they receive voice calls from customers.
Options
| Option | Description |
|---|---|
| In-App Calling (WebRTC) | Calls handled directly in the browser using WebRTC. Requires microphone access. |
| Phone Bridge | Calls forwarded to the solver's personal phone number. Requires phone number in profile. |
Implementation
The preference is saved via the updateProfile mutation:
const handleCallPreferenceChange = (value: "in_app" | "bridge") => {
updateProfile.mutate({ callPreference: value });
};
return (
<RadioGroup
value={solver.callPreference}
onValueChange={(value) =>
handleCallPreferenceChange(value as "in_app" | "bridge")
}
>
<div className="flex items-start space-x-3 rounded-lg border p-4">
<RadioGroupItem value="in_app" id="in_app" />
<div>
<Label htmlFor="in_app">In-App Calling (WebRTC)</Label>
<p className="text-sm text-muted-foreground">
Make and receive calls directly in your browser.
</p>
</div>
</div>
<div className="flex items-start space-x-3 rounded-lg border p-4">
<RadioGroupItem value="bridge" id="bridge" />
<div>
<Label htmlFor="bridge">Phone Bridge</Label>
<p className="text-sm text-muted-foreground">
Calls are bridged to your personal phone number.
</p>
</div>
</div>
</RadioGroup>
);Google Meet Integration
Video calling through Google Meet is available for employed (W-2) solvers with a configured Google Workspace email.
Status States
Enabled - Shows green success banner with connected email:
{solver.employment === "employed" && solver.googleEmail ? (
<div className="flex items-center gap-3 rounded-lg bg-green-50 p-4">
<CheckCircle className="h-5 w-5 text-green-600" />
<div>
<p className="font-medium">Google Meet Enabled</p>
<p className="text-sm">Connected as {solver.googleEmail}</p>
</div>
</div>
)}Not Configured - Shows yellow warning for employed solvers without email:
{solver.employment === "employed" && !solver.googleEmail && (
<div className="rounded-lg bg-yellow-50 p-4">
<p className="font-medium">Google Workspace email not configured</p>
<p className="text-sm">
Contact an administrator to set up your Google Workspace email.
</p>
</div>
)}Not Available - Shows muted message for contract solvers:
{solver.employment !== "employed" && (
<div className="rounded-lg bg-muted p-4">
<p className="text-muted-foreground">
Google Meet is available for employed (W-2) solvers only.
</p>
</div>
)}Notifications
Control browser and sound notifications for platform events.
Options
| Setting | Description |
|---|---|
| Browser Notifications | Push notifications for new tickets and messages |
| Sound Alerts | Audio cues for incoming tickets and messages |
Implementation
Notification preferences are stored locally in the browser:
const [notificationsEnabled, setNotificationsEnabled] = useState(true);
const [soundEnabled, setSoundEnabled] = useState(true);
return (
<>
<div className="flex items-center justify-between">
<div>
<Label htmlFor="notifications">Browser Notifications</Label>
<p className="text-sm text-muted-foreground">
Get notified about new tickets and messages
</p>
</div>
<Switch
id="notifications"
checked={notificationsEnabled}
onCheckedChange={setNotificationsEnabled}
/>
</div>
<p className="text-xs text-muted-foreground">
Note: Notification preferences are stored locally in your browser.
</p>
</>
);Payment Settings
Stripe Connect integration status for receiving payouts.
Connected State
When Stripe is connected, shows success banner and link to Stripe Dashboard:
{solver.stripeConnectId ? (
<div className="space-y-4">
<div className="flex items-center gap-3 rounded-lg bg-green-50 p-4">
<CheckCircle className="h-5 w-5 text-green-600" />
<div>
<p className="font-medium">Stripe Connected</p>
<p className="text-sm">
Your payout account is set up and ready to receive payments.
</p>
</div>
</div>
<Button variant="outline" asChild>
<a href="https://dashboard.stripe.com" target="_blank">
<ExternalLink className="mr-2 h-4 w-4" />
Manage in Stripe Dashboard
</a>
</Button>
</div>
)}Not Connected State
Shows warning and connect button:
{!solver.stripeConnectId && (
<div className="space-y-4">
<div className="rounded-lg bg-yellow-50 p-4">
<p className="font-medium">Payout account not connected</p>
<p className="text-sm">
Connect your Stripe account to receive payouts.
</p>
</div>
<Button>Connect Stripe Account</Button>
</div>
)}Security
Account security is managed through Clerk's user management interface.
Features Available via Clerk
- Password changes
- Two-factor authentication (2FA)
- Connected accounts (Google, etc.)
- Session management
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="h-5 w-5" />
Security
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Account security is managed through Clerk.
</p>
<Button variant="outline" asChild>
<a href="/user" target="_blank">
<ExternalLink className="mr-2 h-4 w-4" />
Manage Security Settings
</a>
</Button>
</CardContent>
</Card>Help & Support
Quick access to documentation and support channels.
Links Provided
| Link | Destination |
|---|---|
| View Documentation | /docs - Platform documentation |
| Contact Support | mailto:support@savvysolve.io |
<div className="grid gap-3 sm:grid-cols-2">
<Button variant="outline" asChild>
<a href="/docs" target="_blank">
<ExternalLink className="mr-2 h-4 w-4" />
View Documentation
</a>
</Button>
<Button variant="outline" asChild>
<a href="mailto:support@savvysolve.io">
<ExternalLink className="mr-2 h-4 w-4" />
Contact Support
</a>
</Button>
</div>Loading State
Displays skeleton placeholders while data loads:
if (isLoading) {
return (
<div className="space-y-6">
<Skeleton className="h-8 w-48" />
<Skeleton className="h-48 w-full" />
<Skeleton className="h-48 w-full" />
</div>
);
}UI Components Used
Card,CardHeader,CardContent,CardTitle,CardDescriptionButton- Action buttons and external linksRadioGroup,RadioGroupItem- Call preference selectionSwitch- Notification togglesLabel- Form field labelsSkeleton- Loading placeholders
File Location
app/(authenticated)/dashboard/settings/
└── page.tsx # Settings page componentRelated Documentation
- Profile Page - Edit personal information
- Google Meet Integration - Video calling setup
- Stripe Integration - Payment processing
- Clerk Integration - Authentication