From 387747b9b035ac87ca663f20744dcf8d28c826f0 Mon Sep 17 00:00:00 2001 From: AmirReza Jamali Date: Sat, 11 Oct 2025 16:41:26 +0330 Subject: [PATCH] feat(settings): implement user profile page and notification handler This commit introduces a new user settings page and enhances push notification functionality. The new settings page, located at `/pages/settings`, allows users to view and update their personal profile information. It fetches the current user's data and provides a form to edit fields such as name, email, phone number, position, and role. The form is built using `react-hook-form` for state management and validation, and it leverages custom hooks (`useProfileQuery`, `useUpdateProfileQuery`) to interact with the API. Additionally, a `notificationclick` event listener has been added to the Firebase messaging service worker. This handler improves the user experience for push notifications by focusing on an existing tab with the relevant URL or opening a new one if none exists when a notification is clicked. --- public/firebase-messaging-sw.js | 25 +++ .../form-layout/_components/contact-form.tsx | 3 - src/app/pages/settings/page.tsx | 178 ++++++++++++++++-- src/components/Auth/SigninWithPassword.tsx | 3 +- .../FormElements/InputGroup/index.tsx | 4 +- src/components/FormElements/select.tsx | 3 +- .../Tables/notification-history/index.tsx | 2 +- src/components/forms/admins/CreateAdmin.tsx | 7 +- .../forms/customers/CreateCustomer.tsx | 13 +- src/constants/enums.ts | 4 + src/constants/regex.ts | 1 + src/contexts/User.ctx.tsx | 14 +- src/hooks/queries/useProfileQueries.ts | 26 ++- src/lib/api/endpoints.ts | 1 + src/lib/api/services/profile-service.ts | 37 +++- src/lib/api/types/Profile.ts | 14 ++ src/utils/shared.ts | 16 ++ 17 files changed, 302 insertions(+), 49 deletions(-) diff --git a/public/firebase-messaging-sw.js b/public/firebase-messaging-sw.js index ef27238..7e965b7 100644 --- a/public/firebase-messaging-sw.js +++ b/public/firebase-messaging-sw.js @@ -14,3 +14,28 @@ firebase.initializeApp({ }); const messaging = firebase.messaging(); + +self.addEventListener("notificationclick", (event) => { + event.notification.close(); + + const urlToOpen = event.notification.data.url || "/"; + + event.waitUntil( + clients + .matchAll({ + type: "window", + includeUncontrolled: true, + }) + .then((clientList) => { + for (const client of clientList) { + if (client.url === urlToOpen && "focus" in client) { + return client.focus(); + } + } + + if (clients.openWindow) { + return clients.openWindow(urlToOpen); + } + }), + ); +}); diff --git a/src/app/forms/form-layout/_components/contact-form.tsx b/src/app/forms/form-layout/_components/contact-form.tsx index 710eeb8..76d126a 100644 --- a/src/app/forms/form-layout/_components/contact-form.tsx +++ b/src/app/forms/form-layout/_components/contact-form.tsx @@ -1,6 +1,3 @@ -import InputGroup from "@/components/FormElements/InputGroup"; -import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area"; -import { Select } from "@/components/FormElements/select"; import { ShowcaseSection } from "@/components/Layouts/showcase-section"; export function ContactForm() { diff --git a/src/app/pages/settings/page.tsx b/src/app/pages/settings/page.tsx index 81eb6ab..d54a818 100644 --- a/src/app/pages/settings/page.tsx +++ b/src/app/pages/settings/page.tsx @@ -1,23 +1,165 @@ -import type { Metadata } from "next"; -import { PersonalInfoForm } from "./_components/personal-info"; -import { UploadPhotoForm } from "./_components/upload-photo"; - -export const metadata: Metadata = { - title: "Settings Page", -}; +"use client"; +import Loading from "@/app/loading"; +import InputGroup from "@/components/FormElements/InputGroup"; +import { Select } from "@/components/FormElements/select"; +import { ShowcaseSection } from "@/components/Layouts/showcase-section"; +import FormFooter from "@/components/ui/FormFooter"; +import { AdminRoles } from "@/constants/enums"; +import { REGEX } from "@/constants/regex"; +import { FormErrorMessages } from "@/constants/Texts"; +import { useProfileQuery, useUpdateProfileQuery } from "@/hooks/queries"; +import { TUpdateProfileCredentials, UpdateProfileCredentials } from "@/lib/api"; +import { getEnumAsArray } from "@/utils/shared"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; +import { ZodSafeParseResult } from "zod"; export default function SettingsPage() { + const { data, isLoading } = useProfileQuery(); + const { mutate } = useUpdateProfileQuery(); + const { register, reset, handleSubmit } = useForm({ + mode: "onChange", + defaultValues: data, + }); + + useEffect(() => { + if (data) { + reset(data); + } + }, [data, reset]); + const updateUser = (data: TUpdateProfileCredentials) => { + const validation: ZodSafeParseResult = + UpdateProfileCredentials.safeParse(data); + if (validation.success) { + mutate({ credentials: validation.data }); + } else { + console.error(validation.error); + } + }; + if (isLoading) return ; return ( -
Settings
- //
- //
- //
- // - //
- //
- // - //
- //
- //
+ +
+ + + + + + +