Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions src/components/filters/DropDownFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ interface DropDownFilterProps {
genre: string;
}

const DropDownFilter: React.FC<DropDownFilterProps> = ({ onClick, isOpen, filterByGenre, genre }) => {
const categories: Category[] = [
export const categories: Category[] = [

@nadav-cohen11 nadav-cohen11 Dec 26, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Exporting categories: You exported categories, which is good for reusability. However, keep in mind:

    1.1. If categories is only used in this component, exporting might introduce dead code elsewhere.
    1.2. If it is reused (as we see in Card), this solution is appropriate. Consider adding a comment or utility
    folder structure for constants (like categories).

  2. Performance Optimization: The categories array is recreated on every render, which is unnecessary. Instead:

You can define it as a const outside the component to ensure it's only created once.

export const categories: Category[] = [...]; // Move outside the function.

{ id: 'All', name: 'All Categories' },
{ id: "men's clothing", name: "Men's Clothing" },
{ id: "women's clothing", name: "Women's Clothing" },
{ id: 'electronics', name: 'Electronics' },
{ id: 'jewelery', name: 'Jewelery' },
];

const DropDownFilter: React.FC<DropDownFilterProps> = ({ onClick, isOpen, filterByGenre, genre }) => {

return (
<div className={`dropdown-wrapper ${isOpen ? 'open' : ''}`}>
<div
Expand Down
15 changes: 9 additions & 6 deletions src/components/product-components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import React from 'react';
import { Product } from '../../types';
import { categories } from '../filters/DropDownFilter';

interface CardProps {
product: Product
}

const Card: React.FC<CardProps> = () => {
const Card: React.FC<CardProps> = (props: CardProps) => {

@nadav-cohen11 nadav-cohen11 Dec 26, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Destructure Props:

Destructure props to improve readability:

const { product } = props;

const maxRatings = 5

@nadav-cohen11 nadav-cohen11 Dec 26, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic Numbers (maxRatings):

Use constants or make the logic more descriptive.
const MAX_RATINGS = 5;


return (
<div className='product scale-effect'>
<div className='product-image'>
<img />
<img src={props.product.image}/>

@nadav-cohen11 nadav-cohen11 Dec 26, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error Handling for Loading Image:

props.product.image is used directly. If the image URL fails, it might display a broken image. Add an onError:

<img src={props.product.image} alt={props.product.title} onError={(e) => (e.target.src = '/placeholder.png')} />

</div>
<div className='product-info'>
<h2 className='product-title'></h2>
<h2 className='product-title'>{props.product.title}</h2>
<div className='product-brief'>
<p><strong>Price: </strong></p>
<p><strong>Rating: </strong></p>
<p><strong>Category: </strong></p>
<p><strong>{`Price: ${props.product.price}`}</strong></p>
<p><strong>{`Rating: ${props.product.rating.rate}/${maxRatings} (${props.product.rating.count} Reviews)`}</strong></p>
<p><strong>{`Category: ${categories.find((category) => category.id == props.product.category)?.name}`}</strong></p>

@nadav-cohen11 nadav-cohen11 Dec 26, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing categories:

Good use of categories.find. However, watch out for cases where find might return undefined. To make it more robust, provide a fallback value:

const categoryName = categories.find(category => category.id == props.product.category)?.name || 'Unknown Category';

</div>
</div>
</div>
Expand Down
28 changes: 22 additions & 6 deletions src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import axios, { all } from 'axios';
import '../assets/css/common.css';
import '../assets/css/main.css';
import Navbar from '../components/ui-elements/Navbar';
import DropDownFilter from '../components/filters/DropDownFilter';
import Loading from '../components/ui-elements/Loading';
import Card from '../components/product-components/Card';
import { Product } from '../types';
import InputFilter from '../components/filters/InputFilter';

const Home: React.FC = () => {
const [allProducts, setAllProducts] = useState<Product[]>([]);
const [products, setProducts] = useState<Product[]>([]);
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
const [selectedCategory, setSelectedCategory] = useState<string>('All');
const allProductsCategory = "All";
const [selectedCategory, setSelectedCategory] = useState<string>(allProductsCategory);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const baseURL = "https://fakestoreapi.com/products";

//TODO - useEffect + axios
useEffect(() => {
axios.get(baseURL)
.then((response) => {
setAllProducts(response.data)
setProducts(response.data)
setLoading(false)
})
.catch((error) => {
setError(error)
setLoading(false)
})
},[])

const showFilterByCategory = () => {
setIsDropdownOpen(!isDropdownOpen);
};

// TODO - filter products by category - BONUS
const filterByCategory = (category: string) => {
setSelectedCategory(category);
//TODO - filter products by category
const filteredProducts = category === allProductsCategory? allProducts : allProducts.filter((product) => product.category === category)
setProducts(filteredProducts)
};

if (loading) {
Expand Down Expand Up @@ -57,7 +71,9 @@ const Home: React.FC = () => {
<div className='container'>
<section>
<div className='products-grid' id='products-list'>
{/* TODO - map products */}
{products.map((product) => {
return <Card key={product.id} product={product}></Card>
})}
</div>
</section>
</div>
Expand Down
15 changes: 12 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
export interface Rating {
//TODO
rate: number,
count: number
}

export interface Product {
//TODO
id: number,
title: string,
price: number,
desctiption: string,
category: string,
image: string,
rating: Rating
}

export interface Category {
//TODO
id: string,
name: string
}