From 2a1c81181efdd29e967635c113f879bf77b9e9a7 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 21 Dec 2025 14:41:21 +0330 Subject: [PATCH] notification infiti scroll --- src/pages/notification/Notification.tsx | 16 +++--- .../notification/hooks/useNotificationData.ts | 16 ++---- .../service/NotificationService.ts | 9 ++-- .../notification/types/NotificationTypes.ts | 32 ++++++++++-- src/pages/orders/components/PaymentInfo.tsx | 51 ++++++++++++++++++- src/pages/orders/types/Types.ts | 18 +++---- 6 files changed, 103 insertions(+), 39 deletions(-) diff --git a/src/pages/notification/Notification.tsx b/src/pages/notification/Notification.tsx index 6ae2c58..a8a627f 100644 --- a/src/pages/notification/Notification.tsx +++ b/src/pages/notification/Notification.tsx @@ -17,11 +17,11 @@ const Notifications: FC = () => { // const navigate = useNavigate() const { t } = useTranslation('global'); const ref = useOutsideClick(() => setShowModal(false)); - const [activeTab, setActiveTab] = useState<'read' | 'unread'>('unread'); + const [activeTab, setActiveTab] = useState<'seen' | 'unseen'>('unseen'); const [showModal, setShowModal] = useState(false); const { data, fetchNextPage, hasNextPage, refetch } = useGetNotification(activeTab); const readAll = useReadAll() - const posts = data?.pages.flatMap((page) => page.data?.notifications || []) || []; + const posts = data?.pages.flatMap((page: { data: NotificationItemType[] }) => page.data || []) || []; // const getDashboard = useGetDashboard() const handleAllRead = () => { @@ -99,19 +99,19 @@ const Notifications: FC = () => {
setActiveTab('unread')} + onClick={() => setActiveTab('unseen')} className={clx( 'flex-1 border-l cursor-pointer text-white border-white border-opacity-70 bg-transparent flex justify-center items-center', - activeTab === 'unread' ? 'bg-white bg-opacity-70 text-black' : '' + activeTab === 'unseen' ? 'bg-white bg-opacity-70 text-black' : '' )} > خوانده نشده
setActiveTab('read')} + onClick={() => setActiveTab('seen')} className={clx( 'flex-1 cursor-pointer text-white border-white bg-transparent flex justify-center items-center', - activeTab === 'read' ? 'bg-white bg-opacity-70 text-black' : '' + activeTab === 'seen' ? 'bg-white bg-opacity-70 text-black' : '' )} > خوانده شده @@ -142,13 +142,13 @@ const Notifications: FC = () => { posts.map((item: NotificationItemType) => (
handleRedirect()} className="bg-white cursor-pointer h-fit gap-4 items-start rounded-xl bg-opacity-60 p-3 mb-4 flex" key={item.id}> { - !item.isRead && + !item.seenAt &&
}
-
{item.message}
+
{item.content}
{timeAgo(item.createdAt)}
diff --git a/src/pages/notification/hooks/useNotificationData.ts b/src/pages/notification/hooks/useNotificationData.ts index 40eeb97..7425eac 100644 --- a/src/pages/notification/hooks/useNotificationData.ts +++ b/src/pages/notification/hooks/useNotificationData.ts @@ -1,20 +1,14 @@ import * as api from "../service/NotificationService"; import { useInfiniteQuery, useMutation } from "@tanstack/react-query"; -export const useGetNotification = (status: "all" | "read" | "unread") => { +export const useGetNotification = (status: "all" | "seen" | "unseen") => { return useInfiniteQuery({ queryKey: ["notifications", status], - queryFn: ({ pageParam = 1 }) => api.getNotifications(pageParam, status), // فراخوانی API برای گرفتن داده‌ها - initialPageParam: 1, // صفحه اول به طور پیشفرض + queryFn: ({ pageParam }) => + api.getNotifications(pageParam as string | undefined, status), // فراخوانی API برای گرفتن داده‌ها + initialPageParam: undefined as string | undefined, // اولین درخواست بدون cursor getNextPageParam: (lastPage) => { - const currentPage = lastPage.data?.pager?.page; - const totalPages = lastPage.data?.pager?.totalPages; - - if (!currentPage || !totalPages) { - return undefined; - } - - return currentPage < totalPages ? currentPage + 1 : undefined; + return lastPage.nextCursor || undefined; }, }); }; diff --git a/src/pages/notification/service/NotificationService.ts b/src/pages/notification/service/NotificationService.ts index abc4405..93fa2b1 100644 --- a/src/pages/notification/service/NotificationService.ts +++ b/src/pages/notification/service/NotificationService.ts @@ -2,15 +2,16 @@ import axios from "../../../config/axios"; import type { GetNotificationsResponse } from "../types/NotificationTypes"; export const getNotifications = async ( - page: number, - status: "all" | "read" | "unread" + cursor: string | undefined, + status: "all" | "seen" | "unseen" ): Promise => { let query = ``; if (status !== "all") { - query = `&isRead=${status === "read" ? 1 : 0}`; + query = `&status=${status}`; } + const cursorParam = cursor ? `&cursor=${cursor}` : ``; const { data } = await axios.get( - `/admin/notifications?page=${page}${query}` + `/admin/notifications?limit=10${cursorParam}${query}` ); return data; }; diff --git a/src/pages/notification/types/NotificationTypes.ts b/src/pages/notification/types/NotificationTypes.ts index 2d91060..22f2adc 100644 --- a/src/pages/notification/types/NotificationTypes.ts +++ b/src/pages/notification/types/NotificationTypes.ts @@ -1,12 +1,32 @@ import type { IResponse } from "@/types/response.types"; +export type NotificationUser = { + id: string; + createdAt: string; + updatedAt: string; + deletedAt: string | null; + firstName: string; + lastName: string; + birthDate: string; + marriageDate: string; + referrer: string | null; + isActive: boolean; + gender: boolean; + avatarUrl: string | null; + phone: string; +}; + export type NotificationItemType = { id: string; - title: string; - message: string; createdAt: string; - isRead: boolean; - type: NotificationTypeEnum; + updatedAt: string; + deletedAt: string | null; + restaurant: string; + user: NotificationUser; + admin: string | null; + title: string; + content: string; + seenAt: string | null; }; export type NotificationPager = { @@ -19,7 +39,9 @@ export type NotificationData = { pager: NotificationPager; }; -export type GetNotificationsResponse = IResponse; +export type GetNotificationsResponse = IResponse & { + nextCursor?: string; +}; export enum NotificationTypeEnum { USER_LOGIN = "USER_LOGIN", diff --git a/src/pages/orders/components/PaymentInfo.tsx b/src/pages/orders/components/PaymentInfo.tsx index cf8d10d..45d5529 100644 --- a/src/pages/orders/components/PaymentInfo.tsx +++ b/src/pages/orders/components/PaymentInfo.tsx @@ -2,6 +2,8 @@ import type { FC } from 'react' import type { Order } from '../types/Types' import { PaymentStatusEnum } from '../enum/Enum' import { OrderStatus } from '../enum/Enum' +import { DeliveryMethodEnum } from '@/pages/shipmentMethod/enum/Enum' +import { PaymentMethodEnum } from '@/pages/paymentMethods/enum/Enum' import { formatPrice, formatFaNumber } from '@/helpers/func' interface PaymentInfoProps { @@ -19,6 +21,26 @@ const PaymentInfo: FC = ({ }) => { const paymentStatus = order.paymentStatus || (order.status === OrderStatus.PAID ? PaymentStatusEnum.Paid : PaymentStatusEnum.Pending) + const getDeliveryMethodText = (method: string): string => { + const methodMap: Record = { + [DeliveryMethodEnum.DineIn]: 'سرو در رستوران', + [DeliveryMethodEnum.CustomerPickup]: 'دریافت از محل', + [DeliveryMethodEnum.DeliveryCar]: 'تحویل به خودرو', + [DeliveryMethodEnum.DeliveryCourier]: 'بیرون بر', + } + return methodMap[method] || method + } + + const getPaymentMethodText = (method: string): string => { + const methodMap: Record = { + [PaymentMethodEnum.Cash]: 'پرداخت نقدی', + [PaymentMethodEnum.Online]: 'پرداخت آنلاین', + [PaymentMethodEnum.CardOnDelivery]: 'پرداخت در محل', + [PaymentMethodEnum.Wallet]: 'کیف پول', + } + return methodMap[method] || method + } + return (
@@ -37,11 +59,36 @@ const PaymentInfo: FC = ({
- نوع پرداخت + روش ارسال
-
{order.paymentMethod?.description || '-'}
+
{order.deliveryMethod ? getDeliveryMethodText(order.deliveryMethod.method) : '-'}
+ {order.deliveryMethod?.description && ( +
+
+ توضیحات روش ارسال +
+
{order.deliveryMethod.description}
+
+ )} + +
+
+ روش پرداخت +
+
{order.paymentMethod ? getPaymentMethodText(order.paymentMethod.method) : '-'}
+
+ + {order.paymentMethod?.description && ( +
+
+ توضیحات روش پرداخت +
+
{order.paymentMethod.description}
+
+ )} + {order.paymentMethod?.gateway && (
diff --git a/src/pages/orders/types/Types.ts b/src/pages/orders/types/Types.ts index d92fda1..9b73784 100644 --- a/src/pages/orders/types/Types.ts +++ b/src/pages/orders/types/Types.ts @@ -40,11 +40,11 @@ export interface OrderRestaurant { deletedAt: string | null; name: string; slug: string; - logo: string; - address: string; - menuColor: string; - latitude: number; - longitude: number; + logo: string | null; + address: string | null; + menuColor: string | null; + latitude: number | null; + longitude: number | null; serviceArea: ServiceArea; isActive: boolean; establishedYear: number | null; @@ -52,7 +52,7 @@ export interface OrderRestaurant { instagram: string | null; telegram: string | null; whatsapp: string | null; - description: string; + description: string | null; seoTitle: string | null; seoDescription: string | null; tagNames: string | null; @@ -72,8 +72,8 @@ export interface OrderDeliveryMethod { restaurant: string; deliveryFee: number; deliveryFeeType: string; - kilometerNumber: number | null; - deliveryFeeForKilometer: number | null; + perKilometerFee: number | null; + distanceBasedMinCost: number | null; minOrderPrice: number; description: string; enabled: boolean; @@ -124,7 +124,7 @@ export interface OrderFood { content: string[]; price: number; order: number | null; - prepareTime: number; + prepareTime: number | null; weekDays: number[]; mealTypes: string[]; isActive: boolean;