diff --git a/package.json b/package.json
index de17b7cb7..78985a100 100644
--- a/package.json
+++ b/package.json
@@ -68,6 +68,7 @@
"react-email": "2.1.5",
"react-hook-form": "^7.52.2",
"react-paginate": "^8.2.0",
+ "react-toastify": "^10.0.5",
"recharts": "^2.12.7",
"sharp": "^0.33.4",
"swiper": "^11.1.9",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d7b81ef63..a058996d6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -152,6 +152,9 @@ importers:
react-paginate:
specifier: ^8.2.0
version: 8.2.0(react@18.3.1)
+ react-toastify:
+ specifier: ^10.0.5
+ version: 10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
recharts:
specifier: ^2.12.7
version: 2.12.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -4484,6 +4487,12 @@ packages:
'@types/react':
optional: true
+ react-toastify@10.0.5:
+ resolution: {integrity: sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==}
+ peerDependencies:
+ react: '>=18'
+ react-dom: '>=18'
+
react-transition-group@4.4.5:
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
peerDependencies:
@@ -10020,6 +10029,12 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.3
+ react-toastify@10.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ clsx: 2.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.25.0
diff --git a/public/images/productimage.png b/public/images/productimage.png
new file mode 100644
index 000000000..55cef508e
Binary files /dev/null and b/public/images/productimage.png differ
diff --git a/public/images/user.png b/public/images/user.png
new file mode 100644
index 000000000..6f728aaa5
Binary files /dev/null and b/public/images/user.png differ
diff --git a/public/messages/en.json b/public/messages/en.json
index 2e703f3c0..eef7daedd 100644
--- a/public/messages/en.json
+++ b/public/messages/en.json
@@ -46,7 +46,7 @@
"otpExpiresIn": "OTP expires in: {timeLeft}",
"resendCode": "Didn't receive the code? resend",
"dataProcessing": "We would process your data as set forth in our Terms of Use, Privacy Policy and Data Processing Agreement",
- "alreadyHaveAccount": "Already Have An Account? Login"
+ "alreadyHaveAccount": "Already Have An Account?"
},
"HomePage": {
"title": "Hello world!"
@@ -153,6 +153,7 @@
},
"noJobs": {
"noJobsTitle": "No available Jobs at the moment",
+
"noJobsContent": "Sign up for our newsletter to get updates on job postings",
"modalTitle": "Newsletter",
"button": "Sign up for newsletter",
diff --git a/src/app/(landing-routes)/blog/page.tsx b/src/app/(landing-routes)/blog/page.tsx
index 3ec42db7f..646d72f53 100644
--- a/src/app/(landing-routes)/blog/page.tsx
+++ b/src/app/(landing-routes)/blog/page.tsx
@@ -1,14 +1,62 @@
"use client";
+import axios from "axios";
+import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
+import { useEffect, useState } from "react";
+import { getApiUrl } from "~/actions/getApiUrl";
import CustomButton from "~/components/common/common-button/common-button";
import HeroSection from "~/components/extDynamicPages/blogCollection/BlogPageHero";
import BlogCard from "~/components/layouts/BlogCards";
+import { useToast } from "~/components/ui/use-toast";
import { blogPosts } from "./data/mock";
const BlogHome = () => {
const router = useRouter();
+ const { toast } = useToast();
+ const { data: session } = useSession();
+ const [, setBlogPost] = useState("");
+
+ useEffect(() => {
+ async function fetchBlog() {
+ try {
+ const apiUrl = await getApiUrl();
+ const token = session?.access_token;
+ const response = await axios.get(`${apiUrl}/api/v1/blogs`, {
+ headers: {
+ Authorization: `Bearer: ${token}`,
+ },
+ });
+ const data = response.data;
+ setBlogPost(data);
+ toast({
+ title:
+ Array.isArray(data.data) && data.data.length === 0
+ ? "No Blog Post Available"
+ : "Blog Posts Retrieved",
+ description:
+ Array.isArray(data.data) && data.data.length === 0
+ ? "Blog posts are empty"
+ : "Blog posts retrieved successfully",
+ variant:
+ Array.isArray(data.data) && data.data.length === 0
+ ? "destructive"
+ : "default",
+ });
+ } catch (error) {
+ toast({
+ title: "Error occured",
+ description:
+ error instanceof Error
+ ? error.message
+ : "An unknown error occurred",
+ variant: "destructive",
+ });
+ }
+ }
+ fetchBlog();
+ }, [session?.access_token, toast]);
return (
diff --git a/src/app/dashboard/(admin)/admin/(settings)/settings/data-and-privacy/page.tsx b/src/app/dashboard/(admin)/admin/(settings)/settings/data-and-privacy/page.tsx
index dfd73041e..aa0e9bd79 100644
--- a/src/app/dashboard/(admin)/admin/(settings)/settings/data-and-privacy/page.tsx
+++ b/src/app/dashboard/(admin)/admin/(settings)/settings/data-and-privacy/page.tsx
@@ -2,6 +2,8 @@
import { useState } from "react";
+import CustomButton from "~/components/common/common-button/common-button";
+
interface ToggleSwitchProperties {
label: string;
description: string;
@@ -21,7 +23,7 @@ const ToggleSwitch: React.FC
= ({
return (
-
+
);
};
diff --git a/src/app/dashboard/(admin)/admin/(settings)/settings/notification/page.tsx b/src/app/dashboard/(admin)/admin/(settings)/settings/notification/page.tsx
index e1e1d263f..431eb04df 100644
--- a/src/app/dashboard/(admin)/admin/(settings)/settings/notification/page.tsx
+++ b/src/app/dashboard/(admin)/admin/(settings)/settings/notification/page.tsx
@@ -77,7 +77,7 @@ const NotificationPage = () => {
};
return (
-
+
Notification
@@ -178,7 +178,7 @@ const NotificationPage = () => {
/>
-
+
}
diff --git a/src/app/dashboard/(admin)/admin/(settings)/settings/organization/members/page.tsx b/src/app/dashboard/(admin)/admin/(settings)/settings/organization/members/page.tsx
index 9fa6ea504..85488d79b 100644
--- a/src/app/dashboard/(admin)/admin/(settings)/settings/organization/members/page.tsx
+++ b/src/app/dashboard/(admin)/admin/(settings)/settings/organization/members/page.tsx
@@ -8,7 +8,14 @@ import { useState } from "react";
import CustomButton from "~/components/common/common-button/common-button";
import { Input } from "~/components/common/input";
import InviteMemberModal from "~/components/common/modals/invite-member";
+import DeleteMember from "~/components/common/modals/invite-member/DeleteMembers";
import LoadingSpinner from "~/components/miscellaneous/loading-spinner";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "~/components/ui/dropdown-menu";
import {
Select,
SelectContent,
@@ -71,8 +78,15 @@ const activeMembers: number = memberData.length;
const Members = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
+ const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+
const [exporting, setExporting] = useState(false);
const [text, setText] = useState("Export CSV");
+ const [isVisible, setIsVisible] = useState(false);
+
+ const toggleVisibility = () => {
+ setIsVisible(!isVisible);
+ };
const { toast } = useToast();
const handleCopy = () => {
@@ -87,10 +101,18 @@ const Members = () => {
setIsModalOpen(true);
};
+ const handleDeleteOpen = () => {
+ setIsDeleteModalOpen(true);
+ };
+
const handleModalClose = () => {
setIsModalOpen(false);
};
+ const handleDeleteClose = () => {
+ setIsDeleteModalOpen(false);
+ };
+
const exportMembers = async () => {
setExporting(true);
setText("Exporting...");
@@ -160,25 +182,28 @@ const Members = () => {
{}}
+ onChange={toggleVisibility}
+ checked={isVisible}
/>
-
-
- https://www.figma.com/design/7hCSTNzQOJLl9aww6wEEd1/Managing-Users----Team-Learn-AI?node-i
-
-
- Copy link
-
-
+ {isVisible && (
+
+
+ https://www.figma.com/design/7hCSTNzQOJLl9aww6wEEd1/Managing-Users----Team-Learn-AI?node-i
+
+
+ Copy link
+
+
+ )}
Manage members
@@ -246,7 +271,19 @@ const Members = () => {
- {}} className="flex-shrink-0" />
+
+
+ {}}
+ className="flex-shrink-0"
+ />
+
+
+
+ Delete Member
+
+
+
);
})}
@@ -276,6 +313,7 @@ const Members = () => {
+
);
};
diff --git a/src/app/dashboard/(admin)/admin/(settings)/settings/payment-information/page.tsx b/src/app/dashboard/(admin)/admin/(settings)/settings/payment-information/page.tsx
index bf10a7cec..fa909b5d2 100644
--- a/src/app/dashboard/(admin)/admin/(settings)/settings/payment-information/page.tsx
+++ b/src/app/dashboard/(admin)/admin/(settings)/settings/payment-information/page.tsx
@@ -213,10 +213,6 @@ const PaymentInformation = () => {
-
-
);
};
diff --git a/src/app/dashboard/(admin)/admin/(settings)/settings/subscription/page.tsx b/src/app/dashboard/(admin)/admin/(settings)/settings/subscription/page.tsx
new file mode 100644
index 000000000..db4d38750
--- /dev/null
+++ b/src/app/dashboard/(admin)/admin/(settings)/settings/subscription/page.tsx
@@ -0,0 +1,5 @@
+const page = () => {
+ return page
;
+};
+
+export default page;
diff --git a/src/app/dashboard/(user-dashboard)/products/_components/new-product-modal.tsx b/src/app/dashboard/(user-dashboard)/products/_components/new-product-modal.tsx
index 69f7b2c77..04064b833 100644
--- a/src/app/dashboard/(user-dashboard)/products/_components/new-product-modal.tsx
+++ b/src/app/dashboard/(user-dashboard)/products/_components/new-product-modal.tsx
@@ -1,4 +1,5 @@
// components/admin/NewProductModal.tsx
+
import { zodResolver } from "@hookform/resolvers/zod";
import { AnimatePresence, motion } from "framer-motion";
import { Loader, X } from "lucide-react";
diff --git a/src/app/dashboard/(user-dashboard)/products/_components/product-detail-modal.tsx b/src/app/dashboard/(user-dashboard)/products/_components/product-detail-modal.tsx
index 271c00fce..a49fddded 100644
--- a/src/app/dashboard/(user-dashboard)/products/_components/product-detail-modal.tsx
+++ b/src/app/dashboard/(user-dashboard)/products/_components/product-detail-modal.tsx
@@ -1,3 +1,5 @@
+"use client";
+
import { AnimatePresence, motion } from "framer-motion";
import { Loader2, X } from "lucide-react";
import { useSession } from "next-auth/react";
diff --git a/src/app/dashboard/(user-dashboard)/products/_components/productcadrcomponent.tsx b/src/app/dashboard/(user-dashboard)/products/_components/productcadrcomponent.tsx
new file mode 100644
index 000000000..e77bc85ed
--- /dev/null
+++ b/src/app/dashboard/(user-dashboard)/products/_components/productcadrcomponent.tsx
@@ -0,0 +1,67 @@
+"use client";
+
+import Image, { StaticImageData } from "next/image";
+
+interface ProductCardProperties {
+ title: string;
+ price: string;
+ description: string;
+ inStock: boolean;
+ imageUrl: string | StaticImageData;
+}
+
+const Delete = () => {
+ alert("Are you sure you want to delete");
+};
+
+const Edit = () => {
+ alert("Proceed to edit");
+};
+
+const ProductCard: React.FC = ({
+ title,
+ price,
+ description,
+ inStock,
+ imageUrl,
+}) => {
+ return (
+
+
+
+
+
{description}
+
+ {inStock ? "In stock" : "Out of stock"}
+
+
+
+
+
+
+
+ );
+};
+
+export default ProductCard;
diff --git a/src/app/dashboard/(user-dashboard)/products/mainproductdetailpage/page.tsx b/src/app/dashboard/(user-dashboard)/products/mainproductdetailpage/page.tsx
new file mode 100644
index 000000000..55ba4ce42
--- /dev/null
+++ b/src/app/dashboard/(user-dashboard)/products/mainproductdetailpage/page.tsx
@@ -0,0 +1,382 @@
+"use client";
+
+import Image from "next/image";
+import Link from "next/link";
+import { ChangeEvent, FormEvent, useState } from "react";
+
+import user from "../../../../../../public/images/user.png";
+
+const Discard = () => {
+ alert("Changes discard");
+};
+
+const ProductDetail = () => {
+ const [textValue, setTextValue] = useState("Product 2");
+ const [messageValue, setmessageValue] = useState(
+ "A fusion of ripe bananas, pure honey, and succulent raspberries with our bread. Crafted to perfection.",
+ );
+ const [image, setImage] = useState();
+ const [smallQuantity, setSmallQuantity] = useState(0);
+ const [standardQuantity, setStandardQuantity] = useState(24);
+ const [largeQuantity, setLargeQuantity] = useState(0);
+ const [smallPrice, setSmallPrice] = useState("$12.00");
+ const [standardPrice, setStandardPrice] = useState("$29.00");
+ const [largePrice, setLargePrice] = useState("$32.00");
+
+ const handleSubmit = (event: FormEvent) => {
+ event.preventDefault();
+
+ if (
+ !textValue.trim() ||
+ !messageValue.trim() ||
+ !smallQuantity ||
+ !standardQuantity ||
+ !largeQuantity ||
+ !smallPrice ||
+ !standardPrice ||
+ !largePrice ||
+ !largePrice ||
+ !image
+ ) {
+ alert(
+ "Please fill in all the necessary fields including your image before submitting.",
+ );
+ return;
+ }
+ alert("Details updated");
+ };
+
+ const handleSmallQty = (event: ChangeEvent) => {
+ setSmallQuantity(Number(event.target.value));
+ };
+
+ const handleStandardQty = (event: ChangeEvent) => {
+ setStandardQuantity(Number(event.target.value));
+ };
+
+ const handleLargeQty = (event: ChangeEvent) => {
+ setLargeQuantity(Number(event.target.value));
+ };
+
+ //upload media section
+ const handleImageChange = (event: ChangeEvent) => {
+ const file = event.target.files?.[0];
+ if (file) {
+ const reader = new FileReader();
+ reader.onloadend = () => {
+ setImage(reader.result as string);
+ };
+ reader.readAsDataURL(file);
+ }
+ };
+
+ //comment section
+ const [comments, setComments] = useState([
+ {
+ name: "Adetunji Oluwatobi",
+ date: "02 Jan, 2020",
+ time: "Wed 02:30pm",
+ comment: "Living a balanced lifestyle is essential...",
+ },
+ {
+ name: "Afolabi Oyewole",
+ date: "02 Jan, 2020",
+ time: "Wed 02:30pm",
+ comment: "Living a balanced lifestyle is essential...",
+ },
+ ]);
+ const [newComment, setNewComment] = useState("");
+
+ const handleCommentChange = (
+ event: React.ChangeEvent,
+ ) => {
+ setNewComment(event.target.value);
+ };
+
+ const handleCommentSubmit = () => {
+ if (newComment.trim()) {
+ const currentDate = new Date();
+ const formattedDate = `${currentDate.getDate()} ${currentDate.toLocaleString("default", { month: "short" })}, ${currentDate.getFullYear()}`;
+ const formattedTime = `${currentDate.toLocaleString("default", { weekday: "short" })} ${currentDate.getHours()}:${currentDate.getMinutes() < 10 ? "0" : ""}${currentDate.getMinutes()}pm`;
+
+ const commentToAdd = {
+ name: "New User",
+ date: formattedDate,
+ time: formattedTime,
+ comment: newComment,
+ };
+
+ setComments([...comments, commentToAdd]);
+ setNewComment("");
+ }
+ };
+
+ return (
+
+
+
+
+
Comments
+ {comments.map((comment, index) => (
+
+
+
+
+
{comment.name}
+
{`${comment.date} ${comment.time}`}
+
+
+
{comment.comment}
+
+ ))}
+
+
+
+
+
+
+ );
+};
+
+export default ProductDetail;
diff --git a/src/app/dashboard/(user-dashboard)/products/productcard/page.tsx b/src/app/dashboard/(user-dashboard)/products/productcard/page.tsx
new file mode 100644
index 000000000..baca39210
--- /dev/null
+++ b/src/app/dashboard/(user-dashboard)/products/productcard/page.tsx
@@ -0,0 +1,19 @@
+import productimage from "/public/images/productimage.png";
+
+import ProductCard from "../_components/productcadrcomponent";
+
+const Home: React.FC = () => {
+ return (
+
+ );
+};
+
+export default Home;
diff --git a/src/components/common/modals/invite-member/DeleteMembers/index.tsx b/src/components/common/modals/invite-member/DeleteMembers/index.tsx
new file mode 100644
index 000000000..eb5c7e6ec
--- /dev/null
+++ b/src/components/common/modals/invite-member/DeleteMembers/index.tsx
@@ -0,0 +1,61 @@
+"use client";
+
+import { Button } from "~/components/ui/button";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "~/components/ui/dialog";
+
+interface ModalProperties {
+ show: boolean;
+ onClose: () => void;
+}
+
+const DeleteMember: React.FC = ({ show, onClose }) => {
+ return (
+
+ );
+};
+
+export default DeleteMember;
diff --git a/src/components/layouts/footer/index.tsx b/src/components/layouts/footer/index.tsx
index 6e0c3b550..91c8a4b24 100644
--- a/src/components/layouts/footer/index.tsx
+++ b/src/components/layouts/footer/index.tsx
@@ -156,8 +156,6 @@ const Footer = () => {
{ route: "termsOfUse", link: "/terms-and-conditions" },
];
- //
-
return (