Add search to dashboard customer and order lists
This commit is contained in:
parent
cb6f311d68
commit
156b90a213
@ -10,7 +10,12 @@
|
|||||||
</header>
|
</header>
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<header class="panel-header">
|
<header class="panel-header">
|
||||||
<h4></h4>
|
<form class="search-form">
|
||||||
|
<input type="search" placeholder="Search customers by name or email" name="q" {% if query %}value="{{query}}"{% endif %}>
|
||||||
|
{% if query %}
|
||||||
|
<a href="{% url 'dashboard:customer-list' %}"><button type="button">Clear search</button></a>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
</header>
|
</header>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@ -10,7 +10,12 @@
|
|||||||
</header>
|
</header>
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<header class="panel-header">
|
<header class="panel-header">
|
||||||
<h3></h3>
|
<form class="search-form">
|
||||||
|
<input type="search" placeholder="Search orders by no. or customer" name="q" {% if query %}value="{{query}}"{% endif %}>
|
||||||
|
{% if query %}
|
||||||
|
<a href="{% url 'dashboard:order-list' %}"><button type="button">Clear search</button></a>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
</header>
|
</header>
|
||||||
<table>
|
<table>
|
||||||
{% include 'dashboard/order/_table.html' with order_list=order_list %}
|
{% include 'dashboard/order/_table.html' with order_list=order_list %}
|
||||||
|
|||||||
@ -226,19 +226,28 @@ class OrderListView(LoginRequiredMixin, ListView):
|
|||||||
paginate_by = 50
|
paginate_by = 50
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
query = self.request.GET.get('status')
|
status = self.request.GET.get('status')
|
||||||
if query == 'unfulfilled':
|
query = self.request.GET.get('q')
|
||||||
object_list = Order.objects.filter(
|
|
||||||
Q(status=OrderStatus.UNFULFILLED) |
|
|
||||||
Q(status=OrderStatus.PARTIALLY_FULFILLED)
|
|
||||||
).order_by('-created_at').select_related('customer')
|
|
||||||
|
|
||||||
else:
|
object_list = Order.objects.order_by(
|
||||||
object_list = Order.objects.order_by(
|
|
||||||
'-created_at'
|
'-created_at'
|
||||||
).select_related('customer')
|
).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):
|
class OrderDetailView(LoginRequiredMixin, DetailView):
|
||||||
@ -641,12 +650,33 @@ def update_sorting(request):
|
|||||||
return JsonResponse({'message': 'Sorting updated'})
|
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):
|
class CustomerListView(LoginRequiredMixin, ListView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'dashboard/customer/list.html'
|
template_name = 'dashboard/customer/list.html'
|
||||||
paginate_by = 100
|
paginate_by = 100
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
query = self.request.GET.get('q')
|
||||||
object_list = User.objects.filter(
|
object_list = User.objects.filter(
|
||||||
Exists(
|
Exists(
|
||||||
Order.objects.filter(customer=OuterRef('pk'))
|
Order.objects.filter(customer=OuterRef('pk'))
|
||||||
@ -657,9 +687,18 @@ class CustomerListView(LoginRequiredMixin, ListView):
|
|||||||
num_orders=Count('orders')
|
num_orders=Count('orders')
|
||||||
).order_by('first_name', 'last_name')
|
).order_by('first_name', 'last_name')
|
||||||
|
|
||||||
|
if query:
|
||||||
|
object_list = find_user_by_name_or_email(object_list, query)
|
||||||
|
|
||||||
return object_list
|
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):
|
class CustomerDetailView(LoginRequiredMixin, DetailView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'dashboard/customer/detail.html'
|
template_name = 'dashboard/customer/detail.html'
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
--color-bg: #eff5f8;
|
--color-bg: #eff5f8;
|
||||||
--color-bg-alt: #bdc8d2;
|
--color-bg-alt: #bdc8d2;
|
||||||
--color-rgb-bg-alt: 189, 200, 210;
|
--color-rgb-bg-alt: 189, 200, 210;
|
||||||
--color-gray: #9d9d9d;
|
--color-gray: #9d9d9d;
|
||||||
--color-yellow: #f8a911;
|
--color-yellow: #f8a911;
|
||||||
--color-yellow-alt: #f6c463;
|
--color-yellow-alt: #f6c463;
|
||||||
--color-yellow-highlight: #f9e476;
|
--color-yellow-highlight: #f9e476;
|
||||||
@ -153,6 +153,7 @@ tfoot th {
|
|||||||
input[type=text],
|
input[type=text],
|
||||||
input[type=email],
|
input[type=email],
|
||||||
input[type=number],
|
input[type=number],
|
||||||
|
input[type=search],
|
||||||
input[type=date],
|
input[type=date],
|
||||||
input[type=password],
|
input[type=password],
|
||||||
select[multiple=multiple],
|
select[multiple=multiple],
|
||||||
@ -205,6 +206,10 @@ input[type=radio] {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=search] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.btn,
|
.btn,
|
||||||
input[type=submit],
|
input[type=submit],
|
||||||
button {
|
button {
|
||||||
@ -409,6 +414,16 @@ main > article > header {
|
|||||||
border-bottom: var(--default-border);
|
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) {
|
@media screen and (max-width: 800px) {
|
||||||
.object-header,
|
.object-header,
|
||||||
.panel-header {
|
.panel-header {
|
||||||
|
|||||||
@ -159,6 +159,7 @@ input[type=checkbox] {
|
|||||||
width: 2rem;
|
width: 2rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
accent-color: var(--yellow-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=radio] + label,
|
input[type=radio] + label,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user