This commit is contained in:
Marwan Alwali 2025-02-23 13:17:11 +03:00
parent 5ce971b4bd
commit 3458671826
26 changed files with 1569 additions and 1225 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -5,6 +5,7 @@ from django.conf import settings
from django.conf.urls.i18n import i18n_patterns
from inventory import views
import debug_toolbar
from schema_graph.views import Schema
# from two_factor.urls import urlpatterns as tf_urls
urlpatterns = [
@ -26,6 +27,7 @@ urlpatterns += i18n_patterns(
path("haikalbot/", include("haikalbot.urls")),
path('appointment/', include('appointment.urls')),
path('plans/', include('plans.urls')),
path("schema/", Schema.as_view()),
# path('', include(tf_urls)),
)

0
data.json Normal file
View File

View File

@ -7,6 +7,8 @@ from appointment import models as appointment_models
from import_export.admin import ExportMixin
from import_export.resources import ModelResource
from .models import Car
# Define resource class
# class CarSerieResource(ModelResource):
# class Meta:
@ -22,7 +24,7 @@ admin.site.register(models.Staff)
admin.site.register(models.Vendor)
# admin.site.register(models.SaleQuotation)
# admin.site.register(models.SaleQuotationCar)
# admin.site.register(models.SalesOrder)
admin.site.register(models.SaleOrder)
admin.site.register(models.CarFinance)
admin.site.register(models.CarColors)
@ -144,3 +146,4 @@ class ItemTransactionModelAdmin(admin.ModelAdmin):
actions = [export_to_pdf_landscape, export_to_pdf_portrait]

View File

@ -935,30 +935,15 @@ class Staff(models.Model, LocalizedNameMixin):
name = models.CharField(max_length=255, verbose_name=_("Name"))
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number"))
staff_type = models.CharField(
choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type")
)
staff_type = models.CharField(choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type"))
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
objects = StaffUserManager()
def clean(self):
quota_dict = get_user_quota(self.dealer.user)
allowed_users = quota_dict.get("Users")
if allowed_users is None:
raise ValidationError(_("The user quota for staff members is not defined. Please contact support."))
current_staff_count = self.dealer.staff.count()
if current_staff_count >= allowed_users:
raise ValidationError(_("You have reached the maximum number of staff users allowed for your plan."))
def save(self, *args, **kwargs):
self.clean()
super().save(*args, **kwargs)
@property
def user(self):
return self.staff_member.user
return self.staff_member.user
@property
def groups(self):

View File

@ -1,6 +1,8 @@
from django.contrib.auth.models import Group
from decimal import Decimal
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save
from plans.quota import get_user_quota
from .utils import to_dict
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
@ -18,6 +20,8 @@ from django_ledger.models import (
from . import models
from django.utils.timezone import now
from django.db import transaction
from django.core.exceptions import ValidationError
User = get_user_model()
@ -876,4 +880,14 @@ def update_car_status_on_reservation_update(sender, instance, **kwargs):
# activity_type='Schedule Created',
# created_by=instance.scheduled_by,
# notes=f"New schedule created for {instance.purpose} with {instance.lead.full_name} on {instance.scheduled_at}."
# )
# )
@receiver(post_save, sender=models.Staff)
def check_users_quota(sender, instance, **kwargs):
quota_dict = get_user_quota(instance.dealer.user)
allowed_users = quota_dict.get("Users")
if allowed_users is None:
raise ValidationError(_("The user quota for staff members is not defined. Please contact support."))
current_staff_count = instance.dealer.staff.count()
if current_staff_count == allowed_users:
raise ValidationError(_("You have reached the maximum number of staff users allowed for your plan."))

View File

@ -1,24 +0,0 @@
from django.core.exceptions import ValidationError
from plans.quota import get_user_quota
class DealerStaffQuotaValidator:
"""
Validator to ensure a Dealer cannot add more than the allowed number of Staff members.
"""
def __init__(self, quota_name='Users'):
self.quota_name = quota_name
def __call__(self, dealer):
# Get the quota for the dealer's plan
quota_limit = get_user_quota(dealer.user, self.quota_name)
# Count the number of staff members associated with the dealer
staff_count = dealer.staff.count()
# Check if the quota is exceeded
if staff_count >= quota_limit:
raise ValidationError(
f"You have reached the maximum number of staff members ({quota_limit}) allowed by your plan."
)

View File

@ -1,14 +1,11 @@
from django.db.models import Func
from django.contrib.auth.models import Permission
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
from datetime import timedelta
from calendar import month_name
from random import randint
from django_tables2 import SingleTableView
from django_tables2.export.views import ExportMixin
from django_pdf_actions.actions import export_to_pdf_landscape
from plans.quota import get_user_quota
from reportlab.lib.pagesizes import landscape, A4
from rich import print
from decimal import Decimal
from django.core.paginator import Paginator
@ -39,29 +36,20 @@ from django_ledger.forms.bank_account import (
BankAccountUpdateForm,
)
from django_ledger.forms.customer import CustomerModelForm
from django_ledger.forms.bill import BillModelCreateForm
from django_ledger.forms.invoice import (
DraftInvoiceModelUpdateForm,
ApprovedInvoiceModelUpdateForm,
PaidInvoiceModelUpdateForm,
)
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
# from django_ledger.forms.estimate import EstimateModelCreateForm
from django_ledger.forms.invoice import InvoiceModelCreateForm
from django_ledger.forms.item import (
ServiceCreateForm,
ExpenseItemCreateForm,
ExpenseItemUpdateForm,
)
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm
from django_ledger.io import roles
from django.contrib.admin.models import LogEntry
import logging
import json
import datetime
from django.db.models.functions import Coalesce
from django.db.models.functions import Coalesce, TruncDate, TruncDay
from django.shortcuts import HttpResponse
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
@ -85,9 +73,8 @@ from django.urls import reverse, reverse_lazy
from django.contrib import messages
from django.db.models import Sum, F, Count
from django.db import transaction
from twilio.rest.verify.v2 import form
from shapely.speedups import available
from .forms import VendorForm
from .services import (
decodevin,
get_make,
@ -365,7 +352,17 @@ class ManagerDashboard(LoginRequiredMixin, TemplateView):
new_leads = models.Lead.objects.filter(dealer=dealer, status=models.Status.NEW).count()
pending_leads = models.Lead.objects.filter(dealer=dealer, status=models.Status.PENDING).count()
canceled_leads = models.Lead.objects.filter(dealer=dealer, status=models.Status.CANCELED).count()
available_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.AVAILABLE).count()
sold_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.SOLD).count()
reserved_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.RESERVED).count()
hold_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.HOLD).count()
damaged_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.DAMAGED).count()
transfer_cars = models.Car.objects.filter(dealer=dealer, status=models.CarStatusChoices.TRANSFER).count()
reserved_percentage = reserved_cars / total_cars * 100
sold_percentage = sold_cars / total_cars * 100
qs = models.Car.objects.values('id_car_make__name').annotate(count=Count('id')).order_by('id_car_make__name')
car_by_make = list(qs)
print(qs)
context["dealer"] = dealer
context["total_cars"] = total_cars
context["total_reservations"] = total_reservations
@ -375,6 +372,16 @@ class ManagerDashboard(LoginRequiredMixin, TemplateView):
context['new_leads'] = new_leads
context['pending_leads'] = pending_leads
context['canceled_leads'] = canceled_leads
context['reserved_percentage'] = reserved_percentage
context['sold_percentage'] = sold_percentage
context['available_cars'] = available_cars
context['sold_cars'] = sold_cars
context['reserved_cars'] = reserved_cars
context['hold_cars'] = hold_cars
context['damaged_cars'] = damaged_cars
context['transfer_cars'] = transfer_cars
context['car'] = json.dumps(car_by_make)
return context
@ -2024,7 +2031,18 @@ class UserCreateView(
def form_valid(self, form):
dealer = get_user_type(self.request)
quota_dict = get_user_quota(dealer.user)
allowed_users = quota_dict.get("Users")
if allowed_users is None:
messages.error(self.request, _("The user quota for staff members is not defined. Please contact support."))
return self.form_invalid(form)
current_staff_count = dealer.staff.count()
if current_staff_count >= allowed_users:
messages.error(self.request, _("You have reached the maximum number of staff users allowed for your plan."))
return self.form_invalid(form)
email = form.cleaned_data["email"]
password = "Tenhal@123"
user = User.objects.create_user(username=form.cleaned_data["name"], email=email, password=password)

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
static/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

45
static/js/echarts.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -245,7 +245,6 @@
color: getColor('secondary-bg')
}
},
zlevel: 2
},
{
type: 'line',

View File

@ -702,7 +702,14 @@
axisTick: {
show: false
},
data: [
'NOV-DEC',
'SEP-OCT',
'JUL-AUG',
'MAY-JUN',
'MAR-APR',
'JAN-FEB'
],
axisLabel: {
color: getColor('secondary-text-emphasis'),
margin: 8,

View File

@ -101,6 +101,8 @@
<script src="{% static 'vendors/echarts/echarts.min.js' %}"></script>
<script src="{% static 'js/crm-analytics.js' %}"></script>
<script src="{% static 'js/travel-agency-dashboard.js' %}"></script>
<script src="{% static 'js/crm-dashboard.js' %}"></script>
<script src="{% static 'js/projectmanagement-dashboard.js' %}"></script>
<script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script>
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>

View File

@ -1,358 +1,406 @@
{% extends 'base.html' %}
{% load i18n static %}
{% block content %}
<div class="content">
<div class="row mb-4 mb-xl-6 mb-xxl-4 gy-3 justify-content-between">
<div class="col-auto">
<h2 class="mb-0 text-body-emphasis">{{ dealer.get_local_name }}</h2>
</div>
<div class="col-auto">
<div class="d-flex gap-3"><a class="btn btn-phoenix-primary" href="#!"><span class="fa-solid fa-plus me-2"></span>New Package</a><a class="btn btn-primary px-4 px-sm-11" href="#!"><span class="fa-regular fa-calendar-days me-2"></span>Book Now</a></div>
</div>
</div>
<div class="row gx-3">
<div class="col-xxl-7">
<div class="row gx-7 pe-xxl-3">
<div class="col-12 col-xl-5 col-xxl-12">
<script src="{% static 'js/echarts.js' %}"></script>
<div class="row justify-content-between">
<div class="col-12 col-lg-6">
<div class="row g-2">
<h3 class="fs-4 fs-md-4 fs-xl-4 fw-black mb-4">
<span class="text-gradient-info me-3">{{ dealer.get_local_name }}</span>
</h3>
<div class="card mb-3">
<div class="bg-holder" style="background-image:url({% static 'images/bg/38.png' %});background-position:left bottom;background-size:auto;"></div>
<div class="card-body d-flex justify-content-between position-relative">
<div class="col-sm-7 col-md-8 col-xxl-8 mb-md-3 mb-lg-0">
<h3 class="mb-3">{{ _("Inventory by Status")}}</h3>
<div class="row g-0">
<div class="col-6 col-xl-12 col-xxl-6 border-bottom border-end border-end-xl-0 border-end-xxl pb-4 pt-4 pt-xl-0 pt-xxl-4 pe-4 pe-sm-5 pe-xl-0 pe-xxl-5">
<h5 class="text-body mb-4">{% trans 'inventory'|capfirst %}</h5>
<div class="d-md-flex flex-between-center">
<div class="echart-booking-value order-1 order-sm-0 order-md-1" style="height:54px; width: 90px"></div>
<div class="mt-4 mt-md-0">
<h3 class="text-body-highlight mb-2">{{ total_cars }}</h3><span class="badge badge-phoenix badge-phoenix-primary me-2 fs-10"><span class="fa-solid fa-plus me-1"></span>23.35%</span><span class="fs-9 text-body-secondary d-block d-sm-inline mt-1">From last month</span>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100 border-1 border-bottom border-end border-translucent">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-success" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Available") }}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ available_cars }}</h3>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 border-bottom py-4 ps-4 ps-sm-5 ps-xl-0 ps-xxl-5">
<h5 class="text-body mb-4">{% trans 'inventory value'|capfirst %}</h5>
<div class="d-md-flex flex-between-center">
<div class="d-md-flex align-items-center gap-2 order-sm-0 order-md-1"><span class="fa-solid fa-money-bill-trend-up fs-5 text-warning-light dark__text-opacity-75" data-bs-theme="light"></span>
<div class="d-flex d-md-block gap-2 align-items-center mt-1 mt-md-0">
<p class="fs-9 mb-0 mb-md-2 text-body-tertiary text-nowrap">{% trans "Profits"|upper %}</p>
<h4 class="text-body-highlight mb-0">{{ total_profit }} {% trans 'SAR' %}</h4>
</div>
</div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">{{ total_selling_price }} {% trans 'SAR' %}</h3><span class="badge badge-phoenix badge-phoenix-success me-2 fs-10"><span class="fa-solid fa-plus me-1"></span>3.98%</span><span class="fs-9 text-body-secondary text-nowrap d-block d-sm-inline mt-1">From last month</span>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100 border-1 border-bottom border-end-md-0 border-end-xl border-translucent">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-warning" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Sold")}}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ sold_cars }}</h3>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 border-bottom-xl border-bottom-xxl-0 border-end border-end-xl-0 border-end-xxl py-4 pe-4 pe-sm-5 pe-xl-0 pe-xxl-5">
<h5 class="text-body mb-4">{% trans 'Commissions' %}</h5>
<div class="d-md-flex flex-between-center">
<div class="echart-commission order-sm-0 order-md-1" style="height: 54px; width: 54px"></div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">$3,339.00</h3>
<span class="badge badge-phoenix badge-phoenix-danger me-2 fs-10">
<span class="fa-solid fa-minus me-1"></span>12.21%</span>
<span class="fs-9 text-body-secondary d-block d-sm-inline mt-1">From last month</span>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100 border-1 border-bottom border-end border-end-md border-end-xl-0 border-translucent">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-danger" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Reserved") }}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ reserved_cars }}</h3>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 py-4 ps-4 ps-sm-5 ps-xl-0 ps-xxl-5">
<h5 class="text-body mb-4">Canceled Booking</h5>
<div class="d-md-flex flex-between-center">
<div class="chart-cancel-booking order-sm-0 order-md-1" style="height:54px; width:78px"></div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">120.00</h3><span class="badge badge-phoenix badge-phoenix-danger me-2 fs-10"><span class="fa-solid fa-plus me-1"></span>5.76%</span><span class="fs-9 text-body-secondary d-block d-sm-inline mt-1">From last month</span>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100 border-1 border-end-xl border-bottom border-bottom-xl-0 border-translucent">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-primary" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Transfer") }}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ transfer_cars }}</h3>
</div>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100 border-1 border-end border-translucent">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-warning-light" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Hold") }}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ hold_cars }}</h3>
</div>
</div>
<div class="col-6 col-xl-4">
<div class="d-flex flex-column flex-center align-items-sm-start flex-md-row justify-content-md-between flex-xxl-column p-3 ps-sm-3 ps-md-4 p-md-3 h-100">
<div class="d-flex align-items-center mb-1"><span class="fa-solid fa-square fs-11 me-2 text-secondary-dark" data-fa-transform="up-2"></span><span class="mb-0 fs-9 text-body">{{ _("Damaged") }}</span></div>
<h3 class="fw-semibold ms-xl-3 ms-xxl-0 pe-md-2 pe-xxl-0 mb-0 mb-sm-3">{{ damaged_cars }}</h3>
</div>
</div>
</div>
</div>
<div class="col-12 col-xl-7 col-xxl-12">
<div class="mt-5 mt-xl-0 mt-xxl-5 mb-5 mb-xxl-0">
<div class="row flex-between-end gy-3 gx-2">
<div class="col-auto">
<h3 class="text-body-highlight">Financial activities</h3>
<p class="mb-0 text-body-tertiary">Balance</p>
</div>
<div class="col-auto order-md-1 order-lg-0 order-xxl-1">
<!--<div class="dropdown">
<button class="btn btn-sm btn-phoenix-secondary bg-body-emphasis bg-body-hover action-btn" 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" data-fa-transform="shrink-2"></span></button>
<div class="dropdown-menu dropdown-menu-end"><a class="dropdown-item" href="#">Action</a><a class="dropdown-item" href="#">Another action</a><a class="dropdown-item" href="#">Something else here</a></div>
</div>-->
</div>
<div class="col-12 col-md-auto col-lg-12 col-xxl-auto mx-auto order-1 order-sm-0">
<div class="d-flex justify-content-center gap-6 gap-xxl-4">
<button class="btn d-flex align-items-center p-0 shadow-none fw-semibold" id="profit"><span class="bg-primary-light me-2" style="width: 16px; height: 6px; border-radius: 1px" data-bs-theme="light"></span><span class="text-body-secondary">Profit</span></button>
<button class="btn d-flex align-items-center p-0 shadow-none fw-semibold" id="revenue"><span class="bg-success-light me-2" style="width: 16px; height: 6px; border-radius: 1px" data-bs-theme="light"></span><span class="text-body-secondary">Revenue</span></button>
<button class="btn d-flex align-items-center p-0 shadow-none fw-semibold" id="expanses"><span class="bg-info-light me-2" style="width: 16px; height: 6px; border-radius: 1px" data-bs-theme="light"></span><span class="text-body-secondary">Expanses</span></button>
</div>
</div>
<div class="col-sm-5 col-md-4 col-xxl-4 my-3 my-sm-0">
<div class="position-relative d-flex flex-center mb-sm-4 mb-xl-0 echart-cars-by-status-container mt-sm-7 mt-lg-4 mt-xl-0">
<div id="echart-cars-by-status" style="min-height:245px;width:100%"></div>
<div class="position-absolute rounded-circle bg-primary-subtle top-50 start-50 translate-middle d-flex flex-center" style="height:100px; width:100px;">
<h3 class="mb-0 text-primary-dark fw-bolder" data-label="data-label"></h3>
</div>
<div class="echart-financial-Activities" data-options='{"optionOne":"profit","optionTwo":"revenue","optionThree":"expanses"}'></div>
</div>
</div>
</div>
</div>
</div>
<div class="row g-2">
<div class="col-12 mb-8">
<div class="mb-3">
<h3>{{ _("New Leads and Customers")}}</h3>
<p class="text-body-tertiary mb-0">{{ _("Payment received across all channels")}}</p>
</div>
<div class="row g-6">
<div class="col-xl-6 mb-2 mb-sm-0">
<div class="d-flex align-items-center"><span class="me-2 text-info" data-feather="users" style="min-height:24px; width:24px"></span>
<h4 class="text-body-tertiary mb-0">{{ _("New Customers")}} :
<span class="text-body-emphasis"> 42</span>
</h4>
<span class="badge badge-phoenix fs-10 badge-phoenix-success d-inline-flex align-items-center ms-2">
<span class="badge-label d-inline-block lh-base">+24.5%</span>
<span class="ms-1 fa-solid fa-caret-up d-inline-block lh-1"></span>
</span>
</div>
<div class="pb-0 pt-4">
<div class="echarts-new-users" style="min-height:110px;width:100%;"></div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex align-items-center"><span class="me-2 text-primary" data-feather="zap" style="height:24px; width:24px"></span>
<h4 class="text-body-tertiary mb-0">{{ _("New Leads")}} :<span class="text-body-emphasis"> 45</span></h4>
<span class="badge badge-phoenix fs-10 badge-phoenix-success d-inline-flex align-items-center ms-2">
<span class="badge-label d-inline-block lh-base">+30.5%</span>
<span class="ms-1 fa-solid fa-caret-up d-inline-block lh-1"></span>
</span>
</div>
<div class="pb-0 pt-4">
<div class="echarts-new-leads" style="min-height:110px;width:100%;"></div>
</div>
</div>
</div>
</div>
<div class="col-xxl-5">
<div class="row g-3">
<div class="col-12 col-md-6 col-xxl-12">
<div class="col-12">
<div class="card mb-3">
<div class="bg-holder bg-card" style="background-image:url({% static 'images/spot-illustrations/39.png' %});background-position: bottom right 0px; background-size: auto;">
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<div class="card-body z-5">
<div>
<h3 class="text-body-highlight mb-3">{{ _("Leads") }}</h3>
<div class="col-6 col-md-6">
<div class="row align-items-center g-9">
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-success-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-success" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-star text-success " data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ new_leads }} </h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("New")}}</p>
<div class="row g-3 pe-xxl-3">
<div class="col-12 col-xl-6 col-xxl-12">
<div class="row">
<div class="col-6 col-xl-12 col-xxl-6 border-bottom border-end border-end-xl-0 border-end-xxl pb-4 pt-4 pt-xl-0 pt-xxl-4 pe-4 pe-sm-5 pe-xl-0 pe-xxl-5">
<h4 class="text-body mb-4">{% trans 'inventory'|upper %}</h4>
<div class="d-md-flex flex-between-center">
<div id="car-chart-by-make" class="order-sm-0 order-md-1" style="height:64px;width: 128px;"></div>
<div class="mt-4 mt-md-0">
<h1 class="text-body-highlight mb-2">{{ total_cars }}</h1>
<span class="badge badge-phoenix badge-phoenix-primary me-2 fs-10"> <span class="fs-10 text-body-secondary me-1">{{ _("As of")}}</span>{% now "SHORT_DATETIME_FORMAT" %}</span>
</div>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 border-bottom py-4 ps-4 ps-sm-5 ps-xl-0 ps-xxl-5">
<h4 class="text-body mb-4">{% trans 'inventory value'|upper %}</h4>
<div class="d-md-flex flex-between-center">
<div class="d-md-flex align-items-center gap-2 order-sm-0 order-md-1 fa-2x align-items-center">
<i class="fas fa-money-check-alt fs-4 text-success-light dark__text-opacity-75"></i>
<div class="d-flex d-md-block gap-2 align-items-center mt-1 mt-md-0">
<p class="fs-9 mb-0 mb-md-2 text-body-tertiary text-nowrap"></p>
<h4 class="text-body-highlight mb-0"></h4>
</div>
</div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">{{ total_selling_price }} {{ CURRENCY }}</h3>
</div>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 border-bottom-xl border-bottom-xxl-0 border-end border-end-xl-0 border-end-xxl py-4 pe-4 pe-sm-5 pe-xl-0 pe-xxl-5">
<h4 class="text-body mb-4">{% trans "Profits"|upper %}</h4>
<div class="d-md-flex flex-between-center">
<div class="d-md-flex align-items-center gap-2 order-sm-0 order-md-1">
<span class="fa-solid fa-money-bill-trend-up fs-4 text-warning-light dark__text-opacity-75" data-bs-theme="light"></span>
<div class="d-flex d-md-block gap-2 align-items-center mt-1 mt-md-0">
<p class="fs-9 mb-0 mb-md-2 text-body-tertiary text-nowrap"></p>
<h4 class="text-body-highlight mb-0"></h4>
</div>
</div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">{{ total_profit }} {{ CURRENCY }}</h3>
</div>
</div>
</div>
<div class="col-6 col-xl-12 col-xxl-6 py-4 ps-4 ps-sm-5 ps-xl-0 ps-xxl-5">
<h5 class="text-body mb-4">{{ _("Canceled Invoices")}}</h5>
<div class="d-md-flex flex-between-center">
<div class="chart-cancel-booking order-sm-0 order-md-1" style="height:54px; width:78px"></div>
<div class="mt-3 mt-md-0">
<h3 class="text-body-highlight mb-2">120.00</h3>
<span class="badge badge-phoenix badge-phoenix-danger me-2 fs-10"> <span class="fa-solid fa-plus me-1"></span>5.76%</span>
<span class="fs-9 text-body-secondary d-block d-sm-inline mt-1">{{ _("From last month")}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-warning-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-warning" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-pause text-warning " data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ pending_leads }}</h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("Pending")}}</p>
</div>
</div>
</div>
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-danger-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-danger" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-xmark text-danger " data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ canceled_leads }}</h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("Canceled")}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card h-100" data-list='{"valueNames":["country","users","status"],"page":4}'>
<div class="card-header border-0 d-flex justify-content-between align-items-start">
<div>
<h3 class="text-body-highlight">Visitors</h3>
<p class="mb-0 text-body-tertiary">Users across countries</p>
</div>
<div class="dropdown">
<button class="btn btn-sm btn-phoenix-secondary bg-body-emphasis bg-body-hover action-btn" 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" data-fa-transform="shrink-2"></span></button>
<div class="dropdown-menu dropdown-menu-end"><a class="dropdown-item" href="#">Action</a><a class="dropdown-item" href="#">Another action</a><a class="dropdown-item" href="#">Something else here</a></div>
</div>
</div>
<div class="card-body py-0">
<h4 class="d-flex align-items-center gap-2 text-body-highlight mb-3"><span class="real-time-user" data-countup='{"endValue":119}'>0</span><span class="fs-9 fw-normal">User per second</span></h4>
<div class="echart-country-wise-visitors" style="height: 43px; width: 100%"></div>
<div class="table-responsive scrollbar mt-3">
<table class="table fs-10 mb-0">
<thead>
<tr>
<th class="sort ps-0 align-middle" data-sort="country" style="min-width: 100px">COUNTRY NAME</th>
<th class="sort align-middle" data-sort="users" style="min-width: 115px">USERS</th>
<th class="sort text-end align-middle" data-sort="status">STATUS</th>
</tr>
</thead>
<tbody class="list" id="table-country-wise-visitors">
<tr>
<td class="py-2 white-space-nowrap ps-0 country"><a class="d-flex align-items-center text-primary py-md-1 py-xxl-0" href="#!"><img src="{% static 'images/country/india-2.png' %}" alt="" width="40" />
<p class="mb-0 ps-3 fw-bold fs-9">India</p>
</a></td>
<td class="py-2 align-middle users">
<h6>92,896<span class="text-body-tertiary fw-semibold ms-2">(41.6%)</span></h6>
</td>
<td class="py-2 align-middle text-end status"><span class="badge badge-phoenix fs-10 badge-phoenix-info"><span class="fa-solid fa-plus me-1"></span>15.21%</span></td>
</tr>
<tr>
<td class="py-2 white-space-nowrap ps-0 country"><a class="d-flex align-items-center text-primary py-md-1 py-xxl-0" href="#!"><img src="{% static 'images/country/china-2.png' %}" alt="" width="40" />
<p class="mb-0 ps-3 fw-bold fs-9">China</p>
</a></td>
<td class="py-2 align-middle users">
<h6>50,496<span class="text-body-tertiary fw-semibold ms-2">(32.8%)</span></h6>
</td>
<td class="py-2 align-middle text-end status"><span class="badge badge-phoenix fs-10 badge-phoenix-warning"><span class="fa-solid fa-plus me-1"></span>05.21%</span></td>
</tr>
<tr>
<td class="py-2 white-space-nowrap ps-0 country"><a class="d-flex align-items-center text-primary py-md-1 py-xxl-0" href="#!"><img src="{% static 'images/country/usa-2.png' %}" alt="" width="40" />
<p class="mb-0 ps-3 fw-bold fs-9">USA</p>
</a></td>
<td class="py-2 align-middle users">
<h6>45,679<span class="text-body-tertiary fw-semibold ms-2">(24.3%)</span></h6>
</td>
<td class="py-2 align-middle text-end status"><span class="badge badge-phoenix fs-10 badge-phoenix-primary"><span class="fa-solid fa-plus me-1"></span>22.12%</span></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer pt-3 border-0">
<div class="d-flex align-items-center">
<div class="pagination d-none"></div>
<p class="mb-0 d-none d-sm-block me-3 fw-semibold text-body" data-list-info="data-list-info"></p><a class="fw-bold fs-9 ms-auto" href="#!">View all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-6 col-xxl-12">
</div>
<div class="col-12 col-xl-6 col-xxl-12 mb-3">
<div class="card h-100">
<div class="card-header border-0 pb-2 d-flex justify-content-between align-items-start">
<div>
<h3 class="text-body-highlight">Holidays</h3>
<p class="mb-sm-0 text-body-tertiary">Holidays next month</p>
</div><a class="btn btn-sm btn-phoenix-secondary d-flex align-items-center w-max-content" href="#!"><span class="text-nowrap">Calender</span><span class="fa-solid fa-chevron-right ms-2 fs-10"></span></a>
</div>
<div class="card-body">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row g-3 mb-5">
<div class="col-xl-5 col-xxl-7">
<div class="card h-xxl-100">
<div class="card-header pb-3">
<div class="row justify-content-between g-3">
<div class="col-auto">
<h3 class="text-body-highlight">Gross Profit</h3>
<p class="mb-0">Annual income according to the board</p>
</div>
<div class="col-auto">
<select class="form-select form-select-sm">
<option>Last Fiscal Year</option>
<option>Last Calendar year</option>
<option>Last Quarter</option>
</select>
</div>
</div>
</div>
<div class="card-body">
<div class="row align-items-center h-100 gy-5">
<div class="col-12 col-md-auto col-xl-12 col-xxl-auto order-md-1 order-xl-0 order-xxl-1 px-md-8 px-xl-6">
<div class="echart-gross-profit mx-auto mt-3 mt-md-0 mt-xl-3 mt-xxl-0" style="width: 250px; height: 250px"></div>
</div>
<div class="col-12 col-md-auto col-xl-12 col-xxl-auto flex-1 h-md-100">
<div class="d-flex flex-column justify-content-between h-md-100 h-xl-auto h-xxl-100">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-primary-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Flight</h6>
<h5 class="mb-0 text-body">$162,791,400</h5>
</div>
<div class="card-header pb-3">
<div class="row justify-content-between g-3">
<div class="col-auto">
<h3 class="text-body-highlight">{{ _("Gross Profit")}}</h3>
<p class="mb-0">Annual income according to the board</p>
</div>
</div>
</div>
<div class="card-body">
<div class="row align-items-center h-100 gy-5">
<div class="col-12 col-md-auto col-xl-12 col-xxl-auto order-md-1 order-xl-0 order-xxl-1 px-md-8 px-xl-6">
<div class="echart-gross-profit mx-auto mt-3 mt-md-0 mt-xl-3 mt-xxl-0" style="width: 250px; height: 250px"></div>
</div>
<div class="col-12 col-md-auto col-xl-12 col-xxl-auto flex-1 h-md-100">
<div class="d-flex flex-column justify-content-between h-md-100 h-xl-auto h-xxl-100">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-primary-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Flight</h6>
<h5 class="mb-0 text-body">$162,791,400</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-primary">
<span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">15.50%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-info-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Flight (Package)</h6>
<h5 class="mb-0 text-body">$135,659,500</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-danger">
<span class="fw-bold" data-feather="trending-down" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">11.09%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-warning-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Hotel</h6>
<h5 class="mb-0 text-body">$271,319,000</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-warning">
<span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">29.98%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-success-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Hotel (Package)</h6>
<h5 class="mb-0 text-body">$162,791,400</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-success">
<span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">03.90%</p>
</div>
</div>
<hr class="d-none" />
</div>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-primary"><span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">15.50%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-info-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Flight (Package)</h6>
<h5 class="mb-0 text-body">$135,659,500</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-danger"><span class="fw-bold" data-feather="trending-down" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">11.09%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-warning-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Hotel</h6>
<h5 class="mb-0 text-body">$271,319,000</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-warning"><span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">29.98%</p>
</div>
</div>
<hr />
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex gap-2">
<div class="bullet-item bg-success-light" data-bs-theme="light"></div>
<div>
<h6 class="mb-0 text-body fw-semibold mb-2">Hotel (Package)</h6>
<h5 class="mb-0 text-body">$162,791,400</h5>
</div>
</div>
<div class="d-flex align-items-center gap-2 text-success"><span class="fw-bold" data-feather="trending-up" style="width: 24px; height: 24px"></span>
<p class="mb-0 fw-bold">03.90%</p>
</div>
</div>
<hr class="d-none" />
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-7 col-xxl-5">
<div class="card h-100">
<div class="card-header pb-3 d-sm-flex d-xl-block d-xxl-flex justify-content-between align-items-start">
<div>
<h3 class="text-body-highlight">Bookings</h3>
<p class="mb-0">Completed and canceled bookings</p>
</div>
<select class="form-select form-select-sm pe-9 w-auto mt-3 mt-sm-0 mt-xl-3 mt-xxl-0" data-booking-options="data-booking-options">
<option value="0">Hotel</option>
<option value="1">Flight</option>
<option value="2">Trip</option>
</select>
</div>
<div class="card-body">
<div class="echart-bookings" style="height: 100%;min-height: 322px; width: 100%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
const profitData = [
[350000, 390000, 410700, 450000, 390000, 410700],
[245000, 310000, 420000, 480000, 530000, 580000],
[278450, 513220, 359890, 444567, 201345, 589000]
];
const revenueData = [
[-810000, -640000, -630000, -590000, -620000, -780000],
[-482310, -726590, -589120, -674832, -811245, -455678],
[-432567, -688921, -517389, -759234, -601876, -485112]
];
const expansesData = [
[-450000, -250000, -200000, -120000, -230000, -270000],
[-243567, -156789, -398234, -120456, -321890, -465678],
[-235678, -142345, -398765, -287456, -173890, -451234]
];
</script>
document.addEventListener("DOMContentLoaded", function () {
/* Car Chart By Make */
const getColor = (name, dom = document.documentElement) => {
return getComputedStyle(dom).getPropertyValue(`--phoenix-${name}`).trim();
};
const handleTooltipPosition = ([pos, , dom, , size]) => {
// only for mobile device
if (window.innerWidth <= 540) {
const tooltipHeight = dom.offsetHeight;
const obj = {top: pos[1] - tooltipHeight - 20};
obj[pos[0] < size.viewSize[0] / 2 ? 'left' : 'right'] = 5;
return obj;
}
return null; // else default behaviour
};
const carData = {{ car|safe }}
const carNames = carData.map(item => item.id_car_make__name);
const carCounts = carData.map(item => item.count);
const car_chart = echarts.init(document.getElementById('car-chart-by-make'));
option = {
color: getColor("danger"),
tooltip: {
trigger: 'axis',
position: (...params) => handleTooltipPosition(params),
padding: [7, 10],
axisPointer: {
type: 'none'
},
},
extraCssText: 'z-index: 1000',
responsive: true,
xAxis: [
{
type: 'category',
boundaryGap: false,
data: carNames,
axisLine: {
show: true,
lineStyle: {color: getColor('secondary-bg')}
},
axisTick: {
show: false
},
}
],
yAxis: [
{
show: false,
type: 'value',
}
],
series: [
{
type: 'bar',
barWidth: 3,
backgroundStyle: {
borderRadius: [0.5, 0.5, 0, 0],
},
data: carCounts
},
],
grid: {
bottom: 0,
top: 0,
left: 10,
right: 10,
containLabel: false
}
};
car_chart.setOption(option);
/* Car Status Chart */
const chartElContainer = document.querySelector('.echart-cars-by-status-container');
const car_status = echarts.init(document.getElementById('echart-cars-by-status'));
const chartLabel = chartElContainer.querySelector('[data-label]');
const data = [
{value: {{available_cars}}, name: '{{ _("Available") }}'},
{value: {{sold_cars}}, name: '{{ _("Sold")}}'},
{value: {{reserved_cars}}, name: '{{ _("Reserved") }}'},
{value: {{transfer_cars}}, name: '{{ _("Transfer") }}'},
{value: {{hold_cars}}, name: '{{ _("Hold") }}'},
{value: {{damaged_cars}}, name: '{{ _("Damaged") }}'}
];
const totalCars = data.reduce((acc, val) => val.value + acc, 0);
if (chartLabel) {
chartLabel.innerHTML = totalCars;
}
option = {
color: [
getColor('success'),
getColor('warning'),
getColor('danger'),
getColor('primary'),
getColor('warning-lighter'),
getColor('secondary-dark')
],
tooltip: {
trigger: 'item',
padding: [7, 10],
backgroundColor: getColor('body-highlight-bg'),
borderColor: getColor('border-color'),
textStyle: {color: getColor('light-text-emphasis')},
borderWidth: 1,
transitionDuration: 0,
extraCssText: 'z-index: 1000'
},
responsive: true,
maintainAspectRatio: false,
series: [
{
name: '',
type: 'pie',
radius: ['55%', '90%'],
startAngle: 90,
avoidLabelOverlap: false,
itemStyle: {
borderColor: getColor('body-bg'),
borderWidth: 3
},
label: {
show: false
},
emphasis: {
label: {
show: false
}
},
labelLine: {
show: false
},
data
}
],
grid: {
bottom: 0,
top: 0,
left: 0,
right: 0,
containLabel: false
}
};
car_status.setOption(option);
});
</script>
{% endblock %}

View File

@ -131,9 +131,8 @@
</div>
</div>
<div class="col-12 col-lg-3">
<div class="card h-100">
<div class="bg-holder d-dark-none" style="background-image:url({% static 'images/bg/10.png' %});background-position:left bottom;background-size:auto;"></div>
<div class="bg-holder d-light-none" style="background-image:url({% static 'images/bg/10-dark.png' %});background-position:left bottom;background-size:auto;"></div>
<div class="card h-100">
<div class="bg-holder" style="background-image:url({% static 'images/bg/bg-2.png' %});background-position:left bottom;background-size:auto;"></div>
<div class="card-body d-flex flex-column justify-content-between position-relative">
<div class="d-flex justify-content-between">
<div class="mb-5 mb-md-0 mb-lg-5">

View File

@ -19,6 +19,7 @@
<tbody class="list">
{% for order in orders %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle"><a href=""></a>{{ order.id }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ order.formatted_order_id }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ order.estimate.customer.customer_name }}</td>
<td class="align-middle product white-space-nowrap">

View File

@ -9,4 +9,59 @@ send_mail(
'info@tenhal.sa', # From email
['recipient@example.com'], # To email
fail_silently=False,
)
)
<div class="card mb-3">
<div class="bg-holder bg-card" style="background-image:url({% static 'images/spot-illustrations/39.png' %});background-position: bottom right 0px; background-size: auto;"></div>
<div class="card-body z-5">
<div>
<h3 class="text-body-highlight mb-3">{{ _("Leads") }}</h3>
<div class="col-6 col-md-6">
<div class="row align-items-center g-9">
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-success-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-success" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-star text-success" data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ new_leads }}</h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("New")}}</p>
</div>
</div>
</div>
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-warning-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-warning" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-pause text-warning" data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ pending_leads }}</h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("Pending")}}</p>
</div>
</div>
</div>
<div class="col-4">
<div class="d-flex align-items-center">
<span class="fa-stack" style="min-height: 46px;min-width: 46px;">
<span class="fa-solid fa-square fa-stack-2x dark__text-opacity-50 text-danger-light" data-fa-transform="down-4 rotate--10 left-4"></span>
<span class="fa-solid fa-circle fa-stack-2x stack-circle text-stats-circle-danger" data-fa-transform="up-4 right-3 grow-2"></span>
<span class="fa-stack-1x fa-solid fa-xmark text-danger" data-fa-transform="shrink-2 up-8 right-6"></span>
</span>
<div class="ms-2">
<h4 class="mb-0">{{ canceled_leads }}</h4>
<p class="text-body-secondary fs-9 mb-0">{{ _("Canceled")}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>