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 (5)
from django.contrib import admin from django.contrib import admin
from .models import Category, Product, Profile from .models import Category, Product, Profile, Order, OrderItem
# Register your models here. # Register your models here.
admin.site.register(Product) admin.site.register(Product)
admin.site.register(Category) admin.site.register(Category)
admin.site.register(Profile) admin.site.register(Profile)
\ No newline at end of file admin.site.register(Order)
admin.site.register(OrderItem)
\ No newline at end of file
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db.models.functions import Now
# Create your models here. # Create your models here.
class Profile(models.Model): class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True) user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True)
credit = models.IntegerField(default=0) credit = models.IntegerField(default=0)
class Category(models.Model): class Category(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
image = models.ImageField(upload_to="products/", default='posts/default.jpg') image = models.ImageField(upload_to="products/", default='posts/default.jpg')
def __str__(self): def __str__(self):
return self.name return self.name
class Product(models.Model): class Product(models.Model):
user_id = models.ForeignKey(User, on_delete=models.CASCADE, default=1) user_id = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
image = models.ImageField(upload_to="products/", default='posts/default.jpg') image = models.ImageField(upload_to="products/", default='posts/default.jpg')
price = models.DecimalField(max_digits=5, decimal_places=2, null=True) price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
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)
def __str__(self): def __str__(self):
return self.name return self.name
class Order(models.Model):
# CATEGORY_CHOICES = [ buyer_id = models.ForeignKey(User, on_delete=models.CASCADE)
# "Christmas", date = models.DateTimeField(auto_now_add=True)
# "Halloween", total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
# "College",
# "Easter", def update_total_price(self):
# "Disco", self.total_price = sum(item.total_price for item in self.orderitem_set.all())
# "Afterski", self.save()
# "Whiteparty",
# "Bachelor",
# "Ice hockey", class OrderItem(models.Model):
# "Football",
# "Valentines Day", order_id = models.ForeignKey(Order, on_delete=models.CASCADE)
# "Hawaii", product_id = models.ForeignKey(Product, on_delete=models.CASCADE)
# "Vacation", orderType = models.CharField(max_length=10, choices={'buy':'buy', 'rent': 'rent'})
# "Kräftskiva", days = models.IntegerField(default=0)
# "Midsommar",
# "October fest" class Meta:
# ] constraints = [
\ No newline at end of file models.UniqueConstraint(fields=['order_id', 'product_id'], name='unique_order_product')
]
# myapp/serializers.py # myapp/serializers.py
from rest_framework import serializers from rest_framework import serializers
from .models import Product, Profile, Category from .models import Product, Profile, Category, Order, OrderItem
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth import authenticate, get_user_model from django.contrib.auth import authenticate, get_user_model
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
...@@ -51,11 +51,23 @@ class UserLoginSerializer(serializers.Serializer): ...@@ -51,11 +51,23 @@ class UserLoginSerializer(serializers.Serializer):
class UserRegisterSerializer(serializers.ModelSerializer): class UserRegisterSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = '__all__' fields = '__all__'
def create(self, clean_data): def create(self, clean_data):
user_obj = User.objects.create_user(username=clean_data['username'], email=clean_data['email'], password=clean_data['password']) user_obj = User.objects.create_user(username=clean_data['username'], email=clean_data['email'], password=clean_data['password'])
user_obj.username = clean_data['username'] user_obj.username = clean_data['username']
user_obj.save() user_obj.save()
return user_obj return user_obj
\ No newline at end of file
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = '__all__'
\ No newline at end of file
...@@ -18,4 +18,7 @@ urlpatterns = [ ...@@ -18,4 +18,7 @@ urlpatterns = [
path('home/', views.HomeView.as_view(), name='home'), path('home/', views.HomeView.as_view(), name='home'),
path('getproducts/', views.ProductView.as_view(), name='product'), path('getproducts/', views.ProductView.as_view(), name='product'),
path('hometry/', views.HomeViewTry.as_view(), name="try"), path('hometry/', views.HomeViewTry.as_view(), name="try"),
path('order/', views.OrderView.as_view(), name='order'),
path('orderItem/', views.OrderItemView.as_view(), name='order_item'),
] ]
...@@ -3,8 +3,8 @@ from rest_framework import viewsets, status, permissions ...@@ -3,8 +3,8 @@ from rest_framework import viewsets, status, permissions
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from .models import Product, Category, Profile from .models import Product, Category, Profile, Order, OrderItem
from .serializers import ProductSerializer, CategorySerializer, ProfileSerializer, UserSerializer, UserLoginSerializer, UserRegisterSerializer from .serializers import ProductSerializer, CategorySerializer, ProfileSerializer, UserSerializer, UserLoginSerializer, UserRegisterSerializer, OrderSerializer, OrderItemSerializer
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .validations import * from .validations import *
...@@ -19,7 +19,7 @@ from django.contrib.auth import login, logout ...@@ -19,7 +19,7 @@ from django.contrib.auth import login, logout
class HomeView(APIView): class HomeView(APIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly] permission_classes = [permissions.IsAuthenticated]
def get(self, request): def get(self, request):
print(request) print(request)
...@@ -141,7 +141,6 @@ class ProductView(APIView): ...@@ -141,7 +141,6 @@ class ProductView(APIView):
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
except: except:
return Response(status=status.HTTP_404_NOT_FOUND) return Response(status=status.HTTP_404_NOT_FOUND)
# def post(self, request, user_id): # def post(self, request, user_id):
# try: # try:
# data = request.data.copy() # data = request.data.copy()
...@@ -153,4 +152,45 @@ class ProductView(APIView): ...@@ -153,4 +152,45 @@ class ProductView(APIView):
# return Response(serializer.data, status=status.HTTP_201_CREATED) # return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# except Exception as e: # except Exception as e:
# return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
\ No newline at end of file
class OrderView(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
orders = Order.objects.all()
serializer = OrderSerializer(orders, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request):
try:
data = request.data.copy()
user = User.objects.filter(id=data['user_id']).first()
order = Order(buyer_id = user, total_price=data['total_price'])
order.save()
serializer = OrderSerializer(order)
return Response({'order': serializer.data}, status=status.HTTP_200_OK)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
class OrderItemView(APIView):
permission_classes = [permissions.IsAuthenticated]
def post(self, request):
try:
data = request.data.copy()
order = Order.objects.filter(id=data['order_id']).first()
product = Product.objects.filter(id=data['product_id']).first()
order_item = OrderItem(
order_id=order,
product_id=product,
orderType=data['orderType'],
days=data['days']
)
order_item.save()
serializer = OrderItemSerializer(order_item)
return Response({'order': serializer.data}, status=status.HTTP_200_OK)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
\ No newline at end of file
...@@ -146,7 +146,6 @@ const [loadingUser, setLoadingUser] = useState(true); ...@@ -146,7 +146,6 @@ const [loadingUser, setLoadingUser] = useState(true);
const fetchUser = async () => { const fetchUser = async () => {
try { try {
const result = await getLoggedInUser(); const result = await getLoggedInUser();
console.log('userrrr:', result.id);
setUser(result.id); setUser(result.id);
// You can perform additional actions here, like updating the UI // You can perform additional actions here, like updating the UI
} catch (error) { } catch (error) {
...@@ -164,12 +163,9 @@ const [loadingUser, setLoadingUser] = useState(true); ...@@ -164,12 +163,9 @@ const [loadingUser, setLoadingUser] = useState(true);
const fetchProducts = async () => { const fetchProducts = async () => {
try { try {
const result = await getAllProducts(); const result = await getAllProducts();
console.log('All Products:', result);
if (user) { if (user) {
console.log('User ID:', user);
const filteredProducts = result.data.filter(product => product.user_id === user); const filteredProducts = result.data.filter(product => product.user_id === user);
console.log('Filtered Products:', filteredProducts);
setProducts(filteredProducts); setProducts(filteredProducts);
} else { } else {
console.warn('User ID is null or undefined'); console.warn('User ID is null or undefined');
......
...@@ -2,6 +2,7 @@ import React, { useState } from 'react'; ...@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import { useCart } from './CartProvider'; import { useCart } from './CartProvider';
import { List, ListItem, ListItemText, IconButton, Typography, Button, Dialog, DialogContent, DialogTitle, TextField, DialogActions, Box } from '@mui/material'; import { List, ListItem, ListItemText, IconButton, Typography, Button, Dialog, DialogContent, DialogTitle, TextField, DialogActions, Box } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
import { orderItem, createOrder } from '../utils/api';
const Cart = () => { const Cart = () => {
const { cartItems, removeFromCart } = useCart(); const { cartItems, removeFromCart } = useCart();
...@@ -30,8 +31,14 @@ const Cart = () => { ...@@ -30,8 +31,14 @@ const Cart = () => {
setOpenCheckout(false); setOpenCheckout(false);
}; };
const handleCheckout = () => { const handleCheckout = async () => {
// Handle the checkout process here // Handle the checkout process here
const totalPrice = getTotalPrice(cartItems);
const orderID = await createOrder(totalPrice);
for (const item of cartItems){
const type = item.type === 'hyr' ? 'rent': 'buy';
await orderItem(orderID, item.id, type, item.days)
}
alert('Checkout successful!'); alert('Checkout successful!');
handleCheckoutClose(); handleCheckoutClose();
}; };
...@@ -53,7 +60,13 @@ const Cart = () => { ...@@ -53,7 +60,13 @@ const Cart = () => {
secondary={ secondary={
<> <>
<img src={item.imageUrl} alt="Product" style={{ maxHeight: '50px' }} /> <img src={item.imageUrl} alt="Product" style={{ maxHeight: '50px' }} />
<Typography variant="body2">Typ: {item.type}</Typography> <Typography variant="body2">
{
item.type === 'hyr' ?
`Hyrs i ${item.days} ${item.days === '1' ? 'dag': 'dagar'}`:
'Köpes'
}
</Typography>
</> </>
} }
/> />
...@@ -68,7 +81,9 @@ const Cart = () => { ...@@ -68,7 +81,9 @@ const Cart = () => {
</Button> </Button>
</Box> </Box>
)} )}
<Typography variant='h4' align="center" marginTop={2}>
Totalpris: {getTotalPrice(cartItems)} kr
</Typography>
<Dialog open={openCheckout} onClose={handleCheckoutClose}> <Dialog open={openCheckout} onClose={handleCheckoutClose}>
<DialogTitle>Checkout</DialogTitle> <DialogTitle>Checkout</DialogTitle>
<DialogContent> <DialogContent>
...@@ -135,3 +150,16 @@ const Cart = () => { ...@@ -135,3 +150,16 @@ const Cart = () => {
export default Cart; export default Cart;
/* HelpFunctions for cart*/
const getTotalPrice = (allItems) => {
let totalPrice = 0;
for (const item of allItems) {
console.log(item, totalPrice)
if (item.type === 'hyr'){
totalPrice += parseFloat(item.price) * item.days;
} else {
totalPrice += parseFloat(item.price)
}
}
return totalPrice;
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import { Card, CardContent, CardMedia, Typography, Dialog, DialogContent, Button } from '@mui/material'; import { Card, CardContent, CardMedia, Typography, Dialog, DialogContent, Button } from '@mui/material';
import TextField from '@mui/material/TextField'
import { styled } from '@mui/system'; import { styled } from '@mui/system';
import { useCart } from './CartProvider' import { useCart } from './CartProvider'
...@@ -16,9 +17,12 @@ const AnimatedCard = styled(Card)({ ...@@ -16,9 +17,12 @@ const AnimatedCard = styled(Card)({
const Product = ({ id, imageUrl, price, rentPrice, name, size }) => { const Product = ({ id, imageUrl, price, rentPrice, name, size }) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const {addToCart} = useCart(); const {addToCart} = useCart();
const [showRentField, setShowRentField] = useState(false);
const [rentDays, setRentDays] = useState('');
const handleOpen = () => { const handleOpen = () => {
setOpen(true); setOpen(true);
setShowRentField(false)
}; };
const handleClose = () => { const handleClose = () => {
...@@ -31,15 +35,20 @@ const Product = ({ id, imageUrl, price, rentPrice, name, size }) => { ...@@ -31,15 +35,20 @@ const Product = ({ id, imageUrl, price, rentPrice, name, size }) => {
handleClose(); // Close the dialog after adding to cart (optional) handleClose(); // Close the dialog after adding to cart (optional)
}; };
const handleRentClick = () => {
setShowRentField(true);
}
const handleRent = () => { const handleRent = () => {
// Add rent logic here // Add rent logic here
addToCart({ id, imageUrl, price: rentPrice, type: 'hyr' }); addToCart({ id, imageUrl, price: rentPrice, type: 'hyr', days: rentDays});
setShowRentField(false)
handleClose(); // Close the dialog after adding to cart handleClose(); // Close the dialog after adding to cart
}; };
const handleBuy = () => { const handleBuy = () => {
// Add buy logic here // Add buy logic here
addToCart({ id, imageUrl, price, type: 'köp' }); addToCart({ id, imageUrl, price, type: 'köp', days: 0});
handleClose(); // Close the dialog after adding to cart handleClose(); // Close the dialog after adding to cart
}; };
...@@ -74,7 +83,16 @@ const Product = ({ id, imageUrl, price, rentPrice, name, size }) => { ...@@ -74,7 +83,16 @@ const Product = ({ id, imageUrl, price, rentPrice, name, size }) => {
<DialogContent> <DialogContent>
<img src={imageUrl} alt="Product Image" style={{ maxWidth: '100%' }} /> <img src={imageUrl} alt="Product Image" style={{ maxWidth: '100%' }} />
</DialogContent> </DialogContent>
<Button variant="contained" color="primary" onClick={handleRent}> {showRentField && (
<TextField
label="Number of Days"
value={rentDays}
onChange={(e) => setRentDays(e.target.value)}
fullWidth
style={{ marginTop: 16 }}
/>
)}
<Button variant="contained" color="secondary" onClick={showRentField ? handleRent : handleRentClick} style={{ marginTop: 16 }}>
Hyr Hyr
</Button> </Button>
<Button variant="contained" color="secondary" onClick={handleBuy} style={{ marginTop: 16 }}> <Button variant="contained" color="secondary" onClick={handleBuy} style={{ marginTop: 16 }}>
......
...@@ -47,7 +47,6 @@ export const addProduct = async (img, price, rentPrice, name, size, userID) => { ...@@ -47,7 +47,6 @@ export const addProduct = async (img, price, rentPrice, name, size, userID) => {
'Authorization': `Bearer ${TOKEN}` 'Authorization': `Bearer ${TOKEN}`
}, },
}); });
console.log('Added product successfully:', response.data);
return response.status return response.status
} catch (error) { } catch (error) {
console.error('Error in adding product:', error) console.error('Error in adding product:', error)
...@@ -105,4 +104,44 @@ export const getAllProducts = async () => { ...@@ -105,4 +104,44 @@ export const getAllProducts = async () => {
console.log('not auth', e) console.log('not auth', e)
return false; return false;
} }
} }
\ No newline at end of file
export const createOrder = async (totalPrice) => {
const user = await getLoggedInUser();
try {
const result = await axios.post('http://127.0.0.1:8000/themeApp/order/', {
'user_id': user.id,
'total_price': totalPrice,
},{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${TOKEN}`
}
});
return result.data.order.id;
} catch (e) {
console.error('Error: ', e)
}
}
export const orderItem = async (orderID, productID, orderType, days=0) => {
try {
const result = await axios.post(`${API_BASE_URL}/themeApp/orderItem/`, {
'order_id': orderID,
'product_id': productID,
'orderType': orderType,
'days': days,
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${TOKEN}`,
}
}
);
console.log('orderItem result:', result);
return result.status
} catch (e) {
console.error('Error: ', e);
}
}