import { createFileRoute, Link } from "@tanstack/react-router"; import { useState } from "react"; import { useApiKeys, useAuth, useChangePassword, useCreateApiKey, useDeleteApiKey, } from "../hooks/useAuth"; import { useCurrency } from "../hooks/useCurrency"; import { useUpdateSetting } from "../hooks/useSettings"; import { useWeightUnit } from "../hooks/useWeightUnit"; import type { Currency, WeightUnit } from "../lib/formatters"; const UNITS: WeightUnit[] = ["g", "oz", "lb", "kg"]; const CURRENCIES: { value: Currency; label: string }[] = [ { value: "USD", label: "$" }, { value: "EUR", label: "€" }, { value: "GBP", label: "£" }, { value: "JPY", label: "¥" }, { value: "CAD", label: "CA$" }, { value: "AUD", label: "A$" }, ]; export const Route = createFileRoute("/settings")({ component: SettingsPage, }); function ChangePasswordSection() { const changePassword = useChangePassword(); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [message, setMessage] = useState<{ type: "success" | "error"; text: string; } | null>(null); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setMessage(null); try { await changePassword.mutateAsync({ currentPassword, newPassword }); setMessage({ type: "success", text: "Password changed" }); setCurrentPassword(""); setNewPassword(""); } catch (err) { setMessage({ type: "error", text: (err as Error).message }); } } return (

Change Password

setCurrentPassword(e.target.value)} required className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200" /> setNewPassword(e.target.value)} required minLength={6} className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200" /> {message && (

{message.text}

)}
); } function ApiKeySection() { const { data: keys } = useApiKeys(); const createKey = useCreateApiKey(); const deleteKey = useDeleteApiKey(); const [name, setName] = useState(""); const [newKey, setNewKey] = useState(null); async function handleCreate(e: React.FormEvent) { e.preventDefault(); const result = await createKey.mutateAsync({ name }); setNewKey(result.key); setName(""); } return (

API Keys

API keys allow programmatic access to GearBox (e.g., from Claude Desktop or scripts).

{newKey && (

Copy this key now — it won't be shown again:

{newKey}
)}
setName(e.target.value)} required className="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-200" />
{keys && keys.length > 0 && (
{keys.map((key) => (
{key.name} {key.keyPrefix}...
))}
)}
); } function SettingsPage() { const unit = useWeightUnit(); const currency = useCurrency(); const updateSetting = useUpdateSetting(); const { data: auth } = useAuth(); return (
← Back

Settings

Weight Unit

Choose the unit used to display weights across the app

{UNITS.map((u) => ( ))}

Currency

Changes the currency symbol displayed. This does not convert values.

{CURRENCIES.map((c) => ( ))}
{auth?.user && (
)}
); }