From bf3662a436bc9bb926ba86209404f4f65cbc5ed7 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sat, 27 Sep 2025 11:59:15 +0330 Subject: [PATCH] list coupons --- src/pages/Coupon/List.tsx | 113 ++++++++++++++++++++-- src/pages/Coupon/Update.tsx | 9 ++ src/pages/Coupon/hooks/useCouponData.ts | 11 +++ src/pages/Coupon/service/CouponService.ts | 14 ++- src/pages/Coupon/types/Types.ts | 40 ++++++++ src/pages/orders/types/Types.ts | 4 +- src/pages/products/types/Types.ts | 16 +++ 7 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 src/pages/Coupon/Update.tsx diff --git a/src/pages/Coupon/List.tsx b/src/pages/Coupon/List.tsx index 39fdd4c..19bedfc 100644 --- a/src/pages/Coupon/List.tsx +++ b/src/pages/Coupon/List.tsx @@ -1,22 +1,121 @@ -import { type FC } from 'react' -import { useGetCoupons } from './hooks/useCouponData' +import { type FC, useState } from 'react' +import { useGetCoupons, useDeleteCoupon } from './hooks/useCouponData' +import { type CouponResponseData } from './types/Types' import PageLoading from '@/components/PageLoading' import Error from '@/components/Error' +import PaginationUi from '@/components/PaginationUi' +import Td from '@/components/Td' +import TrashWithConfrim from '@/components/TrashWithConfrim' +import { Edit } from 'iconsax-react' +import Button from '@/components/Button' +import { Link } from 'react-router-dom' +import { Pages } from '@/config/Pages' +import { useNavigate } from 'react-router-dom' const CouponList: FC = () => { - - const { data, isLoading, error } = useGetCoupons() + const [currentPage, setCurrentPage] = useState(1); + const { data: couponsData, isLoading, error, refetch } = useGetCoupons(currentPage) + const deleteCouponMutation = useDeleteCoupon(); + const navigate = useNavigate(); if (isLoading) { - return + return ( +
+ +
+ ); } if (error) { - return + return ( +
+ +
+ ); } + const handleDeleteCoupon = async (couponId: string) => { + await deleteCouponMutation.mutateAsync(couponId); + refetch() + }; + + const coupons = couponsData?.results?.coupons || []; + const pager = couponsData?.results?.pager; + return ( -
List
+
+
+
+
+ + + + + + + {coupons.length === 0 ? ( + + + + ) : ( + coupons.map((coupon: CouponResponseData) => ( + + + + + )) + )} + +
+ + + + + + + + +
+ هیچ کوپنی یافت نشد +
+ + + + + + +
+ + {coupon.isActive ? 'فعال' : 'غیرفعال'} + +
+
+ +
+ + + + + handleDeleteCoupon(coupon._id)} + isLoading={deleteCouponMutation.isPending} + /> +
+
+
+ + { + setCurrentPage(page); + }} + /> +
) } diff --git a/src/pages/Coupon/Update.tsx b/src/pages/Coupon/Update.tsx new file mode 100644 index 0000000..1a462ae --- /dev/null +++ b/src/pages/Coupon/Update.tsx @@ -0,0 +1,9 @@ +import { type FC } from 'react' + +const UpdateCoupon: FC = () => { + return ( +
UpdateCoupon
+ ) +} + +export default UpdateCoupon \ No newline at end of file diff --git a/src/pages/Coupon/hooks/useCouponData.ts b/src/pages/Coupon/hooks/useCouponData.ts index 735f2f7..3fb5435 100644 --- a/src/pages/Coupon/hooks/useCouponData.ts +++ b/src/pages/Coupon/hooks/useCouponData.ts @@ -19,3 +19,14 @@ export const useCreateCoupon = () => { }, }); }; + +export const useDeleteCoupon = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (couponId: string) => api.deleteCoupon(couponId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["coupons"] }); + }, + }); +}; diff --git a/src/pages/Coupon/service/CouponService.ts b/src/pages/Coupon/service/CouponService.ts index dd3dcb9..2cdbb8a 100644 --- a/src/pages/Coupon/service/CouponService.ts +++ b/src/pages/Coupon/service/CouponService.ts @@ -1,7 +1,13 @@ import axios from "../../../config/axios"; -import type { CreateCouponType, CouponType } from "../types/Types"; +import type { + CreateCouponType, + CouponType, + CouponsResponse, +} from "../types/Types"; -export const getCoupons = async (page: number = 1) => { +export const getCoupons = async ( + page: number = 1 +): Promise => { const { data } = await axios.get(`/admin/coupon/native?page=${page}`); return data; }; @@ -12,3 +18,7 @@ export const createCoupon = async ( const { data } = await axios.post("/admin/coupon", couponData); return data; }; + +export const deleteCoupon = async (couponId: string): Promise => { + await axios.delete(`/admin/coupon/${couponId}`); +}; diff --git a/src/pages/Coupon/types/Types.ts b/src/pages/Coupon/types/Types.ts index edd9f93..afd5557 100644 --- a/src/pages/Coupon/types/Types.ts +++ b/src/pages/Coupon/types/Types.ts @@ -19,3 +19,43 @@ export interface CouponType extends CreateCouponType { createdAt: string; updatedAt: string; } + +export interface CouponResponseData { + _id: string; + shopId: string; + discountPercentage: number; + discountAmount: number; + usageLimit: number; + usageCount: number; + userUsageLimit: number; + code: string; + minPurchaseAmount: number; + category: string[]; + includedProducts: number[]; + excludedProducts: number[]; + description: string; + isActive: boolean; + includeSpecialSale: boolean; + expirationDate: string; + deleted: boolean; + createdAt: string; + updatedAt: string; +} + +export type PagerType = { + page: number; + limit: number; + totalItems: number; + totalPages: number; + prevPage: boolean | null; + nextPage: string | null; +}; + +export interface CouponsResponse { + status: number; + success: boolean; + results: { + coupons: CouponResponseData[]; + pager: PagerType; + }; +} diff --git a/src/pages/orders/types/Types.ts b/src/pages/orders/types/Types.ts index edefea4..ab12099 100644 --- a/src/pages/orders/types/Types.ts +++ b/src/pages/orders/types/Types.ts @@ -187,8 +187,8 @@ export type PagerType = { limit: number; totalItems: number; totalPages: number; - prevPage: boolean; - nextPage: boolean; + prevPage: boolean | null; + nextPage: string | null; }; export type OrdersResponseType = { diff --git a/src/pages/products/types/Types.ts b/src/pages/products/types/Types.ts index b95f2fc..ce834bb 100644 --- a/src/pages/products/types/Types.ts +++ b/src/pages/products/types/Types.ts @@ -267,6 +267,14 @@ export type CreateProductVariantRequestType = { stock: number; }; +export type CreateProductVariantResponseType = { + status: number; + success: boolean; + results: { + variant: ProductVariantDetailType; + }; +}; + // تایپ‌های مربوط به جزئیات محصول export type ProductSpecificationType = { title: string; @@ -373,6 +381,14 @@ export type UpdateVariantRequestType = { specialSale_endDate: string; }; +export type UpdateVariantResponseType = { + status: number; + success: boolean; + results: { + variant: ProductVariantDetailType; + }; +}; + // تایپ‌های مربوط به آپدیت محصول سه مرحله‌ای // مرحله اول: آپدیت جزئیات محصول