diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte
index 37ead8d..29461b0 100644
--- a/src/lib/components/layout/Sidebar.svelte
+++ b/src/lib/components/layout/Sidebar.svelte
@@ -51,6 +51,11 @@
href: '/gallery',
label: 'Gallery',
icon: 'M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z'
+ },
+ {
+ href: '/settings',
+ label: 'Settings',
+ icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z'
}
]);
diff --git a/src/routes/(app)/settings/+page.server.ts b/src/routes/(app)/settings/+page.server.ts
new file mode 100644
index 0000000..775cbb3
--- /dev/null
+++ b/src/routes/(app)/settings/+page.server.ts
@@ -0,0 +1,51 @@
+import type { PageServerLoad, Actions } from './$types';
+import { db } from '$lib/server/db/index.js';
+import { users } from '$lib/server/db/schema.js';
+import { eq } from 'drizzle-orm';
+import { fail } from '@sveltejs/kit';
+import { verifyPassword, hashPassword } from '$lib/server/auth/password.js';
+
+export const load: PageServerLoad = async ({ locals }) => {
+ return { user: locals.user! };
+};
+
+export const actions: Actions = {
+ changePassword: async ({ request, locals }) => {
+ const formData = await request.formData();
+ const currentPassword = formData.get('currentPassword') as string;
+ const newPassword = formData.get('newPassword') as string;
+ const confirmPassword = formData.get('confirmPassword') as string;
+
+ if (!currentPassword || !newPassword || !confirmPassword) {
+ return fail(400, { error: 'All fields are required' });
+ }
+
+ if (newPassword.length < 8) {
+ return fail(400, { error: 'New password must be at least 8 characters' });
+ }
+
+ if (newPassword !== confirmPassword) {
+ return fail(400, { error: 'New passwords do not match' });
+ }
+
+ const [user] = await db
+ .select({ passwordHash: users.passwordHash })
+ .from(users)
+ .where(eq(users.id, locals.user!.id));
+
+ if (!user) return fail(400, { error: 'User not found' });
+
+ const valid = await verifyPassword(user.passwordHash, currentPassword);
+ if (!valid) {
+ return fail(400, { error: 'Current password is incorrect' });
+ }
+
+ const newHash = await hashPassword(newPassword);
+ await db
+ .update(users)
+ .set({ passwordHash: newHash, updatedAt: new Date() })
+ .where(eq(users.id, locals.user!.id));
+
+ return { success: true };
+ }
+};
diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte
new file mode 100644
index 0000000..65e888a
--- /dev/null
+++ b/src/routes/(app)/settings/+page.svelte
@@ -0,0 +1,68 @@
+
+
+