"use client"; import { useState } from "react"; import { useTheme } from "@/lib/use-theme"; import { useAuth } from "@/lib/auth"; import { AppShell } from "@/components/AppShell"; import { AlertBanner, Button, Card, Input, Select, Textarea } from "@/components/ui/Primitives"; import { getFeedbackClient } from "@/lib/feedback-client"; import { toast } from "@/lib/toast"; import { NOTES_API_URL, PLATFORM_SERVICE_URL, MCP_SERVER_URL, PRODUCT_ID } from "@/lib/product-config"; import { getOfflineQueue } from "@/lib/offline-queue"; export default function SettingsPage() { const { theme, toggle } = useTheme(); const { user, logout, changePassword, deleteAccount, isLoading, error, success, clearMessages } = useAuth(); const [feedbackTitle, setFeedbackTitle] = useState(""); const [feedbackBody, setFeedbackBody] = useState(""); const [feedbackType, setFeedbackType] = useState<"bug" | "feature" | "praise" | "other">("bug"); const [submittingFeedback, setSubmittingFeedback] = useState(false); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); async function handleSubmitFeedback() { if (!feedbackTitle.trim()) return; setSubmittingFeedback(true); try { await getFeedbackClient().submitWithScreenshot({ type: feedbackType, title: feedbackTitle.trim(), body: feedbackBody.trim() || undefined, platform: "web", }); toast.success("Feedback submitted"); setFeedbackTitle(""); setFeedbackBody(""); } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to submit feedback"); } finally { setSubmittingFeedback(false); } } async function handleChangePassword(e: React.FormEvent) { e.preventDefault(); clearMessages(); const ok = await changePassword(currentPassword, newPassword); if (ok) { setCurrentPassword(""); setNewPassword(""); toast.success("Password changed"); } } async function handleDeleteAccount() { const pw = prompt("Enter your password to confirm account deletion:"); if (!pw) return; const ok = await deleteAccount(pw); if (ok) toast.success("Account deleted"); } return ( Sign out } >
{/* Profile */} Profile
{user?.name ?? "—"} · {user?.email ?? "—"} · {user?.role ?? "—"}
{/* Appearance */}
Appearance
Switch between dark and light mode
{/* Change password */} Change password {error && ( {error} )} {success && ( {success} )}
setCurrentPassword(e.target.value)} required /> setNewPassword(e.target.value)} required />
{/* Danger zone */} Danger zone
Connect your agent (MCP)

Use your platform access token with the shared MCP server on port 4007. Point tools at the NoteLett backend and product id{" "} {PRODUCT_ID}.

          {`Notes API base: ${NOTES_API_URL}
Platform API: ${PLATFORM_SERVICE_URL}
MCP API base: ${MCP_SERVER_URL}

# Example Cursor / Claude MCP entry (adjust to your installer):
# "mcpServers": {
#   "notelett": { "url": "${MCP_SERVER_URL}" }
# }`}
        

Deep links for tools: see docs/DEEP_LINKS.md in the repo.

API tokens for automation

Scoped tokens for MCP or CI are provisioned through the ByteLyst platform when your tenant enables them. This web app does not yet expose create/revoke; use the platform admin or CLI when available.

Offline queue

Failed writes are retried from local storage via @bytelyst/offline-queue (storage key{" "} {`${PRODUCT_ID}_offline_queue`}). Reload or return online to flush.

{/* Feedback */} Send feedback
setFeedbackTitle(e.target.value)} />