Skip to content
Snippets Groups Projects
Commit 847dff4b authored by Marc Taylor's avatar Marc Taylor
Browse files

Merge branch 'products-by-category' into 'main'

filter by 1 category works

See merge request !16
parents 661264d3 0f1cfda5
No related branches found
No related tags found
1 merge request!16filter by 1 category works
......@@ -23,6 +23,7 @@ class Product(models.Model):
rent_price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
name = models.CharField(max_length=200)
size = models.CharField(max_length=50)
categories = models.ManyToManyField(Category, related_name='products')
def __str__(self):
......
......@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['id', 'name', 'image', 'price', 'rent_price', 'size', 'user_id']
fields = ['id', 'name', 'image', 'price', 'rent_price', 'size', 'user_id', 'categories']
# def add_product(self, clean_data):
# product = Product(
......
......@@ -136,7 +136,13 @@ class ProductView(APIView):
def get(self, request):
try:
products = Product.objects.all()
data = request.data.copy()
if ('category' in data):
category = Category.objects.filter(id=data['category']).first()
products = Product.objects.filter(categories=category)
else:
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
except:
......
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './CategoriesPage.css'; // Import the CSS file
import { useNavigate } from 'react-router-dom';
const CategoriesPage = () => {
const [categories, setCategories] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const navigate = useNavigate()
useEffect(() => {
axios.get('http://127.0.0.1:8000/themeApp/categories/') // Replace with your Django API endpoint
.then(response => {
......@@ -19,6 +21,10 @@ const CategoriesPage = () => {
});
}, []);
const handleCategoryClick = (categoryId) => {
navigate(`/?category=${categoryId}`);
};
if (loading) return <p>Loading...</p>;
if (error) return <p>Error loading categories: {error.message}</p>;
......@@ -29,9 +35,7 @@ const CategoriesPage = () => {
<div
key={index}
className="category-item"
onClick={() => {
window.location.href = category.name;
}}
onClick={() => handleCategoryClick(category.id)}
>
<img
src={category.image}
......
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Carousel from './components/Carousel';
import { Grid, ThemeProvider, Typography } from '@mui/material';
import { Grid, ThemeProvider, Typography, FormControl, InputLabel, Select, MenuItem } from '@mui/material';
import './Home.css';
import ProductViewer from './ProductViewer.js';
import theme from './styles/theme.js'
import theme from './styles/theme.js';
import { getAllProducts } from './utils/api.js';
import Product from './components/Product.js'
import Product from './components/Product.js';
import { useSearchParams } from 'react-router-dom';
const products = await getAllProducts();
const Home = () => {
const [searchParams] = useSearchParams();
const initialCategory = parseFloat(searchParams.get('category' || ''));
const [categories, setCategories] = useState([]);
const [loadingCategories, setLoadingCategories] = useState(true);
const [errorCategories, setErrorCategories] = useState(null);
const [selectedCategory, setSelectedCategory] = useState(initialCategory);
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
......@@ -42,8 +46,21 @@ const Home = () => {
setError(error);
setLoading(false);
});
}, []);
}, []);
const handleCategoryChange = (event) => {
setSelectedCategory(event.target.value);
};
const handleCarouselItemClick = (categoryId) => {
setSelectedCategory(categoryId);
};
const filteredProducts = selectedCategory
? products.filter(product => product.categories.includes(selectedCategory))
: products;
console.log('products: ', products)
return (
<ThemeProvider theme={theme}>
......@@ -54,11 +71,30 @@ const Home = () => {
) : errorCategories ? (
<p>Error loading categories: {errorCategories.message}</p>
) : (
<Carousel showingItems={1} items={categories.map(category => ({
<Carousel
showingItems={1}
items={categories.map(category => ({
name: category.name,
source: category.image
}))} />
source: category.image,
id: category.id,
}))}
onItemClick={handleCarouselItemClick}
/>
)}
<FormControl fullWidth style={{ margin: '16px 0' }}>
<InputLabel id="category-select-label">Filter by Category</InputLabel>
<Select
labelId="category-select-label"
id="category-select"
value={selectedCategory}
onChange={handleCategoryChange}
>
<MenuItem value=""><em>All</em></MenuItem>
{categories.map((category) => (
<MenuItem key={category.id} value={category.id}>{category.name}</MenuItem>
))}
</Select>
</FormControl>
<div style={{ padding: 8 }}>
<Typography
variant='h3'
......@@ -69,7 +105,7 @@ const Home = () => {
</Typography>
<Grid container spacing={2}>
{products.map((product) => (
{filteredProducts.map((product) => (
<Grid key={product.id} item xs={12} sm={6} md={4} lg={3} display={'flex'} justifyContent={'center'}>
<Product
id={product.id}
......
......@@ -29,12 +29,12 @@ const NavigationComponent = ({ goToNextPage, goToPreviousPage, currentPage, tota
);
};
const MoviesDisplay = ({ setOfMovies, goToNextPage, goToPreviousPage, currentPage, totalPages }) => {
const MoviesDisplay = ({ setOfMovies, goToNextPage, goToPreviousPage, currentPage, totalPages, onItemClick }) => {
return (
<div style={styles.moviesContainer}>
<div style={styles.movies}>
{setOfMovies.map((movie, index) => (
<div key={index} style={styles.movie}>
<div key={index} style={styles.movie} onClick={() => onItemClick(movie.id)}>
<img src={movie.source} alt={movie.name} style={styles.image} />
</div>
))}
......@@ -59,7 +59,7 @@ const MoviesDisplay = ({ setOfMovies, goToNextPage, goToPreviousPage, currentPag
</div>
);
};
const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => {
const Carousel = ({ showingItems, items, autoScrollInterval = 3000, onItemClick }) => {
const [currentPage, setCurrentPage] = useState(1);
const TOTAL_PAGES = Math.ceil(items.length / showingItems);
......@@ -80,6 +80,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => {
for (let i = 0; i < items.length; i += showingItems) {
groupingMovies.push(items.slice(i, i + showingItems));
}
// console.log(groupingMovies)
return (
<div style={styles.container}>
......@@ -98,6 +99,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => {
goToPreviousPage={previousPage}
currentPage={currentPage}
totalPages={TOTAL_PAGES}
onItemClick={onItemClick}
/>
</div>
))}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment