Skip to content

Commit

Permalink
Merge pull request #135 from 202306-NEA-DZ-FEW/31-single-product-page
Browse files Browse the repository at this point in the history
Single product page
  • Loading branch information
hocine1212 committed Nov 22, 2023
2 parents 3b3f97b + a5b705e commit 0c00f95
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 99 deletions.
1 change: 0 additions & 1 deletion src/components/EditForm/EditForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ function EditForm() {
if (userData.name) {
await updateProfile(user, {
displayName: userData.name,
photoURL: "https://example.com/jane-q-user/profile.jpg",
});
}

Expand Down
243 changes: 152 additions & 91 deletions src/components/ProductDetails/ProductDetails.jsx
Original file line number Diff line number Diff line change
@@ -1,81 +1,117 @@
import React, { useState, useEffect } from "react";
import Image from "next/image";
import { db } from "../../util/firebase.js";
import { doc, getDoc, collection } from "firebase/firestore";
import { doc, getDoc } from "firebase/firestore";
import { useAuth } from "@/context/AuthContext.js";
import { CartContext } from "@/context/CartContext.js";
import { useContext } from "react";
import Link from "next/link";

function ProductDetails() {
const ProductDetails = ({ productId }) => {
const { addItemToCart } = useContext(CartContext);
const [productData, setProductData] = useState(null);
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const { currentUser } = useAuth();

useEffect(() => {
const fetchProductData = async () => {
const productRef = doc(db, "products", "3AMbn2OGg7MdOmLMsMqo");
const productDoc = await getDoc(productRef);
if (productDoc.exists()) {
setProductData(productDoc.data());
} else {
console.log("No such document!");
}
};
const fetchProductAndUserData = async () => {
try {
const productRef = doc(db, "products", productId);
const productDoc = await getDoc(productRef);

if (productDoc.exists()) {
const productData = {
...productDoc.data(),
id: productDoc.id,
};
setProductData(productData);

const fetchUserData = async () => {
const userRef = doc(db, "userinfo", "e43JDIG05abGPsH43xEKBNsD49e2");
const userDoc = await getDoc(userRef);
if (userDoc.exists()) {
setUserData(userDoc.data());
} else {
console.log("No such document!");
if (currentUser) {
const userRef = doc(
db,
"userinfo",
productData.currentUserUid
);
const userDoc = await getDoc(userRef);

if (userDoc.exists()) {
setUserData(userDoc.data());
} else {
console.log("No such user document!");
// Optionally set userData to a default value or handle accordingly
}
}
} else {
console.log("No such product document!");
}
} catch (error) {
console.error("Error fetching data:", error);
} finally {
setLoading(false);
}
};

fetchProductData();
fetchUserData();
}, []);
if (productId) {
fetchProductAndUserData();
}
}, [productId, currentUser]);

const handleAddToCart = () => {
if (productData) {
addItemToCart(productData);
}
};

if (!productData || !userData) {
if (loading) {
return <div>Loading...</div>;
}

return (
<div
style={{ margin: "40px" }}
className='flex flex-col gap-6 sm:gap-6 sm:flex-col md:flex-col md:justify-center lg:flex-row lg:justify-between'
style={{
margin: "80px ",
// "@media (max-width: 768px)": {
// margin: "180px 80px 50px 100px", // Adjust these values for smaller screens
// },
}}
className='flex flex-col sm:gap-6 sm:flex-col md:flex-col md:justify-center lg:flex-row lg:justify-between'
>
<div className='grid grid-cols-3 md:flex lg:grid lg:grid-rows-3 w-full sm:w-full md:w-full lg:w-1/2 justify-between gap-4'>
<div className='col-span-3 row-span-1 md:grid-rows-2 items-center justify-center overflow-hidden w-full lg:h-80 md:w-[60%] lg:w-full bg-[#EEF2F4] border rounded-md border-[#979797]'>
<div className='lg:p-12 md:p-10 grid grid-cols-3 md:flex lg:grid lg:grid-rows-3 w-full sm:w-full md:w-full lg:w-2/3 justify-between gap-4'>
<div className='col-span-3 row-span-1 md:grid-rows-2 items-center justify-center overflow-hidden w-full lg:h-80 md:w-[60%] lg:w-full bg-[#EEF2F4] border rounded-md border-[#979797]'>
<Image
className='object-cover w-full h-full rounded-md '
src={productData.pictures[0]}
src={productData?.pictures[0]}
width={1600}
height={1000}
alt='product image'
/>
</div>
<div className=' col-span-3 row-span-1 md:w-[40%] lg:w-full rounded-md gap-1'>
<div className='flex justify-between gap-4 md:grid md:grid-cols-2 md:grid-rows-1 sm:gap-2 lg:flex '>
<div className='col-span-2 row-span-1 md:row-span-2 w-full bg-[#EEF2F4] h-20 sm:h-28 md:h-64 lg:h-28 border rounded-md border-[#979797] overflow-hidden'>
<div className=' col-span-3 row-span-1 md:w-[40%] lg:w-full rounded-md gap-1'>
<div className='flex justify-between gap-4 md:grid md:grid-cols-2 md:grid-rows-1 sm:gap-2 lg:flex'>
<div className='col-span-2 row-span-1 md:row-span-2 w-full bg-[#EEF2F4] h-20 sm:h-28 md:h-64 lg:h-28 border rounded-md border-[#979797] overflow-hidden'>
<Image
className='object-cover w-full h-full rounded-md '
src={productData.pictures[1]}
src={productData?.pictures[1]}
width={1600}
height={1000}
alt='product image'
/>
</div>

<div className='w-full col-span-1 row-span-1 bg-[#EEF2F4] h-20 sm:h-28 border rounded-md border-[#979797] overflow-hidden'>
<div className='w-full col-span-1 row-span-1 bg-[#EEF2F4] sm:h-28 border rounded-md border-[#979797] overflow-hidden'>
<Image
className='object-cover w-full h-full '
src={productData.pictures[2]}
src={productData?.pictures[2]}
width={1600}
height={1000}
alt='product image'
/>
</div>
<div className='col-span-1 row-span-1 bg-[#EEF2F4] h-20 sm:h-28 w-full border rounded-md border-[#979797] overflow-hidden lg:w-full'>
<div className='col-span-1 row-span-1 bg-[#EEF2F4] h-20 sm:h-28 w-full border rounded-md border-[#979797] overflow-hidden lg:w-full'>
<Image
className='object-cover w-full h-full '
src={productData.pictures[3]}
src={productData?.pictures[3]}
width={1600}
height={1000}
alt='product image'
Expand All @@ -84,82 +120,107 @@ function ProductDetails() {
</div>
</div>
</div>
<div className=' grid w-full sm:w-full md:w-full lg:w-1/2 grid-cols-4 grid-rows-6 gap-4 text-[#585785]'>

<div className='grid w-full sm:w-full md:w-full lg:w-1/2 text-[#585785]'>
{/* Product Details */}
<div className='col-span-4 md:col-span-2'>
<h1 className='text-3xl font-bold text-[#7874F2] mb-4'>
{productData.title}
<div className='pt-8 col-span-4 md:col-span-2'>
<h1 className='font-bold text-[#7874F2] mb-4 lg:text-5xl md:text-3xl sm:text-lg'>
{productData?.title}
</h1>

<div className='flex mb-2'>
<div className='flex mb-2 '>
<p className='bg-orange-500 py-1 px-2 rounded-2xl font-bold text-white mr-20'>
For {productData?.type}
</p>
</div>

<div className='flex mb-2 mt-6'>
<p className='mr-20'>
<span className='font-bold'>Condition: </span>
{productData.condition}
{productData?.condition}
</p>

<p className=''>
<span className='font-bold'>Category: </span>
{productData.category}
{productData?.category}
</p>
</div>
<div className='flex mb-2'>
<p className='bg-orange-500 py-1 px-2 rounded font-bold text-white mr-20'>
For {productData.type}
</p>
<button className='bg-[#7874F2] py-1 px-2 rounded font-bold text-white ml-12'>
Add to Favorites
</button>
</div>
</div>
<br />

<div className='col-span-4 row-span-1 '>
<h1 className='text-xl font-bold'>Details:</h1>
<div className='col-span-4 row-span-1 flex items-center'>
<h1 className='text-xl font-bold mr-4'>Details:</h1>
<div className='flex-grow' />
<div className='flex items-center'>
<button
onClick={handleAddToCart}
className='text-[#7874F2] border border-[#7874F2] rounded hover:text-[#F1F6FA] hover:bg-[#7874F2] text-lg cursor-pointer p-2'
>
Add to cart
</button>
</div>
</div>
<hr />
<div className='overflow-y-scroll max-h-[100px]'>
{productData.description}
</div>
</div>

{/* User Info */}

<div className='inline-flex ml-8'>
<div className='flex flex-row items-center bg-[#585785] ml-16 w-64 h-16 lg:w-80 lg:h-24 md:w-80 md:h-24 rounded-l-full border-r-4 border-dashed'>
<Image
alt='profile'
width='80'
height='80'
className='w-8 h-8 lg:w-16 lg:h-16 md:w-16 md:h-16 rounded-full sm:w-4'
src={userData.photo}
/>

<div className='m-auto text-left ml-4 text-white text-sm lg:text-base md:text-base'>
<h1 className='font-semibold text-xs lg:text-sm'>
{userData.name} {userData.surname}
</h1>
<h2 className='w-[37vh] overflow-hidden'>
<span className='font-bold'></span>{" "}
<span className='truncate'>
{userData.email}
</span>
</h2>
<h2>
<span className='font-bold'></span>
{productData.location.city},
{productData.location.country}
</h2>
</div>
{productData?.description}
</div>

<div className='bg-orange-500 grid justify-items-center w-16 h-16 lg:w-24 lg:h-24 md:w-24 md:h-24'>
<h1 className='text-white font-semibold text-xs lg:text-xl md:text-base m-auto'>
{productData.price}
{"$"}
</h1>
{/* User Info */}
<div className='mt-2'>
{currentUser ? (
<div className='flex items-center mt-4 shadow-xl lg:p-4'>
<div className='rounded-full overflow-hidden '>
<Image
src={
userData?.photo ||
"/images/profile.jpg"
}
width={85}
height={85}
className='object-cover w-full h-full hidden sm:block md:block'
alt='user picture'
/>
</div>
<div className='ml-4 flex-1'>
<div className='flex flex-col'>
<h2 className='lg:text-xl md:text-lg font-bold '>
{userData?.name} {userData?.surname}
</h2>
<div className='flex items-center'>
<p className='lg:text-lg mr-2'>
{userData?.email}
</p>
<div className='text-center ml-auto'>
<p className='lg:text-4xl md:text-4xl sm:text-2xl font-bold'>
{productData?.price}$
</p>
</div>
</div>
<p className='lg:text-lg '>
{productData?.location?.city},{" "}
{productData?.location?.country}
</p>
</div>
</div>
</div>
) : (
<div className='flex items-center justify-center mt-4 text-center'>
<p className='text-[#32314D] font-bold'>
Please log in to get in touch with the owner
of this product.{" "}
<Link
href='/login'
className='text-[#7874F2]'
>
Log in
</Link>
</p>
</div>
)}
</div>
</div>
</div>
</div>
);
}
};

export default ProductDetails;
15 changes: 14 additions & 1 deletion src/components/ProductDetails/__test__/ProductDetails.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import renderer from "react-test-renderer";

import { AuthProvider } from "@/context/AuthContext";
import ProductDetails from "../ProductDetails";

jest.mock("../../../util/firebase", () => {
Expand All @@ -8,7 +9,19 @@ jest.mock("../../../util/firebase", () => {
};
});

jest.mock("next/router", () => ({
useRouter: () => ({
pathname: "/",
}),
}));

it("renders correctly", () => {
const tree = renderer.create(<ProductDetails />).toJSON();
const tree = renderer
.create(
<AuthProvider>
<ProductDetails />
</AuthProvider>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly 1`] = `
<div>
Loading...
</div>
`;
exports[`renders correctly 1`] = `null`;
2 changes: 1 addition & 1 deletion src/pages/mylistings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const MyListings = () => {
<SideBar />
<div className='flex flex-wrap justify-around items-start p-4'>
{loading ? (
<p>Loading...</p>
<p>Loading....</p>
) : (
<div className='grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4'>
{userListings.map((listing) => (
Expand Down
25 changes: 25 additions & 0 deletions src/pages/singleproduct/[productId].jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import ProductDetails from "@/components/ProductDetails/ProductDetails";
import { useRouter } from "next/router";
import { CartProvider } from "@/context/CartContext";
// import MapComponent from "@/components/Map/Map";

function SingleProduct() {
const router = useRouter();
const { productId } = router.query;

return (
<div className='relative'>
<ProductDetails productId={productId} />

{/* Conditionally render MapComponent based on screen size */}
{/* {productId && (
<div className="hidden lg:block lg:mt-16 lg:relative lg:z-0">
<MapComponent productId={productId} />
</div>
)} */}
</div>
);
}

export default SingleProduct;

0 comments on commit 0c00f95

Please sign in to comment.