diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx
index bf3af1b..e0dd0b3 100644
--- a/web/src/app/page.tsx
+++ b/web/src/app/page.tsx
@@ -4,6 +4,7 @@ export default function Home() {
return (
Lyra
+ Settings
);
diff --git a/web/src/app/settings/page.tsx b/web/src/app/settings/page.tsx
new file mode 100644
index 0000000..a9d104c
--- /dev/null
+++ b/web/src/app/settings/page.tsx
@@ -0,0 +1,11 @@
+import { SettingsForm } from "./settings-form";
+
+export default function SettingsPage() {
+ return (
+
+ Settings
+
+ ← Back to queue
+
+ );
+}
diff --git a/web/src/app/settings/settings-form.tsx b/web/src/app/settings/settings-form.tsx
new file mode 100644
index 0000000..6a80f4d
--- /dev/null
+++ b/web/src/app/settings/settings-form.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import { useEffect, useState } from "react";
+
+type Loaded = { qobuzEmail: string; slskdUrl: string; qobuzPasswordSet: boolean; slskdApiKeySet: boolean };
+
+export function SettingsForm() {
+ const [qobuzEmail, setQobuzEmail] = useState("");
+ const [qobuzPassword, setQobuzPassword] = useState("");
+ const [slskdUrl, setSlskdUrl] = useState("");
+ const [slskdApiKey, setSlskdApiKey] = useState("");
+ const [pwSet, setPwSet] = useState(false);
+ const [keySet, setKeySet] = useState(false);
+ const [saved, setSaved] = useState(false);
+
+ useEffect(() => {
+ fetch("/api/config")
+ .then((r) => r.json())
+ .then((c: Loaded) => {
+ setQobuzEmail(c.qobuzEmail);
+ setSlskdUrl(c.slskdUrl);
+ setPwSet(c.qobuzPasswordSet);
+ setKeySet(c.slskdApiKeySet);
+ });
+ }, []);
+
+ async function submit(e: React.FormEvent) {
+ e.preventDefault();
+ await fetch("/api/config", {
+ method: "PUT",
+ headers: { "content-type": "application/json" },
+ body: JSON.stringify({ qobuzEmail, qobuzPassword, slskdUrl, slskdApiKey }),
+ });
+ setQobuzPassword("");
+ setSlskdApiKey("");
+ setSaved(true);
+ setPwSet(pwSet || qobuzPassword !== "");
+ setKeySet(keySet || slskdApiKey !== "");
+ }
+
+ return (
+
+ );
+}