diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte
new file mode 100644
index 0000000..6cad9d0
--- /dev/null
+++ b/frontend/src/routes/settings/+page.svelte
@@ -0,0 +1,527 @@
+
+
+
+ Settings | Tanabata
+
+
+
+
+
+
+
+
+ Appearance
+
+
+ {$themeStore === 'light' ? 'Light theme' : 'Dark theme'}
+
+
+
+
+
+
+
+ App cache
+ Clear service worker and cached assets. Useful if the app feels stale after an update.
+ {#if pwaSuccess}
+ Cache cleared. Reload the page to fetch fresh assets.
+ {/if}
+
+
+
+
+
+
+
+
+ Active sessions
+ {#if sessionsTotal > 0}({sessionsTotal}){/if}
+
+
+ {#if sessionsError}
+ {sessionsError}
+ {:else if sessionsLoading}
+ Loading…
+ {:else if sessions.length === 0}
+ No active sessions.
+ {:else}
+
+ {/if}
+
+
+
+
\ No newline at end of file
diff --git a/frontend/vite-mock-plugin.ts b/frontend/vite-mock-plugin.ts
index f50b565..ea4afea 100644
--- a/frontend/vite-mock-plugin.ts
+++ b/frontend/vite-mock-plugin.ts
@@ -300,6 +300,19 @@ export function mockApiPlugin(): Plugin {
return json(res, 200, ME);
}
+ // PATCH /users/me
+ if (method === 'PATCH' && path === '/users/me') {
+ const body = (await readBody(req)) as { name?: string; password?: string };
+ if (body.name) ME.name = body.name;
+ return json(res, 200, ME);
+ }
+
+ // DELETE /auth/sessions/{id}
+ const sessionDelMatch = path.match(/^\/auth\/sessions\/(\d+)$/);
+ if (method === 'DELETE' && sessionDelMatch) {
+ return noContent(res);
+ }
+
// GET /files/{id}/thumbnail
const thumbMatch = path.match(/^\/files\/([^/]+)\/thumbnail$/);
if (method === 'GET' && thumbMatch) {