Compare commits

..

6 Commits

55 changed files with 1909 additions and 1285 deletions

View File

@ -1,3 +1,4 @@
import logging
import uuid import uuid
from datetime import datetime from datetime import datetime
from django.conf import settings from django.conf import settings
@ -51,6 +52,10 @@ from imagekit.processors import ResizeToFill
# from simple_history.models import HistoricalRecords # from simple_history.models import HistoricalRecords
from plans.models import Invoice from plans.models import Invoice
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
class Base(models.Model): class Base(models.Model):
id = models.UUIDField( id = models.UUIDField(
unique=True, unique=True,
@ -881,11 +886,11 @@ class Car(Base):
@property @property
def get_additional_services_vat(self): def get_additional_services_vat(self):
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first() vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
return sum([Decimal((x.price)*(vat.rate)) for x in self.additional_services.all()]) return sum([Decimal((x.price)*(vat.rate)) for x in self.additional_services.filter(taxable=True)])
def get_additional_services(self): def get_additional_services(self):
vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first() vat = VatRate.objects.filter(dealer=self.dealer,is_active=True).first()
return {"services": [[x,(x.price)*(vat.rate)] for x in self.additional_services.all()], return {"services": [[x,((x.price)*(vat.rate) if x.taxable else 0)] for x in self.additional_services.all()],
"total_":self.get_additional_services_amount_, "total_":self.get_additional_services_amount_,
"total":self.get_additional_services_amount, "total":self.get_additional_services_amount,
"services_vat":self.get_additional_services_vat} "services_vat":self.get_additional_services_vat}
@ -3721,3 +3726,31 @@ class Ticket(models.Model):
def __str__(self): def __str__(self):
return f"#{self.id} - {self.subject} ({self.status})" return f"#{self.id} - {self.subject} ({self.status})"
class CarImage(models.Model):
car = models.OneToOneField('Car', on_delete=models.CASCADE, related_name='generated_image')
image_hash = models.CharField(max_length=64, unique=True)
image = models.ImageField(upload_to='car_images/', null=True, blank=True)
is_generating = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def generate_hash(self):
"""Simple hash generation"""
car = self.car
hash_string = f"{car.id_car_make.name if car.id_car_make else ''}-{car.id_car_model.name if car.id_car_model else ''}-{car.year}-{getattr(car, 'color', 'default')}"
return hashlib.sha256(hash_string.encode()).hexdigest()
def schedule_generation(self):
"""Schedule image generation"""
from django_q.tasks import async_task
from inventory.tasks import generate_car_image_task
self.is_generating = True
self.save()
async_task(
generate_car_image_task,
self.id,
task_name=f"generate_car_image_{self.car.vin}"
)

View File

@ -413,24 +413,26 @@ def create_item_model(sender, instance, created, **kwargs):
# quotation.save() # quotation.save()
@receiver(post_save, sender=models.CarColors) # @receiver(post_save, sender=models.CarColors)
def update_car_when_color_changed(sender, instance, **kwargs): # def update_car_hash_when_color_changed(sender, instance, **kwargs):
""" # """
Signal receiver to handle updates to a car instance when its related # Signal receiver to handle updates to a car instance when its related
CarColors instance is modified. Triggered by the `post_save` signal # CarColors instance is modified. Triggered by the `post_save` signal
for the `CarColors` model. Ensures that the associated `Car` instance # for the `CarColors` model. Ensures that the associated `Car` instance
is saved, propagating changes effectively. # is saved, propagating changes effectively.
:param sender: The model class (`CarColors`) that was saved. # :param sender: The model class (`CarColors`) that was saved.
:type sender: Type[models.CarColors] # :type sender: Type[models.CarColors]
:param instance: The specific instance of `CarColors` that was saved. # :param instance: The specific instance of `CarColors` that was saved.
:type instance: models.CarColors # :type instance: models.CarColors
:param kwargs: Additional keyword arguments passed by the signal. # :param kwargs: Additional keyword arguments passed by the signal.
:type kwargs: dict # :type kwargs: dict
:return: None # :return: None
""" # """
car = instance.car
car.save() # car = instance.car
# car.hash = car.get_hash
# car.save()
@receiver(post_save, sender=models.Opportunity) @receiver(post_save, sender=models.Opportunity)
@ -1261,3 +1263,40 @@ def send_ticket_notification(sender, instance, created, **kwargs):
), ),
), ),
) )
@receiver(post_save, sender=models.CarColors)
def handle_car_image(sender, instance, created, **kwargs):
"""
Simple handler for car image generation
"""
try:
# Create or get car image record
car = instance.car
car_image, created = models.CarImage.objects.get_or_create(car=car, defaults={'image_hash': car.get_hash})
# Check for existing image with same hash
existing = models.CarImage.objects.filter(
image_hash=car_image.image_hash,
image__isnull=False
).exclude(car=car).first()
if existing:
# Copy existing image
car_image.image.save(
existing.image.name,
existing.image.file,
save=True
)
logger.info(f"Reused image for car {car.vin}")
else:
# Schedule async generation
async_task(
'inventory.tasks.generate_car_image_task',
car_image.id,
task_name=f"generate_car_image_{car.vin}"
)
logger.info(f"Scheduled image generation for car {car.vin}")
except Exception as e:
logger.error(f"Error handling car image for {car.vin}: {e}")

View File

@ -1,5 +1,8 @@
import base64 import base64
import logging import logging
import requests
from PIL import Image
from io import BytesIO
from plans.models import Plan from plans.models import Plan
from django.urls import reverse from django.urls import reverse
from django.conf import settings from django.conf import settings
@ -18,7 +21,8 @@ from .utils import get_accounts_data,create_account
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User, Group, Permission from django.contrib.auth.models import User, Group, Permission
from inventory.models import DealerSettings, Dealer,Schedule,Notification,CarReservation,CarStatusChoices from inventory.models import DealerSettings, Dealer,Schedule,Notification,CarReservation,CarStatusChoices,CarImage
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@ -929,3 +933,29 @@ def remove_reservation_by_id(reservation_id):
def test_task(**kwargs): def test_task(**kwargs):
print("TASK : ",kwargs.get("dealer")) print("TASK : ",kwargs.get("dealer"))
def generate_car_image_task(car_image_id):
"""
Simple async task to generate car image
"""
from inventory.utils import generate_car_image_simple
try:
car_image = CarImage.objects.get(id=car_image_id)
result = generate_car_image_simple(car_image)
return {
'success': result.get('success', False),
'car_image_id': car_image_id,
'error': result.get('error'),
'message': 'Image generated' if result.get('success') else 'Generation failed'
}
except CarImage.DoesNotExist:
error_msg = f"CarImage with id {car_image_id} not found"
logger.error(error_msg)
return {'success': False, 'error': error_msg}
except Exception as e:
error_msg = f"Unexpected error: {e}"
logger.error(error_msg)
return {'success': False, 'error': error_msg}

View File

@ -3,11 +3,15 @@ import secrets
import logging import logging
import datetime import datetime
import requests import requests
from PIL import Image
from io import BytesIO
from decimal import Decimal from decimal import Decimal
from inventory import models from inventory import models
from django.urls import reverse from django.urls import reverse
from django.conf import settings from django.conf import settings
from urllib.parse import urljoin
from django.utils import timezone from django.utils import timezone
from django.db import transaction
from django_ledger.io import roles from django_ledger.io import roles
from django.contrib import messages from django.contrib import messages
from django.shortcuts import redirect from django.shortcuts import redirect
@ -20,16 +24,17 @@ from django_ledger.models import (
BillModel, BillModel,
VendorModel, VendorModel,
) )
from django.core.files.base import ContentFile
from django_ledger.models.items import ItemModel from django_ledger.models.items import ItemModel
from django.utils.translation import get_language from django.utils.translation import get_language
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_q.models import Schedule as DjangoQSchedule
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django_ledger.models.transactions import TransactionModel from django_ledger.models.transactions import TransactionModel
from django_ledger.models.journal_entry import JournalEntryModel from django_ledger.models.journal_entry import JournalEntryModel
from django.db import transaction # from .tasks import generate_car_image_task
from django_q.models import Schedule as DjangoQSchedule
from django_ledger.io import roles
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -1301,7 +1306,7 @@ def get_finance_data(estimate,dealer):
additional_services = car.get_additional_services() additional_services = car.get_additional_services()
discounted_price=(Decimal(car.marked_price) - discount) discounted_price=(Decimal(car.marked_price) - discount)
vat_amount = discounted_price * vat.rate vat_amount = discounted_price * vat.rate
total_services_vat=sum([ x[1] for x in additional_services.get("services")]) total_services_vat=sum([x[1] for x in additional_services.get("services")])
total_vat=vat_amount+total_services_vat total_vat=vat_amount+total_services_vat
return { return {
"car": car, "car": car,
@ -1311,7 +1316,7 @@ def get_finance_data(estimate,dealer):
"vat_rate": vat.rate, "vat_rate": vat.rate,
"discount_amount": discount, "discount_amount": discount,
"additional_services": additional_services, "additional_services": additional_services,
"final_price": discounted_price+ vat_amount, "final_price": discounted_price + vat_amount,
"total_services_vat":total_services_vat, "total_services_vat":total_services_vat,
"total_vat":total_vat, "total_vat":total_vat,
"grand_total": discounted_price + total_vat + additional_services.get("total") "grand_total": discounted_price + total_vat + additional_services.get("total")
@ -2349,3 +2354,273 @@ def create_account(entity, coa, account_data):
logger.info(f"Created default account: {account}") logger.info(f"Created default account: {account}")
except Exception as e: except Exception as e:
logger.error(f"Error creating default account: {account_data['code']}, {e}") logger.error(f"Error creating default account: {account_data['code']}, {e}")
def get_or_generate_car_image(car):
"""
Utility function to get or generate car image asynchronously
"""
try:
car_image, created = models.CarImage.objects.get_or_create(car=car)
if created:
car_image.image_hash = car.get_hash
car_image.save()
if car_image.image:
return car_image.image.url
# Check for existing image with same hash
existing = models.CarImage.objects.filter(
image_hash=car_image.image_hash,
image__isnull=False
).exclude(car=car).first()
if existing:
car_image.image.save(
existing.image.name,
existing.image.file,
save=True
)
return car_image.image.url
# If no image exists and not already generating, schedule generation
if not car_image.is_generating:
car_image.schedule_image_generation()
return None # Return None while image is being generated
except Exception as e:
logger.error(f"Error getting/generating car image: {e}")
return None
def force_regenerate_car_image(car):
"""
Force regeneration of car image (useful for admin actions)
"""
try:
car_image, created = models.CarImage.objects.get_or_create(car=car)
car_image.image_hash = car.get_hash
car_image.image.delete(save=False) # Remove old image
car_image.is_generating = False
car_image.generation_attempts = 0
car_image.last_generation_error = None
car_image.save()
car_image.schedule_image_generation()
return True
except Exception as e:
logger.error(f"Error forcing image regeneration: {e}")
return False
class CarImageAPIClient:
"""Simple client to handle authenticated requests to the car image API"""
BASE_URL = "http://10.10.1.111:8888"
USERNAME = "faheed"
PASSWORD = "Tenhal@123"
def __init__(self):
self.session = None
self.csrf_token = None
def login(self):
"""Login to the API and maintain session"""
try:
# Start fresh session
self.session = requests.Session()
# Step 1: Get CSRF token
response = self.session.get(f"{self.BASE_URL}/login")
response.raise_for_status()
# Get CSRF token from cookies
self.csrf_token = self.session.cookies.get('csrftoken')
if not self.csrf_token:
raise Exception("CSRF token not found in cookies")
# Step 2: Login
login_data = {
"username": self.USERNAME,
"password": self.PASSWORD,
"csrfmiddlewaretoken": self.csrf_token
}
login_response = self.session.post(
f"{self.BASE_URL}/login",
data=login_data
)
if login_response.status_code != 200:
raise Exception(f"Login failed with status {login_response.status_code}")
logger.info("Successfully logged in to car image API")
return True
except Exception as e:
logger.error(f"Login failed: {e}")
self.session = None
self.csrf_token = None
return False
def generate_image(self, payload):
"""Generate car image using authenticated session"""
if not self.session or not self.csrf_token:
if not self.login():
raise Exception("Cannot generate image: Login failed")
try:
headers = {
'X-CSRFToken': self.csrf_token,
'Referer': self.BASE_URL,
}
print(payload)
generate_data = {
"year": payload['year'],
"make": payload['make'],
"model": payload['model'],
"exterior_color": payload['color'],
"angle": "3/4 rear",
"reference_image": ""
}
response = self.session.post(
f"{self.BASE_URL}/generate",
json=generate_data,
headers=headers,
timeout=160
)
response.raise_for_status()
# Parse response
result = response.json()
image_url = result.get('url')
if not image_url:
raise Exception("No image URL in response")
# Download the actual image
image_response = self.session.get(
f"{self.BASE_URL}{image_url}",
timeout=160
)
image_response.raise_for_status()
return image_response.content, None
except requests.RequestException as e:
error_msg = f"API request failed: {e}"
logger.error(error_msg)
return None, error_msg
except Exception as e:
error_msg = f"Unexpected error: {e}"
logger.error(error_msg)
return None, error_msg
# Global client instance
api_client = CarImageAPIClient()
def resize_image(image_data, max_size=(800, 600)):
"""
Resize image to make it smaller while maintaining aspect ratio
Returns resized image data in the same format
"""
try:
img = Image.open(BytesIO(image_data))
original_format = img.format
original_mode = img.mode
# Calculate new size maintaining aspect ratio
img.thumbnail(max_size, Image.Resampling.LANCZOS)
# Save back to bytes in original format
output_buffer = BytesIO()
if original_format and original_format.upper() in ['JPEG', 'JPG']:
img.save(output_buffer, format='JPEG', quality=95, optimize=True)
elif original_format and original_format.upper() == 'PNG':
# Preserve transparency for PNG
if original_mode == 'RGBA':
img.save(output_buffer, format='PNG', optimize=True)
else:
img.save(output_buffer, format='PNG', optimize=True)
else:
# Default to JPEG for other formats
if img.mode in ('RGBA', 'LA', 'P'):
# Convert to RGB if image has transparency
background = Image.new('RGB', img.size, (255, 255, 255))
if img.mode == 'RGBA':
background.paste(img, mask=img.split()[3])
else:
background.paste(img, (0, 0))
img = background
img.save(output_buffer, format='JPEG', quality=95, optimize=True)
resized_data = output_buffer.getvalue()
logger.info(f"Resized image from {len(image_data)} to {len(resized_data)} bytes")
return resized_data, None
except Exception as e:
error_msg = f"Image resizing failed: {e}"
logger.error(error_msg)
return None, error_msg
def generate_car_image_simple(car_image):
"""
Simple function to generate car image with authentication and resizing
"""
car = car_image.car
# Prepare payload
payload = {
'make': car.id_car_make.name if car.id_car_make else '',
'model': car.id_car_model.name if car.id_car_model else '',
'year': car.year,
'color': car.colors.exterior.name
}
logger.info(f"Generating image for car {car.vin}")
# Generate image using API client
image_data, error = api_client.generate_image(payload)
if error:
return {'success': False, 'error': error}
if not image_data:
return {'success': False, 'error': 'No image data received'}
try:
# Resize the image to make it smaller
resized_data, resize_error = resize_image(image_data, max_size=(800, 600))
if resize_error:
# If resizing fails, use original image but log warning
logger.warning(f"Resizing failed, using original image: {resize_error}")
resized_data = image_data
# Determine file extension based on content
try:
img = Image.open(BytesIO(resized_data))
file_extension = img.format.lower() if img.format else 'jpg'
except:
file_extension = 'jpg'
# Save the resized image
car_image.image.save(
f"{car_image.image_hash}.{file_extension}",
ContentFile(resized_data),
save=False
)
logger.info(f"Successfully generated and resized image for car {car.vin}")
return {'success': True}
except Exception as e:
error_msg = f"Image processing failed: {e}"
logger.error(error_msg)
return {'success': False, 'error': error_msg}

View File

@ -4979,6 +4979,7 @@ def create_estimate(request, dealer_slug, slug=None):
.annotate(hash_count=Count("hash")) .annotate(hash_count=Count("hash"))
.distinct() .distinct()
) )
context = { context = {
"form": form, "form": form,
"items": [ "items": [
@ -6328,6 +6329,7 @@ def lead_create(request, dealer_slug):
qs = form.fields["id_car_make"].queryset.filter( qs = form.fields["id_car_make"].queryset.filter(
is_sa_import=True, pk__in=dealer_make_list is_sa_import=True, pk__in=dealer_make_list
) )
# print(qs)
form.fields["staff"].queryset = ( form.fields["staff"].queryset = (
form.fields["staff"] form.fields["staff"]
.queryset.select_related("user") .queryset.select_related("user")
@ -6346,10 +6348,12 @@ def lead_create(request, dealer_slug):
form.fields["staff"].queryset = models.Staff.objects.filter( form.fields["staff"].queryset = models.Staff.objects.filter(
dealer=dealer, pk=request.staff.pk dealer=dealer, pk=request.staff.pk
) )
qs = qs.order_by("name")
form.fields["id_car_make"].queryset = qs form.fields["id_car_make"].queryset = qs
form.fields["id_car_make"].choices = [ form.fields["id_car_make"].choices = [
(obj.id_car_make, obj.get_local_name()) for obj in qs (obj.id_car_make, obj.get_local_name()) for obj in qs
] ]
if first_make := qs.first(): if first_make := qs.first():
form.fields["id_car_model"].queryset = first_make.carmodel_set.all() form.fields["id_car_model"].queryset = first_make.carmodel_set.all()
@ -8435,7 +8439,7 @@ class FiscalYearIncomeStatementViewBase(
""" """
template_name = "ledger/reports/income_statement.html" template_name = "ledger/reports/income_statement.html"
permission_required = ["inventory.view_carfinance"] permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self): def get_login_url(self):
return reverse("account_login") return reverse("account_login")
@ -8574,7 +8578,7 @@ class FiscalYearCashFlowStatementViewBase(
""" """
template_name = "ledger/reports/cash_flow_statement.html" template_name = "ledger/reports/cash_flow_statement.html"
permission_required = ["inventory.view_carfinance"] permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self): def get_login_url(self):
return reverse("account_login") return reverse("account_login")
@ -8763,7 +8767,7 @@ class FiscalYearEntityModelDashboardView(
:type permission_required: list :type permission_required: list
""" """
permission_required = ["inventory.view_carfinance"] permission_required = ["django_ledger.view_ledgermodel"]
def get_login_url(self): def get_login_url(self):
return reverse("account_login") return reverse("account_login")
@ -11433,6 +11437,10 @@ def create_ticket(request,dealer_slug):
def ticket_list(request,dealer_slug): def ticket_list(request,dealer_slug):
dealer= get_object_or_404(models.Dealer, slug=dealer_slug) dealer= get_object_or_404(models.Dealer, slug=dealer_slug)
tickets = models.Ticket.objects.filter(dealer=dealer).order_by('-created_at') tickets = models.Ticket.objects.filter(dealer=dealer).order_by('-created_at')
query=request.GET.get('q')
if query:
tickets=tickets.filter(Q(id__icontains=query)| Q(subject__icontains=query))
return render(request, 'support/ticket_list.html', {'tickets': tickets}) return render(request, 'support/ticket_list.html', {'tickets': tickets})
@login_required @login_required

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

View File

@ -3,52 +3,45 @@
{% load i18n static %} {% load i18n static %}
{% load allauth account %} {% load allauth account %}
{% block title %} {% block title %}
{% trans 'User Settings' %} {% trans 'Dealer Settings' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-md-6">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {% trans "Dealer Settings" %}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <i class="fas fa-solid fa-gear ms-2"></i>
<h3 class="mb-0 fs-4 text-center">
Dealer Settings
<span class="fas fa-solid fa-gear ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle "> <div class="card-body p-4 p-md-5">
<form action="" method="post"> <form action="" method="post" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
<div class="row g-1">
<div class="col-12"> <div class="col-12">
<div class=" mb-4"> <h4 class="mb-4 text-center">{% trans 'Default Invoice Accounts' %}</h4>
<div class="row gx-3 mb-4 gy-6 gy-sm-3"> {{ form.invoice_cash_account|as_crispy_field }}
<div class="col-12"> {{ form.invoice_prepaid_account|as_crispy_field }}
<h4 class="mb-4">{% trans 'Default Invoice Accounts' %}</h4> {{ form.invoice_unearned_account|as_crispy_field }}
<div class="form-icon-container mb-3">{{ form.invoice_cash_account|as_crispy_field }}</div> </div>
<div class="form-icon-container mb-3">{{ form.invoice_prepaid_account|as_crispy_field }}</div> <div class="col-12 mt-4">
<div class="form-icon-container mb-3">{{ form.invoice_unearned_account|as_crispy_field }}</div> <h4 class="mb-4 text-center">{% trans 'Default Bill Accounts' %}</h4>
</div> {{ form.bill_cash_account|as_crispy_field }}
</div> {{ form.bill_prepaid_account|as_crispy_field }}
<div class="row gx-3 mb-4 gy-6 gy-sm-3"> {{ form.bill_unearned_account|as_crispy_field }}
<div class="col-12">
<h4 class="mb-4">{% trans 'Default Bill Accounts' %}</h4>
<div class="form-icon-container mb-3">{{ form.bill_cash_account|as_crispy_field }}</div>
<div class="form-icon-container mb-3">{{ form.bill_prepaid_account|as_crispy_field }}</div>
<div class="form-icon-container mb-3">{{ form.bill_unearned_account|as_crispy_field }}</div>
</div>
</div>
<div class="text-center mb-6">
<div>
<button type="submit" class="btn btn-phoenix-primary"><i class="fa-solid fa-pen-to-square me-1"></i>{% trans 'Update' %}</button>
</div>
</div> </div>
</div> </div>
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-phoenix-primary btn-lg" type="submit">
<i class="fa-solid fa-pen-to-square me-1"></i>
{% trans 'Update' %}
</button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</main>
{% endblock %} {% endblock %}

View File

@ -8,22 +8,17 @@
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
<!----> <div class="col-md-6">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {% trans 'Create Bill' %}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <i class="fas fa-money-bills ms-2"></i>
<h3 class="mb-0 fs-4 text-center">
{% trans 'Create Bill' %}<span class="fas fa-money-bills ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form action="{{ form_action_url }}" method="post" id="djl-bill-model-create-form-id" class="needs-validation" novalidate>
<form action="{{ form_action_url }}" method="post" id="djl-bill-model-create-form-id">
<div class="card-body">
{% csrf_token %} {% csrf_token %}
{% if po_model %} {% if po_model %}
<div class="text-center mb-4"> <div class="text-center mb-4">
@ -36,22 +31,23 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="mb-4"> <div class="mb-4">
{{ form|crispy }} {{ form|crispy }}
</div> </div>
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'bill_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
</div> {{ _("Save") }}
</button>
<a href="{% url 'bill_list' request.dealer.slug%}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}

View File

@ -1,19 +1,20 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n static %}
{% load static %}
{% load django_ledger %} {% load django_ledger %}
{% load widget_tweaks %} {% load widget_tweaks %}
{% block content %} {% block content %}
<div class="container py-5"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="row justify-content-center"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="col-12 text-center mb-4"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<h1 class="display-4">{% trans 'Create Chart of Accounts' %}</h1> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 fw-bold text-center">
{% trans 'Create Chart of Accounts' %}
<i class="fa-solid fa-chart-pie ms-2"></i>
</h3>
</div> </div>
<div class="col-lg-6 col-md-8"> <div class="card-body p-4 p-md-5">
<div class="card shadow-sm"> <form method="post" id="{{ form.get_form_id }}" class="needs-validation" novalidate>
<div class="card-body p-4">
<form method="post" id="{{ form.get_form_id }}">
{% csrf_token %} {% csrf_token %}
{# Bootstrap form rendering #} {# Bootstrap form rendering #}
@ -38,17 +39,21 @@
{% endfor %} {% endfor %}
</div> </div>
<hr class="my-4">
<div class="d-flex justify-content-center gap-2 mt-4"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button type="submit" class="btn btn-phoenix-primary">Submit</button> <button type="submit" class="btn btn-phoenix-primary btn-lg me-md-2">
<a href="{% url 'coa-list' request.dealer.slug request.entity.slug %}" class="btn btn-phoenix-secondary"> <i class="fa-solid fa-plus me-1"></i>
{% trans 'Back' %} {% trans 'Create' %}
</button>
<a href="{% url 'coa-list' request.dealer.slug request.entity.slug %}"
class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans 'Cancel' %}
</a> </a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </main>
</div>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static crispy_forms_filters %} {% load i18n static crispy_forms_filters %}
{% block title %} {% block title %}
{% if object %} {% if object %}
{% trans 'Update Lead' %} {% trans 'Update Lead' %}
@ -7,6 +8,7 @@
{% trans 'Add New Lead' %} {% trans 'Add New Lead' %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block customcss %} {% block customcss %}
<style> <style>
.htmx-indicator{ .htmx-indicator{
@ -28,29 +30,32 @@
} }
</style> </style>
{% endblock customcss %} {% endblock customcss %}
{% block content %} {% block content %}
<div class="row justify-content-center mt-5 mb-3"> <main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
<div class="col-lg-8 col-md-10"> <div class="col-md-8">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 text-center"> <h3 class="mb-0 fs-4 fw-bold text-center">
{% if object %} {% if object %}
{{ _("Update Lead") }} {% trans "Update Lead" %}
<i class="fa-solid fa-edit ms-2"></i>
{% else %} {% else %}
{{ _("Create New Lead") }} {% trans "Create New Lead" %}
<i class="fa-solid fa-bullhorn ms-2"></i>
{% endif %} {% endif %}
<li class="fas fa-bullhorn text-primary ms-2"></li>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form class="form" method="post" enctype="multipart/form-data"> <form class="form" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2">
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit"> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }} {% trans "Save" %}
</button> </button>
<a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg"> <a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i> <i class="fa-solid fa-ban me-1"></i>
@ -61,18 +66,5 @@
</div> </div>
</div> </div>
</div> </div>
</div> </main>
<script>
document.addEventListener('DOMContentLoaded', function() {
const spinner = document.createElement('div');
spinner.id = 'spinner';
spinner.className = 'htmx-indicator spinner-border text-primary inline-spinner';
spinner.innerHTML = '<span class="visually-hidden">Loading...</span>';
const targetFieldDiv = document.getElementById('div_id_id_car_model');
if (targetFieldDiv) {
targetFieldDiv.parentNode.insertBefore(spinner, targetFieldDiv.nextSibling);
}
});
</script>
{% endblock %} {% endblock %}

View File

@ -1,42 +1,60 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n static %} {% load i18n static %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% block title %} {% block title %}
{# Check if an 'object' exists in the context #}
{% if object %} {% if object %}
{% trans 'Update Customer' %} {% trans 'Update Customer' %}
{% else %} {% else %}
{% trans 'Add New Customer' %} {% trans 'Add New Customer' %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row justify-content-center mt-5 mb-3"> <main class="d-flex align-items-center justify-content-center min-vh-100 py-5 ">
<div class="col-lg-8 col-md-10"> <div class="col-md-8">
<div class="card shadow-sm border-o rounded-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 text-center"> <h3 class="mb-0 fs-4 fw-bold text-center">
{% if customer.created %} {% if object %}
{{ _("Edit Customer") }} {% trans "Update Customer" %}
<i class="fa-solid fa-user-edit ms-2"></i>
{% else %} {% else %}
{{ _("Add Customer") }} {% trans "Add New Customer" %}
<i class="fa-solid fa-user-plus ms-2"></i>
{% endif %} {% endif %}
<i class="fa-solid fa-user ms-2 text-primary"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" <form method="post" class="form" enctype="multipart/form-data" novalidate>
class="form row g-3 needs-validation"
enctype="multipart/form-data"
novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> {% if form.errors %}
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <div class="alert alert-danger mt-4" role="alert">
<a href="{% url 'customer_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{% trans "Save" %}
</button>
<a href="{% url 'customer_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} </main>
{% endblock %}

View File

@ -5,32 +5,34 @@
{{ _("Update Dealer Information") }} {{ _("Update Dealer Information") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<!----> <div class="col-md-8">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {{ _("Update Dealer Information") }}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <i class="fas fa-car ms-2"></i>
<h3 class="mb-0 fs-4 text-center">
{{ _("Update Dealer Information") }}<span class="fas fa-car ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form hx-boost="false" method="post" enctype="multipart/form-data" class="needs-validation" novalidate> <form hx-boost="false" method="post" enctype="multipart/form-data" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'dealer_detail' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'dealer_detail' request.dealer.slug %}"
class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}

View File

@ -10,41 +10,49 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<!----> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="col-lg-8 col-md-10"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card shadow-sm border-0 rounded-3"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% if object %}
<h3 class="mb-0 fs-4 text-center"> {% trans "Update Group" %}
{% if staff.created %} <i class="fa-solid fa-user-group ms-2"></i>
{{ _("Edit Group") }}
{% else %} {% else %}
{{ _("Create Group") }} {% trans "Create Group" %}
<i class="fa-solid fa-user-plus ms-2"></i>
{% endif %} {% endif %}
<i class="fa-solid fa-user-group text-primary ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" class="needs-validation" novalidate>
<form class="row g-3 " method="post" class="form" novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}
{% for error in form.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
<hr class="my-2"> {% if form.errors %}
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="alert alert-danger mt-4" role="alert">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<a href="{% url 'group_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button class="btn btn-phoenix-primary btn-lg md-me-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}
</button>
<a href="{% url 'group_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}

View File

@ -6,44 +6,49 @@
{% trans "Groups" %} {% trans "Groups" %}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<main class="py-5">
{% if groups or request.GET.q%} <div class="container">
<section class=""> {% if groups or request.GET.q %}
<div class="row mt-4"> <div class="card border-0 rounded-4 animate__animated animate__fadeInUp">
<div class="col-auto"> <div class="card-header border-bottom d-flex flex-column flex-md-row justify-content-between align-items-md-center p-4">
<div class="d-md-flex justify-content-between"> <h5 class="card-title mb-2 mb-md-0 me-md-4 fw-bold"> <i class="fa-solid fa-user-group fs-3 me-1 text-primary "></i>{% trans "Groups" %}</h5>
<div> <div class="d-flex gap-2">
<a href="{% url 'group_create' request.dealer.slug %}" <a href="{% url 'group_create' request.dealer.slug %}"
class="btn btn-sm btn-phoenix-primary me-5"><span class="fas fa-plus me-2"></span>{% trans "Add Group" %}</a> class="btn btn-phoenix-primary">
<i class="fa-solid fa-user-group fs-9 me-1"></i>
<span class="fas fa-plus me-2"></span>{% trans "Add Group" %}
</a>
<a href="{% url 'user_list' request.dealer.slug %}" <a href="{% url 'user_list' request.dealer.slug %}"
class="btn btn-sm btn-phoenix-secondary"><span class="fas fas fa-arrow-left me-2"></span>{% trans "Back to Staffs" %}</a> class="btn btn-phoenix-secondary">
</div> <span class="fas fas fa-arrow-left me-2"></span>{% trans "Back to Staffs" %}
</a>
</div> </div>
</div> </div>
<div class="card-body p-0">
<div class="table-responsive scrollbar mx-n1 px-1 mt-3"> <div class="table-responsive scrollbar mx-n1 px-1 mt-3">
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-hover mb-0">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-light">
<th>{% trans 'name'|capfirst %}</th> <th scope="col" class="text-secondary text-uppercase fw-bold ps-4">{% trans 'name'|capfirst %}</th>
<th>{% trans 'total Users'|capfirst %}</th> <th scope="col" class="text-secondary text-uppercase fw-bold">{% trans 'total Users'|capfirst %}</th>
<th>{% trans 'total permission'|capfirst %}</th> <th scope="col" class="text-secondary text-uppercase fw-bold">{% trans 'total permission'|capfirst %}</th>
<th>{% trans 'actions'|capfirst %}</th> <th scope="col" class="text-secondary text-uppercase fw-bold text-end pe-4">{% trans 'actions'|capfirst %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for group in groups %} {% for group in groups %}
<tr> <tr>
<td class="align-middle white-space-nowrap ps-1">{{ group.name }}</td> <td class="align-middle white-space-nowrap ps-4">{{ group.name }}</td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<i class="fa-solid fa-users me-1"></i> {{ group.users.count }} <i class="fa-solid fa-users me-1"></i> {{ group.users.count }}
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<i class="fa-solid fa-unlock me-1"></i> {{ group.permissions.count }} <i class="fa-solid fa-unlock me-1"></i> {{ group.permissions.count }}
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap text-end pe-4">
<a class="btn btn-phoenix-success" <a class="btn btn-phoenix-secondary btn-sm"
href="{% url 'group_detail' request.dealer.slug group.id %}"> href="{% url 'group_detail' request.dealer.slug group.id %}">
<i class="fa-solid fa-eye"></i> <i class="fa-solid fa-eye me-1"></i>
{% trans 'view'|capfirst %} {% trans 'view'|capfirst %}
</a> </a>
</td> </td>
@ -52,16 +57,19 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
{% if page_obj.paginator.num_pages > 1 %} {% if page_obj.paginator.num_pages > 1 %}
<div class="d-flex justify-content-end mt-3"> <div class="card-footer bg-light border-top">
<div class="d-flex">{% include 'partials/pagination.html' %}</div> <div class="d-flex justify-content-end">
{% include 'partials/pagination.html' %}
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
</section>
{% else %} {% else %}
{% url "group_create" request.dealer.slug as create_group_url %} {% url "group_create" request.dealer.slug as create_group_url %}
{% include "empty-illustration-page.html" with value="group" url=create_group_url %} {% include "empty-illustration-page.html" with value="group" url=create_group_url %}
{% endif %} {% endif %}
</div>
</main>
{% endblock %} {% endblock %}

View File

@ -3,10 +3,10 @@
<nav class="navbar navbar-vertical navbar-expand-lg "> <nav class="navbar navbar-vertical navbar-expand-lg ">
<div class="collapse navbar-collapse" id="navbarVerticalCollapse"> <div class="collapse navbar-collapse" id="navbarVerticalCollapse">
<div class="navbar-vertical-content d-flex flex-column"> <div class="navbar-vertical-content d-flex flex-column">
<ul class="navbar-nav flex-column" id="navbarVerticalNav" hx-boost="true" hx-target="#main_content" hx-select="#main_content" hx-swap="outerHTML" hx-select-oob="#toast-container" hx-indicator="#spinner"> <ul class="navbar-nav flex-column" id="navbarVerticalNav" hx-boost="false" hx-target="#main_content" hx-select="#main_content" hx-swap="outerHTML" hx-select-oob="#toast-container" hx-indicator="#spinner">
<li class="nav-item"> <li class="nav-item">
<p class="navbar-vertical-label text-primary fs-8 text-truncate">{{request.dealer|default:"Apps"}}</p> {% comment %} <p class="navbar-vertical-label text-primary fs-8 text-truncate">{{request.dealer|default:"Apps"}}</p>
<hr class="navbar-vertical-line"> <hr class="navbar-vertical-line"> {% endcomment %}
{% if perms.inventory.can_view_inventory %} {% if perms.inventory.can_view_inventory %}
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a id="inventory-nav" class="nav-link dropdown-indicator label-1 inventory-nav" href="#nv-inventory" role="button" data-bs-toggle="collapse" aria-expanded="false" aria-controls="nv-inventory"> <a id="inventory-nav" class="nav-link dropdown-indicator label-1 inventory-nav" href="#nv-inventory" role="button" data-bs-toggle="collapse" aria-expanded="false" aria-controls="nv-inventory">
@ -386,7 +386,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item mb-4">
<a class="nav-link" href="#"> <a class="nav-link" href="#">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-robot"></span></span> <span class="nav-link-icon"><span class="fas fa-robot"></span></span>
@ -394,6 +394,19 @@
</div> </div>
</a> </a>
</li> </li>
<li class="nav-item ">
<a class="nav-link" href="#">
<div class="d-flex align-items-center">
{% if user.is_authenticated %}
<span class="nav-link-icon"><span class="fa-solid fa-car"></span></span>
<span class="nav-link-text">{{ request.dealer.user.username }}</span>
{% endif %}
</div>
</a>
</li>
</ul> </ul>
</div> </div>
@ -437,7 +450,7 @@
<div class="navbar-logo"> <div class="navbar-logo">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
{% with name_to_display=request.user.first_name|default:request.dealer.name %} {% with name_to_display=request.user.first_name|default:request.dealer.name %}
<h6 class="text-info ms-2 d-none d-sm-block fs-7" <h6 class="text-gray-600 ms-2 d-none d-sm-block fs-8"
data-bs-toggle="tooltip" data-bs-toggle="tooltip"
data-bs-placement="bottom" data-bs-placement="bottom"
title="{% trans 'Logged in as ' %}{{request.user.username }}"> title="{% trans 'Logged in as ' %}{{request.user.username }}">
@ -518,11 +531,12 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link px-3 d-block" href="{% url 'user_list' request.dealer.slug %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff & Groups") }}</a> <a class="nav-link px-3 d-block" href="{% url 'user_list' request.dealer.slug %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff & Groups") }}</a>
</li> </li>
<li class="nav-item"> {% comment %} <li class="nav-item">
<a class="nav-link px-3 d-block" href="{% url 'dealer_activity' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="lock"></span>{{ _("Activities") }}</a> <a class="nav-link px-3 d-block" href="{% url 'dealer_activity' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="lock"></span>{{ _("Activities") }}</a>
</li> </li> {% endcomment %}
{% endif %} {% endif %}
<li class="nav-item"> <li class="nav-item">
{% if request.is_dealer %} {% if request.is_dealer %}
<a class="nav-link px-3 d-block" href="{% url 'dealer_settings' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>{{ _("Settings") }}</a> <a class="nav-link px-3 d-block" href="{% url 'dealer_settings' request.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>{{ _("Settings") }}</a>
{% endif %} {% endif %}

View File

@ -1,16 +1,41 @@
<!-- templates/cars/car_confirm_delete.html -->
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% block title %}Delete Car{% endblock %} {% block title %}Delete Car{% endblock %}
{% block content %} {% block content %}
<div class="mt-4 ms-4"> <main class="d-flex align-items-center justify-content-center min-vh-50 py-5">
<h1>Delete Car</h1> <div class="col-md-6 ">
<p class="text-danger">Are you sure you want to delete the car "{{ car }}"?</p> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<form method="post">
<div class="card-body p-4 p-md-5 text-center bg-gradient">
<div class="mb-4">
<i class="fa-solid fa-triangle-exclamation text-danger" style="font-size: 2rem;"></i>
</div>
<h1 class="card-title fw-bold mb-3 fs-4">{% trans 'Confirm Deletion' %}</h1>
<p class="fs-7 mb-4">
{% trans "Are you absolutely sure you want to delete the car" %}
</p>
<p class="fs-6 mb-4">
"<strong class="">{{ car }}</strong>"?
</p>
<p class="fs-7 mb-4">
{% trans "This action is permanent and cannot be undone." %}
</p>
<form method="post" class="d-grid gap-3 d-sm-flex justify-content-sm-center">
{% csrf_token %} {% csrf_token %}
<button type="submit" class="btn btn-phoenix-danger">Confirm Delete</button> <button type="submit" class="btn btn-phoenix-danger btn-lg px-5">
<a href="{% url 'car_list' request.dealer.slug %}" <i class="fa-solid fa-trash-can me-2"></i>{% trans 'Confirm Delete' %}
class="btn btn-phoenix-secondary">{% trans 'Cancel' %}</a> </button>
<a href="{% url 'car_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg px-5">
<i class="fa-solid fa-ban me-2"></i>{% trans 'Cancel' %}
</a>
</form> </form>
</div> </div>
</div>
</div>
</main>
{% endblock %} {% endblock %}

View File

@ -76,12 +76,278 @@
{% if perms.inventory.view_car %} {% if perms.inventory.view_car %}
<div class="row-fluid {% if car.status == 'sold' %}disabled{% endif %}"> <div class="row-fluid {% if car.status == 'sold' %}disabled{% endif %}">
<div class="row g-3 justify-content-between"> <div class="row g-3 justify-content-between">
<div class="col-lg-12 col-xl-6">
<div class="avatar avatar-5xl mb-3">
<img class="rounded h-100 w-100" <div class="col-md-6">
src="{% static 'images/cars/' %}{{ car.vin }}.png" <div class="row mb-2">
<div class="col-md-4">
<div class="avatar avatar-6xl mb-3">
<img class="rounded"
src="{% static 'images/car_images/' %}{{ car.get_hash }}.png"
alt="{{ car.vin }}" /> alt="{{ car.vin }}" />
</div> </div>
</div>
<div class="col-md-8">
<div class="card rounded shadow d-flex align-content-center
{% if car.get_transfer %}transfer{% endif %}">
<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.marked_price %}
<tr>
<th>{% trans "Cost Price"|capfirst %}</th>
<td>{{ car.cost_price|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Marked Price"|capfirst %}</th>
<td>{{ car.marked_price|floatformat:2 }}</td>
</tr>
{% comment %} <tr>
<th>{% trans "Selling Price"|capfirst %}</th>
<td>{{ car.finances.selling_price|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Discount Amount"|capfirst %}</th>
<td>{{ car.finances.discount_amount|floatformat:2 }}</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.price_|floatformat:2 }}</td>
</tr>
{% endfor %}
{% endif %}
<tr>
<th>{% trans "VAT Amount"|capfirst %}</th>
<td>{{ car.finances.vat_amount|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Total"|capfirst %}</th>
<td>{{ car.finances.total_vat|floatformat:2 }}</td>
</tr> {% endcomment %}
<tr>
<td colspan="2">
{% if not car.get_transfer %}
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</td>
</tr>
{% else %}
<p>{% trans "No finance details available." %}</p>
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-success btn-sm mb-3">{% trans "Add" %}</a>
{% endif %}
</table>
</div>
</div>
</div>
</div>
</div>
{% if perms.inventory.view_carcolors %}
<div class="card rounded shadow d-flex align-content-center mt-3
{% if car.get_transfer %}transfer{% endif %}">
<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">
<!--test-->
{% if car.colors %}
<tr>
<th>{% trans 'Exterior' %}</th>
<td>
<span>{{ car.colors.exterior.get_local_name }}</span>
</td>
<td class="align-middle">
<div class="text-end color-div"
style="background-color: rgb({{ car.colors.exterior.rgb }})">
</div>
</td>
</tr>
<tr>
<th>{% trans 'Interior' %}</th>
<td>
<span>{{ car.colors.interior.get_local_name }}</span>
</td>
<td class="align-middle">
<div class="text-end color-div"
style="background-color: rgb({{ car.colors.interior.rgb }})">
</div>
</td>
</tr>
{% if perms.inventory.change_carcolors %}
<tr>
<td colspan="2">
{% if not car.get_transfer %}
<a href="{% url 'car_colors_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</td>
</tr>
{% endif %}
{% else %}
<tr>
<td colspan="2">
<p>{% trans "No color details available." %}</p>
{% if perms.inventory.add_carcolors %}
<a class="btn btn-phoenix-success btn-sm mb-3"
href="{% url 'add_color' request.dealer.slug car.slug %}">{{ _("Add Color") }}</a>
{% endif %}
</td>
</tr>
{% endif %}
<!--test-->
</table>
</div>
</div>
</div>
{% endif %}
{% if car.status != 'transfer' %}
{% if perms.inventory.view_carreservation %}
<div class="card rounded shadow d-flex align-content-center mt-3 h-full w-100">
<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>
{% if perms.inventory.change_carreservation %}
<td>
{% if reservation.is_active %}
<form method="post"
action="{% url 'reservations' request.dealer.slug reservation.id %}">
{% csrf_token %}
<div class="btn-group">
<button type="submit"
name="action"
value="renew"
class="btn btn-sm btn-phoenix-success px-3 py-1">
{% trans "Renew" %}
</button>
<button type="submit"
name="action"
value="cancel"
class="btn btn-sm btn-phoenix-secondary px-3 py-1">
{% trans "Cancel" %}
</button>
</div>
</form>
{% else %}
<span class="badge badge-phoenix badge-phoenix-danger fs-10">{% trans "Expired" %}</span>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
{% else %}
{% if perms.inventory.add_carreservation %}
<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>
{% endif %}
</tbody>
{% endif %}
</table>
</div>
</div>
</div>
{% endif %}
{% endif %}
<!-- Transfer Table -->
{% if car.status == 'transfer' and car.get_transfer %}
<div class="card rounded shadow d-flex align-content-center mt-3">
<p class="card-header rounded-top fw-bold">{% trans 'Transfer Details' %}</p>
<div class="card-body">
<div class="table-responsive scrollbar mb-3">
<table class="table table-sm fs-9 mb-0 overflow-hidden">
<thead>
<tr>
<th>{% trans "Action" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "From Showroom" %}</th>
<th>{% trans "To Showroom" %}</th>
<th>{% trans 'Date' %}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="badge badge-phoenix badge-phoenix-info">{% trans "Transfer" %}</span>
</td>
<td>
{% if car.get_transfer.status == "draft" %}
<span class="badge badge-phoenix badge-phoenix-warning">{% trans "waiting for approval" %}</span>
{% elif car.get_transfer.status == "approved" %}
<span class="badge badge-phoenix badge-phoenix-info">{% trans "waiting for dealer acceptance" %}</span>
{% endif %}
</td>
<td>{{ car.get_transfer.from_dealer|title }}</td>
<td>{{ car.get_transfer.to_dealer|title }}</td>
<td>{{ car.get_transfer.transfer_date|date:"Y-m-d" }}</td>
<td>
{% if car.get_transfer.status == "draft" %}
<a class="btn btn-sm btn-phoenix-success"
href="{% url 'transfer_detail' car.get_transfer.pk %}">{% trans "Approve" %}</a>
{% endif %}
</td>
<td>
<a class="btn btn-sm btn-phoenix-success"
href="{% url 'transfer_detail' car.get_transfer.pk %}?action=cancel">{% trans "Cancel" %}</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</div>
<div class="col-md-6">
<div class="card mb-3 rounded shadow d-flex align-content-center <div class="card mb-3 rounded shadow d-flex align-content-center
{% if car.get_transfer %}disabled{% endif %}"> {% if car.get_transfer %}disabled{% endif %}">
<p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p> <p class="card-header rounded-top fw-bold">{% trans 'Car Details' %}</p>
@ -234,7 +500,7 @@
{% if not car.get_transfer %} {% if not car.get_transfer %}
{% if perms.inventory.change_car %} {% if perms.inventory.change_car %}
<a href="{% url 'car_update' request.dealer.slug car.slug %}" <a href="{% url 'car_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-primary btn-sm mt-1">{% trans "Edit" %} class="btn btn-phoenix-primary btn-sm mt-1 me-3 mb-3">{% trans "Edit" %}
<span class="fas fa-solid fa-pencil ms-1"></span> <span class="fas fa-solid fa-pencil ms-1"></span>
</a> </a>
<a href="{% url 'transfer' car.slug %}" <a href="{% url 'transfer' car.slug %}"
@ -249,257 +515,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-6 col-xl-6">
{% if perms.inventory.view_carfinance %}
<div class="card rounded shadow d-flex align-content-center
{% if car.get_transfer %}transfer{% endif %}">
<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.marked_price %}
<tr>
{% if perms.inventory.view_carfinance %}
<th>{% trans "Cost Price"|capfirst %}</th>
<td>{{ car.cost_price|floatformat:2 }}</td>
{% endif %}
</tr>
<tr>
<th>{% trans "Marked Price"|capfirst %}</th>
<td>{{ car.marked_price|floatformat:2 }}</td>
</tr>
{% comment %} <tr>
<th>{% trans "Selling Price"|capfirst %}</th>
<td>{{ car.finances.selling_price|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Discount Amount"|capfirst %}</th>
<td>{{ car.finances.discount_amount|floatformat:2 }}</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.price_|floatformat:2 }}</td>
</tr>
{% endfor %}
{% endif %}
<tr>
<th>{% trans "VAT Amount"|capfirst %}</th>
<td>{{ car.finances.vat_amount|floatformat:2 }}</td>
</tr>
<tr>
<th>{% trans "Total"|capfirst %}</th>
<td>{{ car.finances.total_vat|floatformat:2 }}</td>
</tr> {% endcomment %}
{% if perms.inventory.change_carfinance %}
<tr>
<td colspan="2">
{% if not car.get_transfer %}
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</td>
</tr>
{% endif %}
{% else %}
<p>{% trans "No finance details available." %}</p>
{% if perms.inventory.add_carfinance %}
<a href="{% url 'car_finance_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-success btn-sm mb-3">{% trans "Add" %}</a>
{% endif %}
{% endif %}
</table>
</div>
</div>
</div>
{% endif %}
{% if perms.inventory.view_carcolors %}
<div class="card rounded shadow d-flex align-content-center mt-3
{% if car.get_transfer %}transfer{% endif %}">
<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">
<!--test-->
{% if car.colors %}
<tr>
<th>{% trans 'Exterior' %}</th>
<td>
<span>{{ car.colors.exterior.get_local_name }}</span>
</td>
<td class="align-middle">
<div class="text-end color-div"
style="background-color: rgb({{ car.colors.exterior.rgb }})">
</div>
</td>
</tr>
<tr>
<th>{% trans 'Interior' %}</th>
<td>
<span>{{ car.colors.interior.get_local_name }}</span>
</td>
<td class="align-middle">
<div class="text-end color-div"
style="background-color: rgb({{ car.colors.interior.rgb }})">
</div>
</td>
</tr>
{% if perms.inventory.change_carcolors %}
<tr>
<td colspan="2">
{% if not car.get_transfer %}
<a href="{% url 'car_colors_update' request.dealer.slug car.slug %}"
class="btn btn-phoenix-warning btn-sm mb-3">{% trans "Edit" %}</a>
{% else %}
<span class="badge bg-danger">{% trans "Cannot Edit, Car in Transfer." %}</span>
{% endif %}
</td>
</tr>
{% endif %}
{% else %}
<tr>
<td colspan="2">
<p>{% trans "No color details available." %}</p>
{% if perms.inventory.add_carcolors %}
<a class="btn btn-phoenix-success btn-sm mb-3"
href="{% url 'add_color' request.dealer.slug car.slug %}">{{ _("Add Color") }}</a>
{% endif %}
</td>
</tr>
{% endif %}
<!--test-->
</table>
</div>
</div>
</div>
{% endif %}
{% if car.status != 'transfer' %}
{% if perms.inventory.view_carreservation %}
<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>
{% if perms.inventory.change_carreservation %}
<td>
{% if reservation.is_active %}
<form method="post"
action="{% url 'reservations' request.dealer.slug reservation.id %}">
{% csrf_token %}
<div class="btn-group">
<button type="submit"
name="action"
value="renew"
class="btn btn-sm btn-phoenix-success px-3 py-1">
{% trans "Renew" %}
</button>
<button type="submit"
name="action"
value="cancel"
class="btn btn-sm btn-phoenix-secondary px-3 py-1">
{% trans "Cancel" %}
</button>
</div>
</form>
{% else %}
<span class="badge badge-phoenix badge-phoenix-danger fs-10">{% trans "Expired" %}</span>
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
{% else %}
{% if perms.inventory.add_carreservation %}
<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>
{% endif %}
</tbody>
{% endif %}
</table>
</div>
</div>
</div>
{% endif %}
{% endif %}
<!-- Transfer Table -->
{% if car.status == 'transfer' and car.get_transfer %}
<div class="card rounded shadow d-flex align-content-center mt-3">
<p class="card-header rounded-top fw-bold">{% trans 'Transfer Details' %}</p>
<div class="card-body">
<div class="table-responsive scrollbar mb-3">
<table class="table table-sm fs-9 mb-0 overflow-hidden">
<thead>
<tr>
<th>{% trans "Action" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "From Showroom" %}</th>
<th>{% trans "To Showroom" %}</th>
<th>{% trans 'Date' %}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="badge badge-phoenix badge-phoenix-info">Transfer</span>
</td>
<td>
{% if car.get_transfer.status == "draft" %}
<span class="badge badge-phoenix badge-phoenix-warning">waiting for approval</span>
{% elif car.get_transfer.status == "approved" %}
<span class="badge badge-phoenix badge-phoenix-info">waiting for dealer acceptance</span>
{% endif %}
</td>
<td>{{ car.get_transfer.from_dealer|title }}</td>
<td>{{ car.get_transfer.to_dealer|title }}</td>
<td>{{ car.get_transfer.transfer_date|date:"Y-m-d" }}</td>
<td>
{% if car.get_transfer.status == "draft" %}
<a class="btn btn-sm btn-phoenix-success"
href="{% url 'transfer_detail' car.get_transfer.pk %}">Approve</a>
{% endif %}
</td>
<td>
<a class="btn btn-sm btn-phoenix-success"
href="{% url 'transfer_detail' car.get_transfer.pk %}?action=cancel">Cancel</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
</div>
</div> </div>
{% if car.status == 'sold' %} {% if car.status == 'sold' %}
<img class="car_status" <img class="car_status"
src="{% static 'images/sold.png' %}" src="{% static 'images/sold.png' %}"
@ -508,6 +527,7 @@
alt=""> alt="">
{% endif %} {% endif %}
</div> </div>
<!-- Custom Card Modal --> <!-- Custom Card Modal -->
<div class="modal fade" <div class="modal fade"
id="customCardModal" id="customCardModal"

View File

@ -6,34 +6,34 @@
{% trans 'Edit Car' %} {% trans 'Edit Car' %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<!----> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{% trans 'Edit Car' %} {% trans 'Edit Car' %}
<span class="fas fa-solid fa-car text-primary ms-2"></span> <i class="fas fa-solid fa-car ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" class="needs-validation" novalidate> <form method="post" class="needs-validation" novalidate>
{% csrf_token %} {{ form|crispy }} {% csrf_token %}
<!-- Save and Back Buttons --> {{ form|crispy }}
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'car_detail' request.dealer.slug car.slug %}"
class="btn btn-phoenix-danger btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}

View File

@ -1,33 +1,33 @@
{% extends 'base.html' %} {% extends "base.html" %}
{% load crispy_forms_filters %}
{% load i18n %} {% load i18n %}
{% load crispy_forms_filters %}
{% load custom_filters %} {% load custom_filters %}
{% block title %} {% block title %}
{% trans "Car Finance Details" %} {% trans "Car Finance Details" %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<!----> <div class="col-md-8">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="col-lg-8 col-md-10"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card shadow-sm border-0 rounded-3"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% trans "Finance Details for" %}
<h3 class="mb-0 fs-4 text-center"> <span class="text-gray-300">{{car.id_car_make.name}}&nbsp;{{car.id_car_model.name}}&nbsp;{{car.id_car_serie.serie}}&nbsp;{{car.year}}</span>
{% trans "Finance Details for" %}<span class="fas fa-solid fa-car text-primary ms-2"></span>&nbsp;{{ car.id_car_make.get_local_name }} - {{ car.id_car_model.get_local_name }} <i class="fas fa-solid fa-car ms-2"></i>
</h3> </h3>
<p class="text-center mt-1">VIN:&nbsp;&nbsp;{{car.vin}}</p>
</div>
<div class="card-body p-4 p-md-5">
{% if form.errors %} {% if form.errors %}
<div class="alert alert-danger"> <div class="alert alert-danger mt-4" role="alert">
<ul> <h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
{% for field in form %} <ul class="mb-0">
{% for error in field.errors %}<li>{{ field.label }}: {{ error }}</li>{% endfor %} {% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %} {% endfor %}
{% for error in form.non_field_errors %}<li>{{ error }}</li>{% endfor %}
</ul> </ul>
</div> </div>
{% endif %} {% endif %}
</div>
<div class="card-body bg-light-subtle">
<form method="post" class="needs-validation" novalidate> <form method="post" class="needs-validation" novalidate>
<div class="row g-1"> <div class="row g-1">
<div class="col-lg-4 col-xl-12"> <div class="col-lg-4 col-xl-12">
@ -35,16 +35,20 @@
{{ form|crispy }} {{ form|crispy }}
</div> </div>
</div> </div>
<hr class="my-4">
<hr class="my-2">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'car_detail' request.dealer.slug car.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
<!-- JavaScript Section -->
{% endblock %} {% endblock %}

View File

@ -24,7 +24,6 @@
</style> </style>
{% endblock customCSS %} {% endblock customCSS %}
{% block content %} {% block content %}
{% if cars or request.GET.q%} {% if cars or request.GET.q%}
<div class="container-fluid" id="projectSummary"> <div class="container-fluid" 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">
@ -199,7 +198,7 @@
<div class="col-auto"> <div class="col-auto">
<div class="avatar avatar-3xl"> <div class="avatar avatar-3xl">
<img class="rounded-soft shadow shadow-lg" <img class="rounded-soft shadow shadow-lg"
src="{% static 'images/cars/' %}{{ car.vin }}.png" src="{% static 'images/car_images/' %}{{ car.get_hash }}.png"
alt="{{ car.vin }}" /> alt="{{ car.vin }}" />
</div> </div>
</div> </div>
@ -269,11 +268,11 @@
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a class="dropdown-item" <a class="dropdown-item"
href="{% url 'car_detail' request.dealer.slug car.slug %}"> <span class="fas fa-eye me-2"></span>{{ _("View") }} </a> href="{% url 'car_detail' request.dealer.slug car.slug %}"> <span class="fas fa-eye me-2"></span>{{ _("View") }} </a>
{% if perms.inventory.change_car %} {% if perms.inventory.change_car and not car.status == 'sold' %}
<a class="dropdown-item" <a class="dropdown-item"
href="{% url 'car_update' request.dealer.slug car.slug %}"> <span class="fas fa-edit me-2"></span>{{ _("Edit") }} </a> href="{% url 'car_update' request.dealer.slug car.slug %}"> <span class="fas fa-edit me-2"></span>{{ _("Edit") }} </a>
{% endif %} {% endif %}
{% if perms.inventory.delete_car %} {% if perms.inventory.delete_car and not car.status == 'sold' %}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" <a class="dropdown-item text-danger"
href="{% url 'car_delete' request.dealer.slug car.slug %}"> <span class="fas fa-trash me-2"></span>{{ _("Remove") }} </a> href="{% url 'car_delete' request.dealer.slug car.slug %}"> <span class="fas fa-trash me-2"></span>{{ _("Remove") }} </a>
@ -312,4 +311,3 @@
{% endblock %} {% endblock %}

View File

@ -6,31 +6,35 @@
{{ _("Add New Expense") }} {{ _("Add New Expense") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<!----> <div class="col-md-6">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{{ _("Add Expense") }} {{ _("Add Expense") }}
<span class="fas fa-money-bill-wave ms-2 text-primary"></span> <i class="fas fa-money-bill-wave ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" action=""> <form method="post" action="" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'item_expense_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'item_expense_list' request.dealer.slug %}"
class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock content %} {% endblock content %}

View File

@ -6,48 +6,34 @@
{{ _("Update Expense") }} {{ _("Update Expense") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
{% comment %} <div class="row"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="row justify-content-center"> <div class="col-md-6">
<div class="col-md-8"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card-header">{{ _("Update Expense") }}</div> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-body">
<form method="post" action="">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button>
</form>
</div>
</div>
</div>
</div>
</div> {% endcomment %}
<!---->
<div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{{ _("Update Expense") }} {{ _("Update Expense") }}
<span class="fas fa-money-bill-wave ms-2 text-primary"></span> <i class="fas fa-money-bill-wave ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" action="" class="needs-validation" novalidate>
<form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'item_expense_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'item_expense_list' request.dealer.slug %}"
class="btn btn-phoenix-danger btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock content %} {% endblock content %}

View File

@ -11,39 +11,50 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
<!----> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {% if object %}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% trans "Update Service" %}
<h3 class="mb-0 fs-4 text-center"> <i class="fas fa-tools ms-2"></i>
{% if service.pk %}
{{ _("Update Service") }}
{% else %} {% else %}
{{ _("Add Service") }} {% trans "Add New Service" %}
<i class="fas fa-tools ms-2"></i>
{% endif %} {% endif %}
<span class="fas fa-tools ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" action="" class="needs-validation" novalidate>
<form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> {% if form.errors %}
<div class="alert alert-danger mt-4" role="alert">
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'item_service_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'item_service_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock content %} {% endblock content %}

View File

@ -10,41 +10,50 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
<!----> <div class="col-md-8">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="col-lg-8 col-md-10"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card shadow-sm border-0 rounded-3"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% if object %}
<h3 class="mb-0 fs-4 text-center"> {% trans "Update Bank Account" %}
{% if customer.created %} <i class="fa-solid fa-bank ms-2"></i>
{{ _("Edit Bank Account") }}
{% else %} {% else %}
{{ _("Add Bank Account") }} {% trans "Add New Bank Account" %}
<i class="fa-solid fa-bank ms-2"></i>
{% endif %} {% endif %}
<span class="fas fa-bank ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" class="needs-validation" novalidate>
<form method="post" class="form" novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
{% for error in form.errors %}
<div class="text-danger">{{ error }}</div> {% if form.errors %}
<div class="alert alert-danger mt-4" role="alert">
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %} {% endfor %}
<hr class="my-2"> </ul>
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{% url 'bank_account_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{% trans "Save" %}
</button>
<a href="{% url 'bank_account_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}

View File

@ -34,8 +34,26 @@
<td class="align-middle product white-space-nowrap">{{ bank.account_type|capfirst }}</td> <td class="align-middle product white-space-nowrap">{{ bank.account_type|capfirst }}</td>
<td class="align-middle product white-space-nowrap"> <td class="align-middle product white-space-nowrap">
{% if perms.django_ledger.change_bankaccountmodel %} {% if perms.django_ledger.change_bankaccountmodel %}
<a href="{% url 'bank_account_update' request.dealer.slug bank.pk %}"
class="btn btn-sm btn-phoenix-success">{% trans "Update" %}</a> <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 'bank_account_update' request.dealer.slug bank.pk %}" >
<i class="fa fa-edit me-2"></i>{% trans "Update" %}
</a>
<a class="text-danger dropdown-item" href="#" >
<i class="fa fa-trash me-2"></i>{% trans "Delete" %}
</a>
</div>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>

View File

@ -5,42 +5,36 @@
{{ _("Create Journal Entry") }} {{ _("Create Journal Entry") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
{% comment %} <div class="row mt-4"> <main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
<h3 class="text-center">{% trans "Create Journal Entry" %}</h3> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<form id="mainForm" method="post" class="needs-validation"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 fw-bold text-center">
{% trans "Create Journal Entry" %}
<i class="fas fa-book-open ms-2"></i>
</h3>
</div>
<div class="card-body p-4 p-md-5">
<form id="mainForm" method="post" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
<div class="row g-3"> <div class="row g-3">
{{ form|crispy }} {{ form|crispy }}
</div> </div>
<div class="mt-5 text-center"> <hr class="my-4">
<button type="submit" class="btn btn-phoenix-success me-2"><i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}</button>
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" class="btn btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
</div>
</form>
</div> {% endcomment %}
<!---->
<div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center text-white">{% trans "Create Journal Entry" %}</h3>
</div>
<div class="card-body bg-light-subtle">
<form id="mainForm" method="post" class="needs-validation">
{% csrf_token %}
<div class="row g-3">{{ form|crispy }}</div>
<hr class="my-2">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }} <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button> </button>
<a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}" <a href="{% url 'journalentry_list' request.dealer.slug ledger.pk %}"
class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a> class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </main>
<!---->
{% endblock content %} {% endblock content %}

View File

@ -5,38 +5,36 @@
{{ _("Create Ledger") }} {{ _("Create Ledger") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<!----> <main class="d-flex align-items-center justify-content-center min-vh-100 py-5 ">
<div class="row justify-content-center mt-5 mb-3"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="col-lg-8 col-md-10"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card shadow-sm border-0 rounded-3"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{% trans "Create Ledger" %} {% trans "Create Ledger" %}
<span class="fas fa-book-open ms-2 text-primary"></span> <i class="fas fa-book-open ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form id="mainForm" method="post" class="needs-validation" novalidate>
<form id="mainForm" method="post" class="needs-validation">
{% csrf_token %} {% csrf_token %}
<div class="row g-3"> <div class="row g-3">
{{ form|crispy }} {{ form|crispy }}
</div> </div>
<hr class="my-2"> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'ledger_list' request.dealer.slug request.entity.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'ledger_list' request.dealer.slug request.entity.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock content %} {% endblock content %}

View File

@ -4,37 +4,69 @@
{% trans "Organization Details" %} {% trans "Organization Details" %}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<div class="row my-4"> <main class="py-5 min-vh-80 d-flex justify-content-center align-items-center">
<h2 class="mb-2">{{ organization.get_local_name }}</h2> <div class="container py-4">
<ul class="list-group mb-4"> <div class="row justify-content-center">
<li class="list-group-item"> <div class="col-12 col-lg-8 col-xl-6">
<strong>{% trans "CRN" %}:</strong> {{ organization.crn }} <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h2 class="card-title mb-0 fs-3 fw-bold text-center">
<i class="fas fa-building me-2"></i>
{{ organization.get_local_name }}
</h2>
</div>
<div class="card-body p-4 p-md-5">
<ul class="list-group list-group-flush rounded-3 border">
<li class="list-group-item d-flex justify-content-between align-items-center p-3">
<div class=" fw-semibold">
<i class="fas fa-id-card-alt me-2 text-primary"></i>
{% trans "CRN" %}:
</div>
<span class="">{{ organization.crn }}</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item d-flex justify-content-between align-items-center p-3">
<strong>{% trans "VRN" %}:</strong> {{ organization.vrn }} <div class=" fw-semibold">
<i class="fas fa-receipt me-2 text-primary"></i>
{% trans "VRN" %}:
</div>
<span class="">{{ organization.vrn }}</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item d-flex justify-content-between align-items-center p-3">
<strong>{% trans "Phone" %}:</strong> {{ organization.phone_number }} <div class="fw-semibold">
<i class="fas fa-phone-alt me-2 text-primary"></i>
{% trans "Phone" %}:
</div>
<span class="">{{ organization.phone_number }}</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item d-flex justify-content-between align-items-center p-3">
<strong>{% trans "Address" %}:</strong> {{ organization.address }} <div class="fw-semibold">
<i class="fas fa-map-marker-alt me-2 text-primary"></i>
{% trans "Address" %}:
</div>
<span class=" text-end ms-3">{{ organization.address }}</span>
</li> </li>
</ul> </ul>
<div class="d-flex">
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center mt-4 pt-2">
{% if perms.inventory.change_organization %} {% if perms.inventory.change_organization %}
<a href="{% url 'organization_update' request.dealer.slug organization.slug %}" <a href="{% url 'organization_update' request.dealer.slug organization.slug %}"
class="btn btn-sm btn-phoenix-primary me-2"><span class="fas fa-edit me-1"></span>{% trans "Edit" %}</a> class="btn btn-phoenix-primary btn-lg flex-grow-1"><i class="fas fa-edit me-2"></i>{% trans "Edit Details" %}</a>
{% endif %} {% endif %}
{% if perms.inventory.delete_organization %} {% if perms.inventory.delete_organization %}
<button class="btn btn-phoenix-danger btn-sm delete-btn" <button class="btn btn-phoenix-danger btn-lg delete-btn flex-grow-1"
data-url="{% url 'organization_delete' request.dealer.slug organization.slug %}" data-url="{% url 'organization_delete' request.dealer.slug organization.slug %}"
data-message="Are you sure you want to delete this organization?" data-message="Are you sure you want to delete this organization?"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#deleteModal"> data-bs-target="#deleteModal">
<i class="fas fa-trash me-1"></i> {% trans 'Delete' %} <i class="fas fa-trash me-2"></i>{% trans 'Delete' %}
</button> </button>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% include 'modal/delete_modal.html' %} </div>
</div>
</div>
</div>
</main>
{% include 'modal/delete_modal.html' %}
{% endblock %} {% endblock %}

View File

@ -1,44 +1,61 @@
{% extends 'base.html' %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% block title %} {% block title %}
{# Check if an 'object' exists in the context #}
{% if object %} {% if object %}
{% trans 'Update Organization' %} {% trans 'Update Organization' %}
{% else %} {% else %}
{% trans 'Add New Organization' %} {% trans 'Add New Organization' %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row justify-content-center mt-5 mb-3"> <main class="d-flex align-items-center justify-content-center min-vh-100 py-5">
<div class="col-lg-8 col-md-10"> <div class="col-md-8">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 text-center"> <h3 class="mb-0 fs-4 fw-bold text-center">
{% if object %} {% if object %}
{% trans 'Update Organization'%} {% trans 'Update Organization' %}
<i class="fa-solid fa-edit ms-2"></i>
{% else %} {% else %}
{% trans 'Add New Organization'%} {% trans 'Add New Organization' %}
<i class="fa-solid fa-building ms-2"></i>
{% endif %} {% endif %}
<span class=" fas fa-solid fa-city ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form class="form" method="post" enctype="multipart/form-data"> <form class="form" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> {% if form.errors %}
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="alert alert-danger mt-4" role="alert">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<a href="{% url 'organization_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{% trans "Save" %}
</button>
<a href="{% url 'organization_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</main>
{% endblock %} {% endblock %}

View File

@ -1,60 +1,39 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n crispy_forms_filters %} {% load i18n crispy_forms_filters %}
{% block title %} {% block title %}
{% trans 'Billing Information' %}{% endblock %} {% trans 'Billing Information' %}
{% block content %} {% endblock %}
{% comment %} <div class="row mb-3"> {% block content %}
<div class="col-sm-6"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="post" class="form"> <div class="col-md-8">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3>{% trans "Provide billing data"|upper %}</h3> <h3 class="mb-0 fs-4 fw-bold text-center">
{% csrf_token %} {% trans "Provide billing data"|upper %}
{{ form|crispy }} <i class="fas fa-file-invoice-dollar ms-2"></i>
<button type="submit" class="btn btn-sm btn-phoenix-success me-2">
<i class="fa fa-save me-1"></i>{{ _("Save") }}
</button>
{% if object %}
<a class="btn btn-sm btn-phoenix-danger " href="{% url 'billing_info_delete' %}"><i class="fa-solid fa-trash me-1"></i> {{ _("Delete") }}</a>
{% endif %}
</form>
</div>
</div> {% endcomment %}
<!---->
<div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3">
<h3 class="mb-0 fs-4 text-center">
{% trans "Provide billing data"|upper %}<span class="fas fa-file-invoice-dollar ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}"
method="post" class="needs-validation" novalidate>
<form action="{% url 'billing_info' %}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="post" class="form">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-4">
<hr class="my-2">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
{% if object %} {% if object %}
<a class="btn btn-lg btn-phoenix-danger" href="{% url 'billing_info_delete' %}"><i class="fa-solid fa-trash me-1"></i> {{ _("Delete") }}</a> <a class="btn btn-phoenix-danger btn-lg" href="{% url 'billing_info_delete' %}">
<i class="fa-solid fa-trash me-1"></i>
{{ _("Delete") }}
</a>
{% endif %} {% endif %}
</div> </div>
</form> </form>
</div> </div>
</div> </div>
<!----> </div>
{% endblock %} </main>
{% endblock %}

View File

@ -280,7 +280,7 @@
<tr class="bg-body-secondary total-sum"> <tr class="bg-body-secondary total-sum">
<td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Vat" %} ({{ data.vat_rate }})</td> <td class="align-middle ps-4 fw-semibold text-body-highlight" colspan="7">{% trans "Vat" %} ({{ data.vat_rate }})</td>
<td class="align-middle text-start fw-semibold"> <td class="align-middle text-start fw-semibold">
<span id="">+ {{ data.vat_amount }}<span class="icon-saudi_riyal"></span></span> <span id="">+ {{ data.vat_amount|floatformat:2 }}<span class="icon-saudi_riyal"></span></span>
</td> </td>
</tr> </tr>
<tr class="bg-body-secondary total-sum"> <tr class="bg-body-secondary total-sum">

View File

@ -121,7 +121,7 @@
width: 0; width: 0;
} }
</style> </style>
<div class="row justify-content-center mt-5 mb-3"> <div class="row d-flex justify-content-center align-items-center mt-5 mb-3 ms-6 ps-3" >
<div class="row"> <div class="row">
<div class="col"> <div class="col">
{% if not items %} {% if not items %}
@ -137,19 +137,19 @@
{% endif %} {% endif %}
</div> </div>
<div> <div>
<div class="col-lg-12 col-md-10 needs-validation {% if not items or not customer_count %}d-none{% endif %}"> <div class="col-md-10 ms-4 needs-validation {% if not items or not customer_count %}d-none{% endif %}">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 text-center"> <h3 class="mb-0 fs-4 text-center">
{% trans "Create Quotation" %}<i class="fa-regular fa-file-lines text-primary ms-2"></i> {% trans "Create Quotation" %}<i class="fa-regular fa-file-lines ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form id="mainForm" method="post" class="needs-validation {% if not items and not customer_count %}d-none{% endif %}"> <form id="mainForm" method="post" class="needs-validation {% if not items and not customer_count %}d-none{% endif %}">
{% csrf_token %} {% csrf_token %}
<div class="row g-3 col-12"> <div class="row g-3">
{{ form|crispy }} {{ form|crispy }}
<div class="custom-select"> <div class="custom-select">
<!-- Hidden native select for form submission --> <!-- Hidden native select for form submission -->

View File

@ -6,20 +6,33 @@
{{ _("Sale Order") }} {{ _("Sale Order") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<div class="row"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="row justify-content-center"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="col-md-8"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card-header">{{ _("Sale Order") }}</div> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-body"> {{ _("Create Sale Order") }}
<form method="post" action="{% url 'create_sale_order' request.dealer.slug estimate.pk %}"> <i class="fas fa-file-invoice-dollar ms-2"></i>
</h3>
</div>
<div class="card-body p-4 p-md-5">
<form method="post" action="{% url 'create_sale_order' request.dealer.slug estimate.pk %}" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button> <hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<i class="fa-solid fa-floppy-disk me-1"></i>
{% trans 'Save' %}
</button>
<a href="{% url 'home' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </main>
</div>
{% endblock content %} {% endblock content %}

View File

@ -6,30 +6,34 @@
{{ _("Invoice") }} {{ _("Invoice") }}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<div class="row paid justify-content-center mt-5 mb-3"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-lg-8 col-md-10"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 text-center"> <h3 class="mb-0 fs-4 fw-bold text-center">
{{ _("Add Invoice") }}<i class="fa-solid fa-receipt ms-2 text-primary"></i> {{ _("Add Invoice") }}
<i class="fa-solid fa-receipt ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form method="post" action="" class="needs-validation" novalidate>
<form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-4">
<hr class="my-2">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-success md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'invoice_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'invoice_list' request.dealer.slug %}"
class="btn btn-phoenix-danger btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </main>
<!---->
{% endblock content %} {% endblock content %}

View File

@ -4,18 +4,33 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<div class="card"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="card-header bg-primary text-white"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<h2 class="h4 mb-0">Create Support Ticket</h2> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h3 class="mb-0 fs-4 fw-bold text-center">
{% trans "Create Support Ticket" %}
<i class="fa-solid fa-headset ms-2"></i>
</h3>
</div> </div>
<div class="card-body"> <div class="card-body p-4 p-md-5">
<form method="post"> <form method="post" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
{{form|crispy}} {{ form|crispy }}
<hr class="my-4">
<button type="submit" class="btn btn-primary">Submit Ticket</button> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-secondary">Cancel</a> <button type="submit" class="btn btn-phoenix-primary btn-lg me-md-2">
<i class="fa-solid fa-paper-plane me-1"></i>
{% trans "Submit Ticket" %}
</button>
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div>
</form> </form>
</div> </div>
</div> </div>
</div>
</main>
{% endblock %} {% endblock %}

View File

@ -2,21 +2,26 @@
{% load static %} {% load static %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load i18n %} {% load i18n %}
{% block title %}
{% trans 'Ticket' %} #{{ ticket.id }}
{% endblock title %}
{% block content %} {% block content %}
<div class="card"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<h2 class="h4 mb-0">Ticket #{{ ticket.id }}: {{ ticket.subject }}</h2> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-sm btn-outline-secondary"> <h3 class="mb-0 fs-4 fw-bold text-center">
Back to List {% trans 'Ticket' %} #{{ ticket.id }}
</a> <i class="fas fa-headset ms-2"></i>
</h3>
</div> </div>
<div class="card-body p-4 p-md-5">
<div class="row g-3">
<div class="col-12 text-center mb-3">
<h4 class="h5 fw-bold">{{ ticket.subject }}</h4>
</div> </div>
<div class="card-body"> <div class="col-sm-6">
<div class="row mb-4"> <strong>{% trans 'Status:' %}</strong>
<div class="col-md-6">
<p><strong>Status:</strong>
<span class="badge <span class="badge
{% if ticket.status == 'open' %}bg-primary {% if ticket.status == 'open' %}bg-primary
{% elif ticket.status == 'in_progress' %}bg-info {% elif ticket.status == 'in_progress' %}bg-info
@ -24,8 +29,9 @@
{% else %}bg-secondary{% endif %}"> {% else %}bg-secondary{% endif %}">
{{ ticket.get_status_display }} {{ ticket.get_status_display }}
</span> </span>
</p> </div>
<p><strong>Priority:</strong> <div class="col-sm-6 text-sm-end">
<strong>{% trans 'Priority:' %}</strong>
<span class="badge <span class="badge
{% if ticket.priority == 'low' %}bg-success {% if ticket.priority == 'low' %}bg-success
{% elif ticket.priority == 'medium' %}bg-warning {% elif ticket.priority == 'medium' %}bg-warning
@ -33,28 +39,39 @@
{% else %}bg-dark{% endif %}"> {% else %}bg-dark{% endif %}">
{{ ticket.get_priority_display }} {{ ticket.get_priority_display }}
</span> </span>
</p>
</div> </div>
<div class="col-md-6"> <div class="col-sm-6">
<p><strong>Created:</strong> {{ ticket.created_at|date:"M d, Y H:i" }}</p> <strong>{% trans 'Created:' %}</strong>
<p><strong>Last Updated:</strong> {{ ticket.updated_at|date:"M d, Y H:i" }}</p> <br class="d-sm-none">{{ ticket.created_at|date:"M d, Y" }}
</div>
<div class="col-sm-6 text-sm-end">
<strong>{% trans 'Last Updated:' %}</strong>
<br class="d-sm-none">{{ ticket.updated_at|date:"M d, Y" }}
</div> </div>
</div> </div>
<hr class="my-4">
<div class="mb-4"> <div class="mb-4">
<h3 class="h5">Description</h3> <h5 class="fw-bold mb-2">{% trans 'Description' %}</h5>
<div class="p-3 rounded"> <div class="p-3 bg-light rounded-3">
{{ ticket.description|linebreaks }} {{ ticket.description|linebreaks }}
</div> </div>
</div> </div>
{% if ticket.resolution_notes %}
<div class="mb-4"> <div class="mb-4">
<h3 class="h5">Resolution Notes</h3> <h5 class="fw-bold mb-2">{% trans 'Resolution Notes' %}</h5>
<div class="p-3 rounded"> <div class="p-3 bg-light rounded-3">
{{ ticket.resolution_notes|linebreaks }} {{ ticket.resolution_notes|linebreaks }}
</div> </div>
</div> </div>
{% endif %}
<!-- You can add comments/replies section here later --> <div class="d-grid mt-4">
<a href="{% url 'ticket_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-arrow-left me-1"></i>
{% trans 'Back to Tickets' %}
</a>
</div> </div>
</div> </div>
</div>
</div>
</main>
{% endblock %} {% endblock %}

View File

@ -1,45 +1,72 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% block title %}
{% trans "My Tickets" %}
{% endblock title %}
{% block content %} {% block content %}
<div class="card"> <main class="py-5">
<div class="card-body"> <div class="container">
<h5 class="card-title">Need help?</h5> <div class="row justify-content-center mb-5">
<p class="card-text">Raise a ticket and we will get back to you as soon as possible.</p> <div class="col-lg-8">
<a href="{% url 'create_ticket' request.dealer.slug %}" class="btn btn-phoenix-primary">Raise a Ticket</a> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInDown">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4 text-center">
<i class="fa-solid fa-headset fa-2x mb-2"></i>
<h2 class="card-title fw-bold mb-0">
{% trans "Need Help?" %}
</h2>
</div>
<div class="card-body p-4 p-md-5 text-center bg-white">
<p class="card-text text-muted mb-4">
{% blocktrans %}
Our support team is ready to assist you. Raise a new ticket below, and we'll get back to you as soon as possible.
{% endblocktrans %}
</p>
<a href="{% url 'create_ticket' request.dealer.slug %}" class="btn btn-phoenix-primary btn-lg shadow-sm">
<i class="fa-solid fa-plus me-1"></i>
{% trans "Raise a New Ticket" %}
</a>
</div>
</div>
</div> </div>
</div> </div>
{% if messages %} {% if messages %}
<div class="alert-container mb-4">
{% for message in messages %} {% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert"> <div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }} {{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
{% endfor %} {% endfor %}
{% endif %} </div>
{% endif %}
<div class="card"> <div class="card shadow-lg border-0 rounded-4 animate__animated animate__fadeInUp">
<div class="card-body"> <div class="card-header border-bottom d-flex flex-column flex-md-row justify-content-between align-items-md-center p-4">
<h5 class="card-title">Tickets</h5> <h5 class="card-title mb-2 mb-md-0 me-md-4 fw-bold">{% trans "My Tickets" %}</h5>
<div class="table-responsive"> <div class="input-group w-100 w-md-50">
<table class="table table-striped table-hover"> {% include 'partials/search_box.html' %}
<thead class=""> </div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-striped table-hover mb-0">
<thead class="bg-light">
<tr> <tr>
<th>ID</th> <th scope="col" class="text-secondary text-uppercase fw-bold ps-4">ID</th>
<th>Subject</th> <th scope="col" class="text-secondary text-uppercase fw-bold">Subject</th>
<th>Status</th> <th scope="col" class="text-secondary text-uppercase fw-bold">Status</th>
<th>Priority</th> <th scope="col" class="text-secondary text-uppercase fw-bold">Priority</th>
<th>Created</th> <th scope="col" class="text-secondary text-uppercase fw-bold">Created</th>
<th scope="col" class="text-secondary text-uppercase fw-bold text-end pe-4">Actions</th>
<th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for ticket in tickets %} {% for ticket in tickets %}
<tr> <tr>
<td>#{{ ticket.id }}</td> <td class="text-muted ps-4">#{{ ticket.id }}</td>
<td>{{ ticket.subject }}</td> <td>{{ ticket.subject }}</td>
<td> <td>
<span class="badge <span class="badge
@ -59,22 +86,31 @@
{{ ticket.get_priority_display }} {{ ticket.get_priority_display }}
</span> </span>
</td> </td>
<td>{{ ticket.created_at|date:"M d, Y H:i" }}</td>
<td> <td>
<a href="{% url 'ticket_detail' request.dealer.slug ticket.id %}" class="btn btn-sm btn-outline-primary"> <span class="d-block">{{ ticket.created_at|date:"M d, Y" }}</span>
View <span class="text-muted small d-block">{{ ticket.created_at|time:"H:i" }}</span>
</td>
<td class="text-end pe-4">
<a href="{% url 'ticket_detail' request.dealer.slug ticket.id %}" class="btn btn-phoenix-primary btn-sm">
<i class="fa-solid fa-eye me-1"></i>
{% trans "View" %}
</a> </a>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>
<td colspan="6" class="text-center">No tickets found.</td> <td colspan="6" class="text-center text-muted py-5">
<i class="fas fa-ticket-alt fs-2 mb-3"></i>
<p class="mb-0">{% trans "No tickets found." %}</p>
<p class="text-muted small">{% trans "All your past and present tickets will appear here." %}</p>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
</div>
</main>
{% endblock %} {% endblock %}

View File

@ -1,8 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n crispy_forms_filters %}
{% load crispy_forms_filters %}
{% block title %} {% block title %}
{# Check if an 'object' exists in the context #}
{% if object %} {% if object %}
{% trans 'Update Staff' %} {% trans 'Update Staff' %}
{% else %} {% else %}
@ -10,49 +8,51 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-md-8">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {% if object %}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% trans "Update Staff" %}
<h3 class="mb-0 fs-4 text-center"> <i class="fa-solid fa-user-tie ms-2"></i>
{% if staff.created %}
{{ _("Edit Staff") }}
{% else %} {% else %}
{{ _("Add Staff") }} {% trans "Add New Staff" %}
<i class="fa-solid fa-user-tie ms-2"></i>
{% endif %} {% endif %}
<i class="fa-solid fa-user-tie text-primary ms-2"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form class="row g-3 mb-3" method="post" class="form" novalidate> <form class="needs-validation" method="post" novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form.first_name|as_crispy_field }} {{ form|crispy }}
{{ form.last_name|as_crispy_field }}
{{ form.arabic_name|as_crispy_field }}
{{ form.email|as_crispy_field }}
{{ form.phone_number|as_crispy_field }}
{{ form.address|as_crispy_field }}
{{ form.logo|as_crispy_field }}
{{ form.group|as_crispy_field }}
{% for error in form.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
<hr class="my-2"> {% if form.errors %}
<div class="alert alert-danger mt-4" role="alert">
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'user_list' request.dealer.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'user_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</main>
{% endblock %} {% endblock %}

View File

@ -5,37 +5,46 @@
{% trans "Group" %} {% trans "Group" %}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
<div class="row justify-content-center mt-5 mb-3"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="col-lg-8 col-md-10"> <div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="card shadow-sm border-0 rounded-3"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {{ _("Manage Groups") }}
<h3 class="mb-0 fs-5 text-center"> <i class="fa-solid fa-users ms-2"></i>
{{ _("Manage Groups") }}<i class="fa-solid fa-users ms-2 text-primary"></i>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form class="row g-3 mb-3" method="post" class="form" enctype="multipart/form-data" novalidate > <form class="needs-validation" method="post" enctype="multipart/form-data" novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}
{% for error in form.errors %}<div class="text-danger">{{ error }}</div>{% endfor %}
<hr class="my-2"> {% if form.errors %}
<div class="alert alert-danger mt-4" role="alert">
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'user_detail' request.dealer.slug staff.slug %}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'user_detail' request.dealer.slug staff.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</main>
{% endblock %} {% endblock %}

View File

@ -1,18 +1,20 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-100 py-5"> <main class="d-flex align-items-center justify-content-center min-vh-80 py-5">
<div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5"> <div class="col-12 col-sm-10 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp" style="background-color: #f8f9fa;"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<h1 class="h3 fw-bold mb-0 text-center">
<i class="fas fa-lock me-2"></i> {% trans "Set New Password" %}
</h1>
</div>
<div class="card-body p-4 p-md-5"> <div class="card-body p-4 p-md-5">
<div class="text-center mb-4"> <div class="text-center mb-4">
<h1 class="h3 fw-bold text-dark mb-2">{% trans "Set New Password" %}</h1> <p class="mb-0 fs-5">{% trans "Enter your new password below." %}</p>
<p class="text-muted">{% trans "Enter your new password below." %}</p>
</div> </div>
<form method="post" class="needs-validation" novalidate> <form method="post" class="needs-validation" novalidate>
{% csrf_token %} {% csrf_token %}
{% for field in form %} {% for field in form %}
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ field.errors }} {{ field.errors }}
@ -20,17 +22,16 @@
<label for="{{ field.id_for_label }}">{{ field.label }}</label> <label for="{{ field.id_for_label }}">{{ field.label }}</label>
</div> </div>
{% endfor %} {% endfor %}
<div class="d-grid mt-4"> <div class="d-grid mt-4">
<button type="submit" class="btn btn-primary btn-lg rounded-pill fw-bold"> <button type="submit" class="btn btn-phoenix-primary btn-lg rounded-pill fw-bold">
{% trans "Change Password" %} {% trans "Change Password" %}
</button> </button>
</div> </div>
</form> </form>
</div> </div>
<div class="card-footer bg-light border-0 py-3 text-center"> <div class="card-footer bg-gray-300 border-0 py-3 text-center">
<small class="text-muted"> <small class="text-muted">
{% trans "Remember to choose a strong password." %} <i class="fas fa-info-circle me-1"></i> {% trans "Remember to choose a strong password." %}
</small> </small>
</div> </div>
</div> </div>

View File

@ -2,7 +2,6 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% block title %} {% block title %}
{# Check if an 'object' exists in the context #}
{% if object %} {% if object %}
{% trans 'Update Vendor' %} {% trans 'Update Vendor' %}
{% else %} {% else %}
@ -10,37 +9,51 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="d-flex align-items-center justify-content-center min-vh-80 py-5 ">
<div class="col-md-8 ">
<div class="row justify-content-center mt-5 mb-3"> <div class="card shadow-lg border-0 rounded-4 overflow-hidden animate__animated animate__fadeInUp">
<div class="card-header bg-gradient py-4 border-0 rounded-top-4">
<div class="col-lg-8 col-md-10"> <h3 class="mb-0 fs-4 fw-bold text-center">
<div class="card shadow-sm border-0 rounded-3"> {% if object %}
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-3"> {% trans "Update Vendor" %}
<h3 class="mb-0 fs-4 text-center"> <i class="fas fa-cube ms-2"></i>
{% if vendor.created %}
{{ _("Edit Vendor") }}
{% else %} {% else %}
{{ _("Add Vendor") }} {% trans "Add New Vendor" %}
<i class="fas fa-cube ms-2"></i>
{% endif %} {% endif %}
<span class="fas fa-cube ms-2 text-primary"></span>
</h3> </h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body p-4 p-md-5">
<form class="row g-3 mb-3" method="post" class="form" enctype="multipart/form-data" novalidate > <form class="needs-validation" method="post" enctype="multipart/form-data" novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}
{% for error in form.errors %}<div class="text-danger">{{ error }}</div>{% endfor %}
<hr class="my-2"> {% if form.errors %}
<div class="alert alert-danger mt-4" role="alert">
<h4 class="alert-heading small">{% trans "Please correct the following errors:" %}</h4>
<ul class="mb-0">
{% for field, errors in form.errors.items %}
<li><strong>{{ field|capfirst }}:</strong> {% for error in errors %}{{ error }}{% endfor %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<hr class="my-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3"> <div class="d-grid gap-2 d-md-flex justify-content-md-center mt-3">
<button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button> <button class="btn btn-phoenix-primary btn-lg me-md-2" type="submit">
<a href="{% url 'vendor_list' request.dealer.slug%}" class="btn btn-lg btn-phoenix-secondary"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a> <i class="fa-solid fa-floppy-disk me-1"></i>
{{ _("Save") }}
</button>
<a href="{% url 'vendor_list' request.dealer.slug %}" class="btn btn-phoenix-secondary btn-lg">
<i class="fa-solid fa-ban me-1"></i>
{% trans "Cancel" %}
</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<!----> </main>
{% endblock %} {% endblock %}