"use client"; import { useState, useEffect, useRef } from "react"; import { User } from "@prisma/client"; import { Loader2, Eye, EyeOff, Upload, AlertTriangle, CheckCircle2 } from "lucide-react"; interface UserPreferences { theme: string; defaultWeightUnit: string; defaultRestSeconds: number; enableClaudeAI: boolean; claudeApiKey?: string; } export default function SettingsForm({ user }: { user: User }) { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const [showApiKey, setShowApiKey] = useState(false); const [preferences, setPreferences] = useState({ theme: "system", defaultWeightUnit: "lbs", defaultRestSeconds: 90, enableClaudeAI: false, }); useEffect(() => { const fetchPreferences = async () => { try { const response = await fetch("/api/preferences"); if (response.ok) { const data = await response.json(); setPreferences(data); } } catch (err) { console.error("Failed to fetch preferences:", err); } }; fetchPreferences(); }, []); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(null); setSuccess(false); setLoading(true); try { const response = await fetch("/api/preferences", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(preferences), }); if (!response.ok) { const data = await response.json(); throw new Error(data.error || "Failed to save preferences"); } setSuccess(true); setTimeout(() => setSuccess(false), 3000); } catch (err) { setError(err instanceof Error ? err.message : "An error occurred"); } finally { setLoading(false); } }; return (
{/* Status Messages */} {error && (
{error}
)} {success && (
Settings saved successfully!
)} {/* Profile Section */}

Profile

{/* Preferences Section */}

Preferences

{/* Weight Unit */}
{["lbs", "kg"].map((unit) => ( ))}

Kettlebell exercises always default to kg

{/* Theme */}
{/* Claude AI Section */}

Claude AI Integration

Enable Claude AI to get personalized workout recommendations and program optimization suggestions.

{/* Enable Toggle */}
Enable Claude AI
{/* API Key Input - Only show if enabled */} {preferences.enableClaudeAI && (
setPreferences((prev) => ({ ...prev, claudeApiKey: e.target.value, })) } placeholder="sk-..." className="w-full px-3 py-2 border border-zinc-700 rounded-lg bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 pr-10" />

Get your API key from{" "} console.anthropic.com

)}
{/* Save Button */} {/* Database Import Section */} ); } // ---------- Database Import Component ---------- function DatabaseImport() { const fileInputRef = useRef(null); const [importing, setImporting] = useState(false); const [importError, setImportError] = useState(null); const [importSuccess, setImportSuccess] = useState<{ message: string; stats: { users: number; exercises: number; workouts: number }; } | null>(null); const [confirmOpen, setConfirmOpen] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const handleFileSelect = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; setImportError(null); setImportSuccess(null); setSelectedFile(file); setConfirmOpen(true); }; const handleImport = async () => { if (!selectedFile) return; setImporting(true); setImportError(null); setImportSuccess(null); setConfirmOpen(false); try { const formData = new FormData(); formData.append("database", selectedFile); const response = await fetch("/api/settings/import-db", { method: "POST", body: formData, }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Import failed"); } setImportSuccess({ message: data.message, stats: data.stats, }); // Clear the file input if (fileInputRef.current) fileInputRef.current.value = ""; setSelectedFile(null); } catch (err) { setImportError( err instanceof Error ? err.message : "An error occurred during import" ); } finally { setImporting(false); } }; const handleCancel = () => { setConfirmOpen(false); setSelectedFile(null); if (fileInputRef.current) fileInputRef.current.value = ""; }; return (

Import Database

Upload an existing Workout Planner database file (app.db) to restore your workout history. A backup of the current database will be created automatically.

{/* Error message */} {importError && (
{importError}
)} {/* Success message */} {importSuccess && (

{importSuccess.message}

Imported: {importSuccess.stats.users} user(s),{" "} {importSuccess.stats.exercises} exercises,{" "} {importSuccess.stats.workouts} workouts

)} {/* Confirmation dialog */} {confirmOpen && selectedFile && (

Replace current database?

File: {selectedFile.name} ( {(selectedFile.size / 1024).toFixed(0)} KB)

Your current database will be backed up before replacement.

)} {/* File input and upload button */} {!confirmOpen && (

Located at prisma/data/app.db in your local project

)}
); }