backend setup

This commit is contained in:
Stanislaw-Golebiewski 2020-01-05 21:41:14 +01:00
parent a748900ac1
commit 527d60c70c
22 changed files with 672 additions and 55 deletions

0
bk_api/bills/__init__.py Normal file
View File

6
bk_api/bills/admin.py Normal file
View File

@ -0,0 +1,6 @@
from django.contrib import admin
# Register your models here.
from .models import Tag, Product, ProductOnBill, Receipt, ShopTag, Shop
admin.site.register([Tag, Product, ProductOnBill, Receipt, ShopTag, Shop])

5
bk_api/bills/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class BillsConfig(AppConfig):
name = 'bills'

16
bk_api/bills/endpoints.py Normal file
View File

@ -0,0 +1,16 @@
from django.conf.urls import include, url
from rest_framework import routers
from .views import TagViewSet, ProductViewSet, ReceiptViewSet, ProductOnBillViewSet, ShopTagViewSet, ShopViewSet
router = routers.DefaultRouter()
router.register('tags', TagViewSet)
router.register('shop_tags', ShopTagViewSet)
router.register('shops', ShopViewSet)
router.register('products', ProductViewSet)
router.register('products_on_bills', ProductOnBillViewSet)
router.register('receipts', ReceiptViewSet)
urlpatterns = [
url("^", include(router.urls)),
]

View File

View File

@ -0,0 +1,34 @@
{
"tags":[
{"name": "owoce", "color": "green"},
{"name": "warzywa", "color": "green"},
{"name": "pieczywo", "color": "yellow"},
{"name": "słodycze", "color": "blue"}
],
"shop_tags": [
{"name": "sklep", "color": "green"},
{"name": "stołówka", "color": "green"},
{"name": "restauracja", "color": "green"}
],
"shops": [
{"name": "Biedronka",
"tags": [
{"name": "sklep"}
]},
{"name": "Lidl",
"tags": [
{"name": "sklep"}
]},
{"name": "Piotr i Paweł",
"tags": [
{"name": "sklep"}
]}
],
"products": [
{"name": "banany", "price": 5.50, "tags": [{"name": "owoce"}]},
{"name": "mandarynki", "price": 2.99, "tags": [{"name": "owoce"}]},
{"name": "marchew", "price": 1.99, "tags": [{"name": "warzywa"}]},
{"name": "bułka kajzerka", "price": 0.39, "tags": [{"name": "pieczywo"}]},
{"name": "jogurt naturalny", "price": 1.59, "tags": [{"name": "nabiał", "color": "wihte"}]}
]
}

View File

@ -0,0 +1,111 @@
import json
import random
from datetime import date, timedelta
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
from bills.serializers import TagSerializer, ShopTagSerializer, ShopSerializer, ReceiptSerializer
class Command(BaseCommand):
args = '<foo bar ...>'
help = 'our help string comes here'
def _load_data(self):
with open("./bills/management/commands/data.json", 'r') as json_file:
self.data = json.load(json_file)
def _user_exists(self, username):
return User.objects.filter(username=username).exists()
def _create_user(self, username: str):
password = f"{username}_pass"
user_exists = self._user_exists(username)
if user_exists:
if input(f">: Delete {username} from db? [y/N]: ") != 'y':
return None
else:
User.objects.get(username=username).delete()
self.stdout.write(f"> User '{username}' deleted!")
user = User.objects.create_user(username, "", password)
self.stdout.write(f"> Created user '{username}' with password '{password}'")
return user
def _create_tags(self, user):
created_tags = []
for tag in self.data["tags"]:
created_tag = TagSerializer(data=tag)
created_tag.is_valid()
created_tag.save(owner=user)
self.stdout.write(f"> Created tag: '{created_tag.data['name']}'")
created_tags.append(created_tag.data['name'])
self.stdout.write(f"> Created tags")
return created_tags
def _create_shop_tags(self, user):
created_tags = []
for tag in self.data["shop_tags"]:
created_tag = ShopTagSerializer(data=tag)
created_tag.is_valid()
created_tag.save(owner=user)
self.stdout.write(f"> Created shop tag: '{created_tag.data['name']}'")
created_tags.append(created_tag.data['name'])
self.stdout.write(f"> Created shop tags")
return created_tags
def _create_shops(self, user, shop_tags):
created_shops = []
for shop in self.data["shops"]:
created_shop = ShopSerializer(data=shop)
created_shop.is_valid()
created_shop.save(owner=user)
self.stdout.write(f"> Created shop: '{created_shop.data['name']}'")
created_shops.append(created_shop.data)
self.stdout.write(f"> Created shop")
return created_shops
def _create_receipts(self, user, shops, tags, shop_tags):
# dates for last 30 days
for d in [date.today() - timedelta(31) + timedelta(n)for n in range(31)]:
if random.random() > 0.4:
continue
receipt_date = f"{d.year}-{d.month}-{d.day}"
receipt_schop = random.choice(shops)
receipt_products = [random.choice(self.data["products"])]
for product in self.data["products"]:
if random.random() < 0.20:
receipt_products.append(product)
new_receipt_data = {
"shop": receipt_schop,
"date": receipt_date,
"products": receipt_products
}
created_receipt = ReceiptSerializer(data=new_receipt_data)
is_valid = created_receipt.is_valid()
if not is_valid:
print(created_receipt.errors)
break;
created_receipt.save(owner=user)
self.stdout.write(f"> Created receipt: {receipt_date} | {receipt_schop['name']}")
def handle(self, *args, **options):
self.stdout.write(f"_/-\__/-\_POPULATE DB _/-\__/-\_")
user = self._create_user("demo_user")
if user != None:
self._load_data()
tags = self._create_tags(user)
shop_tags = self._create_shop_tags(user)
shops = self._create_shops(user, shop_tags)
self._create_receipts(user,shops, tags, shop_tags)
self.stdout.write(f"_/-\__/-\_ DONE _/-\__/-\_")

View File

@ -0,0 +1,80 @@
# Generated by Django 3.0 on 2020-01-05 12:40
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Tag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('color', models.CharField(default='#f2f2f2', max_length=30)),
('created_at', models.DateField(auto_now_add=True)),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tags', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='ShopTag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('color', models.CharField(default='#f2f2f2', max_length=30)),
('created_at', models.DateField(auto_now_add=True)),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shop_tags', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Shop',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('created_at', models.DateField(auto_now_add=True)),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shops', to=settings.AUTH_USER_MODEL)),
('tags', models.ManyToManyField(blank=True, to='bills.ShopTag')),
],
),
migrations.CreateModel(
name='Receipt',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateField(auto_now_add=True)),
('date', models.DateField()),
('total_price', models.FloatField(default=0.0)),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to=settings.AUTH_USER_MODEL)),
('shop', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to='bills.Shop')),
],
),
migrations.CreateModel(
name='ProductOnBill',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('created_at', models.DateField(auto_now_add=True)),
('price', models.DecimalField(decimal_places=2, max_digits=5)),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products_on_bills', to=settings.AUTH_USER_MODEL)),
('receipt', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='bills.Receipt')),
('tags', models.ManyToManyField(blank=True, to='bills.Tag')),
],
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=30)),
('created_at', models.DateField(auto_now_add=True)),
('default_tags', models.ManyToManyField(blank=True, to='bills.Tag')),
('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products', to=settings.AUTH_USER_MODEL)),
],
),
]

View File

66
bk_api/bills/models.py Normal file
View File

@ -0,0 +1,66 @@
from django.db import models
from django.contrib.auth.models import User
class Tag(models.Model):
name = models.CharField(max_length=30)
color = models.CharField(max_length=30, default="#f2f2f2")
created_at = models.DateField(auto_now_add=True)
owner = models.ForeignKey(User, related_name="tags", on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.name} | {self.owner.username}"
class ShopTag(models.Model):
name = models.CharField(max_length=30)
color = models.CharField(max_length=30, default="#9e9e9e")
created_at = models.DateField(auto_now_add=True)
owner = models.ForeignKey(User, related_name="shop_tags", on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.name} | {self.owner.username}"
class Shop(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateField(auto_now_add=True)
tags = models.ManyToManyField(ShopTag, blank=True)
owner = models.ForeignKey(User, related_name="shops", on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.name} | {self.owner.username}"
class Product(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateField(auto_now_add=True)
owner = models.ForeignKey(User, related_name="products", on_delete=models.CASCADE, null=True)
default_tags = models.ManyToManyField(Tag, blank=True)
def __str__(self):
return f"{self.name} | {self.owner.username}"
class Receipt(models.Model):
shop = models.ForeignKey(Shop, related_name="receipts", on_delete=models.CASCADE, blank=True)
created_at = models.DateField(auto_now_add=True)
date = models.DateField(auto_now_add=False)
owner = models.ForeignKey(User, related_name="receipts", on_delete=models.CASCADE, null=True)
total_price = models.FloatField(default=float(0.00))
def __str__(self):
return f"{self.shop} | {self.total_price} zł | {self.owner.username}"
class ProductOnBill(models.Model):
name = models.CharField(max_length=30)
created_at = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
receipt = models.ForeignKey(Receipt, related_name="products", on_delete=models.CASCADE)
tags = models.ManyToManyField(Tag, blank=True)
owner = models.ForeignKey(User, related_name="products_on_bills", on_delete=models.CASCADE, null=True)
def __str__(self):
return f"{self.name} | {self.price} zł | {self.owner.username}"

107
bk_api/bills/serializers.py Normal file
View File

@ -0,0 +1,107 @@
from rest_framework import serializers
from .models import Tag, Product, ProductOnBill, Receipt, ShopTag, Shop
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name', 'color', 'pk')
class ShopTagSerializer(serializers.ModelSerializer):
class Meta:
model = ShopTag
fields = ('name', 'color', 'pk')
class ShopSerializer(serializers.ModelSerializer):
tags = ShopTagSerializer(many=True)
class Meta:
model = Shop
fields = ('pk', 'name', 'tags')
def create(self, validated_data):
tags_data = validated_data.pop("tags")
shop_data = Shop.objects.create(**validated_data)
shop_data.save()
for tag in tags_data:
tag_ref, _ = ShopTag.objects.get_or_create(name=tag["name"], owner=validated_data["owner"])
shop_data.tags.add(tag_ref)
return shop_data
class ProductSerializer(serializers.ModelSerializer):
default_tags = TagSerializer(many=True)
class Meta:
model = Product
fields = ('pk', 'name', 'default_tags')
def create(self, validated_data):
default_tags_data = validated_data.pop("default_tags")
product_data = Product.objects.create(**validated_data)
product_data.save()
for tag in default_tags_data:
tag_ref, _ = Tag.objects.get_or_create(name=tag["name"], owner=self.context['request'].user)
product_data.default_tags.add(tag_ref)
return product_data
class ProductOnBillSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
class Meta:
model = ProductOnBill
fields = ['pk', 'name', 'price', 'tags']
class ReceiptSerializer(serializers.ModelSerializer):
products = ProductOnBillSerializer(many=True)
shop = ShopSerializer()
class Meta:
model = Receipt
fields = ['pk', 'shop', 'date', 'products', 'total_price']
def create(self, validated_data):
owner_data = validated_data.pop("owner")
products_data = validated_data.pop("products")
shop_data = validated_data.pop("shop")
total_price_data = 0
# get total price of products
for p in products_data:
total_price_data += p["price"]
# create shop if it does not exist yet
shop_ref, _ = Shop.objects.get_or_create(name=shop_data["name"], owner=owner_data)
receipt = Receipt.objects.create(owner=owner_data, total_price=total_price_data, shop=shop_ref, **validated_data)
for p in products_data:
# create product if it does not exists in products base
product_data, created = Product.objects.get_or_create(name=p["name"], owner=owner_data)
tags_data = p.pop("tags")
# create product on bill record
created_product_on_bill = ProductOnBill.objects.create(owner=owner_data, receipt=receipt, **p)
for tag in tags_data:
tag_ref, _ = Tag.objects.get_or_create(name=tag["name"], owner=owner_data )
created_product_on_bill.tags.add(tag_ref)
# if it's new product, set present tags as default tags
if created:
product_data.default_tags.add(tag_ref)
return receipt

3
bk_api/bills/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

79
bk_api/bills/views.py Normal file
View File

@ -0,0 +1,79 @@
from django.shortcuts import render
from rest_framework import viewsets, permissions, pagination
from .models import Tag, Product, ProductOnBill, Receipt, Shop, ShopTag
from .serializers import TagSerializer, ProductSerializer, ProductOnBillSerializer, ReceiptSerializer, ShopSerializer, ShopTagSerializer
class TagViewSet(viewsets.ModelViewSet):
queryset = Tag.objects.all()
# permission_classes = [permissions.AllowAny]
serializer_class = TagSerializer
def get_queryset(self):
return self.request.user.tags.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ShopTagViewSet(viewsets.ModelViewSet):
queryset = ShopTag.objects.all()
# permission_classes = [permissions.AllowAny]
serializer_class = ShopTagSerializer
def get_queryset(self):
return self.request.user.shop_tags.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ShopViewSet(viewsets.ModelViewSet):
queryset = Shop.objects.all()
# permission_classes = [permissions.AllowAny]
serializer_class = ShopSerializer
def get_queryset(self):
return self.request.user.shops.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
# permission_classes = [permissions.AllowAny]
serializer_class = ProductSerializer
def get_queryset(self):
return self.request.user.products.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ProductOnBillViewSet(viewsets.ModelViewSet):
queryset = ProductOnBill.objects.all()
# permission_classes = [permissions.AllowAny]
serializer_class = ProductOnBillSerializer
def get_queryset(self):
return self.request.user.products_on_bills.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class StandardResultsSetPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
class ReceiptViewSet(viewsets.ModelViewSet):
queryset = Receipt.objects.all()
serializer_class = ReceiptSerializer
pagination_class = StandardResultsSetPagination
def get_queryset(self):
return self.request.user.receipts.all()
def perform_create(self, serializer):
serializer.save(owner=self.request.user)

View File

@ -25,12 +25,23 @@ SECRET_KEY = 'i(12@f48%x!p8q^4gbn3++@^$g45!os)+3=8p0hf4g)j)5bqmf'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# ALLOWED_HOSTS = ["api.app.localhost.pl"]
ALLOWED_HOSTS = []
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
# 'rest_framework.permissions.AllowAny',
],
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication', 'rest_framework.authentication.SessionAuthentication'),
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 'PAGE_SIZE': 10
}
# Application definition
INSTALLED_APPS = [
'bills',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@ -38,6 +49,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework',
'knox'
# 'rest_framework.authtoken'
]
MIDDLEWARE = [
@ -116,11 +130,19 @@ USE_L10N = True
USE_TZ = True
CSRF_COOKIE_SECURE = False
# CSRF_COOKIE_NAME = "XSRF-TOKEN"
# CSRF_COOKIE_DOMAIN = "localhost.pl"
# CSRF_COOKIE_SAMESITE = None
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'

View File

@ -16,10 +16,24 @@ Including another URLconf
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin
from django.urls import include, path
from django.conf.urls import url
from knox import views as knox_views
from .views import LoginView
# from rest_framework.authtoken import views
from bills import endpoints
urlpatterns = [
path('bills/', include('core.urls')),
# path('bills/', include('core.urls')),
path('admin/', admin.site.urls),
url('^api/', include(endpoints)),
# url(r'^api/auth/', views.obtain_auth_token)
# url(r'api/auth/', include('knox.urls'))
url(r'api/auth/login/', LoginView.as_view(), name='knox_login'),
url(r'api/auth/logout/', knox_views.LogoutView.as_view(), name='knox_logout'),
url(r'api/auth/logoutall/', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
]
urlpatterns += staticfiles_urlpatterns()

14
bk_api/bk_api/views.py Normal file
View File

@ -0,0 +1,14 @@
from django.contrib.auth import login
from rest_framework import permissions
from rest_framework.authtoken.serializers import AuthTokenSerializer
from knox.views import LoginView as KnoxLoginView
class LoginView(KnoxLoginView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format=None):
serializer = AuthTokenSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
login(request, user)
return super(LoginView, self).post(request, format=None)

1
bk_webapp/.env Normal file
View File

@ -0,0 +1 @@
API_URL=http://localhost:8000

View File

@ -8038,6 +8038,11 @@
}
}
},
"js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"js-levenshtein": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",

View File

@ -7,6 +7,7 @@
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"axios": "^0.19.0",
"js-cookie": "^2.2.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-minimal-pie-chart": "^6.0.1",

View File

@ -1,54 +0,0 @@
import React from "react";
import {
Button,
Form,
Grid,
Segment,
Container,
Image
} from "semantic-ui-react";
import { useHistory } from "react-router-dom";
import logo from "../../img/logo_project.svg";
import "./Login.css";
function Login() {
let history = useHistory();
return (
<Container className="login-container">
<Grid columns={1} verticalAlign="middle" style={{ height: "100%" }}>
<Grid.Column>
<Image src={logo} size="medium" centered />
<Segment>
<Form size="large">
<Form.Input
fluid
icon="user"
iconPosition="left"
placeholder="Email address"
/>
<Form.Input
fluid
icon="lock"
iconPosition="left"
placeholder="Password"
type="password"
/>
<Button
basic
fluid
color="yellow"
size="large"
onClick={() => history.push("/home")}
>
Login
</Button>
</Form>
</Segment>
</Grid.Column>
</Grid>
</Container>
);
}
export default Login;

View File

@ -0,0 +1,107 @@
import React, { useState } from "react";
import {
Button,
Form,
Grid,
Segment,
Container,
Image
} from "semantic-ui-react";
import { useHistory } from "react-router-dom";
import axios from "axios";
import Cookies from "js-cookie";
import logo from "../../img/logo_project.svg";
import "./Login.css";
function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const handleSubmit = () => {
// console.log(process.env);
const bodyFormData = new FormData();
bodyFormData.set("username", username);
bodyFormData.set("password", password);
axios({
method: "get",
url: "http://api.app.localhost.pl/api-auth/login/",
withCredentials: true
// data: bodyFormData,
// headers: { "Content-Type": "multipart/form-data" }
})
.then(function(response) {
//handle success
console.log("success");
const csrfToken = Cookies.get("csrftoken");
console.log(csrfToken);
axios({
method: "post",
url: "http://api.app.localhost.pl/api-auth/login/",
withCredentials: true,
data: bodyFormData,
// headers: { "X-CSRFToken": csrfToken },
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-CSRFToken"
})
.then(resp => {
console.log("success x 2!!!");
console.log(resp);
})
.catch(err => {
console.log(err);
});
})
.catch(function(response) {
//handle error
console.log("error");
console.log(response);
});
};
return (
<Container className="login-container">
<Grid columns={1} verticalAlign="middle" style={{ height: "100%" }}>
<Grid.Column>
<Image src={logo} size="medium" centered />
<Segment>
<Form size="large">
<Form.Input
fluid
icon="user"
iconPosition="left"
placeholder="Nawa użytkownika"
onChange={e => {
setUsername(e.target.value);
}}
/>
<Form.Input
fluid
icon="lock"
iconPosition="left"
placeholder="Hasło"
type="password"
onChange={e => {
setPassword(e.target.value);
}}
/>
<Button
basic
fluid
color="yellow"
size="large"
onClick={() => handleSubmit()}
>
Login
</Button>
</Form>
</Segment>
</Grid.Column>
</Grid>
</Container>
);
}
export default Login;