keh
This commit is contained in:
parent
7d5a3626c6
commit
6430ab919e
@ -10,6 +10,7 @@ router.register('shops', ShopViewSet)
|
|||||||
router.register('products', ProductViewSet)
|
router.register('products', ProductViewSet)
|
||||||
router.register('products_on_bills', ProductOnBillViewSet)
|
router.register('products_on_bills', ProductOnBillViewSet)
|
||||||
router.register('receipts', ReceiptViewSet)
|
router.register('receipts', ReceiptViewSet)
|
||||||
|
# router.register('stats', GeneralStats)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url("^", include(router.urls)),
|
url("^", include(router.urls)),
|
||||||
|
32
bk_api/bills/statistics.py
Normal file
32
bk_api/bills/statistics.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from django.db.models import Count
|
||||||
|
|
||||||
|
from .models import Tag, Product, ProductOnBill, Receipt, Shop, ShopTag
|
||||||
|
|
||||||
|
|
||||||
|
def get_general_stats(user, date_range=None):
|
||||||
|
out = {
|
||||||
|
"receipts": user.receipts.all().count(),
|
||||||
|
"products": user.products.all().count(),
|
||||||
|
"shops": user.shops.all().count(),
|
||||||
|
"purchases": user.products_on_bills.all().count(),
|
||||||
|
"product_tags": user.tags.all().count(),
|
||||||
|
"shop_tags": user.shop_tags.all().count(),
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def get_shops_stats(user):
|
||||||
|
def shop_cout(name):
|
||||||
|
return user.receipts.all().filter(shop__name=name).count()
|
||||||
|
|
||||||
|
out = [{"name": s.name, "count": shop_cout(s.name)} for s in user.shops.all()]
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def get_products_stats(user):
|
||||||
|
# def shop_cout(name):
|
||||||
|
# return user..all().filter(pro__name=name).count()
|
||||||
|
out = [
|
||||||
|
{"name": "product", "count": "times bought"}
|
||||||
|
]
|
||||||
|
return out
|
9
bk_api/bills/urls.py
Normal file
9
bk_api/bills/urls.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from .views import general_stats_view, shops_stats_view, products_stats_view
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', general_stats_view),
|
||||||
|
path('shops/', shops_stats_view),
|
||||||
|
path('products/', products_stats_view),
|
||||||
|
]
|
@ -1,10 +1,15 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from rest_framework import viewsets, permissions, pagination, filters
|
from rest_framework import viewsets, permissions, pagination, filters
|
||||||
|
from django.http import JsonResponse
|
||||||
|
|
||||||
from .models import Tag, Product, ProductOnBill, Receipt, Shop, ShopTag
|
from .models import Tag, Product, ProductOnBill, Receipt, Shop, ShopTag
|
||||||
from .serializers import TagSerializer, ProductSerializer, ProductOnBillSerializer, ReceiptSerializer, ShopSerializer, ShopTagSerializer
|
from .serializers import TagSerializer, ProductSerializer, ProductOnBillSerializer, ReceiptSerializer, ShopSerializer, ShopTagSerializer
|
||||||
|
|
||||||
|
from .statistics import get_general_stats, get_shops_stats, get_products_stats
|
||||||
|
|
||||||
|
|
||||||
class TagViewSet(viewsets.ModelViewSet):
|
class TagViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Tag.objects.all()
|
queryset = Tag.objects.all()
|
||||||
@ -21,6 +26,7 @@ class ShopTagViewSet(viewsets.ModelViewSet):
|
|||||||
queryset = ShopTag.objects.all()
|
queryset = ShopTag.objects.all()
|
||||||
# permission_classes = [permissions.AllowAny]
|
# permission_classes = [permissions.AllowAny]
|
||||||
serializer_class = ShopTagSerializer
|
serializer_class = ShopTagSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.request.user.shop_tags.all()
|
return self.request.user.shop_tags.all()
|
||||||
|
|
||||||
@ -62,7 +68,6 @@ class ProductOnBillViewSet(viewsets.ModelViewSet):
|
|||||||
serializer.save(owner=self.request.user)
|
serializer.save(owner=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StandardResultsSetPagination(pagination.PageNumberPagination):
|
class StandardResultsSetPagination(pagination.PageNumberPagination):
|
||||||
page_size = 10
|
page_size = 10
|
||||||
page_size_query_param = 'page_size'
|
page_size_query_param = 'page_size'
|
||||||
@ -80,3 +85,25 @@ class ReceiptViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
serializer.save(owner=self.request.user)
|
serializer.save(owner=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
# === STATS VIEWS ===
|
||||||
|
|
||||||
|
# def GeneralStats(APIView):
|
||||||
|
# # authentication_classes = [authentication.TokenAuthentication]
|
||||||
|
# # permission_classes = [permissions.IsAdminUser]
|
||||||
|
|
||||||
|
# def get(self, request, format=None):
|
||||||
|
# print(request.user)
|
||||||
|
# return Response(get_general_stats(request.user))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# # def shops_stats_view(request):
|
||||||
|
# # responseData = get_shops_stats(request.user)
|
||||||
|
# # return JsonResponse(responseData, safe=False)
|
||||||
|
|
||||||
|
|
||||||
|
# # def products_stats_view(request):
|
||||||
|
# # responseData = get_products_stats(request.user)
|
||||||
|
# # return JsonResponse(responseData, safe=False)
|
||||||
|
@ -40,6 +40,10 @@ REST_FRAMEWORK = {
|
|||||||
# 'PAGE_SIZE': 10
|
# 'PAGE_SIZE': 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REST_KNOX = {
|
||||||
|
'TOKEN_TTL': None,
|
||||||
|
}
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
@ -22,11 +22,13 @@ from knox import views as knox_views
|
|||||||
from .views import LoginView
|
from .views import LoginView
|
||||||
from bills import endpoints
|
from bills import endpoints
|
||||||
import core
|
import core
|
||||||
|
import bills
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('api/photo/', include('core.urls')),
|
path('api/photo/', include('core.urls')),
|
||||||
path('api/admin/', admin.site.urls),
|
path('api/admin/', admin.site.urls),
|
||||||
url('^api/', include(endpoints)),
|
url('^api/', include(endpoints)),
|
||||||
|
# path('api/stats/', include('bills.urls')),
|
||||||
url(r'api/auth/login/', LoginView.as_view(), name='knox_login'),
|
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/logout/', knox_views.LogoutView.as_view(), name='knox_logout'),
|
||||||
url(r'api/auth/logoutall/', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
|
url(r'api/auth/logoutall/', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
|
||||||
|
@ -60,4 +60,3 @@ def upload_bill_debug_text(request):
|
|||||||
products = [{'name': prod, 'price': pri} for _, prod, pri in product_list]
|
products = [{'name': prod, 'price': pri} for _, prod, pri in product_list]
|
||||||
response = JsonResponse({'products': products, 'text': full_text})
|
response = JsonResponse({'products': products, 'text': full_text})
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
184
bk_webapp/package-lock.json
generated
184
bk_webapp/package-lock.json
generated
@ -4277,6 +4277,67 @@
|
|||||||
"type": "^1.0.1"
|
"type": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-array": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-KQ41bAF2BMakf/HdKT865ALd4cgND6VcIztVQZUTt0+BH3RWy6ZYnHghVXf6NFjt2ritLr8H1T8LreAAlfiNcw=="
|
||||||
|
},
|
||||||
|
"d3-color": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg=="
|
||||||
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-mm/nE2Y9HgGyjP+rKIekeITVgBtX97o1nrvHCWX8F/yBYyevUTvu9vb5pUnKwrcSw7o7GuwMOWjS9gFDs4O+uQ=="
|
||||||
|
},
|
||||||
|
"d3-interpolate": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-path": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-huz5byJO/6MPpz6Q8d4lg7GgSpTjIZW/l+1MQkzKfu2u8P6hjaXaStOpmyrD6ymKoW87d2QVFCKvSjLwjzx/rA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "1.2.0 - 2",
|
||||||
|
"d3-format": "1",
|
||||||
|
"d3-interpolate": "^1.2.0",
|
||||||
|
"d3-time": "1",
|
||||||
|
"d3-time-format": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-shape": {
|
||||||
|
"version": "1.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
|
||||||
|
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-path": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
|
||||||
@ -4346,6 +4407,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||||
},
|
},
|
||||||
|
"decimal.js-light": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-b3VJCbd2hwUpeRGG3Toob+CRo8W22xplipNhP3tN7TSVB/cyMX71P1vM2Xjc9H74uV6dS2hDDmo/rHq8L87Upg=="
|
||||||
|
},
|
||||||
"decode-uri-component": {
|
"decode-uri-component": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||||
@ -4593,6 +4659,14 @@
|
|||||||
"utila": "~0.4"
|
"utila": "~0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dom-helpers": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dom-serializer": {
|
"dom-serializer": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
|
||||||
@ -8377,6 +8451,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
},
|
},
|
||||||
|
"lodash-es": {
|
||||||
|
"version": "4.17.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
|
||||||
|
"integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
|
||||||
|
},
|
||||||
"lodash._reinterpolate": {
|
"lodash._reinterpolate": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||||
@ -8507,6 +8586,11 @@
|
|||||||
"object-visit": "^1.0.0"
|
"object-visit": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"math-expression-evaluator": {
|
||||||
|
"version": "1.2.22",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.22.tgz",
|
||||||
|
"integrity": "sha512-L0j0tFVZBQQLeEjmWOvDLoRciIY8gQGWahvkztXUal8jH8R5Rlqo9GCvgqvXcy9LQhEWdQCVvzqAbxgYNt4blQ=="
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
@ -10885,6 +10969,11 @@
|
|||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"raf-schd": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ=="
|
||||||
|
},
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
@ -11114,6 +11203,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||||
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
|
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
|
||||||
},
|
},
|
||||||
|
"react-lifecycles-compat": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
|
},
|
||||||
"react-minimal-pie-chart": {
|
"react-minimal-pie-chart": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-minimal-pie-chart/-/react-minimal-pie-chart-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-minimal-pie-chart/-/react-minimal-pie-chart-6.0.1.tgz",
|
||||||
@ -11136,6 +11230,18 @@
|
|||||||
"warning": "^4.0.2"
|
"warning": "^4.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-resize-detector": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-ZfPMBPxXi0o3xox42MIEtz84tPSVMW9GgwLHYvjVXlFM+OkNzbeEtpVSV+mSTJmk4Znwomolzt35zHN9LNBQMQ==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.17.15",
|
||||||
|
"lodash-es": "^4.17.15",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"raf-schd": "^4.0.2",
|
||||||
|
"resize-observer-polyfill": "^1.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-router": {
|
"react-router": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
|
||||||
@ -11271,6 +11377,28 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-smooth": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-eW057HT0lFgCKh8ilr0y2JaH2YbNcuEdFpxyg7Gf/qDKk9hqGMyXryZJ8iMGJEuKH0+wxS0ccSsBBB3W8yCn8w==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "~4.17.4",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"raf": "^3.4.0",
|
||||||
|
"react-transition-group": "^2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-transition-group": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
|
||||||
|
"requires": {
|
||||||
|
"dom-helpers": "^3.4.0",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||||
@ -11342,6 +11470,32 @@
|
|||||||
"util.promisify": "^1.0.0"
|
"util.promisify": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"recharts": {
|
||||||
|
"version": "2.0.0-beta.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/recharts/-/recharts-2.0.0-beta.1.tgz",
|
||||||
|
"integrity": "sha512-awJH2DE6JRgp5ymzmH5dKh2Pu6prqZJCr3NRaYCcyub1fBa+fIG3ZlpLyl9hWizHPGEvfZLvcjIM+qgTsr9aSQ==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"core-js": "^3.4.2",
|
||||||
|
"d3-interpolate": "^1.3.0",
|
||||||
|
"d3-scale": "^3.1.0",
|
||||||
|
"d3-shape": "^1.3.5",
|
||||||
|
"lodash": "^4.17.5",
|
||||||
|
"prop-types": "^15.6.0",
|
||||||
|
"react-resize-detector": "^4.2.1",
|
||||||
|
"react-smooth": "^1.0.5",
|
||||||
|
"recharts-scale": "^0.4.2",
|
||||||
|
"reduce-css-calc": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recharts-scale": {
|
||||||
|
"version": "0.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.3.tgz",
|
||||||
|
"integrity": "sha512-t8p5sccG9Blm7c1JQK/ak9O8o95WGhNXD7TXg/BW5bYbVlr6eCeRBNpgyigD4p6pSSMehC5nSvBUPj6F68rbFA==",
|
||||||
|
"requires": {
|
||||||
|
"decimal.js-light": "^2.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"recursive-readdir": {
|
"recursive-readdir": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||||
@ -11359,6 +11513,31 @@
|
|||||||
"strip-indent": "^3.0.0"
|
"strip-indent": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reduce-css-calc": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz",
|
||||||
|
"integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=",
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^0.4.2",
|
||||||
|
"math-expression-evaluator": "^1.2.14",
|
||||||
|
"reduce-function-call": "^1.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
|
||||||
|
"integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reduce-function-call": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==",
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
||||||
@ -11593,6 +11772,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||||
},
|
},
|
||||||
|
"resize-observer-polyfill": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.12.2",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-scripts": "3.3.0",
|
"react-scripts": "3.3.0",
|
||||||
"react-semantic-ui-datepickers": "^2.3.0",
|
"react-semantic-ui-datepickers": "^2.3.0",
|
||||||
|
"recharts": "^2.0.0-beta.1",
|
||||||
"semantic-ui-react": "^0.88.2",
|
"semantic-ui-react": "^0.88.2",
|
||||||
"use-global-hook": "^0.1.12"
|
"use-global-hook": "^0.1.12"
|
||||||
},
|
},
|
||||||
|
@ -37,7 +37,7 @@ function Home() {
|
|||||||
icon
|
icon
|
||||||
size="massive"
|
size="massive"
|
||||||
className="home-button-wrapper"
|
className="home-button-wrapper"
|
||||||
onClick={() => history.push("/home/statistics")}
|
onClick={() => history.push("/home/statistics/summary")}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
className="home-button-icon"
|
className="home-button-icon"
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
import { Container, Icon, Menu, Sidebar } from "semantic-ui-react";
|
|
||||||
import { useHistory } from "react-router-dom";
|
|
||||||
import PieChart from "react-minimal-pie-chart";
|
|
||||||
|
|
||||||
import "./Statistics.css";
|
|
||||||
|
|
||||||
function Statistics() {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sidebar.Pushable>
|
|
||||||
<Sidebar
|
|
||||||
as={Menu}
|
|
||||||
animation="overlay"
|
|
||||||
icon="labeled"
|
|
||||||
inverted
|
|
||||||
onHide={() => setVisible(false)}
|
|
||||||
vertical
|
|
||||||
visible={visible}
|
|
||||||
width="thin"
|
|
||||||
>
|
|
||||||
<Menu.Item>Ogólne</Menu.Item>
|
|
||||||
<Menu.Item>Tagi</Menu.Item>
|
|
||||||
<Menu.Item>Produkty</Menu.Item>
|
|
||||||
<Menu.Item>Zakupy</Menu.Item>
|
|
||||||
</Sidebar>
|
|
||||||
|
|
||||||
<Sidebar.Pusher dimmed={visible}>
|
|
||||||
<Menu icon>
|
|
||||||
<Menu.Item onClick={() => history.push("/home")}>
|
|
||||||
<Icon name="arrow left" />
|
|
||||||
</Menu.Item>
|
|
||||||
|
|
||||||
<Menu.Item position="right" onClick={() => setVisible(true)}>
|
|
||||||
<Icon name="sidebar" />
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
<Container>
|
|
||||||
<PieChart
|
|
||||||
animate={true}
|
|
||||||
animationDuration={500}
|
|
||||||
animationEasing="ease-out"
|
|
||||||
cx={50}
|
|
||||||
cy={50}
|
|
||||||
data={[
|
|
||||||
{
|
|
||||||
color: "#E38627",
|
|
||||||
title: "One",
|
|
||||||
value: 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: "#C13C37",
|
|
||||||
title: "Two",
|
|
||||||
value: 15
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: "#6A2135",
|
|
||||||
title: "Three",
|
|
||||||
value: 20
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
label
|
|
||||||
labelPosition={50}
|
|
||||||
labelStyle={{
|
|
||||||
fill: "#121212",
|
|
||||||
fontFamily: "sans-serif",
|
|
||||||
fontSize: "5px"
|
|
||||||
}}
|
|
||||||
lengthAngle={360}
|
|
||||||
lineWidth={100}
|
|
||||||
onClick={undefined}
|
|
||||||
onMouseOut={undefined}
|
|
||||||
onMouseOver={undefined}
|
|
||||||
paddingAngle={0}
|
|
||||||
radius={50}
|
|
||||||
rounded={false}
|
|
||||||
startAngle={0}
|
|
||||||
viewBoxSize={[100, 100]}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
</Sidebar.Pusher>
|
|
||||||
</Sidebar.Pushable>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Statistics;
|
|
74
bk_webapp/src/screens/Statistics/Statistics.jsx
Normal file
74
bk_webapp/src/screens/Statistics/Statistics.jsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Container, Icon, Menu, Sidebar } from "semantic-ui-react";
|
||||||
|
import {
|
||||||
|
Link,
|
||||||
|
Switch,
|
||||||
|
Route,
|
||||||
|
useHistory,
|
||||||
|
useRouteMatch
|
||||||
|
} from "react-router-dom";
|
||||||
|
|
||||||
|
import "./Statistics.css";
|
||||||
|
import { Shops, Products, Summary } from "./subscreens";
|
||||||
|
|
||||||
|
function Statistics() {
|
||||||
|
const history = useHistory();
|
||||||
|
const match = useRouteMatch();
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const handleSidebarItemClick = (event, data) => {
|
||||||
|
history.push(`${match.path}/${data.target}`);
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sidebar.Pushable>
|
||||||
|
<Sidebar
|
||||||
|
as={Menu}
|
||||||
|
animation="overlay"
|
||||||
|
icon="labeled"
|
||||||
|
inverted
|
||||||
|
onHide={() => setVisible(false)}
|
||||||
|
vertical
|
||||||
|
visible={visible}
|
||||||
|
width="thin"
|
||||||
|
>
|
||||||
|
<Menu.Item target="summary" onClick={handleSidebarItemClick}>
|
||||||
|
Ogólne
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item target="products" onClick={handleSidebarItemClick}>
|
||||||
|
Produkty
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item target="shops" onClick={handleSidebarItemClick}>
|
||||||
|
Sklepy
|
||||||
|
</Menu.Item>
|
||||||
|
</Sidebar>
|
||||||
|
|
||||||
|
<Sidebar.Pusher dimmed={visible}>
|
||||||
|
<Menu icon>
|
||||||
|
<Menu.Item onClick={() => history.push("/home")}>
|
||||||
|
<Icon name="arrow left" />
|
||||||
|
</Menu.Item>
|
||||||
|
|
||||||
|
<Menu.Item position="right" onClick={() => setVisible(true)}>
|
||||||
|
<Icon name="sidebar" />
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
<Container>
|
||||||
|
<Switch>
|
||||||
|
<Route path={`${match.path}/summary`}>
|
||||||
|
<Summary />
|
||||||
|
</Route>
|
||||||
|
<Route path={`${match.path}/shops`}>
|
||||||
|
<Shops />
|
||||||
|
</Route>
|
||||||
|
<Route path={`${match.path}/products`}>
|
||||||
|
<Products />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</Container>
|
||||||
|
</Sidebar.Pusher>
|
||||||
|
</Sidebar.Pushable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Statistics;
|
@ -0,0 +1,8 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Container, Icon, Menu, Accordion, Table } from "semantic-ui-react";
|
||||||
|
|
||||||
|
function Products() {
|
||||||
|
return <h1>Produkty</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Products;
|
73
bk_webapp/src/screens/Statistics/subscreens/Shops/Shops.jsx
Normal file
73
bk_webapp/src/screens/Statistics/subscreens/Shops/Shops.jsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Container, Icon, Menu, Accordion, Table } from "semantic-ui-react";
|
||||||
|
import PieChart from "react-minimal-pie-chart";
|
||||||
|
import {
|
||||||
|
LineChart,
|
||||||
|
Line,
|
||||||
|
BarChart,
|
||||||
|
Bar,
|
||||||
|
Brush,
|
||||||
|
Cell,
|
||||||
|
CartesianGrid,
|
||||||
|
ReferenceLine,
|
||||||
|
ReferenceDot,
|
||||||
|
XAxis,
|
||||||
|
YAxis,
|
||||||
|
Tooltip,
|
||||||
|
Legend,
|
||||||
|
ErrorBar,
|
||||||
|
LabelList
|
||||||
|
} from "recharts";
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
color: "#E38627",
|
||||||
|
title: "Biedronka",
|
||||||
|
value: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: "#C13C37",
|
||||||
|
title: "Lidl",
|
||||||
|
value: 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: "#6A2135",
|
||||||
|
title: "Piotr i Paweł",
|
||||||
|
value: 10
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function Shops() {
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<h1>Sklepy</h1>
|
||||||
|
<PieChart
|
||||||
|
animate={true}
|
||||||
|
animationDuration={500}
|
||||||
|
animationEasing="ease-out"
|
||||||
|
cx={50}
|
||||||
|
cy={50}
|
||||||
|
data={data}
|
||||||
|
label={({ data, dataIndex }) => data[dataIndex].title}
|
||||||
|
labelPosition={50}
|
||||||
|
labelStyle={{
|
||||||
|
fill: "#121212",
|
||||||
|
fontFamily: "sans-serif",
|
||||||
|
fontSize: "5px"
|
||||||
|
}}
|
||||||
|
lengthAngle={360}
|
||||||
|
lineWidth={100}
|
||||||
|
onClick={undefined}
|
||||||
|
onMouseOut={undefined}
|
||||||
|
onMouseOver={undefined}
|
||||||
|
paddingAngle={0}
|
||||||
|
radius={50}
|
||||||
|
rounded={false}
|
||||||
|
startAngle={0}
|
||||||
|
viewBoxSize={[100, 100]}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Shops;
|
@ -0,0 +1,69 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Container, Label, List } from "semantic-ui-react";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
import useGlobal from "../../../../utils/global_state";
|
||||||
|
import config from "../../../../config";
|
||||||
|
|
||||||
|
function Summary() {
|
||||||
|
const [summaryData, setSummaryData] = useState([]);
|
||||||
|
const [globalState, setGlobalState] = useGlobal();
|
||||||
|
const [summaryLoading, setSummaryLoading] = useState(true);
|
||||||
|
|
||||||
|
// load data on first render
|
||||||
|
useEffect(() => {
|
||||||
|
setSummaryLoading(true);
|
||||||
|
axios
|
||||||
|
.get(`${config.api_url}/api/stats/`, {
|
||||||
|
headers: { Authorization: `Token ${globalState.auth_token}` }
|
||||||
|
})
|
||||||
|
.then(resp => {
|
||||||
|
processResponse(resp.data);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
setSummaryLoading(false);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const processResponse = data => {};
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<h1>Podsumowanie</h1>
|
||||||
|
<List divided relaxed size="big">
|
||||||
|
<List.Item>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Zapisanych paragonów</List.Header>
|
||||||
|
<List.Description as="a">31</List.Description>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Sklepów</List.Header>
|
||||||
|
<List.Description as="a">3</List.Description>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Zapisanych produktów</List.Header>
|
||||||
|
<List.Description as="a">14</List.Description>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Tagów produktów</List.Header>
|
||||||
|
<List.Description as="a">4</List.Description>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Tagów sklepów</List.Header>
|
||||||
|
<List.Description as="a">2</List.Description>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
</List>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Summary;
|
5
bk_webapp/src/screens/Statistics/subscreens/index.js
Normal file
5
bk_webapp/src/screens/Statistics/subscreens/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import Shops from "./Shops/Shops";
|
||||||
|
import Products from "./Products/Products";
|
||||||
|
import Summary from "./Summary/Summary";
|
||||||
|
|
||||||
|
export { Shops, Products, Summary };
|
Loading…
Reference in New Issue
Block a user