Skip to content

Commit

Permalink
#1150 [Recommendation] Adjust product detail page to show similar pro…
Browse files Browse the repository at this point in the history
…duct

- update UI
  • Loading branch information
Chinh Duong committed Oct 10, 2024
1 parent f7259c8 commit ff5d081
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class RelatedProductVm {

private List<ImageVm> productImages;

private String slug;

public RelatedProductVm() {
}
}
Expand Down
52 changes: 52 additions & 0 deletions storefront/common/components/SimilarProductCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import clsx from 'clsx';
import Link from 'next/link';
import { useLayoutEffect, useState } from 'react';

import { getMediaById } from '@/modules/media/services/MediaService';
import { ProductThumbnail } from 'modules/catalog/models/ProductThumbnail';
import { formatPrice } from 'utils/formatPrice';
import ImageWithFallBack from './ImageWithFallback';

import styles from 'styles/ProductCard.module.css';

export interface Props {
product: ProductThumbnail;
thumbnailUrl?: string;
className?: string[];
}

export default function SimilarProductCard({ product, className, thumbnailUrl }: Props) {
return (
<Link
className={clsx(
styles['product'],
className?.map((item) => styles[item])
)}
href={`/products/${product.slug}`}
>
<div className={styles['product-card']}>
<div className={styles['image-wrapper']}>
<ImageWithFallBack src={thumbnailUrl} alt={product.name} />
</div>
<div className={styles['info-wrapper']}>
<h3 className={styles['prod-name']}>{product.name}</h3>
<div className={styles['rating-sold']}>
<div className={styles['star']}>
0 <i className="bi bi-star-fill"></i>
</div>{' '}
|{' '}
<div className={styles['sold']}>
0 <span>sold</span>
</div>
</div>

<div className={styles['price']}>{formatPrice(product.price)}</div>

<hr />

<div className={styles['delivery']}>Fast delivery 2 hours</div>
</div>
</div>
</Link>
);
}
47 changes: 47 additions & 0 deletions storefront/modules/catalog/components/SimilarProduct.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useState } from 'react';
import { Col, Row } from 'react-bootstrap';

import SimilarProductCard from '@/common/components/SimilarProductCard';
import { ProductThumbnail } from '../models/ProductThumbnail';
import { getSimilarProductsByProductId } from '../services/ProductService';

type SimilarProductProps = {
productId: number;
};

const SimilarProduct = ({ productId }: SimilarProductProps) => {
const [products, setProducts] = useState<ProductThumbnail[]>([]);

useEffect(() => {
fetchSimilarProducts();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const fetchSimilarProducts = () => {
getSimilarProductsByProductId(productId)
.then((response) => setProducts(response))
.catch((error) => console.log(error));
};

return (
<div className="my-5">
<h4 className="mb-2 text-black">Similar Products</h4>
{products.length > 0 && (
<Row md={5}>
{products.map((product) => (
<Col key={product.id}>
<SimilarProductCard
product={product}
thumbnailUrl={product && product.thumbnail && product.thumbnail.url ? product.thumbnail.url : ''}
/>
</Col>
))}
</Row>
)}

{products.length === 0 && <p className="mt-4">No product</p>}
</div>
);
};

export default SimilarProduct;
3 changes: 2 additions & 1 deletion storefront/modules/catalog/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import DetailHeader from './DetailHeader';
import ProductDetails from './ProductDetails';
import RelatedProduct from './RelatedProducts';
import SimilarProduct from './SimilarProduct';

export { DetailHeader, ProductDetails, RelatedProduct };
export { DetailHeader, ProductDetails, RelatedProduct, SimilarProduct};
11 changes: 11 additions & 0 deletions storefront/modules/catalog/services/ProductService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,14 @@ export async function getRelatedProductsByProductId(productId: number): Promise<
if (res.status >= 200 && res.status < 300) return res.json();
return Promise.reject(res);
}

export async function getSimilarProductsByProductId(productId: number): Promise<ProductsGet> {
const res = await fetch(`/api/recommendation/embedding/product/${productId}/similarity`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (res.status >= 200 && res.status < 300) return res.json();
return Promise.reject(res);
}
3 changes: 2 additions & 1 deletion storefront/pages/products/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Tabs from 'react-bootstrap/Tabs';
import BreadcrumbComponent from '../../common/components/BreadcrumbComponent';

import { BreadcrumbModel } from '../../modules/breadcrumb/model/BreadcrumbModel';
import { ProductDetails, RelatedProduct } from '../../modules/catalog/components';
import { ProductDetails, RelatedProduct, SimilarProduct } from '../../modules/catalog/components';
import { ProductDetail } from '../../modules/catalog/models/ProductDetail';
import { ProductOptions } from '../../modules/catalog/models/ProductOptions';
import { ProductVariation } from '../../modules/catalog/models/ProductVariation';
Expand Down Expand Up @@ -260,6 +260,7 @@ const ProductDetailsPage = ({ product, productOptions, productVariations, pvid }

{/* Related products */}
<RelatedProduct productId={product.id} />
<SimilarProduct productId={product.id} />
</Container>
);
};
Expand Down

0 comments on commit ff5d081

Please sign in to comment.