feat(notifications): Implement functional header notification dropdown

This commit replaces the static notification dropdown in the header with a fully functional component that fetches live data from the API.

Key features include:
- Fetches and displays the latest notifications.
- Shows a badge with the count of unseen notifications.
- Opens a modal with notification details upon clicking an item.
- Marks notifications as seen when they are viewed.

Additionally, this commit includes several related improvements:
- refactor: Replaced the global loading component with a custom Tailwind CSS spinner for a consistent look and feel.
- feat: Enhanced the DatePicker component to optionally include a time picker.
- style: Improved the layout of the notification details page by moving the message to a dedicated section and capitalizing the 'priority' and 'type' fields for better readability.
This commit is contained in:
AmirReza Jamali
2025-09-29 15:28:16 +03:30
parent dde2fc5a05
commit 021ee7d11e
11 changed files with 245 additions and 121 deletions
@@ -7,6 +7,7 @@ import { useGetNotificationDetails } from "@/hooks/queries/useNotificationQuerie
import { BreadcrumbItem } from "@/types/shared";
import { unixToDate } from "@/utils/shared";
import { use } from "react";
import { capitalize } from "../../../../utils/shared";
interface IProps {
params: Promise<{ id: string }>;
@@ -36,11 +37,6 @@ const NotificationDetailsPage = ({ params }: IProps) => {
<Breadcrumb items={breadcrumbItems} />
<ShowcaseSection title={`${data?.data.title}`}>
<div className="mt-4 grid grid-cols-4 gap-15 pb-4">
<IsVisible condition={!!data?.data.message}>
<ShowcaseSection title="Message">
{data?.data.message}
</ShowcaseSection>
</IsVisible>
<IsVisible condition={!!data?.data.event_type}>
<ShowcaseSection title="Event Type">
{data?.data.event_type}
@@ -52,12 +48,14 @@ const NotificationDetailsPage = ({ params }: IProps) => {
<IsVisible condition={!!data?.data.priority}>
<ShowcaseSection title="Priority">
{data?.data.priority}
{capitalize(data?.data.priority ?? "")}
</ShowcaseSection>
</IsVisible>
<IsVisible condition={!!data?.data.type}>
<ShowcaseSection title="Type">{data?.data.type}</ShowcaseSection>
<ShowcaseSection title="Type">
{capitalize(data?.data.type ?? "")}
</ShowcaseSection>
</IsVisible>
<IsVisible condition={!!data?.data.seen_at}>
<ShowcaseSection title="Seen at">
@@ -72,6 +70,12 @@ const NotificationDetailsPage = ({ params }: IProps) => {
{data?.data.seen ? "Yes" : "No"}
</ShowcaseSection>
</div>
<hr className="py-4" />
<IsVisible condition={!!data?.data.message}>
<ShowcaseSection title="Message">
{data?.data.message}
</ShowcaseSection>
</IsVisible>
</ShowcaseSection>
</>
);
+2 -1
View File
@@ -3,10 +3,11 @@ import { cn } from "../lib/utils";
interface IProps {
className?: string | null;
}
const Loading = ({ className = "w-svw h-svh" }: IProps) => {
return (
<div className={cn("flex items-center justify-center", className)}>
<span className="loading loading-dots loading-xl"></span>
<div className="h-5 w-5 animate-spin rounded-full border-b-2 border-primary"></div>
</div>
);
};