Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • marta873/tddd27_2024
1 result
Show changes
Commits on Source (2)
...@@ -23,6 +23,7 @@ class Product(models.Model): ...@@ -23,6 +23,7 @@ class Product(models.Model):
rent_price = models.DecimalField(max_digits=5, decimal_places=2, null=True) rent_price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
size = models.CharField(max_length=50) size = models.CharField(max_length=50)
categories = models.ManyToManyField(Category, related_name='products')
def __str__(self): def __str__(self):
......
...@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError ...@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
class ProductSerializer(serializers.ModelSerializer): class ProductSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Product 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): # def add_product(self, clean_data):
# product = Product( # product = Product(
......
...@@ -136,7 +136,13 @@ class ProductView(APIView): ...@@ -136,7 +136,13 @@ class ProductView(APIView):
def get(self, request): def get(self, request):
try: 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) serializer = ProductSerializer(products, many=True)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
except: except:
......
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import axios from 'axios'; import axios from 'axios';
import './CategoriesPage.css'; // Import the CSS file import './CategoriesPage.css'; // Import the CSS file
import { useNavigate } from 'react-router-dom';
const CategoriesPage = () => { const CategoriesPage = () => {
const [categories, setCategories] = useState([]); const [categories, setCategories] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const navigate = useNavigate()
useEffect(() => { useEffect(() => {
axios.get('http://127.0.0.1:8000/themeApp/categories/') // Replace with your Django API endpoint axios.get('http://127.0.0.1:8000/themeApp/categories/') // Replace with your Django API endpoint
.then(response => { .then(response => {
...@@ -19,6 +21,10 @@ const CategoriesPage = () => { ...@@ -19,6 +21,10 @@ const CategoriesPage = () => {
}); });
}, []); }, []);
const handleCategoryClick = (categoryId) => {
navigate(`/?category=${categoryId}`);
};
if (loading) return <p>Loading...</p>; if (loading) return <p>Loading...</p>;
if (error) return <p>Error loading categories: {error.message}</p>; if (error) return <p>Error loading categories: {error.message}</p>;
...@@ -29,9 +35,7 @@ const CategoriesPage = () => { ...@@ -29,9 +35,7 @@ const CategoriesPage = () => {
<div <div
key={index} key={index}
className="category-item" className="category-item"
onClick={() => { onClick={() => handleCategoryClick(category.id)}
window.location.href = category.name;
}}
> >
<img <img
src={category.image} src={category.image}
......
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import axios from 'axios'; import axios from 'axios';
import Carousel from './components/Carousel'; 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 './Home.css';
import ProductViewer from './ProductViewer.js'; import ProductViewer from './ProductViewer.js';
import theme from './styles/theme.js' import theme from './styles/theme.js';
import { getAllProducts } from './utils/api.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 products = await getAllProducts();
const Home = () => { const Home = () => {
const [searchParams] = useSearchParams();
const initialCategory = parseFloat(searchParams.get('category' || ''));
const [categories, setCategories] = useState([]); const [categories, setCategories] = useState([]);
const [loadingCategories, setLoadingCategories] = useState(true); const [loadingCategories, setLoadingCategories] = useState(true);
const [errorCategories, setErrorCategories] = useState(null); const [errorCategories, setErrorCategories] = useState(null);
const [selectedCategory, setSelectedCategory] = useState(initialCategory);
const [products, setProducts] = useState([]); const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
...@@ -42,8 +46,21 @@ const Home = () => { ...@@ -42,8 +46,21 @@ const Home = () => {
setError(error); setError(error);
setLoading(false); 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 ( return (
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
...@@ -54,11 +71,30 @@ const Home = () => { ...@@ -54,11 +71,30 @@ const Home = () => {
) : errorCategories ? ( ) : errorCategories ? (
<p>Error loading categories: {errorCategories.message}</p> <p>Error loading categories: {errorCategories.message}</p>
) : ( ) : (
<Carousel showingItems={1} items={categories.map(category => ({ <Carousel
showingItems={1}
items={categories.map(category => ({
name: category.name, 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 }}> <div style={{ padding: 8 }}>
<Typography <Typography
variant='h3' variant='h3'
...@@ -69,7 +105,7 @@ const Home = () => { ...@@ -69,7 +105,7 @@ const Home = () => {
</Typography> </Typography>
<Grid container spacing={2}> <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'}> <Grid key={product.id} item xs={12} sm={6} md={4} lg={3} display={'flex'} justifyContent={'center'}>
<Product <Product
id={product.id} id={product.id}
......
...@@ -29,12 +29,12 @@ const NavigationComponent = ({ goToNextPage, goToPreviousPage, currentPage, tota ...@@ -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 ( return (
<div style={styles.moviesContainer}> <div style={styles.moviesContainer}>
<div style={styles.movies}> <div style={styles.movies}>
{setOfMovies.map((movie, index) => ( {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} /> <img src={movie.source} alt={movie.name} style={styles.image} />
</div> </div>
))} ))}
...@@ -59,7 +59,7 @@ const MoviesDisplay = ({ setOfMovies, goToNextPage, goToPreviousPage, currentPag ...@@ -59,7 +59,7 @@ const MoviesDisplay = ({ setOfMovies, goToNextPage, goToPreviousPage, currentPag
</div> </div>
); );
}; };
const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => { const Carousel = ({ showingItems, items, autoScrollInterval = 3000, onItemClick }) => {
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const TOTAL_PAGES = Math.ceil(items.length / showingItems); const TOTAL_PAGES = Math.ceil(items.length / showingItems);
...@@ -80,6 +80,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => { ...@@ -80,6 +80,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => {
for (let i = 0; i < items.length; i += showingItems) { for (let i = 0; i < items.length; i += showingItems) {
groupingMovies.push(items.slice(i, i + showingItems)); groupingMovies.push(items.slice(i, i + showingItems));
} }
// console.log(groupingMovies)
return ( return (
<div style={styles.container}> <div style={styles.container}>
...@@ -98,6 +99,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => { ...@@ -98,6 +99,7 @@ const Carousel = ({ showingItems, items, autoScrollInterval = 3000 }) => {
goToPreviousPage={previousPage} goToPreviousPage={previousPage}
currentPage={currentPage} currentPage={currentPage}
totalPages={TOTAL_PAGES} totalPages={TOTAL_PAGES}
onItemClick={onItemClick}
/> />
</div> </div>
))} ))}
......