Skip to content

Commit 7398844

Browse files
committed
Update and remove coupons
1 parent d5a6ed7 commit 7398844

File tree

6 files changed

+201
-76
lines changed

6 files changed

+201
-76
lines changed

src/app/(admin)/admin/coupons/AddCoupon.js

+2-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
// This component needs to be refactored and optimized
2+
13
"use client";
24

35
import { useMutation, useQueryClient } from "@tanstack/react-query";
46
import persian_fa from "react-date-object/locales/persian_fa";
57
import persian from "react-date-object/calendars/persian";
6-
import { usePathname, useRouter } from "next/navigation";
78
import DatePicker from "react-multi-date-picker";
89
import { toast } from "react-hot-toast";
910
import { TbPlus } from "react-icons/tb";
@@ -39,8 +40,6 @@ const validationSchema = Yup.object({
3940
});
4041

4142
export default function AddCoupon() {
42-
const router = useRouter();
43-
const pathname = usePathname();
4443
const [type, setType] = useState("");
4544
const queryClient = useQueryClient();
4645
const [productIds, setProductIds] = useState([]);
@@ -55,24 +54,13 @@ export default function AddCoupon() {
5554
onSuccess: (data) => {
5655
queryClient.invalidateQueries({ queryKey: ["get-coupons"] });
5756
toast.success(data?.message);
58-
router.refresh(pathname);
5957
},
6058
onError: (error) => {
6159
toast.error(error?.response?.data?.message);
6260
},
6361
});
6462

6563
const sumbitHandler = async (values) => {
66-
console.log(
67-
{
68-
...values,
69-
type,
70-
expireDate: new Date(expireDate).toISOString(),
71-
productIds: productIds.map((product) => product._id),
72-
},
73-
"values"
74-
);
75-
7664
try {
7765
const { message } = await mutateAsync({
7866
...values,

src/app/(admin)/admin/coupons/CouponsTable.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import {
44
toPersianNumbers,
55
toPersianNumbersWithComma,
66
} from "@/utils/toPersianNumbers";
7+
import Link from "next/link";
78
import { TbEye } from "react-icons/tb";
89
import RemoveCoupon from "./RemoveCoupon";
910
import UpdateCoupon from "./UpdateCoupon";
1011
import { Tooltip, useDisclosure } from "@nextui-org/react";
1112
import { toLocalDateStringShort } from "@/utils/toLocalDate";
12-
import Link from "next/link";
1313

1414
export default function CouponsTable({ coupon, index }) {
1515
const {
@@ -24,8 +24,6 @@ export default function CouponsTable({ coupon, index }) {
2424
amount,
2525
} = coupon || {};
2626

27-
console.log(productIds);
28-
2927
const { isOpen, onOpen, onOpenChange } = useDisclosure();
3028

3129
return (

src/app/(admin)/admin/coupons/RemoveCoupon.js

+26-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { usePathname, useRouter } from "next/navigation";
2-
import { useMutation } from "@tanstack/react-query";
1+
import { deleteCoupon } from "@/services/adminServices";
2+
import { useMutation, useQueryClient } from "@tanstack/react-query";
33
import { TbX } from "react-icons/tb";
44
import toast from "react-hot-toast";
55
import {
@@ -13,23 +13,24 @@ import {
1313
} from "@nextui-org/react";
1414

1515
export default function RemoveCoupon({ id }) {
16+
const queryClient = useQueryClient();
1617
const { isOpen, onOpen, onOpenChange } = useDisclosure();
17-
const router = useRouter();
18-
const pathname = usePathname();
1918

20-
// const { isLoading, mutateAsync } = useMutation({
21-
// mutationFn: removeCoupon,
22-
// });
19+
const { isLoading, mutateAsync } = useMutation({
20+
mutationFn: deleteCoupon,
21+
onSuccess: (data) => {
22+
toast.success(data?.message);
23+
queryClient.invalidateQueries({ queryKey: ["get-coupons"] });
24+
},
25+
onError: (error) => {
26+
toast.error(error?.response?.data?.message);
27+
},
28+
});
2329

2430
const removeCouponHandler = async () => {
2531
try {
26-
// const { message } = await mutateAsync(id);
27-
28-
// toast.success(message);
29-
router.refresh(pathname);
30-
} catch (error) {
31-
toast.error(error?.response?.data?.message);
32-
}
32+
const { message } = await mutateAsync(id);
33+
} catch (error) {}
3334
};
3435

3536
return (
@@ -51,10 +52,12 @@ export default function RemoveCoupon({ id }) {
5152
<ModalContent className="text-slate-900 bg-sky-100/70 p-3">
5253
{(onClose) => (
5354
<>
54-
<ModalHeader className="text-xl font-extrabold">پاک کردن کد تخفیف</ModalHeader>
55+
<ModalHeader className="text-xl font-extrabold">
56+
پاک کردن کد تخفیف
57+
</ModalHeader>
5558

5659
<ModalBody>
57-
{/* <Button
60+
<Button
5861
type="submit"
5962
color="danger"
6063
className="btn__fifth w-full mb-3"
@@ -63,11 +66,16 @@ export default function RemoveCoupon({ id }) {
6366
isLoading={isLoading}
6467
>
6568
پاک کردن
66-
</Button> */}
69+
</Button>
6770
</ModalBody>
6871

6972
<ModalFooter>
70-
<Button color="danger" variant="light" onPress={onClose} className="font-bold">
73+
<Button
74+
color="danger"
75+
variant="light"
76+
onPress={onClose}
77+
className="font-bold"
78+
>
7179
بستن
7280
</Button>
7381
</ModalFooter>

src/app/(admin)/admin/coupons/UpdateCoupon.js

+160-39
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import { usePathname, useRouter } from "next/navigation";
2-
import { useMutation } from "@tanstack/react-query";
3-
import { toast } from "react-hot-toast";
1+
// This component needs to be refactored and optimized
2+
3+
import { useMutation, useQueryClient } from "@tanstack/react-query";
4+
import persian_fa from "react-date-object/locales/persian_fa";
5+
import persian from "react-date-object/calendars/persian";
6+
import DatePicker from "react-multi-date-picker";
47
import { TbEdit } from "react-icons/tb";
8+
import { toast } from "react-hot-toast";
59
import { useFormik } from "formik";
10+
import Select from "react-select";
11+
import { useState } from "react";
612
import * as Yup from "yup";
713
import {
814
Modal,
@@ -14,58 +20,76 @@ import {
1420
useDisclosure,
1521
} from "@nextui-org/react";
1622

17-
import Box from "@mui/material/Box";
18-
import InputLabel from "@mui/material/InputLabel";
19-
import MenuItem from "@mui/material/MenuItem";
20-
import FormControl from "@mui/material/FormControl";
21-
import Select from "@mui/material/Select";
22-
23+
import { updateCoupon } from "@/services/adminServices";
24+
import { useGetCourses } from "@/hooks/useProducts";
25+
import RadioInput from "@/common/RadioInput";
2326
import TextField from "@/common/TextField";
2427

2528
const initialValues = {
26-
type: "",
2729
code: "",
2830
amount: "",
2931
usageLimit: "",
30-
productIds: "",
31-
expireDate: "",
3232
};
3333

34-
const validationSchema = Yup.object({});
34+
const validationSchema = Yup.object({
35+
code: Yup.string().required("این فیلد نمی تواند خالی باشد"),
36+
amount: Yup.number("عدد وارد کنید").required("این فیلد نمی تواند خالی باشد"),
37+
usageLimit: Yup.number("عدد وارد کنید").required("این فیلد نمی تواند خالی باشد"),
38+
});
3539

36-
export default function UpdateCoupon({ id, category }) {
40+
export default function UpdateCoupon({ coupon }) {
41+
const [type, setType] = useState("");
42+
const queryClient = useQueryClient();
43+
const [productIds, setProductIds] = useState([]);
3744
const { isOpen, onOpen, onOpenChange } = useDisclosure();
38-
const router = useRouter();
39-
const pathname = usePathname();
45+
const [expireDate, setExpireDate] = useState(new Date());
46+
47+
const { _id, code, usageLimit, amount } = coupon || {};
4048

41-
// const { isLoading, mutateAsync } = useMutation({
42-
// mutationFn: updateCaoupon,
43-
// });
49+
const { data: coursesData, isLoading: coursesLoading } = useGetCourses();
50+
const { products } = coursesData || {};
4451

45-
// const sumbitHandler = async ({}) => {
46-
// const body = {} || {};
52+
const { isLoading, mutateAsync } = useMutation({
53+
mutationFn: updateCoupon,
54+
onSuccess: (data) => {
55+
queryClient.invalidateQueries({ queryKey: ["get-coupons"] });
56+
toast.success(data?.message);
57+
},
58+
onError: (error) => {
59+
toast.error(error?.response?.data?.message);
60+
},
61+
});
4762

48-
// try {
49-
// const { message } = await mutateAsync({ body, id });
63+
const sumbitHandler = async (values) => {
64+
const data = {
65+
...values,
66+
type,
67+
expireDate: new Date(expireDate).toISOString(),
68+
productIds: productIds?.map((product) => product?._id),
69+
};
5070

51-
// toast.success(message);
52-
// router.refresh(pathname);
53-
// } catch (error) {
54-
// toast.error(error?.response?.data?.message);
55-
// }
56-
// };
71+
try {
72+
const { message } = await mutateAsync({
73+
id: _id,
74+
data,
75+
});
76+
} catch (error) {}
77+
};
5778

58-
// const formik = useFormik({
59-
// initialValues: initialValues,
60-
// onSubmit: sumbitHandler,
61-
// validationSchema: validationSchema,
62-
// validateOnMount: true,
63-
// });
79+
const formik = useFormik({
80+
initialValues: initialValues,
81+
onSubmit: sumbitHandler,
82+
validationSchema: validationSchema,
83+
validateOnMount: true,
84+
});
6485

6586
return (
6687
<div>
6788
<button onClick={onOpen}>
68-
<TbEdit size={25} className="hover:text-slate-400 transition-all duration-250" />
89+
<TbEdit
90+
size={25}
91+
className="hover:text-slate-400 transition-all duration-250"
92+
/>
6993
</button>
7094

7195
<Modal
@@ -79,12 +103,109 @@ export default function UpdateCoupon({ id, category }) {
79103
<ModalContent className="text-slate-900 bg-sky-100/70 p-3">
80104
{(onClose) => (
81105
<>
82-
<ModalHeader className="text-xl font-extrabold">آپدیت کردن کد تخفیف</ModalHeader>
106+
<ModalHeader className="text-xl font-extrabold">
107+
آپدیت کردن کد تخفیف
108+
</ModalHeader>
109+
110+
<ModalBody>
111+
<form
112+
onSubmit={formik.handleSubmit}
113+
className="space-y-5 md:p-10 p-5 rounded-xl"
114+
>
115+
<TextField
116+
label="کد"
117+
name="code"
118+
formik={formik}
119+
placeholder={code}
120+
/>
121+
122+
<TextField
123+
label="مقدار"
124+
name="amount"
125+
type="number"
126+
formik={formik}
127+
placeholder={amount}
128+
/>
129+
130+
<TextField
131+
label="ظرفیت"
132+
name="usageLimit"
133+
type="number"
134+
formik={formik}
135+
placeholder={usageLimit}
136+
/>
137+
138+
<div className="flex flex-col gap-2">
139+
<span className="">نوع کد تخفیف</span>
140+
<div className="flex items-center gap-4 border border-slate-300 rounded-xl p-3 w-[250px]">
141+
<RadioInput
142+
id="percent-type"
143+
key=""
144+
label="درصد"
145+
name="type"
146+
value="percent"
147+
checked={type === "percent"}
148+
onChange={(e) => setType(e.target.value)}
149+
/>
150+
151+
<RadioInput
152+
id="fixedProduct-type"
153+
key=""
154+
label="قیمت ثابت"
155+
name="type"
156+
value="fixedProduct"
157+
checked={type === "fixedProduct"}
158+
onChange={(e) => setType(e.target.value)}
159+
/>
160+
</div>
161+
</div>
162+
163+
<div className="flex flex-col gap-2">
164+
<span className="">انتخاب دوره</span>
165+
<Select
166+
instanceId="products"
167+
isMulti
168+
onChange={setProductIds}
169+
options={products}
170+
getOptionLabel={(option) => option.title}
171+
getOptionValue={(option) => option._id}
172+
/>
173+
</div>
174+
175+
<div className="flex flex-col gap-2">
176+
<span>تاریخ انقضا</span>
177+
<DatePicker
178+
inputClass="textField__input"
179+
value={expireDate}
180+
onChange={(date) => setExpireDate(date)}
181+
format="YYYY/MM/DD"
182+
calendar={persian}
183+
locale={persian_fa}
184+
/>
185+
</div>
83186

84-
<ModalBody></ModalBody>
187+
<Button
188+
type="submit"
189+
color="primary"
190+
className="w-full"
191+
isLoading={coursesLoading}
192+
isDisabled={
193+
!formik.isValid || !type || !productIds.length || !expireDate
194+
}
195+
onPress={onClose}
196+
>
197+
ثبت
198+
</Button>
199+
</form>
200+
</ModalBody>
85201

86202
<ModalFooter>
87-
<Button color="danger" variant="light" onPress={onClose} className="font-bold">
203+
<Button
204+
color="danger"
205+
variant="light"
206+
onPress={onClose}
207+
className="font-bold"
208+
>
88209
بستن
89210
</Button>
90211
</ModalFooter>

0 commit comments

Comments
 (0)