437 lines
17 KiB
HTML
437 lines
17 KiB
HTML
{% extends 'base.html' %}
|
|
{% load i18n static custom_filters %}
|
|
{% block title %}{{ _("Car Details") }}{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
|
|
|
|
<!-- Main Container -->
|
|
<div class="container-fluid">
|
|
<div class="row g-3 justify-content-between">
|
|
<div class="col-lg-12 col-xl-6">
|
|
<div class="card rounded shadow d-flex align-content-center">
|
|
<p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p>
|
|
<div class="card-body">
|
|
<div class="table-responsive scrollbar mb-3">
|
|
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
|
<tr>
|
|
<th>{% trans "VIN" %}</th>
|
|
<td>{{ car.vin }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "year"|capfirst %}</th>
|
|
<td>{{ car.year }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "make"|capfirst %}</th>
|
|
<td>{{ car.id_car_make.get_local_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "model"|capfirst %}</th>
|
|
<td>{{ car.id_car_model.get_local_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "series"|capfirst %}</th>
|
|
<td>{{ car.id_car_serie.name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "trim"|capfirst %}</th>
|
|
<td>{{ car.id_car_trim.name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Status"|capfirst %}</th>
|
|
<td>{{ car.get_status_display }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Stock Type"|capfirst %}</th>
|
|
<td>{{ car.get_stock_type_display }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Mileage"|capfirst %}</th>
|
|
<td>{{ car.mileage }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Receiving Date"|capfirst %}</th>
|
|
<td>{{ car.receiving_date|timesince }}</td>
|
|
</tr>
|
|
{% if car.vendor %}
|
|
<tr>
|
|
<th>{% trans "Vendor"|capfirst %}</th>
|
|
<td>{{ car.vendor.get_local_name }}</td>
|
|
</tr>
|
|
{% endif %}
|
|
<tr>
|
|
<th>{% trans "Remarks"|capfirst %}</th>
|
|
<td>{{ car.remarks }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans 'specifications'|capfirst %}</th>
|
|
<td>
|
|
<button type="button" class="btn btn-phoenix-primary btn-sm" id="specification-btn" data-bs-toggle="modal" data-bs-target="#specificationsModal">
|
|
{% trans 'view'|capfirst %}
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% if car.custom_cards %}
|
|
<tr>
|
|
<th>{% trans "Custom Number"|capfirst %}</th>
|
|
<td>{{ car.custom_cards.custom_number }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Custom Date"|capfirst %}</th>
|
|
<td>{{ car.custom_cards.custom_date|date }}</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<th>{% trans "Custom Card" %}</th>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-phoenix-success" data-bs-toggle="modal" data-bs-target="#customCardModal">
|
|
{% trans 'Add' %}
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
<tr>
|
|
<th>{% trans 'Location'|capfirst %}</th>
|
|
<td>
|
|
{% if car.location %} {% if car.location.is_owner_showroom %} {% trans 'Our Showroom' %} {% else %} {{ car.location.showroom.get_local_name }} {% endif %}
|
|
<a href="{% url 'transfer' car.location.pk %}" class="btn btn-phoenix-danger btn-sm">
|
|
{% trans "transfer"|capfirst %}
|
|
</a>
|
|
{% else %} {% trans "No location available." %}
|
|
<a href="{% url 'add_car_location' car.pk %}" class="btn btn-phoenix-success btn-sm ms-2">
|
|
{% trans "Add" %}
|
|
</a>
|
|
</td>
|
|
{% endif %}
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div>
|
|
<a href="{% url 'car_update' car.pk %}" class="btn btn-phoenix-warning btn-sm mt-1">{% trans "Edit" %}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 col-xl-6">
|
|
<div class="card rounded shadow d-flex align-content-center">
|
|
<p class="card-header rounded-top fw-bold">{% trans 'Financial Details' %}</p>
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive scrollbar mb-3">
|
|
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
|
{% if car.finances %}
|
|
<tr>
|
|
<th>{% trans "Cost Price"|capfirst %}</th>
|
|
<td>{{ car.finances.cost_price }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Selling Price"|capfirst %}</th>
|
|
<td>{{ car.finances.selling_price }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Discount Amount"|capfirst %}</th>
|
|
<td>{{ car.finances.discount_amount }} -</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Additional Fee"|capfirst %}</th>
|
|
<td></td>
|
|
</tr>
|
|
{% if car.finances.additional_services.first.pk %}
|
|
{% for service in car.finances.additional_services.all %}
|
|
<tr>
|
|
<td>{{service.name}}</td>
|
|
<td>{{ service.default_amount }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% endif %}
|
|
<tr>
|
|
<th>{% trans "VAT Amount"|capfirst %}</th>
|
|
<td>{{ car.finances.vat_amount }}</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans "Total"|capfirst %}</th>
|
|
<td>{{ car.finances.total_vat }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<a href="{% url 'car_finance_update' car.finances.pk %}" class="btn btn-phoenix-warning btn-sm mb-3">
|
|
{% trans "Edit" %}
|
|
</a>
|
|
{% else %}
|
|
<p>{% trans "No finance details available." %}</p>
|
|
<a href="{% url 'car_finance_create' car.pk %}" class="btn btn-phoenix-success btn-sm mb-3">
|
|
{% trans "Add" %}
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card rounded shadow d-flex align-content-center mt-3">
|
|
<p class="card-header rounded-top fw-bold">{% trans 'Colors Details' %}</p>
|
|
<div class="card-body">
|
|
<div class="table-responsive scrollbar mb-3">
|
|
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
|
{% if car.colors.exists %}
|
|
{% for color in car.colors.all %}
|
|
<tr>
|
|
<th>{% trans 'Exterior' %}</th>
|
|
<td>
|
|
<span>{{ color.exterior.get_local_name }}</span>
|
|
</td>
|
|
<td class="align-middle">
|
|
<div class="text-end color-div" style="background-color: rgb({{ color.exterior.rgb }});"></div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th>{% trans 'Interior' %}</th>
|
|
<td>
|
|
<span>{{ color.interior.get_local_name }}</span>
|
|
</td>
|
|
<td class="align-middle">
|
|
<div class="text-end color-div" style="background-color: rgb({{ color.interior.rgb }});"></div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="2">
|
|
{% trans "No colors available for this car." %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<a href="{% url 'add_color' car.pk %}" class="btn btn-phoenix-success btn-sm">
|
|
{% trans "Add" %}
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card rounded shadow d-flex align-content-center mt-3">
|
|
<p class="card-header rounded-top fw-bold">{% trans 'Reservations Details' %}</p>
|
|
<div class="card-body">
|
|
<div class="table-responsive scrollbar mb-3">
|
|
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
|
{% if car.is_reserved %}
|
|
<thead>
|
|
<tr>
|
|
<th>{% trans "Reserved By" %}</th>
|
|
<th>{% trans "Expires At" %}</th>
|
|
<th>{% trans 'Actions' %}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for reservation in car.reservations.all %}
|
|
<tr>
|
|
<td>{{ reservation.reserved_by.dealer }}</td>
|
|
<td>{{ reservation.reserved_until }}</td>
|
|
<td>
|
|
{% if reservation.is_active %}
|
|
<form method="post" action="{% url 'reservations' reservation.id %}">
|
|
{% csrf_token %}
|
|
<button type="submit" name="action" value="renew" class="btn btn-sm btn-phoenix-success">
|
|
{% trans "Renew" %}
|
|
</button>
|
|
<button type="submit" name="action" value="cancel" class="btn btn-sm btn-phoenix-secondary">
|
|
{% trans "Cancel" %}
|
|
</button>
|
|
</form>
|
|
{% else %}
|
|
<span class="badge bg-danger" style="width: 120px;">
|
|
{% trans "Expired" %}
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %} {% else %}
|
|
<tr>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-phoenix-success" data-bs-toggle="modal" data-bs-target="#reserveModal">
|
|
{% trans 'Reserve' %}
|
|
</button>
|
|
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
{% endif %}
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Custom Card Modal -->
|
|
<div class="modal fade" id="customCardModal" tabindex="-1" aria-labelledby="customCardModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-sm">
|
|
<div class="modal-content">
|
|
<div class="modal-header bg-primary">
|
|
<h5 class="modal-title text-light" id="customCardModalLabel">{% trans 'Custom Card' %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<!-- Content will be loaded here via AJAX -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Reservation Modal -->
|
|
<div class="modal fade" id="reserveModal" tabindex="-1" aria-labelledby="reserveModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-sm">
|
|
<div class="modal-content">
|
|
<div class="modal-header bg-primary">
|
|
<h5 class="modal-title text-light" id="reserveModalLabel">{% trans 'Car Reservation' %}</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
{% trans 'Are you sure you want to reserve this car?' %}
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-sm btn-phoenix-danger" data-bs-dismiss="modal">
|
|
{% trans 'No' %}
|
|
</button>
|
|
<form method="POST" action="{% url 'reserve_car' car.id %}" class="d-inline">
|
|
{% csrf_token %}
|
|
<button type="submit" class="btn btn-phoenix-success btn-sm">{% trans "Yes" %}</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Specification Modal -->
|
|
<div class="modal fade" id="specificationsModal" tabindex="-1" aria-labelledby="specificationsModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="specificationsModalLabel">{% trans 'specifications'|upper %}</h5>
|
|
<button class="btn btn-close p-1" type="button" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="specificationsContent"></div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-phoenix-primary" type="button" data-bs-dismiss="modal">{% trans 'Close' %}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
function getCookie(name) {
|
|
let cookieValue = null;
|
|
if (document.cookie && document.cookie !== "") {
|
|
const cookies = document.cookie.split(";");
|
|
for (let cookie of cookies) {
|
|
cookie = cookie.trim();
|
|
if (cookie.substring(0, name.length + 1) === name + "=") {
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cookieValue;
|
|
}
|
|
|
|
const csrfToken = getCookie("csrftoken");
|
|
const ajaxUrl = "{% url 'ajax_handler' %}";
|
|
|
|
const modal = document.getElementById("customCardModal");
|
|
const modalBody = modal.querySelector(".modal-body");
|
|
|
|
// When the modal is triggered, load the form
|
|
modal.addEventListener("show.bs.modal", function () {
|
|
const url = "{% url 'add_custom_card' car.pk %}";
|
|
|
|
fetch(url)
|
|
.then((response) => response.text())
|
|
.then((html) => {
|
|
modalBody.innerHTML = html;
|
|
})
|
|
.catch((error) => {
|
|
modalBody.innerHTML = '<p class="text-danger">Error loading form. Please try again later.</p>';
|
|
console.error("Error loading form:", error);
|
|
});
|
|
});
|
|
|
|
modal.addEventListener("hidden.bs.modal", function () {
|
|
modalBody.innerHTML = "";
|
|
});
|
|
|
|
const showSpecificationButton = document.getElementById("specification-btn");
|
|
const specificationsContent = document.getElementById("specificationsContent");
|
|
|
|
showSpecificationButton.addEventListener("click", function () {
|
|
specificationsContent.innerHTML = "";
|
|
fetch(`${ajaxUrl}?action=get_specifications&trim_id={{ car.id_car_trim.id_car_trim }}`, {
|
|
headers: {
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
"X-CSRFToken": csrfToken,
|
|
},
|
|
})
|
|
.then((response) => response.json())
|
|
.then((data) => {
|
|
if (data.length > 0) {
|
|
data.forEach(function (parent) {
|
|
const parentSpec = document.createElement("div");
|
|
parentSpec.classList.add("mb-2");
|
|
parentSpec.innerHTML = `<strong>${parent.parent_name}</strong>`;
|
|
|
|
parent.specifications.forEach(function (specification) {
|
|
const specificationDiv = document.createElement("div");
|
|
specificationDiv.classList.add("ms-3");
|
|
specificationDiv.innerHTML = `· ${specification.s_name}: ${specification.s_value} ${specification.s_unit}`;
|
|
parentSpec.appendChild(specificationDiv);
|
|
});
|
|
|
|
specificationsContent.appendChild(parentSpec);
|
|
});
|
|
} else {
|
|
specificationsContent.innerHTML = '<p>{% trans "No specifications available." %}</p>';
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
specificationsContent.innerHTML = '<p>{% trans "Error loading specifications." %}</p>';
|
|
console.error("Error fetching specifications:", error);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll(".reserve-btn").forEach((button) => {
|
|
button.addEventListener("click", async function () {
|
|
try {
|
|
const response = await fetch(`{% url 'reserve_car' car.pk %}`, {
|
|
method: "POST",
|
|
headers: {
|
|
"X-CSRFToken": csrfToken,
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
},
|
|
});
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
this.textContent = "Reserved";
|
|
this.classList.remove("btn-success");
|
|
this.classList.add("btn-danger");
|
|
this.disabled = true;
|
|
alert("Car reserved successfully.");
|
|
} else {
|
|
alert(data.message || "Failed to reserve the car.");
|
|
}
|
|
} catch (error) {
|
|
console.error("Error:", error);
|
|
alert("An error occurred. Please try again.");
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
{% endblock %}
|