"use client"; import * as React from "react"; import { toast } from "sonner"; import { Loader2, Save, Wifi, WifiOff } from "lucide-react"; import { Header } from "@/components/layout/header"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; type Settings = { ollamaUrl: string; model: string; watchDir: string; watching: boolean; }; export default function SettingsPage() { const [settings, setSettings] = React.useState({ ollamaUrl: "", model: "", watchDir: "", watching: false, }); const [loading, setLoading] = React.useState(true); const [saving, setSaving] = React.useState(false); const [ollamaStatus, setOllamaStatus] = React.useState<"unknown" | "connected" | "error">("unknown"); React.useEffect(() => { fetch("/api/settings") .then((r) => r.json()) .then((data) => { setSettings(data); setLoading(false); }) .catch(() => { setLoading(false); }); }, []); const handleSave = async () => { setSaving(true); try { const res = await fetch("/api/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(settings), }); if (!res.ok) throw new Error(); toast.success("Settings saved"); } catch { toast.error("Failed to save settings"); } finally { setSaving(false); } }; const testOllamaConnection = async () => { setOllamaStatus("unknown"); try { const url = settings.ollamaUrl || "http://192.168.68.108:11434"; const res = await fetch(`${url}/api/tags`, { signal: AbortSignal.timeout(5000), }); if (res.ok) { setOllamaStatus("connected"); toast.success("Connected to Ollama"); } else { setOllamaStatus("error"); toast.error("Ollama responded with an error"); } } catch { setOllamaStatus("error"); toast.error("Cannot reach Ollama. Check the URL and ensure it's running."); } }; const toggleWatch = async () => { try { const action = settings.watching ? "stop" : "start"; const res = await fetch("/api/watch", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ action, watchDir: settings.watchDir }), }); if (!res.ok) throw new Error(); setSettings((s) => ({ ...s, watching: !s.watching })); toast.success(action === "start" ? "Folder watching started" : "Folder watching stopped"); } catch { toast.error("Failed to toggle folder watching"); } }; if (loading) { return (
); } return (
{/* Ollama Configuration */}
Ollama Configuration Connect to your Ollama instance for OCR processing
{ollamaStatus === "connected" && } {ollamaStatus === "error" && } {ollamaStatus === "connected" ? "Connected" : ollamaStatus === "error" ? "Error" : "Not tested"}
setSettings((s) => ({ ...s, ollamaUrl: e.target.value }))} placeholder="http://192.168.68.108:11434" />
setSettings((s) => ({ ...s, model: e.target.value }))} placeholder="llava:7b" />

Recommended: llava:7b, moondream, or llama3.2-vision

{/* Folder Watch */} Folder Monitoring Automatically process new PDFs dropped into a folder
setSettings((s) => ({ ...s, watchDir: e.target.value }))} placeholder="/data/watch" />

Absolute path on the server. Mount a host folder into the container.

{settings.watching && ( Active )}
{/* Monday.com Integration (placeholder) */} Monday.com Integration Push scanned card data to Monday.com boards (coming soon)

API endpoints are ready. Configure Monday.com connection in a future update.

Use the REST API at /api/cards to integrate with n8n, Zapier, or Monday.com directly.

); }