update
This commit is contained in:
parent
c94c0e0de4
commit
ffb770bfe2
@ -390,3 +390,100 @@ def bill_item_formset_table(context, item_formset):
|
||||
'total_amount__sum': context['total_amount__sum'],
|
||||
'item_formset': item_formset,
|
||||
}
|
||||
|
||||
|
||||
@register.filter
|
||||
def get_vehicle_image(car_serie):
|
||||
"""
|
||||
Returns the appropriate car image filename based on car series
|
||||
"""
|
||||
if not car_serie:
|
||||
return 'sedan.png'
|
||||
|
||||
serie_lower = car_serie.name.lower()
|
||||
|
||||
# SUV mapping
|
||||
if 'suv' in serie_lower:
|
||||
if 'sport' in serie_lower or '3 doors' in serie_lower:
|
||||
return 'crossover.png'
|
||||
else:
|
||||
return 'suv.png'
|
||||
|
||||
# Pickup mapping
|
||||
elif 'pickup' in serie_lower:
|
||||
if 'cabriolet' in serie_lower:
|
||||
return 'pickup_cabriolet.png'
|
||||
elif 'double' in serie_lower or 'crew' in serie_lower:
|
||||
return 'double_pickup.png'
|
||||
else:
|
||||
return 'single_pickup.png'
|
||||
|
||||
# Van/Minivan mapping
|
||||
elif 'minivan' in serie_lower:
|
||||
return 'minivan.png'
|
||||
elif 'van' in serie_lower:
|
||||
if 'cargo' in serie_lower:
|
||||
return 'van_cargo.png'
|
||||
else:
|
||||
return 'van.png'
|
||||
elif 'compactvan' in serie_lower:
|
||||
return 'van.png'
|
||||
|
||||
# Hatchback mapping
|
||||
elif 'hatchback' in serie_lower:
|
||||
return 'hatchback.png'
|
||||
|
||||
# Wagon mapping
|
||||
elif 'wagon' in serie_lower:
|
||||
return 'van.png' # Closest match
|
||||
|
||||
# Coupe/Sports mapping
|
||||
elif 'cabriolet' in serie_lower:
|
||||
return 'cabriolet.png'
|
||||
elif 'coupe' in serie_lower:
|
||||
return 'coupe.png'
|
||||
elif 'speedster' in serie_lower:
|
||||
return 'sport_car.png'
|
||||
|
||||
# Liftback mapping
|
||||
elif 'liftback' in serie_lower:
|
||||
return 'hatchback.png' # Closest match
|
||||
|
||||
# Sedan mapping (including 2 doors)
|
||||
elif 'sedan' in serie_lower:
|
||||
if '2 doors' in serie_lower:
|
||||
return 'coupe.png'
|
||||
else:
|
||||
return 'sedan.png'
|
||||
|
||||
# Default fallback
|
||||
else:
|
||||
return 'sedan.png'
|
||||
|
||||
|
||||
@register.filter
|
||||
def get_vehicle_type_name(car_serie):
|
||||
"""
|
||||
Returns the vehicle type name for styling purposes
|
||||
"""
|
||||
if not car_serie:
|
||||
return 'sedan'
|
||||
|
||||
serie_lower = car_serie.name.lower()
|
||||
|
||||
if 'suv' in serie_lower:
|
||||
return 'suv'
|
||||
elif 'pickup' in serie_lower:
|
||||
return 'pickup'
|
||||
elif any(word in serie_lower for word in ['van', 'minivan']):
|
||||
return 'van'
|
||||
elif 'hatchback' in serie_lower:
|
||||
return 'hatchback'
|
||||
elif 'wagon' in serie_lower:
|
||||
return 'wagon'
|
||||
elif any(word in serie_lower for word in ['coupe', 'cabriolet', 'speedster']):
|
||||
return 'coupe'
|
||||
elif 'liftback' in serie_lower:
|
||||
return 'liftback'
|
||||
else:
|
||||
return 'sedan'
|
||||
@ -1,6 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n custom_filters humanize %}
|
||||
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
||||
{% load static i18n custom_filters humanize %}
|
||||
{%block title%} {%trans 'Inventory'%} {%endblock%}
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
.htmx-indicator{
|
||||
@ -25,13 +25,21 @@
|
||||
{% block content %}
|
||||
<div class="mb-9">
|
||||
<div id="projectSummary">
|
||||
<!-- Page Header -->
|
||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||
<div class="col-12 col-sm-auto">
|
||||
<h1 class="text-body-emphasis fw-bold fs-2 mb-0">{{ _("Inventory") }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Tabs -->
|
||||
<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-target=".vehicles-container"
|
||||
hx-select=".vehicles-container"
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
@ -39,27 +47,44 @@
|
||||
<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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
<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>
|
||||
<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>
|
||||
@ -74,12 +99,12 @@
|
||||
<input class="form-control search-input search"
|
||||
name='search'
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
placeholder="Search vehicles..."
|
||||
aria-label="Search"
|
||||
hx-get="{% url 'car_list' %}"
|
||||
hx-trigger='keyup changed delay:500ms'
|
||||
hx-target='.table-responsive'
|
||||
hx-select='.table-responsive'
|
||||
hx-target='.vehicles-container'
|
||||
hx-select='.vehicles-container'
|
||||
hx-swap="innerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
hx-on::before-request="on_before_request()"
|
||||
@ -90,7 +115,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center d-none filter">
|
||||
|
||||
<!-- Filter Section -->
|
||||
<div class="d-flex align-items-center d-none filter mb-4">
|
||||
<select hx-get="{% url 'car_list' %}"
|
||||
name="make"
|
||||
hx-target='.model-select'
|
||||
@ -98,7 +125,7 @@
|
||||
hx-swap="outerHTML show:window:top"
|
||||
hx-indicator=".htmx-indicator"
|
||||
class="form-select form-control-sm me-1 make"
|
||||
aria-label="Default select example"
|
||||
aria-label="Select make"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Make") }}</option>
|
||||
@ -112,7 +139,7 @@
|
||||
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"
|
||||
aria-label="Select model"
|
||||
hx-on::before-request="filter_before_request()"
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<option selected="" value="" disabled>{{ _("Model") }}</option>
|
||||
@ -120,14 +147,14 @@
|
||||
</select>
|
||||
<select class="form-select form-control-sm me-1 year"
|
||||
name="year"
|
||||
aria-label="Default select example">
|
||||
aria-label="Select year">
|
||||
<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>
|
||||
aria-label="Select status">
|
||||
<option selected="" value="">{{ _("All Status") }}</option>
|
||||
<option value="available">{{ _("Available") }}</option>
|
||||
<option value="reserved">{{ _("Reserved") }}</option>
|
||||
<option value="sold">{{ _("Sold") }}</option>
|
||||
@ -137,165 +164,261 @@
|
||||
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-target='.vehicles-container'
|
||||
hx-select='.vehicles-container'
|
||||
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>
|
||||
hx-on::after-request="filter_after_request()">
|
||||
<span class="fas fa-search me-1"></span>{{ _("Search") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Vehicles Container -->
|
||||
<div class="row">
|
||||
<div class="table-responsive scrollbar transition">
|
||||
<div class="vehicles-container 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-target=".vehicles-container"
|
||||
hx-select=".vehicles-container"
|
||||
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">{{ _("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 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>
|
||||
|
||||
<!-- Vehicle Cards Grid -->
|
||||
<div class="w-100">
|
||||
{% for car in cars %}
|
||||
<div class="card border mb-3">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<!-- Vehicle Image/Icon -->
|
||||
<div class="col-auto">
|
||||
{% if car.main_image %}
|
||||
<img src="{{ car.main_image.url }}"
|
||||
alt="{{ car.id_car_make.name }} {{ car.id_car_model.name }}"
|
||||
class="rounded border car-image"
|
||||
style="width: 120px; height: 80px; object-fit: cover;">
|
||||
{% else %}
|
||||
<!-- Dynamic Car Image with Color Styling -->
|
||||
<div class="rounded border d-flex align-items-center justify-content-center position-relative overflow-hidden"
|
||||
style="width: 120px; height: 80px;
|
||||
{% if car.colors.exterior.rgb %}
|
||||
background: linear-gradient(135deg, rgba({{ car.colors.exterior.rgb }}, 0.5) 0%, rgba({{ car.colors.exterior.rgb }}, 0.5) 100%);
|
||||
|
||||
|
||||
{% endif %}">
|
||||
|
||||
<!-- Car Image -->
|
||||
<img src="{% static 'images/cars/' %}{{ car.id_car_serie|get_vehicle_image }}"
|
||||
alt="{{ car.id_car_serie|get_vehicle_type_name|title }}"
|
||||
class="car-image"
|
||||
style="width: 100%; height: 100%; object-fit: contain;
|
||||
{% if car.colors.exterior.rgb %}
|
||||
filter: sepia(0.3) saturate(1.5) brightness(1.1);
|
||||
{% endif %}">
|
||||
|
||||
<!-- Vehicle Type Badge -->
|
||||
<span class="badge bg-dark bg-opacity-75 text-white position-absolute bottom-0 start-0 m-1 fs-10">
|
||||
{{ car.id_car_serie|get_vehicle_type_name|title }}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Vehicle Details -->
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<!-- Make/Model/Specs -->
|
||||
<div class="col-md-4">
|
||||
<h5 class="text-body-emphasis fw-bold mb-1">
|
||||
<a href="{% url 'car_detail' car.slug %}"
|
||||
class="text-decoration-none text-body-emphasis">
|
||||
{% if car.id_car_make %}
|
||||
{{ car.id_car_make.get_local_name|default:car.id_car_make.name }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</h5>
|
||||
<p class="text-body mb-1 fw-semibold">
|
||||
{% if car.id_car_model %}
|
||||
{{ car.id_car_model.get_local_name|default:car.id_car_model.name }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<small class="text-body-secondary">
|
||||
{% if car.id_car_trim %}{{ car.id_car_trim }}{% endif %}
|
||||
{% if car.year %} ({{ car.year }}){% endif %}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Color and Date -->
|
||||
<div class="col-md-3">
|
||||
<p class="text-body mb-1">
|
||||
{% if car.colors.exterior %}
|
||||
{{ car.colors.exterior.get_local_name }}
|
||||
{% endif %}
|
||||
</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-11 badge-phoenix-success text-uppercase px-3 py-2">{{ _("Available") }}</span>
|
||||
{% elif car.status == "reserved" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-warning text-uppercase px-3 py-2">{{ _("Reserved") }}</span>
|
||||
{% elif car.status == "sold" %}
|
||||
<span class="badge badge-phoenix fs-11 badge-phoenix-danger text-uppercase px-3 py-2">{{ _("Sold") }}</span>
|
||||
{% elif car.status == "transfer" %}
|
||||
<span class="badge badge-phoenix fs-11 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">
|
||||
{% 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-semibold">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-semibold">NO</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<!-- 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>
|
||||
</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>
|
||||
{% 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>
|
||||
|
||||
<!-- Pagination -->
|
||||
{% if is_paginated %}
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<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 pagination-sm mb-0">
|
||||
{% if page_obj.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">
|
||||
<span class="fas fa-chevron-left"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
{% if page_obj.number == num %}
|
||||
<li class="page-item active">
|
||||
<span class="page-link">{{ num }}</span>
|
||||
</li>
|
||||
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}">
|
||||
<span class="fas fa-chevron-right"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
</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')
|
||||
}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function toggle_filter() {
|
||||
const filter = document.querySelector('.filter');
|
||||
filter.classList.toggle('d-none');
|
||||
|
||||
const icon = document.querySelector('.filter-icon');
|
||||
if (filter.classList.contains('d-none')) {
|
||||
icon.classList.remove('fa-caret-up');
|
||||
icon.classList.add('fa-caret-down');
|
||||
} else {
|
||||
icon.classList.remove('fa-caret-down');
|
||||
icon.classList.add('fa-caret-up');
|
||||
}
|
||||
}
|
||||
|
||||
function on_before_request() {
|
||||
const container = document.querySelector('.vehicles-container');
|
||||
if (container) {
|
||||
container.classList.add('on-before-request');
|
||||
}
|
||||
}
|
||||
|
||||
function on_after_request() {
|
||||
const container = document.querySelector('.vehicles-container');
|
||||
if (container) {
|
||||
container.classList.remove('on-before-request');
|
||||
}
|
||||
}
|
||||
|
||||
function filter_before_request() {
|
||||
on_before_request();
|
||||
}
|
||||
|
||||
function filter_after_request() {
|
||||
on_after_request();
|
||||
}
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user