Merge branch 'main' of http://10.10.1.136:3000/ismail/haikal into frontend
This commit is contained in:
commit
91db23e063
@ -279,6 +279,11 @@ urlpatterns = [
|
||||
views.CarFinanceUpdateView.as_view(),
|
||||
name="car_finance_update",
|
||||
),
|
||||
path(
|
||||
"htmx/cars/bulk_update_car_price/",
|
||||
views.bulk_update_car_price,
|
||||
name="bulk_update_car_price",
|
||||
),
|
||||
path("ajax/", views.AjaxHandlerView.as_view(), name="ajax_handler"),
|
||||
path(
|
||||
"cars/<slug:slug>/add-color/", views.CarColorCreate.as_view(), name="add_color"
|
||||
|
||||
@ -23,6 +23,7 @@ from inventory.models import Status as LeadStatus
|
||||
from django.db import IntegrityError
|
||||
from background_task.models import Task
|
||||
from django.views.generic import FormView
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.db.models.deletion import RestrictedError
|
||||
from django.http.response import StreamingHttpResponse
|
||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||
@ -9288,3 +9289,26 @@ def upload_cars(request,pk=None):
|
||||
return render(request, 'csv_upload.html',{"make_data":models.CarMake.objects.all(),"form":form,"item":item})
|
||||
###############################################################
|
||||
###############################################################
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
def bulk_update_car_price(request):
|
||||
if request.method == "POST":
|
||||
cars = request.POST.getlist('car')
|
||||
price = request.POST.get('price')
|
||||
|
||||
if not price or int(price) <= 0:
|
||||
messages.error(request, "Please enter a valid price")
|
||||
elif not cars:
|
||||
messages.error(request, "No cars selected for price update")
|
||||
else:
|
||||
for car_pk in cars:
|
||||
car_finance , created = models.CarFinance.objects.get_or_create(car__pk=car_pk, cost_price=Decimal(price),selling_price=0)
|
||||
if not created:
|
||||
car_finance.cost_price = Decimal(price)
|
||||
car_finance.selling_price = 0
|
||||
car_finance.save()
|
||||
messages.success(request, "Price updated successfully")
|
||||
|
||||
response = HttpResponse()
|
||||
response['HX-Redirect'] = reverse('car_list')
|
||||
return response
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock content %}
|
||||
@ -109,7 +109,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
@ -117,9 +117,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<p>{% trans "No model change audit events found." %}</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>{% trans "No model change audit events found." %}</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@ -102,7 +102,7 @@
|
||||
<!-- Tour Manager -->
|
||||
<script src="{% static 'js/tours/tour-manager.js' %}"></script>
|
||||
|
||||
<script src="{% static 'js/tours/help-button.js' %}"></script>
|
||||
<script src="{% static 'js/tours/help-button.js' %}"></script>
|
||||
<script src="{% static 'vendors/lodash/lodash.min.js' %}"></script>
|
||||
<script src="{% static 'vendors/list.js/list.min.js' %}"></script>
|
||||
<script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
{% block title %}Bill Details - {{ block.super }}{% endblock %}
|
||||
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
<style>
|
||||
/* Optional custom overrides for Bootstrap 5 */
|
||||
.table th,
|
||||
.table td {
|
||||
@ -26,17 +26,17 @@
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
#djl-vendor-card-widget{
|
||||
#djl-vendor-card-widget{
|
||||
|
||||
max-height:30rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid py-4">
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row g-4" >
|
||||
<!-- Left Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
@ -237,6 +237,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "bill/includes/mark_as.html" %}
|
||||
</div>
|
||||
{% include "bill/includes/mark_as.html" %}
|
||||
{% endblock %}
|
||||
@ -6,7 +6,7 @@
|
||||
{% load widget_tweaks crispy_forms_filters %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-4">
|
||||
<div class="container py-4">
|
||||
<div class="row g-4">
|
||||
<!-- Vendor Card -->
|
||||
<div class="col-12">
|
||||
@ -52,6 +52,6 @@
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "bill/includes/mark_as.html" %}
|
||||
{% endblock %}
|
||||
@ -267,18 +267,18 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.card-footer .btn-link {
|
||||
.card-footer .btn-link {
|
||||
padding: 1rem;
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.card-footer .btn-link:hover {
|
||||
}
|
||||
.card-footer .btn-link:hover {
|
||||
background-color: rgba(0,0,0,0.03);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.showPOModal = function(title, actionUrl, buttonText) {
|
||||
const modalEl = document.getElementById('POModal');
|
||||
if (!modalEl) {
|
||||
@ -302,5 +302,5 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
modal.show();
|
||||
};
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -19,5 +19,5 @@
|
||||
<p class="card-text">{% trans 'No available notes to display...' %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
polygon(15px 0, 100% 0, 100% 100%, 15px 100%, 0 50%)
|
||||
{% endif %};
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.kanban-header::after {
|
||||
|
||||
@ -50,4 +50,4 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static widget_tweaks custom_filters %}
|
||||
{% block title %}
|
||||
{% block title %}
|
||||
{# Check if an 'object' exists in the context #}
|
||||
{% if object %}
|
||||
{% trans 'Update Opportunity'%}
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
<div id="opportunities-grid" class="row g-4 px-2 px-lg-4 mt-1">
|
||||
{% include 'crm/opportunities/partials/opportunity_grid.html' %}
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %}
|
||||
{% include 'partials/pagination.html' %}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{% load static i18n %}
|
||||
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
<style>
|
||||
.color-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
@ -68,11 +68,11 @@
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="container mt-4">
|
||||
<h2>Upload Cars CSV</h2>
|
||||
<div class="d-flex justify-content-end">
|
||||
<a href="{% static 'sample/cars_sample.csv' %}" class="btn btn-outline-success mt-4">
|
||||
@ -153,8 +153,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if item %}
|
||||
<h3 class="mt-4">List of Items</h3>
|
||||
<ul class="list-group">
|
||||
@ -173,5 +173,5 @@
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
<a href="{{ request.META.HTTP_REFERER }}" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -4,10 +4,10 @@
|
||||
{% block title %}Haikal Bot{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="container mt-5">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0"><i class="fas fa-robot me-2"></i>{% trans "HaikalBot" %}</h5>
|
||||
@ -29,17 +29,17 @@
|
||||
<canvas id="chart-canvas" height="200px"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const chatHistory = document.getElementById('chat-history');
|
||||
const chartContainer = document.getElementById('chart-container');
|
||||
const chartCanvas = document.getElementById('chart-canvas');
|
||||
const exportBtn = document.getElementById('export-btn');
|
||||
let chartInstance = null;
|
||||
let latestDataTable = null;
|
||||
<script>
|
||||
const chatHistory = document.getElementById('chat-history');
|
||||
const chartContainer = document.getElementById('chart-container');
|
||||
const chartCanvas = document.getElementById('chart-canvas');
|
||||
const exportBtn = document.getElementById('export-btn');
|
||||
let chartInstance = null;
|
||||
let latestDataTable = null;
|
||||
|
||||
function getCookie(name) {
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== "") {
|
||||
const cookies = document.cookie.split(";");
|
||||
@ -54,13 +54,13 @@ function getCookie(name) {
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
function speak(text) {
|
||||
function speak(text) {
|
||||
const utterance = new SpeechSynthesisUtterance(text);
|
||||
utterance.lang = document.documentElement.lang || "en";
|
||||
window.speechSynthesis.speak(utterance);
|
||||
}
|
||||
}
|
||||
|
||||
function renderTable(data) {
|
||||
function renderTable(data) {
|
||||
latestDataTable = data;
|
||||
exportBtn.style.display = 'inline-block';
|
||||
const headers = Object.keys(data[0]);
|
||||
@ -72,9 +72,9 @@ function renderTable(data) {
|
||||
});
|
||||
html += '</tbody></table></div>';
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
function appendMessage(role, htmlContent) {
|
||||
function appendMessage(role, htmlContent) {
|
||||
const align = role === 'AI' ? 'bg-secondary-light' : 'bg-primary-light';
|
||||
chatHistory.innerHTML += `
|
||||
<div class="mb-3 p-3 rounded ${align}">
|
||||
@ -82,9 +82,9 @@ function appendMessage(role, htmlContent) {
|
||||
</div>
|
||||
`;
|
||||
chatHistory.scrollTop = chatHistory.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('chat-form').addEventListener('submit', async function(e) {
|
||||
document.getElementById('chat-form').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
const input = document.getElementById('chat-input');
|
||||
const prompt = input.value.trim();
|
||||
@ -151,9 +151,9 @@ document.getElementById('chat-form').addEventListener('submit', async function(e
|
||||
: `<p>${result.data}</p>`;
|
||||
appendMessage('AI', content);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('export-btn').addEventListener('click', () => {
|
||||
document.getElementById('export-btn').addEventListener('click', () => {
|
||||
if (!latestDataTable) return;
|
||||
const csv = Papa.unparse(latestDataTable);
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||
@ -164,10 +164,10 @@ document.getElementById('export-btn').addEventListener('click', () => {
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
});
|
||||
|
||||
// Voice input (speech-to-text)
|
||||
document.getElementById('mic-btn').addEventListener('click', () => {
|
||||
document.getElementById('mic-btn').addEventListener('click', () => {
|
||||
const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
|
||||
recognition.lang = document.documentElement.lang || "en";
|
||||
recognition.interimResults = false;
|
||||
@ -183,6 +183,6 @@ document.getElementById('mic-btn').addEventListener('click', () => {
|
||||
};
|
||||
|
||||
recognition.start();
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -6,11 +6,11 @@
|
||||
{% endblock title %}
|
||||
|
||||
{% block description %}
|
||||
AI assistant
|
||||
AI assistant
|
||||
{% endblock description %}
|
||||
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
<style>
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
@ -54,13 +54,13 @@ AI assistant
|
||||
color: #dc3545;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
|
||||
{% block content %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
<div class="card shadow-none mb-3">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
<div class="card shadow-none mb-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
|
||||
<img class="d-dark-none" src="{% static 'images/favicons/haikalbot_v1.png' %}" alt="{% trans 'home' %}" width="32" />
|
||||
@ -99,16 +99,16 @@ AI assistant
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<script>
|
||||
// Global configuration
|
||||
const MAX_MESSAGE_LENGTH = 400;
|
||||
const WARNING_THRESHOLD = 350;
|
||||
const isArabic = '{{ LANGUAGE_CODE }}' === 'ar';
|
||||
const MAX_MESSAGE_LENGTH = 400;
|
||||
const WARNING_THRESHOLD = 350;
|
||||
const isArabic = '{{ LANGUAGE_CODE }}' === 'ar';
|
||||
|
||||
// Chart rendering function
|
||||
function renderInsightChart(labels, data, chartType = 'bar', title = 'Insight Chart') {
|
||||
function renderInsightChart(labels, data, chartType = 'bar', title = 'Insight Chart') {
|
||||
const canvasId = 'chart_' + Date.now();
|
||||
const chartHtml = `<div class="chart-container"><canvas id="${canvasId}"></canvas></div>`;
|
||||
$('#chatMessages').append(chartHtml);
|
||||
@ -136,9 +136,9 @@ function renderInsightChart(labels, data, chartType = 'bar', title = 'Insight Ch
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function() {
|
||||
// DOM elements
|
||||
const messageInput = $('#messageInput');
|
||||
const charCount = $('#charCount');
|
||||
@ -516,6 +516,6 @@ $(document).ready(function() {
|
||||
}
|
||||
|
||||
scrollToBottom();
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
@ -145,8 +145,14 @@
|
||||
hx-on::after-request="filter_after_request()">{{ _("Search") }}</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form class="update-price-form d-flex flex-row align-items-center ms-auto w-25 d-none" action="" method="post" style="float:right;">
|
||||
<input class="form-control me-2" type="number" placeholder='{{ _("Search") }}' name="price" aria-label="Price">
|
||||
<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">
|
||||
@ -186,7 +192,7 @@
|
||||
<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" id="car-{{car.pk}}">
|
||||
<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">
|
||||
@ -275,8 +281,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block customJS %}
|
||||
{% endblock %}
|
||||
{% block customJS %}
|
||||
<script>
|
||||
links = document.querySelectorAll('.nav-link')
|
||||
links.forEach(link => {
|
||||
@ -313,18 +319,31 @@
|
||||
|
||||
document.getElementById('select-all').addEventListener('change', function() {
|
||||
const checkboxes = document.querySelectorAll('#project-list-table-body input[type="checkbox"]');
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = this.checked;
|
||||
});
|
||||
});
|
||||
document.getElementById('car-checkbox').addEventListener('change', function() {
|
||||
const form = document.querySelector('.update-price-form');
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
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 %}
|
||||
{% endblock customJS %}
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
#065535
|
||||
#000000
|
||||
#133337
|
||||
#ffc0cb</a>
|
||||
#ffc0cb</a>
|
||||
<br>
|
||||
<span class="glyphicon glyphicon-star"></span>707
|
||||
</div>
|
||||
|
||||
@ -351,4 +351,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -130,7 +130,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block customerJS %}
|
||||
<script>
|
||||
<script>
|
||||
// Handle delete modal for all tables
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var deleteModal = document.getElementById('deleteModal');
|
||||
@ -140,5 +140,5 @@
|
||||
document.getElementById('deleteAccountBtn').href = `/accounts/delete/${accountId}/`;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -1,6 +1,6 @@
|
||||
{% load i18n %}
|
||||
{% if accounts %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
@ -54,16 +54,16 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
</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>
|
||||
{% else %}
|
||||
<div class="alert ">
|
||||
<div class="alert ">
|
||||
{% trans "No accounts found in this category." %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="container mt-4">
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
<form method="post">
|
||||
@ -59,10 +59,10 @@
|
||||
<a href="{% url 'purchase_order_list' %}" class="btn btn-phoenix-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const container = document.getElementById('formset-container');
|
||||
const addBtn = document.getElementById('add-item');
|
||||
const totalForms = document.querySelector('#id_form-TOTAL_FORMS');
|
||||
@ -99,11 +99,11 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
totalForms.value = parseInt(totalForms.value) - 1;
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Empty form template -->
|
||||
<div class="empty-form d-none">
|
||||
<div class="empty-form d-none">
|
||||
<div class="item-form row g-3 mb-3 align-items-end">
|
||||
<div class="col-md-2">
|
||||
<select name="form-__prefix__-make" class="form-select make-select"></select>
|
||||
@ -130,6 +130,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
<button type="button" class="btn btn-phoenix-danger btn-sm remove-row">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@ -1,7 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static i18n crispy_forms_tags %}
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
<style>
|
||||
.color-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
@ -67,10 +67,10 @@
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form action="" method="post">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="row g-4">
|
||||
<div class="col">
|
||||
@ -140,5 +140,5 @@
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-5">Add New Item To Inventory</button>
|
||||
</form>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
@ -2,7 +2,7 @@
|
||||
{% load django_ledger %}
|
||||
{% load widget_tweaks %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.showPOModal = function(title, actionUrl, buttonText) {
|
||||
const modalEl = document.getElementById('POModal');
|
||||
if (!modalEl) {
|
||||
@ -26,7 +26,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
modal.show();
|
||||
};
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% if not create_po %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form action="{% url 'inventory_item_create' po_model.pk %}" method="post">
|
||||
<form action="{% url 'inventory_item_create' po_model.pk %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% include "purchase_orders/partials/po-select.html" with name="make" target="model" data=make_data pk=po_model.pk %}
|
||||
{% include "purchase_orders/partials/po-select.html" with name="model" target="serie" data=model_data pk=po_model.pk %}
|
||||
@ -22,6 +22,6 @@
|
||||
<input type="number" class="form-control" id="quantity" name="quantity" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-phoenix-primary">Add New Item To Inventory</button>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<form action="" method="post">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<label for="account">Name</label>
|
||||
@ -18,6 +18,6 @@
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-phoenix-primary mt-2">Add New Item To Inventory</button>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@ -6,7 +6,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="container mt-4">
|
||||
<h2>Confirm Deletion</h2>
|
||||
<p>Are you sure you want to delete the Purchase Order <strong>"{{ po.po_number }}"</strong>?</p>
|
||||
|
||||
@ -15,5 +15,5 @@
|
||||
<button type="submit" class="btn btn-phoenix-danger">Yes, Delete</button>
|
||||
<a href="{% url 'purchase_order_detail' po.id %}" class="btn btn-phoenix-secondary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -5,7 +5,7 @@
|
||||
{% load django_ledger %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid mt-4">
|
||||
<div class="container-fluid mt-4">
|
||||
<div class="row g-4">
|
||||
<!-- Left Sidebar -->
|
||||
<div class="col-lg-4">
|
||||
@ -64,14 +64,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "purchase_orders/includes/mark_as.html" %}
|
||||
{% include "purchase_orders/includes/mark_as.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block customJS %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.showPOModal = function(title, actionUrl, buttonText) {
|
||||
const modalEl = document.getElementById('POModal');
|
||||
if (!modalEl) {
|
||||
@ -95,6 +95,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
modal.show();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
@ -6,7 +6,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<div class="container mt-4">
|
||||
<h2>Purchase Order: {{ po.po_number }}</h2>
|
||||
<p><strong>Status:</strong>
|
||||
<span class="">
|
||||
@ -60,8 +60,8 @@
|
||||
<a href="{% url 'purchase_order_list' %}" class="btn btn-phoenix-secondary">Back to List</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="POModal" data-bs-keyboard="true" tabindex="-1" aria-labelledby="POModalLabel" aria-hidden="true">
|
||||
</div>
|
||||
<div class="modal fade" id="POModal" data-bs-keyboard="true" tabindex="-1" aria-labelledby="POModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
|
||||
|
||||
@ -93,8 +93,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block customJS %}
|
||||
<script>
|
||||
function showPOModal(title, actionUrl, buttonText) {
|
||||
<script>
|
||||
function showPOModal(title, actionUrl, buttonText) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('POModal'));
|
||||
document.getElementById('POModalTitle').innerText = title;
|
||||
|
||||
@ -105,6 +105,6 @@ function showPOModal(title, actionUrl, buttonText) {
|
||||
</a>
|
||||
`;
|
||||
modal.show();
|
||||
}
|
||||
</script>
|
||||
}
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
@ -1,10 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="mt-4">
|
||||
<h1><i class="fa-solid fa-cart-shopping me-1"></i>{{po.po_number}}</h1>
|
||||
<div class="mt-4">
|
||||
<h1><i class="fa-solid fa-cart-shopping me-1"></i>{{po.po_number}}</h1>
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<h4>Status:</h4>
|
||||
{% comment %} Apply appropriate text color based on po.po_status {% endcomment %}
|
||||
{% if po.po_status == 'draft' %}
|
||||
@ -20,7 +20,7 @@
|
||||
{% else %}
|
||||
<h4 class="ms-2 text-muted mb-0">{{ po.po_status|capfirst }}</h4> {# Use muted for unknown/default status #}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
{% endblock customCSS %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{% load static i18n humanize %}
|
||||
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
<style>
|
||||
/* Custom CSS for additional styling */
|
||||
.status-badge {
|
||||
font-size: 0.8rem;
|
||||
@ -67,11 +67,11 @@
|
||||
object-fit: cover;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-0">
|
||||
<div class="container-fluid px-0">
|
||||
<!-- Header -->
|
||||
<header class="bg-primary py-3">
|
||||
<div class="container">
|
||||
@ -81,10 +81,10 @@
|
||||
{{ _("Sale Order")}} #{{ saleorder.formatted_order_id }}
|
||||
</h1>
|
||||
<div>
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
<button class="btn btn-sm btn-outline-light me-2">
|
||||
<i class="fas fa-print me-1"></i> {{ _("Print") }}
|
||||
</button>
|
||||
@ -275,17 +275,17 @@
|
||||
<!-- Documents Card -->
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<h5 class="mb-0">{{ _("Documents") }}</h5>
|
||||
<button class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-plus me-1"></i> {{ _("Add Document")}}
|
||||
=======
|
||||
=======
|
||||
|
||||
<h5 class="mb-0">{{ _("Documents") }}</h5>
|
||||
<button class="btn btn-sm btn-primary">
|
||||
<i class="fas fa-plus me-1"></i> {{ _("Add Document")}}
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@ -330,13 +330,13 @@
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" name="comment" rows="3" placeholder="Add a comment or note..." required></textarea>
|
||||
<div class="d-flex justify-content-end mt-2">
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<button type="submit" class="btn btn-primary btn-sm">{{ _("Post Comment")}}</button>
|
||||
=======
|
||||
=======
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-sm">{{ _("Post Comment")}}</button>
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -379,51 +379,51 @@
|
||||
{% endif %}
|
||||
|
||||
{% comment %} <a href="{% url 'edit_sale_order' saleorder.pk %}" class="btn btn-primary"> {% endcomment %}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
<a href="" class="btn btn-primary">
|
||||
<i class="fas fa-edit me-2"></i> {{ _("Edit Order")}}
|
||||
</a>
|
||||
|
||||
{% if not saleorder.invoice %}
|
||||
{% comment %} <a href="{% url 'create_invoice_from_order' saleorder.pk %}" class="btn btn-info"> {% endcomment %}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<a href="" class="btn btn-info">
|
||||
<i class="fas fa-file-invoice-dollar me-2"></i> {{ _("Create Invoice")}}
|
||||
=======
|
||||
=======
|
||||
|
||||
<a href="" class="btn btn-info">
|
||||
<i class="fas fa-file-invoice-dollar me-2"></i> {{ _("Create Invoice")}}
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if saleorder.status == 'approved' and not saleorder.actual_delivery_date %}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<button class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#deliveryModal">
|
||||
<i class="fas fa-truck me-2"></i> {{ _("Schedule Delivery")}}
|
||||
=======
|
||||
=======
|
||||
|
||||
<button class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#deliveryModal">
|
||||
<i class="fas fa-truck me-2"></i> {{ _("Schedule Delivery")}}
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
{% if saleorder.status != 'cancelled' %}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#cancelModal">
|
||||
<i class="fas fa-times-circle me-2"></i> {{ _("Cancel Order")}}
|
||||
=======
|
||||
=======
|
||||
|
||||
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#cancelModal">
|
||||
<i class="fas fa-times-circle me-2"></i> {{ _("Cancel Order")}}
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
@ -555,10 +555,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Cancel Order Modal -->
|
||||
<div class="modal fade" id="cancelModal" tabindex="-1" aria-labelledby="cancelModalLabel" aria-hidden="true">
|
||||
<div class="modal fade" id="cancelModal" tabindex="-1" aria-labelledby="cancelModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@ -575,23 +575,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
|
||||
<button type="submit" class="btn btn-danger">{{ _("Confirm Cancellation")}}</button>
|
||||
=======
|
||||
=======
|
||||
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
|
||||
<button type="submit" class="btn btn-danger">{{ _("Confirm Cancellation")}}</button>
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schedule Delivery Modal -->
|
||||
<div class="modal fade" id="deliveryModal" tabindex="-1" aria-labelledby="deliveryModalLabel" aria-hidden="true">
|
||||
<div class="modal fade" id="deliveryModal" tabindex="-1" aria-labelledby="deliveryModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@ -612,24 +612,24 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ _("Schedule Delivery")}}</button>
|
||||
=======
|
||||
=======
|
||||
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ _("Schedule Delivery")}}</button>
|
||||
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
>>>>>>> e9e2fd3 (add bulk insert + po item insert)
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block customJS %}
|
||||
<script>
|
||||
<script>
|
||||
// Status update function
|
||||
function updateStatus(newStatus) {
|
||||
fetch("", {
|
||||
@ -669,5 +669,5 @@
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
@ -12,12 +12,12 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content fs-9">
|
||||
<div class="row">
|
||||
<div class="content fs-9">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<!-- English Section -->
|
||||
<h2>Date: 1/1/2025</h2>
|
||||
<section id="terms">
|
||||
<section id="terms">
|
||||
<h2>Terms of Service</h2>
|
||||
<p>Welcome to <strong>Haikal</strong>, an advanced car inventory management platform owned and operated by <strong>Tenhal Information Technology Company</strong> ("we", "our", "us"). By accessing or using the Haikal system ("the Service"), you agree to be legally bound by the terms outlined below.</p>
|
||||
<h3>1. Acceptance of Terms</h3>
|
||||
@ -66,11 +66,11 @@
|
||||
|
||||
<h3>11. Governing Law</h3>
|
||||
<p>These terms are governed by the laws of the Kingdom of Saudi Arabia. Any disputes will be resolved exclusively in courts located in Riyadh.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
<section id="privacy">
|
||||
<section id="privacy">
|
||||
<h2>Privacy Policy</h2>
|
||||
|
||||
<p>We value your privacy and are committed to protecting your personal and business data. This Privacy Policy explains how we collect, use, and protect your information when you use Haikal.</p>
|
||||
@ -120,7 +120,7 @@
|
||||
|
||||
<h3>9. Changes to this Policy</h3>
|
||||
<p>We may revise this Privacy Policy from time to time. Updates will be posted here with a revised effective date.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
<div class="col-6" dir="rtl">
|
||||
<h2>التاريخ: ١/١/٢٠٢٥</h2>
|
||||
<!-- Arabic Section -->
|
||||
<section class="arabic">
|
||||
<section class="arabic">
|
||||
<h2>شروط الخدمة</h2>
|
||||
<p>مرحبًا بك في <strong>هيكل</strong>، منصة متقدمة لإدارة مخزون السيارات، مملوكة وتديرها <strong>شركة تنحل لتقنية المعلومات</strong> ("نحن"، "خاصتنا"). باستخدامك لنظام هيكل، فإنك توافق على الالتزام القانوني بالشروط التالية:</p>
|
||||
|
||||
@ -178,11 +178,11 @@
|
||||
|
||||
<h3>١١. القانون الحاكم</h3>
|
||||
<p>تخضع هذه الشروط لقوانين المملكة العربية السعودية، ويكون الاختصاص القضائي لمحاكم الرياض فقط.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
<hr>
|
||||
|
||||
<section class="arabic">
|
||||
<section class="arabic">
|
||||
<h2>سياسة الخصوصية</h2>
|
||||
|
||||
<p>نحن نهتم بخصوصيتك وملتزمون بحماية بياناتك الشخصية والتجارية. توضح هذه السياسة كيفية جمع واستخدام وحماية بياناتك عند استخدام نظام هيكل.</p>
|
||||
@ -232,10 +232,10 @@
|
||||
|
||||
<h3>٩. التحديثات</h3>
|
||||
<p>قد نُجري تغييرات على هذه السياسة، وسيتم نشر التعديلات مع تاريخ سريان جديد.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row border-top">
|
||||
<div class="col-6">
|
||||
<section id="contact">
|
||||
@ -247,7 +247,7 @@
|
||||
📧 <a href="mailto:info@tenhal.sa">info@tenhal.sa</a><br>
|
||||
🌐 <a href="https://www.tenhal.sa" target="_blank">www.tenhal.sa</a>
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-6" dir="rtl">
|
||||
<section class="arabic">
|
||||
@ -259,7 +259,7 @@
|
||||
📧 <a href="mailto:info@tenhal.sa">info@tenhal.sa</a><br>
|
||||
🌐 <a href="https://www.tenhal.sa" target="_blank">tenhal.sa</a>
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{% block title %}{{ tour.name }} - Interactive Guide{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<div class="container my-4">
|
||||
<h1>{{ tour.name }}</h1>
|
||||
<p class="lead">{{ tour.description }}</p>
|
||||
|
||||
@ -16,16 +16,16 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
<script>
|
||||
// Auto-start the tour after a short delay
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(() => {
|
||||
window.tourManager.loadTour('{{ tour.slug }}');
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -3,7 +3,7 @@
|
||||
{% block title %}Interactive Guides{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<div class="container my-4">
|
||||
<h1>Interactive Guides</h1>
|
||||
<p class="lead">Learn how to use the car inventory system with these interactive step-by-step guides.</p>
|
||||
|
||||
@ -28,5 +28,5 @@
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user