From 156b90a213d85862fd5aa47c3f87918008363ddd Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Tue, 4 Jul 2023 15:06:45 -0600 Subject: [PATCH] Add search to dashboard customer and order lists --- .../templates/dashboard/customer/list.html | 7 ++- dashboard/templates/dashboard/order/list.html | 7 ++- dashboard/views.py | 57 ++++++++++++++++--- static/styles/dashboard.css | 17 +++++- static/styles/main.css | 1 + 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/dashboard/templates/dashboard/customer/list.html b/dashboard/templates/dashboard/customer/list.html index 982cef0..6bc0fde 100644 --- a/dashboard/templates/dashboard/customer/list.html +++ b/dashboard/templates/dashboard/customer/list.html @@ -10,7 +10,12 @@
-

+
+ + {% if query %} + + {% endif %} +
diff --git a/dashboard/templates/dashboard/order/list.html b/dashboard/templates/dashboard/order/list.html index b9bd21d..0ce810b 100644 --- a/dashboard/templates/dashboard/order/list.html +++ b/dashboard/templates/dashboard/order/list.html @@ -10,7 +10,12 @@
-

+
+ + {% if query %} + + {% endif %} +
{% include 'dashboard/order/_table.html' with order_list=order_list %} diff --git a/dashboard/views.py b/dashboard/views.py index a529b8e..fa7d136 100644 --- a/dashboard/views.py +++ b/dashboard/views.py @@ -226,19 +226,28 @@ class OrderListView(LoginRequiredMixin, ListView): paginate_by = 50 def get_queryset(self): - query = self.request.GET.get('status') - if query == 'unfulfilled': - object_list = Order.objects.filter( - Q(status=OrderStatus.UNFULFILLED) | - Q(status=OrderStatus.PARTIALLY_FULFILLED) - ).order_by('-created_at').select_related('customer') + status = self.request.GET.get('status') + query = self.request.GET.get('q') - else: - object_list = Order.objects.order_by( + object_list = Order.objects.order_by( '-created_at' ).select_related('customer') - return object_list + if status == 'unfulfilled': + object_list = object_list.filter( + Q(status=OrderStatus.UNFULFILLED) | + Q(status=OrderStatus.PARTIALLY_FULFILLED) + ) + + if query: + object_list = find_order_by_no_or_customer(object_list, query) + + return object_list.order_by('-created_at').select_related('customer') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["query"] = self.request.GET.get("q") + return context class OrderDetailView(LoginRequiredMixin, DetailView): @@ -641,12 +650,33 @@ def update_sorting(request): return JsonResponse({'message': 'Sorting updated'}) +def find_user_by_name_or_email(qs, query): + for term in query.split(): + qs = qs.filter( + Q(first_name__icontains = term) | Q(last_name__icontains = term) + | Q(email__icontains = term) + ) + return qs + + +def find_order_by_no_or_customer(qs, query): + for term in query.split(): + qs = qs.filter( + Q(pk__icontains = term) + | Q(customer__first_name__icontains = term) + | Q(customer__last_name__icontains = term) + | Q(customer__email__icontains = term) + ) + return qs + + class CustomerListView(LoginRequiredMixin, ListView): model = User template_name = 'dashboard/customer/list.html' paginate_by = 100 def get_queryset(self): + query = self.request.GET.get('q') object_list = User.objects.filter( Exists( Order.objects.filter(customer=OuterRef('pk')) @@ -657,9 +687,18 @@ class CustomerListView(LoginRequiredMixin, ListView): num_orders=Count('orders') ).order_by('first_name', 'last_name') + if query: + object_list = find_user_by_name_or_email(object_list, query) + return object_list + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["query"] = self.request.GET.get("q") + return context + + class CustomerDetailView(LoginRequiredMixin, DetailView): model = User template_name = 'dashboard/customer/detail.html' diff --git a/static/styles/dashboard.css b/static/styles/dashboard.css index fec5183..3b01ffc 100644 --- a/static/styles/dashboard.css +++ b/static/styles/dashboard.css @@ -3,7 +3,7 @@ --color-bg: #eff5f8; --color-bg-alt: #bdc8d2; --color-rgb-bg-alt: 189, 200, 210; - --color-gray: #9d9d9d; + --color-gray: #9d9d9d; --color-yellow: #f8a911; --color-yellow-alt: #f6c463; --color-yellow-highlight: #f9e476; @@ -153,6 +153,7 @@ tfoot th { input[type=text], input[type=email], input[type=number], +input[type=search], input[type=date], input[type=password], select[multiple=multiple], @@ -205,6 +206,10 @@ input[type=radio] { vertical-align: middle; } +input[type=search] { + width: 100%; +} + .btn, input[type=submit], button { @@ -409,6 +414,16 @@ main > article > header { border-bottom: var(--default-border); } +.search-form { + width: 100%; + display: flex; + gap: 1rem; + align-items: center; +} +a button { + white-space: nowrap; +} + @media screen and (max-width: 800px) { .object-header, .panel-header { diff --git a/static/styles/main.css b/static/styles/main.css index 08a05e3..a098f1a 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -159,6 +159,7 @@ input[type=checkbox] { width: 2rem; height: 2rem; vertical-align: middle; + accent-color: var(--yellow-color); } input[type=radio] + label,