Loading...
;
17 | if (!isLoading && isError) content = ) => {
24 | return acc + curr.rating.toString();
25 | },
26 | 0
27 | )
28 |
29 | const avgRating =
30 | taskReviewsLength > 0
31 | ? Math.ceil((taskReviewsSum / taskReviewsLength))
32 | : 0;
33 |
34 | console.log(avgRating);
35 |
36 |
37 | return (
38 |
46 |
53 |
54 |
{task.title}
55 |
56 | {Array(avgRating)
57 | .fill(0)
58 | .map((_, index) => (
59 |
65 | )).slice(0,4)}
66 |
67 |
${task.price}
68 |
69 |
{task.description}
70 |
71 | Get Service
72 |
73 |
74 | );
75 | });
76 | }
77 |
78 | return (
79 |
80 |
81 |
82 |
90 |
91 | Tasks Near You
92 |
93 |
94 | We make sure your expert suits your academic needs. All our
95 | writers pass several application tests and undergo thorough
96 | training before they start working.
97 |
98 |
99 |
100 |
101 | {content}
102 |
103 |
104 |
105 | );
106 | };
107 |
108 | export default Tasks;
109 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-tasks/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import { useDeleteUserMutation } from "@/redux/features/auth/authApi";
5 | import {
6 | useTaskDeleteMutation,
7 | useTasksQuery,
8 | } from "@/redux/features/tasks/tasksApi";
9 | import { format } from "date-fns";
10 | import { useSession } from "next-auth/react";
11 | import Image from "next/image";
12 | import Link from "next/link";
13 | import toast from "react-hot-toast";
14 | import { Metadata } from "next/types";
15 |
16 |
17 | const ManageTasksPage = () => {
18 | const { data: session } = useSession();
19 | const role = (session as any)?.role;
20 | const items = [
21 | {
22 | name: "Dashboard",
23 | slug: `/dashboard`,
24 | },
25 | ];
26 |
27 | const [taskDelete] = useTaskDeleteMutation();
28 | const handleDelete = async (id: string) => {
29 | try {
30 | await taskDelete(id).unwrap();
31 | toast.success("Task deleted successfully");
32 | } catch (error) {
33 | toast.error("Something went wrong");
34 | }
35 | };
36 |
37 | const query = "";
38 | const { data, isLoading, isError } = useTasksQuery(query);
39 | // decide what to render
40 | let content = null;
41 | if (isLoading) {
42 | content = (
43 |
44 | Loading...
45 |
46 | );
47 | }
48 | if (!isLoading && isError) {
49 | content = (
50 |
51 | Something went wrong happend
52 |
53 | );
54 | }
55 | if (!isLoading && !isError && data && data?.data.length > 0) {
56 | content = data?.data?.map((task, index) => (
57 |
58 |
59 | {index + 1}
60 |
61 |
62 |
63 |
64 |
65 | {task?.imageUrl && (
66 |
72 | )}
73 |
74 |
75 |
76 |
77 | {task?.title}
78 | {task?.description}
79 | {format(new Date(task?.createdAt), "dd/MM/yyyy")}
80 | {task?.price}
81 | {task?.address}
82 |
83 |
87 | Edit
88 |
89 | handleDelete(task?.id)}
91 | className="btn btn-secondary btn-xs mb-2"
92 | >
93 | Delete
94 |
95 |
96 |
97 | ));
98 | }
99 |
100 | return (
101 |
102 |
103 | Tasks Information
104 |
108 | Create Task
109 |
110 |
111 |
112 |
113 |
114 | Serial
115 | Image
116 | Title
117 | Description
118 | Created At
119 | Price
120 | Address
121 | Action
122 |
123 |
124 | {content}
125 |
126 |
127 |
128 | );
129 | };
130 |
131 | export default ManageTasksPage;
132 |
--------------------------------------------------------------------------------
/src/components/ui/Navbar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useProfileQuery } from "@/redux/features/profile/profileApi";
4 |
5 | import logo from "@/assets/svg/logo-white-text.svg";
6 | import { logout } from "@/lib/authOptions";
7 | import Image from "next/image";
8 | import Link from "next/link";
9 | import Container from "./Container";
10 | import "./Navbar.css";
11 | import Button from "./Button";
12 |
13 | const Navbar = () => {
14 | const { data, isLoading } = useProfileQuery(undefined);
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
29 |
35 |
36 |
37 |
41 |
42 | Dashboard
43 |
44 |
45 | Contact Us
46 |
47 | {!isLoading && data?.name && (
48 |
49 | Logout
50 |
51 | )}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Dashboard
62 |
63 |
64 | Contact Us
65 |
66 |
67 | {!isLoading && data?.name ? (
68 | <>
69 | {!data.avatarUrl && data.name && (
70 |
74 | Logout
75 |
76 | )}
77 | {data.avatarUrl && (
78 |
79 |
80 |
90 |
91 |
92 |
93 | Logout
94 |
95 |
96 |
97 | )}
98 | >
99 | ) : (
100 |
101 | Login
102 |
103 | )}
104 |
105 |
106 |
107 | );
108 | };
109 |
110 | export default Navbar;
111 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-tasks/add/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormImageUpload from "@/components/ui/FormImageUpload";
7 | import FormInput from "@/components/ui/FormInput";
8 | import FormSelect, { SelectOptions } from "@/components/ui/FormSelect";
9 | import { useCategoriesQuery } from "@/redux/features/categories/categoriesApi";
10 | import { useProfileQuery } from "@/redux/features/profile/profileApi";
11 | import { useCreateTaskMutation } from "@/redux/features/tasks/tasksApi";
12 | import { useSession } from "next-auth/react";
13 | import toast from "react-hot-toast";
14 |
15 | import { Metadata } from "next/types";
16 |
17 |
18 | const CreateAdminPage = () => {
19 | const { data: session } = useSession();
20 | const role = (session as any)?.role;
21 | const items = [
22 | {
23 | name: "Dashboard",
24 | slug: `/dashboard`,
25 | },
26 | {
27 | name: "Manage Tasks",
28 | slug: `/dashboard/manage-tasks`,
29 | },
30 | ];
31 |
32 | const [createTask] = useCreateTaskMutation();
33 | const { data: profile } = useProfileQuery(undefined);
34 | const {
35 | data: categories,
36 | isLoading,
37 | isError,
38 | } = useCategoriesQuery(undefined);
39 |
40 | let categoryOptions: SelectOptions[] = [];
41 | if (isLoading) {
42 | categoryOptions = [{ label: "Loading...", value: "loading" }];
43 | }
44 | if (!isLoading && isError) {
45 | categoryOptions = [{ label: "Error", value: "error" }];
46 | }
47 | categoryOptions = categories?.data?.map((category) => ({
48 | label: category.name,
49 | value: category.id,
50 | })) as SelectOptions[];
51 |
52 | const handleSubmit = async (values: any) => {
53 | try {
54 | values.sellerId = profile.id;
55 | const obj = { ...values };
56 | const file = obj["imageUrl"];
57 |
58 | delete obj["imageUrl"];
59 | const data = JSON.stringify(obj);
60 | const formData = new FormData();
61 | formData.append("file", file as Blob);
62 | formData.append("data", data);
63 |
64 | await createTask(formData);
65 | toast.success("Task created Successfully");
66 | } catch (error) {
67 | toast.error("Failed to Register");
68 | }
69 | };
70 |
71 | return (
72 |
73 |
74 | Create New Task
75 |
116 |
117 | );
118 | };
119 |
120 | export default CreateAdminPage;
121 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-admins/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import { useAdminsQuery } from "@/redux/features/admin/adminApi";
5 | import { useDeleteUserMutation } from "@/redux/features/auth/authApi";
6 | import { format } from "date-fns";
7 | import { useSession } from "next-auth/react";
8 | import Image from "next/image";
9 | import Link from "next/link";
10 | import toast from "react-hot-toast";
11 | import { Metadata } from "next/types";
12 |
13 |
14 | const ManageAdminsPage = () => {
15 | const { data: session } = useSession();
16 | const items = [
17 | {
18 | name: "Dashboard",
19 | slug: `/dashboard`,
20 | },
21 | ];
22 |
23 | const [deleteUser] = useDeleteUserMutation();
24 | const handleDelete = async (id: string) => {
25 | try {
26 | await deleteUser(id).unwrap();
27 | toast.success("Buyer deleted successfully");
28 | } catch (error) {
29 | toast.error("Something went wrong");
30 | }
31 | };
32 |
33 | const { data, isLoading, isError } = useAdminsQuery(undefined);
34 | // decide what to render
35 |
36 | let content = null;
37 | if (isLoading) {
38 | content = (
39 |
40 | Loading...
41 |
42 | );
43 | }
44 | if (!isLoading && isError) {
45 | content = (
46 |
47 | Something went wrong happend
48 |
49 | );
50 | }
51 | if (!isLoading && !isError && data && data?.data.length > 0) {
52 | content = data?.data?.map((admin, index) => (
53 |
54 |
55 | {index + 1}
56 |
57 |
58 |
59 |
60 |
61 | {admin?.avatarUrl && (
62 |
68 | )}
69 |
70 |
71 |
72 |
{admin?.name}
73 |
{admin?.presentAddress}
74 |
75 |
76 |
77 |
78 | {admin?.email}
79 |
80 | {admin?.occupation && (
81 |
82 | {admin?.occupation}
83 |
84 | )}
85 |
86 | {format(new Date(admin?.dateOfBirth), "dd/MM/yyyy")}
87 | {admin?.contactNo}
88 | {admin?.bloodGroup}
89 | {admin?.gender}
90 |
91 |
95 | Edit
96 |
97 | handleDelete(admin?.userId)}
99 | className="btn btn-secondary btn-xs"
100 | >
101 | Delete
102 |
103 |
104 |
105 | ));
106 | }
107 |
108 | return (
109 |
110 |
111 |
115 | Add New Admin
116 |
117 | Admins Information
118 |
119 |
120 |
121 |
122 | Serial
123 | Name & Location
124 | Email & Occupation
125 | Date Of Birth
126 | Contact No
127 | Blood Group
128 | Gender
129 | Action
130 |
131 |
132 | {content}
133 |
134 |
135 |
136 | );
137 | };
138 |
139 | export default ManageAdminsPage;
140 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-sellers/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | // Page tsx
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import { useDeleteUserMutation } from "@/redux/features/auth/authApi";
5 | import { useSellersQuery } from "@/redux/features/seller/sellerApi";
6 | import { format } from "date-fns";
7 | import { useSession } from "next-auth/react";
8 | import Image from "next/image";
9 | import Link from "next/link";
10 | import toast from "react-hot-toast";
11 |
12 | import { Metadata } from "next/types";
13 |
14 |
15 | const ManageSellersPage = () => {
16 | const { data: session } = useSession();
17 | const role = (session as any)?.role;
18 | const items = [
19 | {
20 | name: "Dashboard",
21 | slug: `/dashboard`,
22 | },
23 | ];
24 |
25 | const [deleteUser] = useDeleteUserMutation();
26 | const handleDelete = async (id: string) => {
27 | try {
28 | await deleteUser(id).unwrap();
29 | toast.success("Seller deleted successfully");
30 | } catch (error) {
31 | toast.error("Something went wrong");
32 | }
33 | };
34 |
35 | const { data, isLoading, isError } = useSellersQuery(undefined);
36 | // decide what to render
37 | let content = null;
38 | if (isLoading) {
39 | content = (
40 |
41 | Loading...
42 |
43 | );
44 | }
45 | if (!isLoading && isError) {
46 | content = (
47 |
48 | Something went wrong happend
49 |
50 | );
51 | }
52 | if (!isLoading && !isError && data && data?.data.length > 0) {
53 | content = data?.data?.map((seller, index) => (
54 |
55 |
56 | {index + 1}
57 |
58 |
59 |
60 |
61 |
62 | {seller?.avatarUrl && (
63 |
69 | )}
70 |
71 |
72 |
73 |
{seller?.name}
74 |
{seller?.presentAddress}
75 |
76 |
77 |
78 |
79 | {seller?.email}
80 |
81 | {seller?.occupation && (
82 |
83 | {seller?.occupation}
84 |
85 | )}
86 |
87 | {format(new Date(seller?.dateOfBirth), "dd/MM/yyyy")}
88 | {seller?.contactNo}
89 | {seller?.bloodGroup}
90 | {seller?.gender}
91 |
92 |
96 | Edit
97 |
98 | handleDelete(seller?.userId)}
100 | className="btn btn-secondary btn-xs"
101 | >
102 | Delete
103 |
104 |
105 |
106 | ));
107 | }
108 |
109 | return (
110 |
111 |
112 | Sellers Information
113 |
134 |
135 | );
136 | };
137 |
138 | export default ManageSellersPage;
139 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-buyers/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import { useDeleteUserMutation } from "@/redux/features/auth/authApi";
5 | import { useBuyersQuery } from "@/redux/features/buyer/buyerApi";
6 | import { format } from "date-fns";
7 | import { useSession } from "next-auth/react";
8 | import Image from "next/image";
9 | import Link from "next/link";
10 | import toast from "react-hot-toast";
11 |
12 | import { Metadata } from "next/types";
13 |
14 |
15 |
16 | const ManageBuyersPage = () => {
17 | const { data: session } = useSession();
18 | const role = (session as any)?.role;
19 | const items = [
20 | {
21 | name: "Dashboard",
22 | slug: `/dashboard`,
23 | },
24 | ];
25 |
26 | const [deleteUser] = useDeleteUserMutation();
27 | const handleDelete = async (id: string) => {
28 | try {
29 | await deleteUser(id).unwrap();
30 | toast.success("Buyer deleted successfully");
31 | } catch (error) {
32 | toast.error("Something went wrong");
33 | }
34 | };
35 |
36 | const { data, isLoading, isError } = useBuyersQuery(undefined);
37 | // decide what to render
38 | let content = null;
39 | if (isLoading) {
40 | content = (
41 |
42 | Loading...
43 |
44 | );
45 | }
46 | if (!isLoading && isError) {
47 | content = (
48 |
49 | Something went wrong happend
50 |
51 | );
52 | }
53 | if (!isLoading && !isError && data && data?.data.length === 0) {
54 | content = (
55 |
56 | No data found
57 |
58 | );
59 | }
60 | if (!isLoading && !isError && data && data?.data.length > 0) {
61 | content = data?.data?.map((buyer, index) => (
62 |
63 |
64 | {index + 1}
65 |
66 |
67 |
68 |
69 | {buyer?.avatarUrl && (
70 |
71 |
77 |
78 | )}
79 |
80 |
81 |
{buyer?.name}
82 |
{buyer?.presentAddress}
83 |
84 |
85 |
86 |
87 | {buyer?.email}
88 |
89 | {buyer?.occupation && (
90 |
91 | {buyer?.occupation}
92 |
93 | )}
94 |
95 | {format(new Date(buyer?.dateOfBirth), "dd/MM/yyyy")}
96 | {buyer?.contactNo}
97 | {buyer?.bloodGroup}
98 | {buyer?.gender}
99 |
100 |
104 | Edit
105 |
106 | handleDelete(buyer?.userId)}
108 | className="btn btn-secondary btn-xs"
109 | >
110 | Delete
111 |
112 |
113 |
114 | ));
115 | }
116 |
117 | return (
118 |
119 |
120 | Buyers Information
121 |
122 |
123 |
124 |
125 | Serial
126 | Name & Location
127 | Email & Occupation
128 | Date Of Birth
129 | Contact No
130 | Blood Group
131 | Gender
132 | Action
133 |
134 |
135 | {content}
136 |
137 |
138 |
139 | );
140 | };
141 |
142 | export default ManageBuyersPage;
143 |
--------------------------------------------------------------------------------
/src/components/home/Guarantees.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Container from "../ui/Container";
3 | import Image from "next/image";
4 | import moneIcon from "@/assets/svg/ico_money.svg";
5 | import "./Guarantees.css";
6 | const Guarantees = () => {
7 | return (
8 |
9 |
10 |
16 | GUARANTEES WE OFFER
17 |
18 |
19 |
20 |
26 |
27 |
28 |
Money-back guarantee
29 |
30 |
31 | In case you don’t receive the paper you’ve asked for, or you
32 | wish to cancel the order for any reason, you can get a full or
33 | partial refund.
34 |
35 |
36 |
42 |
43 |
44 |
Free revisions
45 |
46 |
47 | Do My Works expert will edit your paper for free if you notice
48 | any flaws within it. Apply for a revision if you want to change
49 | anything in your paper.
50 |
51 |
52 |
58 |
59 |
60 |
61 | Authenticity guarantee
62 |
63 |
64 |
65 | Every paper we deliver is customized. To guarantee its
66 | originality, we double-check every work with our in-house
67 | plagiarism-detection software.
68 |
69 |
70 |
76 |
77 |
78 |
79 | Confidentiality guarantee
80 |
81 |
82 |
83 | We never publicly disclose email addresses or phone numbers that
84 | our customers provide. We want every student to feel safe and
85 | protected while using our service.
86 |
87 |
88 |
89 |
96 |
97 |
98 |
97.98%
99 |
of orders are delivered on time
100 |
101 |
102 |
8.5/10
103 |
customer satisfaction rate
104 |
105 |
106 |
107 |
108 |
109 |
110 | );
111 | };
112 |
113 | export default Guarantees;
114 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-orders/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | // Manage page
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import {
5 | useOrdersQuery,
6 | useRemoveOrderMutation,
7 | useUpdateOrderMutation,
8 | } from "@/redux/features/order/orderApi";
9 | import { format } from "date-fns";
10 | import { useSession } from "next-auth/react";
11 | import Image from "next/image";
12 | import toast from "react-hot-toast";
13 | import { Metadata } from "next/types";
14 |
15 |
16 | const ManageOrdersPage = () => {
17 | const { data: session } = useSession();
18 | const role = (session as any)?.role;
19 | const items = [
20 | {
21 | name: "Dashboard",
22 | slug: `/dashboard`,
23 | },
24 | ];
25 |
26 | const { data, isLoading, isError } = useOrdersQuery(undefined);
27 | const [updateOrder] = useUpdateOrderMutation();
28 | const [removeOrder] = useRemoveOrderMutation();
29 | // decide what to render
30 | const handleUpdateOrder = async (status: any, id: string) => {
31 | const data = {
32 | status,
33 | id,
34 | };
35 | try {
36 | await updateOrder(data).unwrap();
37 | toast.success("Order updated successfully");
38 | } catch (error) {
39 | toast.error("Something went wrong");
40 | }
41 | };
42 |
43 | const handleRemoveOrder = async (id: string) => {
44 | try {
45 | await removeOrder(id).unwrap();
46 | toast.success("Order removed successfully");
47 | } catch (error) {
48 | toast.error("Something went wrong");
49 | }
50 | };
51 |
52 | let content = null;
53 | if (isLoading) {
54 | content = (
55 |
56 | Loading...
57 |
58 | );
59 | }
60 | if (!isLoading && isError) {
61 | content = (
62 |
63 | Something went wrong happend
64 |
65 | );
66 | }
67 | if (!isLoading && !isError && data && data?.length > 0) {
68 | content = data?.map((order, index) => (
69 |
70 |
71 | {index + 1}
72 |
73 |
74 |
75 | {order?.buyer?.avatarUrl && (
76 |
77 |
78 | {order?.buyer?.avatarUrl && (
79 |
85 | )}
86 |
87 |
88 | )}
89 |
90 |
{order?.buyer?.name}
91 |
92 | {order?.buyer?.presentAddress}
93 |
94 |
95 |
96 |
97 | {order?.id}
98 | {format(new Date(order?.createdAt), "dd/MM/yyyy")}
99 | {order?.status}
100 |
101 | handleUpdateOrder("completed", order.id)}
104 | >
105 | Order Completed
106 |
107 | handleUpdateOrder("cancel", order.id)}
109 | className="btn btn-secondary btn-xs"
110 | >
111 | Cancel Order
112 |
113 | handleRemoveOrder(order.id)}
115 | className="btn btn-secondary btn-xs"
116 | >
117 | Remove Order
118 |
119 |
120 |
121 | ));
122 | }
123 |
124 | return (
125 |
126 |
127 |
128 | Manage Orders ({data?.length})
129 |
130 |
131 |
132 |
133 |
134 | Serial
135 | Name, Addres & Image
136 | Order Id
137 | Order Date
138 | Order Status
139 | Action
140 |
141 |
142 | {content}
143 |
144 |
145 |
146 | );
147 | };
148 |
149 | export default ManageOrdersPage;
150 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormDatePicker from "@/components/ui/FormDatePicker";
7 | import FormImageUpload from "@/components/ui/FormImageUpload";
8 | import FormInput from "@/components/ui/FormInput";
9 | import FormSelect from "@/components/ui/FormSelect";
10 | import { bloodGroupOptions, genderOptions } from "@/constants/globals";
11 | import {
12 | useProfileQuery,
13 | useProfileUpdateMutation,
14 | } from "@/redux/features/profile/profileApi";
15 | import { useSession } from "next-auth/react";
16 | import toast from "react-hot-toast";
17 | import { Metadata } from "next/types";
18 |
19 |
20 | const AccountProfile = () => {
21 | const items = [
22 | {
23 | name: "Dashboard",
24 | slug: `/dashboard`,
25 | },
26 | ];
27 |
28 | const { data, isLoading } = useProfileQuery(undefined);
29 | const [updateProfile] = useProfileUpdateMutation();
30 | const onSubmit = async (values: any) => {
31 | try {
32 | const obj = { ...values };
33 | const file = obj["avatarUrl"];
34 |
35 | delete obj["avatarUrl"];
36 | const data = JSON.stringify(obj);
37 | const formData = new FormData();
38 | formData.append("file", file as Blob);
39 | formData.append("data", data);
40 |
41 | await updateProfile(formData).unwrap();
42 | toast.success("Profile Updated Successfully!");
43 | } catch (error) {
44 | toast.error("Something went wrong!");
45 | }
46 | };
47 |
48 | const defaultValues = {
49 | name: data?.name || "",
50 | email: data?.email || "",
51 | dateOfBirth: data?.dateOfBirth || "",
52 | contactNo: data?.contactNo || "",
53 | presentAddress: data?.presentAddress || "",
54 | permanentAddress: data?.permanentAddress || "",
55 | occupation: data?.occupation || "",
56 | bloodGroup: data?.bloodGroup || "",
57 | gender: data?.gender || "MALE",
58 | avatarUrl: data?.avatarUrl || "",
59 | };
60 |
61 | return (
62 |
63 |
64 | Your Profile Information
65 | {!isLoading && data?.id && (
66 |
128 | )}
129 |
130 | );
131 | };
132 |
133 | export default AccountProfile;
134 |
--------------------------------------------------------------------------------
/src/components/ui/FormImageUpload.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "@/utils/cn";
2 | import Image from "next/image";
3 | import React, { useState } from "react";
4 | import { Controller, useFormContext } from "react-hook-form";
5 | import ImageUploading from "react-images-uploading";
6 | import { ImageListType } from "react-images-uploading";
7 |
8 | interface FormImageUploadProps {
9 | name: string;
10 | label?: string;
11 | required?: boolean;
12 | className?: string;
13 | }
14 |
15 | const FormImageUpload = ({
16 | name,
17 | label,
18 | required,
19 | className,
20 | }: FormImageUploadProps) => {
21 | const {
22 | control,
23 | formState: { errors },
24 | setValue,
25 | } = useFormContext();
26 |
27 | const [images, setImages] = useState([]);
28 | const maxNumber = 69;
29 |
30 | const onChange = (
31 | imageList: ImageListType,
32 | addUpdateIndex: number[] | undefined
33 | ) => {
34 | setValue(name, imageList[0]?.file);
35 | setImages(imageList as never[]);
36 | };
37 |
38 | return (
39 | <>
40 |
47 | {({
48 | imageList,
49 | onImageUpload,
50 | onImageRemoveAll,
51 | onImageUpdate,
52 | onImageRemove,
53 | isDragging,
54 | dragProps,
55 | }) => (
56 | // write your building UI
57 |
58 | {imageList?.length === 0 ? (
59 | <>
60 |
66 | Click or Drop here
67 |
68 | >
69 | ) : null}
70 |
71 | {/*
x */}
72 |
(
76 |
77 |
78 | {field.value && imageList.length === 0 && (
79 |
86 | )}
87 | {imageList.map((image, index) => (
88 | <>
89 | onImageRemove(index)}
91 | className="absolute top-0 right-0"
92 | >
93 | X
94 |
95 |
103 | >
104 | ))}
105 |
106 |
107 | )}
108 | />
109 | {/* {imageList.map((image, index) => (
110 |
111 |
112 |
onImageRemove(index)}
114 | className="absolute top-0 right-0"
115 | >
116 | X
117 |
118 |
119 |
126 |
127 |
128 |
129 | onImageUpdate(index)}>Update
130 |
131 |
132 | ))} */}
133 |
134 | )}
135 |
136 | >
137 | );
138 | };
139 |
140 | export default FormImageUpload;
141 |
--------------------------------------------------------------------------------
/src/app/login/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { signIn, useSession } from "next-auth/react";
4 | import Link from "next/link";
5 | import { useRouter } from "next/navigation";
6 | import React from "react";
7 | import { toast } from "react-hot-toast";
8 | import { Metadata } from "next/types";
9 |
10 |
11 | const LoginPage = () => {
12 | const [email, setEmail] = React.useState("");
13 | const [password, setPassword] = React.useState("");
14 | const router = useRouter();
15 | const { data: session } = useSession();
16 |
17 | const handleSubmit = async (e: React.FormEvent) => {
18 | e.preventDefault();
19 | const login = await signIn("my-app-credentials", {
20 | email,
21 | password,
22 | redirect: false,
23 | });
24 |
25 | if (login?.ok) {
26 | toast.success("Login successful");
27 |
28 | router.push("/");
29 | } else {
30 | toast.error(login?.error as string);
31 | }
32 | };
33 |
34 | return (
35 |
36 |
37 |
38 |
Login
39 |
40 | If you are already a member, easily log in
41 |
42 |
43 |
64 |
65 |
70 |
71 | {/*
75 |
81 |
85 |
89 |
93 |
97 |
98 | Login with Google
99 | */}
100 |
101 |
104 |
105 |
106 |
Don't have an account?
107 |
111 | Register
112 |
113 |
114 |
115 |
116 |
117 | );
118 | };
119 |
120 | export default LoginPage;
121 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-tasks/edit/[id]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormImageUpload from "@/components/ui/FormImageUpload";
7 | import FormInput from "@/components/ui/FormInput";
8 | import FormSelect, { SelectOptions } from "@/components/ui/FormSelect";
9 | import { useCategoriesQuery } from "@/redux/features/categories/categoriesApi";
10 | import {
11 | useTaskQuery,
12 | useTaskUpdateMutation,
13 | } from "@/redux/features/tasks/tasksApi";
14 | import { useSession } from "next-auth/react";
15 | import toast from "react-hot-toast";
16 |
17 | import { Metadata } from "next/types";
18 |
19 |
20 | type IEditSellerPageProps = {
21 | params: any;
22 | };
23 |
24 | const EditTaskPage = ({ params }: IEditSellerPageProps) => {
25 | const { data: session } = useSession();
26 | const role = (session as any)?.role;
27 | const items = [
28 | {
29 | name: "Dashboard",
30 | slug: `/dashboard`,
31 | },
32 | {
33 | name: "Manage Tasks",
34 | slug: `/dashboard/manage-tasks`,
35 | },
36 | ];
37 | const id: string = params.id;
38 |
39 | const { data, isLoading, isError } = useTaskQuery(id);
40 | const [updateTask] = useTaskUpdateMutation();
41 |
42 | // decide what to render
43 | let content = null;
44 |
45 | if (isLoading) {
46 | content = Loading...
;
47 | }
48 | if (!isLoading && isError) {
49 | content = Something went wrong happend
;
50 | }
51 | if (!isLoading && !isError && data) {
52 | content = {JSON.stringify(data)}
;
53 | }
54 |
55 | const {
56 | data: categories,
57 | isLoading: isCategoryLoading,
58 | isError: isCategoryError,
59 | } = useCategoriesQuery(undefined);
60 |
61 | let categoryOptions: SelectOptions[] = [];
62 | if (isCategoryLoading) {
63 | categoryOptions = [{ label: "Loading...", value: "loading" }];
64 | }
65 | if (!isCategoryLoading && isCategoryError) {
66 | categoryOptions = [{ label: "Error", value: "error" }];
67 | }
68 | categoryOptions = categories?.data?.map((category) => ({
69 | label: category.name,
70 | value: category.id,
71 | })) as SelectOptions[];
72 |
73 | const onSubmit = async (values: any) => {
74 | try {
75 | const obj = { ...values };
76 | const file = obj["imageUrl"];
77 |
78 | delete obj["imageUrl"];
79 | const data = JSON.stringify(obj);
80 | const formData = new FormData();
81 | formData.append("file", file as Blob);
82 | formData.append("data", data);
83 |
84 | await updateTask({ formData, id }).unwrap();
85 | toast.success("Task Updated Successfully!");
86 | } catch (error) {
87 | toast.error("Something went wrong!");
88 | }
89 | };
90 |
91 | const defaultValues = {
92 | title: data?.title,
93 | description: data?.description,
94 | categoryId: data?.categoryId,
95 | address: data?.address,
96 | price: data?.price,
97 | imageUrl: data?.imageUrl,
98 | };
99 |
100 | return (
101 |
102 |
103 | Update Task Information
104 | {!isLoading && !isError && data?.id && (
105 |
152 | )}
153 |
154 | );
155 | };
156 |
157 | export default EditTaskPage;
158 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-buyers/edit/[id]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | // Page
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormDatePicker from "@/components/ui/FormDatePicker";
7 | import FormImageUpload from "@/components/ui/FormImageUpload";
8 | import FormInput from "@/components/ui/FormInput";
9 | import FormSelect from "@/components/ui/FormSelect";
10 | import { bloodGroupOptions, genderOptions } from "@/constants/globals";
11 | import {
12 | useBuyerQuery,
13 | useBuyerUpdateMutation,
14 | } from "@/redux/features/buyer/buyerApi";
15 | import { useSession } from "next-auth/react";
16 | import React from "react";
17 | import toast from "react-hot-toast";
18 |
19 | type IEditBuyerPageProps = {
20 | params: any;
21 | };
22 |
23 | const EditBuyerPage = ({ params }: IEditBuyerPageProps) => {
24 | const { data: session } = useSession();
25 | const role = (session as any)?.role;
26 | const items = [
27 | {
28 | name: "Dashboard",
29 | slug: `/dashboard`,
30 | },
31 | {
32 | name: "Manage Buyers",
33 | slug: `/dashboard/manage-buyers`,
34 | },
35 | ];
36 | const id: string = params.id;
37 |
38 | const { data, isLoading, isError } = useBuyerQuery(id);
39 | const [updateBuyer] = useBuyerUpdateMutation();
40 |
41 | // decide what to render
42 | let content = null;
43 |
44 | if (isLoading) {
45 | content = Loading...
;
46 | }
47 | if (!isLoading && isError) {
48 | content = Something went wrong happend
;
49 | }
50 |
51 | const onSubmit = async (values: any) => {
52 | try {
53 | const obj = { ...values };
54 | const file = obj["avatarUrl"];
55 |
56 | delete obj["avatarUrl"];
57 | const data = JSON.stringify(obj);
58 | const formData = new FormData();
59 | formData.append("file", file as Blob);
60 | formData.append("data", data);
61 |
62 | await updateBuyer({ formData, id }).unwrap();
63 | toast.success("Buyer Updated Successfully!");
64 | } catch (error) {
65 | toast.error("Something went wrong!");
66 | }
67 | };
68 |
69 | const defaultValues = {
70 | name: data?.name,
71 | email: data?.email,
72 | dateOfBirth: data?.dateOfBirth,
73 | contactNo: data?.contactNo,
74 | presentAddress: data?.presentAddress,
75 | permanentAddress: data?.permanentAddress,
76 | occupation: data?.occupation,
77 | bloodGroup: data?.bloodGroup,
78 | gender: data?.gender,
79 | avatarUrl: data?.avatarUrl,
80 | };
81 |
82 | return (
83 |
84 |
85 | Update Buyer Information
86 | {!isLoading && !isError && data?.id && (
87 |
149 | )}
150 |
151 | );
152 | };
153 |
154 | export default EditBuyerPage;
155 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-admins/edit/[id]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormDatePicker from "@/components/ui/FormDatePicker";
7 | import FormImageUpload from "@/components/ui/FormImageUpload";
8 | import FormInput from "@/components/ui/FormInput";
9 | import FormSelect from "@/components/ui/FormSelect";
10 | import { bloodGroupOptions, genderOptions } from "@/constants/globals";
11 | import {
12 | useAdminQuery,
13 | useAdminUpdateMutation,
14 | } from "@/redux/features/admin/adminApi";
15 | import { useSession } from "next-auth/react";
16 | import React from "react";
17 | import toast from "react-hot-toast";
18 |
19 | import { Metadata } from "next/types";
20 |
21 |
22 | type IEditAdminPageProps = {
23 | params: any;
24 | };
25 |
26 | const EditAdminPage = ({ params }: IEditAdminPageProps) => {
27 | const { data: session } = useSession();
28 | const items = [
29 | {
30 | name: "Dashboard",
31 | slug: `/dashboard`,
32 | },
33 | {
34 | name: "Manage Admins",
35 | slug: `/dashboard/manage-admins`,
36 | },
37 | ];
38 | const id: string = params.id;
39 |
40 | const { data, isLoading, isError } = useAdminQuery(id);
41 | const [updateAdmin] = useAdminUpdateMutation();
42 |
43 | // decide what to render
44 | let content = null;
45 |
46 | if (isLoading) {
47 | content = Loading...
;
48 | }
49 | if (!isLoading && isError) {
50 | content = Something went wrong happend
;
51 | }
52 |
53 | const onSubmit = async (values: any) => {
54 | try {
55 | const obj = { ...values };
56 | const file = obj["avatarUrl"];
57 |
58 | delete obj["avatarUrl"];
59 | const data = JSON.stringify(obj);
60 | const formData = new FormData();
61 | formData.append("file", file as Blob);
62 | formData.append("data", data);
63 |
64 | await updateAdmin({ formData, id }).unwrap();
65 | toast.success("Admin Updated Successfully!");
66 | } catch (error) {
67 | toast.error("Something went wrong!");
68 | }
69 | };
70 |
71 | const defaultValues = {
72 | name: data?.name,
73 | email: data?.email,
74 | dateOfBirth: data?.dateOfBirth,
75 | contactNo: data?.contactNo,
76 | presentAddress: data?.presentAddress,
77 | permanentAddress: data?.permanentAddress,
78 | occupation: data?.occupation,
79 | bloodGroup: data?.bloodGroup,
80 | gender: data?.gender,
81 | avatarUrl: data?.avatarUrl,
82 | };
83 |
84 | return (
85 |
86 |
87 | Update Admin Information
88 | {!isLoading && !isError && data?.id && (
89 |
151 | )}
152 |
153 | );
154 | };
155 |
156 | export default EditAdminPage;
157 |
--------------------------------------------------------------------------------
/src/app/(dashboard)/dashboard/manage-sellers/edit/[id]/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | // Edit page
3 | import BreadCrumb from "@/components/ui/BreadCrumb";
4 | import Button from "@/components/ui/Button";
5 | import Form from "@/components/ui/Form";
6 | import FormDatePicker from "@/components/ui/FormDatePicker";
7 | import FormImageUpload from "@/components/ui/FormImageUpload";
8 | import FormInput from "@/components/ui/FormInput";
9 | import FormSelect from "@/components/ui/FormSelect";
10 | import { bloodGroupOptions, genderOptions } from "@/constants/globals";
11 | import {
12 | useSellerQuery,
13 | useSellerUpdateMutation,
14 | } from "@/redux/features/seller/sellerApi";
15 | import { useSession } from "next-auth/react";
16 | import React from "react";
17 | import toast from "react-hot-toast";
18 |
19 | type IEditSellerPageProps = {
20 | params: any;
21 | };
22 |
23 | const EditSellerPage = ({ params }: IEditSellerPageProps) => {
24 | const { data: session } = useSession();
25 | const role = (session as any)?.role;
26 | const items = [
27 | {
28 | name: "Dashboard",
29 | slug: `/dashboard`,
30 | },
31 | {
32 | name: "Manage Sellers",
33 | slug: `/dashboard/manage-sellers`,
34 | },
35 | ];
36 | const id: string = params.id;
37 |
38 | const { data, isLoading, isError } = useSellerQuery(id);
39 | const [updateSeller] = useSellerUpdateMutation();
40 |
41 | // decide what to render
42 | let content = null;
43 |
44 | if (isLoading) {
45 | content = Loading...
;
46 | }
47 | if (!isLoading && isError) {
48 | content = Something went wrong happend
;
49 | }
50 | if (!isLoading && !isError && data) {
51 | content = {JSON.stringify(data)}
;
52 | }
53 |
54 | const onSubmit = async (values: any) => {
55 | try {
56 | const obj = { ...values };
57 | const file = obj["avatarUrl"];
58 |
59 | delete obj["avatarUrl"];
60 | const data = JSON.stringify(obj);
61 | const formData = new FormData();
62 | formData.append("file", file as Blob);
63 | formData.append("data", data);
64 |
65 | await updateSeller({ formData, id }).unwrap();
66 | toast.success("Seller Updated Successfully!");
67 | } catch (error) {
68 | toast.error("Something went wrong!");
69 | }
70 | };
71 |
72 | const defaultValues = {
73 | name: data?.name,
74 | email: data?.email,
75 | dateOfBirth: data?.dateOfBirth,
76 | contactNo: data?.contactNo,
77 | presentAddress: data?.presentAddress,
78 | permanentAddress: data?.permanentAddress,
79 | occupation: data?.occupation,
80 | bloodGroup: data?.bloodGroup,
81 | gender: data?.gender,
82 | avatarUrl: data?.avatarUrl,
83 | };
84 |
85 | return (
86 |
87 |
88 | Update Seller Information
89 | {!isLoading && !isError && data?.id && (
90 |
152 | )}
153 |
154 | );
155 | };
156 |
157 | export default EditSellerPage;
158 |
--------------------------------------------------------------------------------