Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single product page #135

Merged
merged 20 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a2d5291
feat(add the page structure): add structure
KatiaGhezali Nov 10, 2023
ee4b3e8
fix(products page): resolve conflicts
KatiaGhezali Nov 10, 2023
cb09992
fix(single product page): fi Eslint issues
KatiaGhezali Nov 18, 2023
1ca9cd5
fix(single product page): fix getting data from firebase issue
KatiaGhezali Nov 18, 2023
e86f33f
Merge branch 'develop' into 31-single-product-page
KatiaGhezali Nov 18, 2023
97638b5
fix(single product page): fix getting data from firebase issue
KatiaGhezali Nov 19, 2023
354b7ca
Merge branch 'develop' into 31-single-product-page
KatiaGhezali Nov 20, 2023
4e33a49
fix(single product page): fix user issue
KatiaGhezali Nov 20, 2023
bb5e53a
fix(single product page): fix firebase requests issue
KatiaGhezali Nov 21, 2023
9eca323
feat(single product page): implement the add to cart functionnality i…
KatiaGhezali Nov 21, 2023
7f628c6
feat(single product page): work on responsive details
KatiaGhezali Nov 21, 2023
48caf9d
feat(single product page): add styling changes to the page
KatiaGhezali Nov 21, 2023
f0aca78
Merge branch 'develop' into 31-single-product-page
KatiaGhezali Nov 21, 2023
ba3f21f
fix(single product page branch): fix conflicts
KatiaGhezali Nov 21, 2023
0b8f538
fix(product details): fix the asynchrous call to firebase issue
KatiaGhezali Nov 21, 2023
8f91289
feat(product details): add responsiveness to user data
KatiaGhezali Nov 21, 2023
e17963b
fix(package.json files): fix prettier issues
KatiaGhezali Nov 21, 2023
4255a27
fix(package json files): fix prettier issues
KatiaGhezali Nov 21, 2023
aa8476d
fix: fix prettier issue
KatiaGhezali Nov 21, 2023
a5b705e
feat(product details): fix waiting time issue
KatiaGhezali Nov 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Loading