update
This commit is contained in:
parent
ebd2f06eb6
commit
e1a01ce2d5
@ -1053,7 +1053,7 @@ class CarListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
model = models.Car
|
||||
template_name = "inventory/car_list_view.html"
|
||||
context_object_name = "cars"
|
||||
paginate_by = 30
|
||||
paginate_by = 10
|
||||
permission_required = "inventory.view_car"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
BIN
static/.DS_Store
vendored
BIN
static/.DS_Store
vendored
Binary file not shown.
BIN
static/images/.DS_Store
vendored
BIN
static/images/.DS_Store
vendored
Binary file not shown.
BIN
static/images/car_make/.DS_Store
vendored
BIN
static/images/car_make/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Avatr.png
Normal file
BIN
static/images/car_make/Avatr.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Changfeng.png
Normal file
BIN
static/images/car_make/Changfeng.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Enovate.png
Normal file
BIN
static/images/car_make/Enovate.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/HiPhi.png
Normal file
BIN
static/images/car_make/HiPhi.png
Normal file
Binary file not shown.
BIN
static/images/car_make/Hozon.png
Normal file
BIN
static/images/car_make/Hozon.png
Normal file
Binary file not shown.
BIN
static/images/car_make/Huawei.png
Normal file
BIN
static/images/car_make/Huawei.png
Normal file
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/IM-Motors.png
Normal file
BIN
static/images/car_make/IM-Motors.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Leapmotor.png
Normal file
BIN
static/images/car_make/Leapmotor.png
Normal file
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Lincoln1.png
Normal file
BIN
static/images/car_make/Lincoln1.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/car_make/Xiaomi.png
Normal file
BIN
static/images/car_make/Xiaomi.png
Normal file
Binary file not shown.
BIN
static/images/car_make/Zeekr.png
Normal file
BIN
static/images/car_make/Zeekr.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/cars/.DS_Store
vendored
BIN
static/images/cars/.DS_Store
vendored
Binary file not shown.
BIN
static/images/cars/1FM5K7B86EJA77428.png
Normal file
BIN
static/images/cars/1FM5K7B86EJA77428.png
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
static/images/cars/LJXCU3BB0RTF17235.png
Normal file
BIN
static/images/cars/LJXCU3BB0RTF17235.png
Normal file
Binary file not shown.
BIN
static/images/cars/VF3V1ZKX7RZ002134.png
Normal file
BIN
static/images/cars/VF3V1ZKX7RZ002134.png
Normal file
Binary file not shown.
@ -19,3 +19,6 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,361 +1,349 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static i18n custom_filters humanize %}
|
||||
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
||||
|
||||
{%block title%} {%trans 'Inventory'%} {%endblock%}
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
.htmx-indicator {
|
||||
opacity: 0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.htmx-request .htmx-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
.htmx-request.htmx-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
.on-before-request {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
.transition {
|
||||
transition: all ease-in 1s;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.htmx-indicator{
|
||||
opacity:0;
|
||||
transition: opacity 500ms ease-in;
|
||||
}
|
||||
.htmx-request .htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
.htmx-request.htmx-indicator{
|
||||
opacity:1;
|
||||
}
|
||||
.on-before-request{
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
.transition {
|
||||
transition: all ease-in 1s ;
|
||||
}
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
{% block content %}
|
||||
<div class="mb-9">
|
||||
<div id="projectSummary">
|
||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||
<div class="col-12 col-sm-auto">
|
||||
<ul
|
||||
class="nav nav-links mx-n2"
|
||||
hx-boost="true"
|
||||
hx-push-url="false"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1 active" aria-current="page" href="{% url 'car_list' %}"><span>{{ _("All") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.all }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=available"><span>{{ _("Available") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.available }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=reserved"><span>{{ _("Reserved") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.reserved }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=transfer"><span>{{ _("Transfer") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.transfer }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=sold"><span>{{ _("Sold") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.sold }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button hx-on:click="toggle_filter()" class="btn btn-sm btn-phoenix-primary px-2 py-1">
|
||||
<span><span class="fa fa-filter me-1"></span>{{ _("Filter") }}</span><span class="fas fa-caret-down fs-9 ms-1 filter-icon"></span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="spinner-border mx-3 htmx-indicator" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<div class="search-box me-3">
|
||||
<form class="position-relative">
|
||||
<input
|
||||
class="form-control search-input search"
|
||||
name="search"
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-trigger="keyup changed delay:500ms"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()"
|
||||
/>
|
||||
<span class="fas fa-search search-box-icon"></span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center d-none filter">
|
||||
<select
|
||||
hx-get="{% url 'car_list' %}"
|
||||
name="make"
|
||||
hx-target=".model-select"
|
||||
hx-select=".model-select"
|
||||
hx-swap="outerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
class="form-select form-control-sm me-1 make"
|
||||
aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Make") }}</option>
|
||||
{% for m in make %}
|
||||
<option value="{{ m.pk }}">{{ m.get_local_name|default:m.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-include=".make"
|
||||
name="model"
|
||||
hx-target=".year"
|
||||
hx-select=".year"
|
||||
hx-swap="outerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
class="form-select form-control-sm me-1 model-select"
|
||||
aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Model") }}</option>
|
||||
{% for m in model %}
|
||||
<option value="{{ m.pk }}">{{ m.get_local_name|default:m.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select class="form-select form-control-sm me-1 year" name="year" aria-label="Default select example">
|
||||
<option selected="" value="" disabled>{{ _("Year") }}</option>
|
||||
{% for y in year %}
|
||||
<option value="{{ y.0 }}">{{ y.0 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select class="form-select form-control-sm me-1 car_status" name="car_status" aria-label="Default select example">
|
||||
<option selected="" value="">{{ _("All") }}</option>
|
||||
<option value="available">{{ _("Available") }}</option>
|
||||
<option value="reserved">{{ _("Reserved") }}</option>
|
||||
<option value="sold">{{ _("Sold") }}</option>
|
||||
<option value="transfer">{{ _("Transfer") }}</option>
|
||||
</select>
|
||||
<button
|
||||
id="search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-include=".make,.model,.year,.car_status"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="outerHTML show:window:top"
|
||||
class="btn btn-sm btn-phoenix-primary ms-1"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
{{ _("Search") }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form hx-boost="true" action="{% url 'bulk_update_car_price' %}" method="post" hx-include=".car-checkbox" class="update-price-form d-flex flex-row align-items-center ms-auto w-25 d-none" style="float: right;">
|
||||
{% csrf_token %}
|
||||
<div class="form-floating me-2">
|
||||
<input class="form-control" type="number" placeholder='{{ _("Search") }}' name="price" aria-label="Price" id="price" />
|
||||
<label for="price">{{ _("Price") }}</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-primary" type="submit">{{ _("Search") }}</button>
|
||||
</form>
|
||||
<div class="table-responsive scrollbar transition">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between py-3 pe-0 fs-9">
|
||||
<div
|
||||
class="d-flex"
|
||||
hx-boost="true"
|
||||
hx-push-url="false"
|
||||
hx-include=".make,.model,.year,.car_status"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()"></div>
|
||||
<div class="w-100 list table-responsive" >
|
||||
<div class="form-check">
|
||||
<input class="form-check-input ms-4" type="checkbox" id="select-all" /> <span class="ms-1 text-body-tertiary">{{ _("Select All") }}</span>
|
||||
</div>
|
||||
{% for car in cars %}
|
||||
<div class="card border mb-3 py-0 px-0" id="project-list-table-body">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input car-checkbox" type="checkbox" name="car" value="{{ car.pk }}" id="car-{{car.pk}}" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Vehicle Image/Icon -->
|
||||
<div class="col-auto">
|
||||
<div class="avatar avatar-3xl">
|
||||
<img class="rounded-soft shadow shadow-lg" src="{% static 'images/cars/' %}{{ car.vin }}.png" alt="{{ car.vin }}" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Vehicle Details -->
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<!-- Make/Model/Specs -->
|
||||
<div class="col-md-4">
|
||||
<h5 class="text-body-emphasis fw-bold">{{ car.year }}</h5>
|
||||
<p class="text-body-emphasis fw-bold">
|
||||
<a href="{% url 'car_detail' car.slug %}" class="text-decoration-none text-body-emphasis">
|
||||
{{ car.id_car_make.get_local_name }}
|
||||
</a>
|
||||
<small>{{ car.id_car_model.get_local_name }}</small>
|
||||
</p>
|
||||
<small class="text-body-secondary" dir="ltr">
|
||||
{{ car.id_car_trim }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Color and Date -->
|
||||
<div class="col-md-3">
|
||||
<p class="text-body mb-1">
|
||||
{{ car.colors.exterior.get_local_name }}
|
||||
</p>
|
||||
<small class="text-body-secondary">
|
||||
{{ car.receiving_date|naturalday|capfirst }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Status Badge -->
|
||||
<div class="col-md-3">
|
||||
{% if car.status == "available" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-success text-uppercase px-3 py-2">{{ _("Available") }}</span>
|
||||
{% elif car.status == "reserved" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-warning text-uppercase px-3 py-2">{{ _("Reserved") }}</span>
|
||||
{% elif car.status == "sold" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-danger text-uppercase px-3 py-2">{{ _("Sold") }}</span>
|
||||
{% elif car.status == "transfer" %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-info text-uppercase px-3 py-2">{{ _("Transfer") }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Ready Status -->
|
||||
<div class="col-md-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="fs-10 fw-light me-2">{{ _("Inventory Ready") }}</span>
|
||||
{% if car.ready %}
|
||||
<span class="badge bg-success rounded-circle p-1 me-2">
|
||||
<span class="visually-hidden">Ready</span>
|
||||
</span>
|
||||
<span class="text-success fw-bold">{{ _("Yes") }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger rounded-circle p-1 me-2">
|
||||
<span class="visually-hidden">Not Ready</span>
|
||||
</span>
|
||||
<span class="text-danger fw-bold">{{ _("No") }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action Menu -->
|
||||
<div class="col-auto">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item" href="{% url 'car_detail' car.slug %}"> <span class="fas fa-eye me-2"></span>{{ _("View") }} </a>
|
||||
<a class="dropdown-item" href="{% url 'car_update' car.slug %}"> <span class="fas fa-edit me-2"></span>{{ _("Edit") }} </a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="{% url 'car_delete' car.slug %}"> <span class="fas fa-trash me-2"></span>{{ _("Remove") }} </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-9">
|
||||
<div id="projectSummary">
|
||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||
<div class="col-12 col-sm-auto">
|
||||
<ul class="nav nav-links mx-n2"
|
||||
hx-boost="true"
|
||||
hx-push-url='false'
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1 active"
|
||||
aria-current="page"
|
||||
href="{% url 'car_list' %}"><span>{{ _("All") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.all }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1"
|
||||
href="{% url 'car_list' %}?status=available"><span>{{ _("Available") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.available }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1"
|
||||
href="{% url 'car_list' %}?status=reserved"><span>{{ _("Reserved") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.reserved }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1"
|
||||
href="{% url 'car_list' %}?status=transfer"><span>{{ _("Transfer") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.transfer }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 py-1" href="{% url 'car_list' %}?status=sold"><span>{{ _("Sold") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.sold }})</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button hx-on:click="toggle_filter()"
|
||||
class="btn btn-sm btn-phoenix-primary px-2 py-1">
|
||||
<span><span class="fa fa-filter me-1"></span>{{ _("Filter") }}</span><span class="fas fa-caret-down fs-9 ms-1 filter-icon"></span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-sm-auto">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="spinner-border mx-3 htmx-indicator" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<div class="search-box me-3">
|
||||
<form class="position-relative">
|
||||
<input class="form-control search-input search"
|
||||
name='search'
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-trigger='keyup changed delay:500ms'
|
||||
hx-target='.table-responsive'
|
||||
hx-select='.table-responsive'
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()" />
|
||||
<span class="fas fa-search search-box-icon"></span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="text-center py-5">
|
||||
<div class="text-body-secondary">
|
||||
<span class="fas fa-car fa-4x mb-3 opacity-50"></span>
|
||||
<h4 class="text-body-secondary">{{ _("No vehicles found") }}</h4>
|
||||
<p class="text-body-tertiary">{{ _("Try adjusting your search criteria or filters") }}</p>
|
||||
</div>
|
||||
<div class="d-flex align-items-center d-none filter">
|
||||
<select hx-get="{% url 'car_list' %}"
|
||||
name="make"
|
||||
hx-target='.model-select'
|
||||
hx-select='.model-select'
|
||||
hx-swap="outerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
class="form-select form-control-sm me-1 make"
|
||||
aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Make") }}</option>
|
||||
{% for m in make %}<option value="{{ m.pk }}">{{ m.get_local_name|default:m.name }}</option>{% endfor %}
|
||||
</select>
|
||||
<select hx-get="{% url 'car_list' %}"
|
||||
hx-include=".make"
|
||||
name="model"
|
||||
hx-target='.year'
|
||||
hx-select='.year'
|
||||
hx-swap="outerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
class="form-select form-control-sm me-1 model-select"
|
||||
aria-label="Default select example"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Model") }}</option>
|
||||
{% for m in model %}<option value="{{ m.pk }}">{{ m.get_local_name|default:m.name }}</option>{% endfor %}
|
||||
</select>
|
||||
<select class="form-select form-control-sm me-1 year"
|
||||
name="year"
|
||||
aria-label="Default select example">
|
||||
<option selected="" value="" disabled>{{ _("Year") }}</option>
|
||||
{% for y in year %}<option value="{{ y.0 }}">{{ y.0 }}</option>{% endfor %}
|
||||
</select>
|
||||
<select class="form-select form-control-sm me-1 car_status"
|
||||
name="car_status"
|
||||
aria-label="Default select example">
|
||||
<option selected="" value="">{{ _("All") }}</option>
|
||||
<option value="available">{{ _("Available") }}</option>
|
||||
<option value="reserved">{{ _("Reserved") }}</option>
|
||||
<option value="sold">{{ _("Sold") }}</option>
|
||||
<option value="transfer">{{ _("Transfer") }}</option>
|
||||
</select>
|
||||
<button id="search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-include=".make,.model,.year,.car_status"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-target='.table-responsive'
|
||||
hx-select='.table-responsive'
|
||||
hx-swap="outerHTML show:window:top"
|
||||
class="btn btn-sm btn-phoenix-primary ms-1"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">{{ _("Search") }}</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form hx-boost='true' action="{% url 'bulk_update_car_price' %}" method="post"
|
||||
hx-include=".car-checkbox"
|
||||
class="update-price-form d-flex flex-row align-items-center ms-auto w-25 d-none" style="float:right;">
|
||||
{% csrf_token %}
|
||||
<div class="form-floating me-2">
|
||||
<input class="form-control" type="number" placeholder='{{ _("Search") }}' name="price" aria-label="Price" id="price">
|
||||
<label for="price">{{ _("Price") }}</label>
|
||||
</div>
|
||||
<button class="btn btn-outline-primary" type="submit">{{ _("Search") }}</button>
|
||||
</form>
|
||||
<div class="table-responsive scrollbar transition">
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between py-3 pe-0 fs-9">
|
||||
<div class="d-flex"
|
||||
hx-boost="true"
|
||||
hx-push-url='false'
|
||||
hx-include=".make,.model,.year,.car_status"
|
||||
hx-target=".table-responsive"
|
||||
hx-select=".table-responsive"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
hx-on::after-request="on_after_request()"></div>
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead class="text-body">
|
||||
<tr class="bg-body-highlight">
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="select-all" />
|
||||
</div>
|
||||
</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("VIN") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Make") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Model") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Year") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Trim") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Color") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Date Received") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Status") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col">{{ _("Inventory Ready") }}</th>
|
||||
<th class="sort white-space-nowrap align-middle" scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="project-list-table-body">
|
||||
{% for car in cars %}
|
||||
<tr class="position-static">
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input car-checkbox" type="checkbox" name="car" value="{{ car.pk }}" id="car-{{car.pk}}">
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap ps-1">
|
||||
<a class="fw-bold" href="{% url 'car_detail' car.slug %}">{{ car.vin }}</a>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
{% if car.id_car_make %}
|
||||
<p class="text-body mb-0">{{ car.id_car_make.get_local_name|default:car.id_car_make.name }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
{% if car.id_car_model %}
|
||||
<p class="text-body mb-0">{{ car.id_car_model.get_local_name|default:car.id_car_model.name }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<p class="text-body mb-0">{{ car.year }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<p class="fw-bold text-body mb-0">{{ car.id_car_trim }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<div class="d-flex flex-row align-items-center">
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<span class="color-div"
|
||||
style="background: linear-gradient(90deg, rgba({{ car.colors.exterior.rgb }},1) 10%, rgba({{ car.colors.exterior.rgb }},0.10) 100%)"
|
||||
title="{{ car.colors.exterior.get_local_name }}"></span><span>{{ car.colors.exterior.get_local_name }}</span>
|
||||
</div>
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<span class="color-div"
|
||||
style="background: linear-gradient(90deg, rgba({{ car.colors.interior.rgb }},1) 10%, rgba({{ car.colors.interior.rgb }},0.10) 100%)"
|
||||
title="{{ car.colors.interior.get_local_name }}"></span><span>{{ car.colors.interior.get_local_name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap">
|
||||
<p class="fw-bold text-body mb-0">{{ car.receiving_date|naturalday|capfirst }}</p>
|
||||
</td>
|
||||
<td class="align-middle white-space-nowrap statuses">
|
||||
{% if car.status == "available" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-success">{{ _("Available") }}</span>
|
||||
{% elif car.status == "reserved" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-danger">{{ _("Reserved") }}</span>
|
||||
{% elif car.status == "sold" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-info">{{ _("Sold") }}</span>
|
||||
{% elif car.status == "transfer" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-warning">{{ _("Transfer") }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle product white-space-nowrap">
|
||||
{% if not car.ready %}
|
||||
<span class="text-danger"> {{ _("NO") }} </span>
|
||||
{%else%}
|
||||
<span class="text-success"> {{ _("YES") }} </span>
|
||||
{%endif%}
|
||||
</td>
|
||||
<td class="align-middle text-end white-space-nowrap pe-0 action">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-boundary="window"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
data-bs-reference="parent">
|
||||
<span class="fas fa-ellipsis-h fs-10"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end py-2">
|
||||
<a class="dropdown-item" href="{% url 'car_detail' car.slug %}">{{ _("View") }}</a>
|
||||
<a class="dropdown-item" href="#!">{{ _("Export") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %}
|
||||
{% include 'partials/pagination.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %} {% include 'partials/pagination.html' %} {% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %} {% block customJS %}
|
||||
<script>
|
||||
links = document.querySelectorAll(".nav-link");
|
||||
links.forEach((link) => {
|
||||
link.addEventListener("click", () => {
|
||||
links.forEach((link) => {
|
||||
link.classList.remove("active");
|
||||
{% endblock %}
|
||||
{% block customJS %}
|
||||
<script>
|
||||
links = document.querySelectorAll('.nav-link')
|
||||
links.forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
links.forEach(link => {
|
||||
link.classList.remove('active')
|
||||
})
|
||||
link.classList.add('active')
|
||||
})
|
||||
})
|
||||
function on_before_request() {
|
||||
document.querySelector('.table').classList.toggle('on-before-request')
|
||||
document.querySelector('.model-select').classList.add('on-after-request')
|
||||
}
|
||||
function on_after_request() {
|
||||
document.querySelector('.table').classList.remove('on-before-request')
|
||||
document.querySelector('.model-select').classList.remove('on-after-request')
|
||||
}
|
||||
function toggle_filter(){
|
||||
document.querySelector('.filter').classList.toggle('d-none')
|
||||
document.querySelector('.filter-icon').classList.toggle("fa-caret-down");
|
||||
document.querySelector('.filter-icon').classList.toggle("fa-caret-up");
|
||||
}
|
||||
function filter_before_request(){
|
||||
document.querySelector('.model-select').setAttribute('disabled', true)
|
||||
document.querySelector('.year').setAttribute('disabled', true)
|
||||
document.querySelector('.car_status').setAttribute('disabled', true)
|
||||
}
|
||||
function filter_after_request(){
|
||||
document.querySelector('.model-select').removeAttribute('disabled')
|
||||
document.querySelector('.year').removeAttribute('disabled')
|
||||
document.querySelector('.car_status').removeAttribute('disabled')
|
||||
}
|
||||
|
||||
document.getElementById('select-all').addEventListener('change', function() {
|
||||
const checkboxes = document.querySelectorAll('#project-list-table-body input[type="checkbox"]');
|
||||
if (this.checked) {
|
||||
checkboxes.forEach(checkbox => checkbox.checked = true);
|
||||
} else {
|
||||
checkboxes.forEach(checkbox => checkbox.checked = false);
|
||||
}
|
||||
updateFormVisibility();
|
||||
});
|
||||
link.classList.add("active");
|
||||
});
|
||||
});
|
||||
function on_before_request() {
|
||||
document.querySelector(".table").classList.toggle("on-before-request");
|
||||
document.querySelector(".model-select").classList.add("on-after-request");
|
||||
}
|
||||
function on_after_request() {
|
||||
document.querySelector(".table").classList.remove("on-before-request");
|
||||
document.querySelector(".model-select").classList.remove("on-after-request");
|
||||
}
|
||||
function toggle_filter() {
|
||||
document.querySelector(".filter").classList.toggle("d-none");
|
||||
document.querySelector(".filter-icon").classList.toggle("fa-caret-down");
|
||||
document.querySelector(".filter-icon").classList.toggle("fa-caret-up");
|
||||
}
|
||||
function filter_before_request() {
|
||||
document.querySelector(".model-select").setAttribute("disabled", true);
|
||||
document.querySelector(".year").setAttribute("disabled", true);
|
||||
document.querySelector(".car_status").setAttribute("disabled", true);
|
||||
}
|
||||
function filter_after_request() {
|
||||
document.querySelector(".model-select").removeAttribute("disabled");
|
||||
document.querySelector(".year").removeAttribute("disabled");
|
||||
document.querySelector(".car_status").removeAttribute("disabled");
|
||||
}
|
||||
|
||||
document.getElementById("select-all").addEventListener("change", function () {
|
||||
const checkboxes = document.querySelectorAll('#project-list-table-body input[type="checkbox"]');
|
||||
if (this.checked) {
|
||||
checkboxes.forEach((checkbox) => (checkbox.checked = true));
|
||||
} else {
|
||||
checkboxes.forEach((checkbox) => (checkbox.checked = false));
|
||||
}
|
||||
updateFormVisibility();
|
||||
});
|
||||
const cbox = document.querySelectorAll('.car-checkbox');
|
||||
cbox.forEach(checkbox => {
|
||||
checkbox.addEventListener('change', function() {
|
||||
updateFormVisibility();
|
||||
});
|
||||
});
|
||||
|
||||
const cbox = document.querySelectorAll(".car-checkbox");
|
||||
cbox.forEach((checkbox) => {
|
||||
checkbox.addEventListener("change", function () {
|
||||
updateFormVisibility();
|
||||
});
|
||||
});
|
||||
|
||||
function updateFormVisibility() {
|
||||
const form = document.querySelector(".update-price-form");
|
||||
const checkedCount = document.querySelectorAll(".car-checkbox:checked").length;
|
||||
const submitButton = form.querySelector('button[type="submit"]');
|
||||
if (checkedCount > 0) {
|
||||
form.classList.remove("d-none");
|
||||
submitButton.textContent = `Update Cost Price (${checkedCount})`;
|
||||
} else {
|
||||
form.classList.add("d-none");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
</div>
|
||||
function updateFormVisibility() {
|
||||
const form = document.querySelector('.update-price-form');
|
||||
const checkedCount = document.querySelectorAll('.car-checkbox:checked').length;
|
||||
const submitButton = form.querySelector('button[type="submit"]');
|
||||
if (checkedCount > 0) {
|
||||
form.classList.remove('d-none');
|
||||
submitButton.textContent = `Update Cost Price (${checkedCount})`;
|
||||
} else {
|
||||
form.classList.add('d-none');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
|
||||
@ -1,90 +1,64 @@
|
||||
{% load i18n static %}
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4">
|
||||
<div class="text-body-secondary">
|
||||
{{ _("Showing") }} {{ page_obj.start_index }} {{ _("to") }} {{ page_obj.end_index }}
|
||||
{{ _("of") }} {{ page_obj.paginator.count }} {{ _("results") }}
|
||||
</div>
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination flex items-center justify-center space-x-2 py-4 text-sm">
|
||||
<ul class="pagination mb-0">
|
||||
{# First Page Link #}
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item rounded-md overflow-hidden">
|
||||
<a class="page-link px-3 py-2 border border-gray-300 bg-white text-blue-600 hover:bg-gray-100 transition-colors duration-200" href="?page=1{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'First' %}">
|
||||
<span class="fas fa-angle-double-left" aria-hidden="true"></span>
|
||||
{% if LANGUAGE_CODE == 'ar' %}الأول{% else %}First{% endif %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1{% if q %}&q={{q}}{% endif %}">
|
||||
<span class="fas fa-angle-double-{% if LANGUAGE_CODE == 'ar' %}right{% else %}left{% endif %}"> </span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled rounded-md overflow-hidden">
|
||||
<span class="page-link px-3 py-2 border border-gray-200 bg-gray-50 text-gray-400 cursor-not-allowed">
|
||||
<span class="fas fa-angle-double-left" aria-hidden="true"></span>
|
||||
{% if LANGUAGE_CODE == 'ar' %}الأول{% else %}First{% endif %}
|
||||
<li class="page-item">
|
||||
<span class="page-link">
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}right{% else %}left{% endif %}"> </span>
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{# Previous Page Link #}
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item rounded-md overflow-hidden">
|
||||
<a class="page-link px-3 py-2 border border-gray-300 bg-white text-blue-600 hover:bg-gray-100 transition-colors duration-200" href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'Previous' %}">
|
||||
<span class="fas fa-chevron-left" aria-hidden="true"></span>
|
||||
<span class="">{% trans 'Previous' %}</span>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}">
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}right{% else %}left{% endif %}"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled rounded-md overflow-hidden">
|
||||
<span class="page-link px-3 py-2 border border-gray-200 bg-gray-50 text-gray-400 cursor-not-allowed">
|
||||
<span class="fas fa-chevron-left" aria-hidden="true"></span>
|
||||
<span class="">{% trans 'Previous' %}</span>
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{# Page Numbers #}
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
|
||||
{% if num == 1 or num == page_obj.paginator.num_pages or num >= page_obj.number|add:-2 and num <= page_obj.number|add:2 %}
|
||||
<li class="page-item rounded-md overflow-hidden {% if num == page_obj.number %}bg-blue-600 text-white shadow-md{% else %}bg-white text-blue-600 hover:bg-gray-100{% endif %}">
|
||||
<a class="page-link block px-3 py-2 border {% if num == page_obj.number %}border-blue-600{% else %}border-gray-300{% endif %} transition-colors duration-200"
|
||||
<li class="page-item {% if num == page_obj.number %}active{% endif %}">
|
||||
<a class="page-link" {% if num == page_obj.number %}aria-current="page"{% endif %}
|
||||
href="?page={{ num }}{% if q %}&q={{q}}{% endif %}">
|
||||
{{ num }}
|
||||
</a>
|
||||
</li>
|
||||
{% elif num == page_obj.number|add:-3 or num == page_obj.number|add:3 %}
|
||||
<li class="page-item disabled rounded-md overflow-hidden">
|
||||
<span class="page-link px-3 py-2 border border-gray-300 bg-white text-gray-600 cursor-default">...</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{# Next Page Link #}
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item rounded-md overflow-hidden">
|
||||
<a class="page-link px-3 py-2 border border-gray-300 bg-white text-blue-600 hover:bg-gray-100 transition-colors duration-200" href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'Next' %}">
|
||||
<span class="fas fa-chevron-right" aria-hidden="true"></span>
|
||||
<span class="">{% trans 'Next' %}</span>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}">
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}left{% else %}right{% endif %}"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled rounded-md overflow-hidden">
|
||||
<span class="page-link px-3 py-2 border border-gray-200 bg-gray-50 text-gray-400 cursor-not-allowed">
|
||||
<span class="fas fa-chevron-right" aria-hidden="true"></span>
|
||||
<span class="">{% trans 'Next' %}</span>
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{# Last Page Link #}
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item rounded-md overflow-hidden">
|
||||
<a class="page-link px-3 py-2 border border-gray-300 bg-white text-blue-600 hover:bg-gray-100 transition-colors duration-200" href="?page={{ page_obj.paginator.num_pages }}{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'Last' %}">
|
||||
<span class="fas fa-angle-double-right" aria-hidden="true"></span>
|
||||
{% if LANGUAGE_CODE == 'ar' %}الأخير{% else %}Last{% endif %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if q %}&q={{q}}{% endif %}">
|
||||
<span class="fas fa-angle-double-{% if LANGUAGE_CODE == 'ar' %}left{% else %}right{% endif %}"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled rounded-md overflow-hidden">
|
||||
<span class="page-link px-3 py-2 border border-gray-200 bg-gray-50 text-gray-400 cursor-not-allowed">
|
||||
<span class="fas fa-angle-double-right" aria-hidden="true"></span>
|
||||
{% if LANGUAGE_CODE == 'ar' %}الأخير{% else %}Last{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user