update car list cards
BIN
static/.DS_Store
vendored
BIN
static/images/.DS_Store
vendored
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
BIN
static/images/cars/.DS_Store
vendored
BIN
static/images/cars/1g6a85sx8k0144230.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1003 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 987 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
@ -1,352 +1,361 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load static i18n custom_filters humanize %}
|
{% load static i18n custom_filters humanize %}
|
||||||
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
.htmx-indicator{
|
.htmx-indicator {
|
||||||
opacity:0;
|
opacity: 0;
|
||||||
transition: opacity 500ms ease-in;
|
transition: opacity 500ms ease-in;
|
||||||
}
|
}
|
||||||
.htmx-request .htmx-indicator{
|
.htmx-request .htmx-indicator {
|
||||||
opacity:1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.htmx-request.htmx-indicator{
|
.htmx-request.htmx-indicator {
|
||||||
opacity:1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
.on-before-request{
|
.on-before-request {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.transition {
|
.transition {
|
||||||
transition: all ease-in 1s ;
|
transition: all ease-in 1s;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock customCSS %}
|
{% endblock customCSS %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mb-9">
|
<div class="mb-9">
|
||||||
<div id="projectSummary">
|
<div id="projectSummary">
|
||||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||||
<div class="col-12 col-sm-auto">
|
<div class="col-12 col-sm-auto">
|
||||||
<ul class="nav nav-links mx-n2"
|
<ul
|
||||||
hx-boost="true"
|
class="nav nav-links mx-n2"
|
||||||
hx-push-url='false'
|
hx-boost="true"
|
||||||
hx-target=".table-responsive"
|
hx-push-url="false"
|
||||||
hx-select=".table-responsive"
|
hx-target=".table-responsive"
|
||||||
hx-swap="innerHTML show:window:top"
|
hx-select=".table-responsive"
|
||||||
hx-indicator=".htmx-indicator"
|
hx-swap="innerHTML show:window:top"
|
||||||
hx-on::before-request="on_before_request()"
|
hx-indicator=".htmx-indicator"
|
||||||
hx-on::after-request="on_after_request()">
|
hx-on::before-request="on_before_request()"
|
||||||
<li class="nav-item">
|
hx-on::after-request="on_after_request()">
|
||||||
<a class="nav-link px-2 py-1 active"
|
<li class="nav-item">
|
||||||
aria-current="page"
|
<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>
|
||||||
href="{% url 'car_list' %}"><span>{{ _("All") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.all }})</span></a>
|
</li>
|
||||||
</li>
|
<li class="nav-item">
|
||||||
<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>
|
||||||
<a class="nav-link px-2 py-1"
|
</li>
|
||||||
href="{% url 'car_list' %}?status=available"><span>{{ _("Available") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.available }})</span></a>
|
<li class="nav-item">
|
||||||
</li>
|
<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 class="nav-item">
|
</li>
|
||||||
<a class="nav-link px-2 py-1"
|
<li class="nav-item">
|
||||||
href="{% url 'car_list' %}?status=reserved"><span>{{ _("Reserved") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.reserved }})</span></a>
|
<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>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link px-2 py-1"
|
<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>
|
||||||
href="{% url 'car_list' %}?status=transfer"><span>{{ _("Transfer") }}</span><span class="text-body-tertiary fw-semibold">({{ stats.transfer }})</span></a>
|
</li>
|
||||||
</li>
|
<li class="nav-item">
|
||||||
<li class="nav-item">
|
<button hx-on:click="toggle_filter()" class="btn btn-sm btn-phoenix-primary px-2 py-1">
|
||||||
<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>
|
<span><span class="fa fa-filter me-1"></span>{{ _("Filter") }}</span><span class="fas fa-caret-down fs-9 ms-1 filter-icon"></span>
|
||||||
</li>
|
</button>
|
||||||
<li class="nav-item">
|
</li>
|
||||||
<button hx-on:click="toggle_filter()"
|
</ul>
|
||||||
class="btn btn-sm btn-phoenix-primary px-2 py-1">
|
</div>
|
||||||
<span><span class="fa fa-filter me-1"></span>{{ _("Filter") }}</span><span class="fas fa-caret-down fs-9 ms-1 filter-icon"></span>
|
<div class="col-12 col-sm-auto">
|
||||||
</button>
|
<div class="d-flex align-items-center">
|
||||||
</li>
|
<div class="spinner-border mx-3 htmx-indicator" role="status">
|
||||||
</ul>
|
<span class="visually-hidden">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-auto">
|
<div class="search-box me-3">
|
||||||
<div class="d-flex align-items-center">
|
<form class="position-relative">
|
||||||
<div class="spinner-border mx-3 htmx-indicator" role="status">
|
<input
|
||||||
<span class="visually-hidden">Loading...</span>
|
class="form-control search-input search"
|
||||||
</div>
|
name="search"
|
||||||
<div class="search-box me-3">
|
type="search"
|
||||||
<form class="position-relative">
|
placeholder="Search"
|
||||||
<input class="form-control search-input search"
|
aria-label="Search"
|
||||||
name='search'
|
hx-get="{% url 'car_list' %}"
|
||||||
type="search"
|
hx-trigger="keyup changed delay:500ms"
|
||||||
placeholder="Search"
|
hx-target=".table-responsive"
|
||||||
aria-label="Search"
|
hx-select=".table-responsive"
|
||||||
hx-get="{% url 'car_list' %}"
|
hx-swap="innerHTML show:window:top"
|
||||||
hx-trigger='keyup changed delay:500ms'
|
hx-indicator=".htmx-indicator"
|
||||||
hx-target='.table-responsive'
|
hx-on::before-request="on_before_request()"
|
||||||
hx-select='.table-responsive'
|
hx-on::after-request="on_after_request()"
|
||||||
hx-swap="innerHTML show:window:top"
|
/>
|
||||||
hx-indicator=".htmx-indicator"
|
<span class="fas fa-search search-box-icon"></span>
|
||||||
hx-on::before-request="on_before_request()"
|
</form>
|
||||||
hx-on::after-request="on_after_request()" />
|
</div>
|
||||||
<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>
|
|
||||||
<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">
|
|
||||||
<div class="avatar avatar-2xl avatar-bordered me-4">
|
|
||||||
<img class="rounded-circle" src="{% static 'images/cars/'%}{{ car.vin }}.png" alt="{{ car.vin }}" width="50" height="50">
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
</div>
|
||||||
{% block customJS %}
|
</div>
|
||||||
<script>
|
<div class="d-flex align-items-center d-none filter">
|
||||||
links = document.querySelectorAll('.nav-link')
|
<select
|
||||||
links.forEach(link => {
|
hx-get="{% url 'car_list' %}"
|
||||||
link.addEventListener('click', () => {
|
name="make"
|
||||||
links.forEach(link => {
|
hx-target=".model-select"
|
||||||
link.classList.remove('active')
|
hx-select=".model-select"
|
||||||
})
|
hx-swap="outerHTML show:window:top"
|
||||||
link.classList.add('active')
|
hx-indicator=".htmx-indicator"
|
||||||
})
|
class="form-select form-control-sm me-1 make"
|
||||||
})
|
aria-label="Default select example"
|
||||||
function on_before_request() {
|
hx-on::before-request="filter_before_request()"
|
||||||
document.querySelector('.table').classList.toggle('on-before-request')
|
hx-on::after-request="filter_after_request()">
|
||||||
document.querySelector('.model-select').classList.add('on-after-request')
|
<option selected="" value="" disabled>{{ _("Make") }}</option>
|
||||||
}
|
{% for m in make %}
|
||||||
function on_after_request() {
|
<option value="{{ m.pk }}">{{ m.get_local_name|default:m.name }}</option>
|
||||||
document.querySelector('.table').classList.remove('on-before-request')
|
{% endfor %}
|
||||||
document.querySelector('.model-select').classList.remove('on-after-request')
|
</select>
|
||||||
}
|
<select
|
||||||
function toggle_filter(){
|
hx-get="{% url 'car_list' %}"
|
||||||
document.querySelector('.filter').classList.toggle('d-none')
|
hx-include=".make"
|
||||||
document.querySelector('.filter-icon').classList.toggle("fa-caret-down");
|
name="model"
|
||||||
document.querySelector('.filter-icon').classList.toggle("fa-caret-up");
|
hx-target=".year"
|
||||||
}
|
hx-select=".year"
|
||||||
function filter_before_request(){
|
hx-swap="outerHTML show:window:top"
|
||||||
document.querySelector('.model-select').setAttribute('disabled', true)
|
hx-indicator=".htmx-indicator"
|
||||||
document.querySelector('.year').setAttribute('disabled', true)
|
class="form-select form-control-sm me-1 model-select"
|
||||||
document.querySelector('.car_status').setAttribute('disabled', true)
|
aria-label="Default select example"
|
||||||
}
|
hx-on::before-request="filter_before_request()"
|
||||||
function filter_after_request(){
|
hx-on::after-request="filter_after_request()">
|
||||||
document.querySelector('.model-select').removeAttribute('disabled')
|
<option selected="" value="" disabled>{{ _("Model") }}</option>
|
||||||
document.querySelector('.year').removeAttribute('disabled')
|
{% for m in model %}
|
||||||
document.querySelector('.car_status').removeAttribute('disabled')
|
<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>
|
||||||
|
|
||||||
document.getElementById('select-all').addEventListener('change', function() {
|
<!-- Color and Date -->
|
||||||
const checkboxes = document.querySelectorAll('#project-list-table-body input[type="checkbox"]');
|
<div class="col-md-3">
|
||||||
if (this.checked) {
|
<p class="text-body mb-1">
|
||||||
checkboxes.forEach(checkbox => checkbox.checked = true);
|
{{ car.colors.exterior.get_local_name }}
|
||||||
} else {
|
</p>
|
||||||
checkboxes.forEach(checkbox => checkbox.checked = false);
|
<small class="text-body-secondary">
|
||||||
}
|
{{ car.receiving_date|naturalday|capfirst }}
|
||||||
updateFormVisibility();
|
</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>
|
||||||
|
</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>
|
||||||
|
{% 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");
|
||||||
});
|
});
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
const cbox = document.querySelectorAll('.car-checkbox');
|
document.getElementById("select-all").addEventListener("change", function () {
|
||||||
cbox.forEach(checkbox => {
|
const checkboxes = document.querySelectorAll('#project-list-table-body input[type="checkbox"]');
|
||||||
checkbox.addEventListener('change', function() {
|
if (this.checked) {
|
||||||
updateFormVisibility();
|
checkboxes.forEach((checkbox) => (checkbox.checked = true));
|
||||||
});
|
} else {
|
||||||
});
|
checkboxes.forEach((checkbox) => (checkbox.checked = false));
|
||||||
|
}
|
||||||
|
updateFormVisibility();
|
||||||
|
});
|
||||||
|
|
||||||
function updateFormVisibility() {
|
const cbox = document.querySelectorAll(".car-checkbox");
|
||||||
const form = document.querySelector('.update-price-form');
|
cbox.forEach((checkbox) => {
|
||||||
const checkedCount = document.querySelectorAll('.car-checkbox:checked').length;
|
checkbox.addEventListener("change", function () {
|
||||||
const submitButton = form.querySelector('button[type="submit"]');
|
updateFormVisibility();
|
||||||
if (checkedCount > 0) {
|
});
|
||||||
form.classList.remove('d-none');
|
});
|
||||||
submitButton.textContent = `Update Cost Price (${checkedCount})`;
|
|
||||||
} else {
|
function updateFormVisibility() {
|
||||||
form.classList.add('d-none');
|
const form = document.querySelector(".update-price-form");
|
||||||
}
|
const checkedCount = document.querySelectorAll(".car-checkbox:checked").length;
|
||||||
}
|
const submitButton = form.querySelector('button[type="submit"]');
|
||||||
</script>
|
if (checkedCount > 0) {
|
||||||
{% endblock customJS %}
|
form.classList.remove("d-none");
|
||||||
|
submitButton.textContent = `Update Cost Price (${checkedCount})`;
|
||||||
|
} else {
|
||||||
|
form.classList.add("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock customJS %}
|
||||||
|
</div>
|
||||||
|
|||||||