From 090c0d1c3c1b6bf2f569eb4c9e1164523f048319 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 7 Jun 2025 15:11:29 +0000 Subject: feat(web): Redesign the user settings page --- apps/web/app/settings/info/page.tsx | 4 +- apps/web/components/settings/ChangePassword.tsx | 225 ++++++++++++++++-------- apps/web/components/settings/UserDetails.tsx | 71 +++++--- apps/web/components/settings/UserOptions.tsx | 192 ++++++++++---------- 4 files changed, 302 insertions(+), 190 deletions(-) (limited to 'apps') diff --git a/apps/web/app/settings/info/page.tsx b/apps/web/app/settings/info/page.tsx index c7d8f808..52a6ce9d 100644 --- a/apps/web/app/settings/info/page.tsx +++ b/apps/web/app/settings/info/page.tsx @@ -1,10 +1,10 @@ import { ChangePassword } from "@/components/settings/ChangePassword"; import UserDetails from "@/components/settings/UserDetails"; -import { UserOptions } from "@/components/settings/UserOptions"; +import UserOptions from "@/components/settings/UserOptions"; export default async function InfoPage() { return ( -
+
diff --git a/apps/web/components/settings/ChangePassword.tsx b/apps/web/components/settings/ChangePassword.tsx index f8c2b8dd..703b9c16 100644 --- a/apps/web/components/settings/ChangePassword.tsx +++ b/apps/web/components/settings/ChangePassword.tsx @@ -1,6 +1,7 @@ "use client"; import type { z } from "zod"; +import { useState } from "react"; import { ActionButton } from "@/components/ui/action-button"; import { Form, @@ -15,12 +16,19 @@ import { toast } from "@/components/ui/use-toast"; import { useTranslation } from "@/lib/i18n/client"; import { api } from "@/lib/trpc"; import { zodResolver } from "@hookform/resolvers/zod"; +import { Eye, EyeOff, Lock } from "lucide-react"; import { useForm } from "react-hook-form"; import { zChangePasswordSchema } from "@karakeep/shared/types/users"; +import { Button } from "../ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; + export function ChangePassword() { const { t } = useTranslation(); + const [showCurrentPassword, setShowCurrentPassword] = useState(false); + const [showNewPassword, setShowNewPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); const form = useForm>({ resolver: zodResolver(zChangePasswordSchema), defaultValues: { @@ -55,83 +63,150 @@ export function ChangePassword() { } return ( -
-
- {t("settings.info.change_password")} -
-
- - { - return ( - - {t("settings.info.current_password")} - - - - - - ); - }} - /> - { - return ( - - {t("settings.info.new_password")} - - - - - - ); - }} - /> - { - return ( - - - {t("settings.info.confirm_new_password")} + + + + + Security + + + + + + ( + + + {t("settings.info.current_password")} - - - +
+ + + + +
- ); - }} - /> - - {t("actions.save")} - - - -
+ )} + /> + +
+ ( + + + {t("settings.info.new_password")} + +
+ + + + +
+ +
+ )} + /> + + ( + + + {t("settings.info.confirm_new_password")} + +
+ + + + +
+ +
+ )} + /> +
+ +
+ + {t("actions.save")} + +
+ + + + ); } diff --git a/apps/web/components/settings/UserDetails.tsx b/apps/web/components/settings/UserDetails.tsx index af6698ad..6135df47 100644 --- a/apps/web/components/settings/UserDetails.tsx +++ b/apps/web/components/settings/UserDetails.tsx @@ -1,35 +1,60 @@ import { Input } from "@/components/ui/input"; import { useTranslation } from "@/lib/i18n/server"; import { api } from "@/server/api/client"; +import { Mail, User } from "lucide-react"; + +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; +import { Label } from "../ui/label"; export default async function UserDetails() { const { t } = await useTranslation(); const whoami = await api.users.whoami(); - const details = [ - { - label: t("common.name"), - value: whoami.name ?? undefined, - }, - { - label: t("common.email"), - value: whoami.email ?? undefined, - }, - ]; - return ( -
-
- {t("settings.info.basic_details")} -
-
- {details.map(({ label, value }) => ( -
-
{label}
- + + +
+
+ + + {t("settings.info.basic_details")} + +
+
+
+ +
+
+ + +
+
+ +
+ +
- ))} -
-
+
+ + ); } diff --git a/apps/web/components/settings/UserOptions.tsx b/apps/web/components/settings/UserOptions.tsx index 3918ceed..483c3f2b 100644 --- a/apps/web/components/settings/UserOptions.tsx +++ b/apps/web/components/settings/UserOptions.tsx @@ -7,6 +7,7 @@ import { useInterfaceLang } from "@/lib/userLocalSettings/bookmarksLayout"; import { updateInterfaceLang } from "@/lib/userLocalSettings/userLocalSettings"; import { useUserSettings } from "@/lib/userSettings"; import { zodResolver } from "@hookform/resolvers/zod"; +import { Archive, Bookmark, Globe } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -17,6 +18,7 @@ import { zUserSettingsSchema, } from "@karakeep/shared/types/users"; +import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"; import { Form, FormField } from "../ui/form"; import { Label } from "../ui/label"; import { @@ -26,6 +28,7 @@ import { SelectTrigger, SelectValue, } from "../ui/select"; +import { Separator } from "../ui/separator"; import { toast } from "../ui/use-toast"; const LanguageSelect = () => { @@ -37,7 +40,7 @@ const LanguageSelect = () => { await updateInterfaceLang(val); }} > - + @@ -51,7 +54,7 @@ const LanguageSelect = () => { ); }; -export default function UserSettings() { +export default function UserOptions() { const { t } = useTranslation(); const clientConfig = useClientConfig(); const data = useUserSettings(); @@ -101,97 +104,106 @@ export default function UserSettings() { return (
- ( -
-