Compare commits
15 Commits
d18d4326b3
...
5a24f572f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a24f572f6 | |||
| b99c14d502 | |||
| 31fcbeb9f9 | |||
| e8b4bc5770 | |||
| aaf2a268da | |||
| a0a0a76deb | |||
| 86c7098606 | |||
| d4e084b1db | |||
| bccf7a1481 | |||
| 32b67ff8f2 | |||
| 9cedb3f0d9 | |||
| 4474c18ca7 | |||
| 1b18e71518 | |||
| 7bd18296ac | |||
| e8deb08818 |
@ -20,7 +20,7 @@ class Command(BaseCommand):
|
||||
count = opts['count']
|
||||
client = Client() # lives inside management command
|
||||
|
||||
for n in range(1, 10):
|
||||
for n in range(6, 9):
|
||||
self.stdout.write(f"🚗 Seeding dealer #{n}")
|
||||
self._create_dealer(client, n)
|
||||
# self._create_cars(client, n)
|
||||
@ -114,4 +114,5 @@ class Command(BaseCommand):
|
||||
price=additional_service["price"],
|
||||
description=additional_service["description"],
|
||||
dealer=dealer,
|
||||
uom="Unit"
|
||||
)
|
||||
|
||||
@ -26,12 +26,13 @@ class Command(BaseCommand):
|
||||
dealers = Dealer.objects.all()
|
||||
|
||||
for dealer in dealers:
|
||||
self._create_random_po(dealer)
|
||||
self._create_random_vendors(dealer)
|
||||
# self._create_random_po(dealer)
|
||||
# self._create_random_vendors(dealer)
|
||||
# self._create_random_staff(dealer)
|
||||
# self._create_random_cars(dealer)
|
||||
self._create_random_customers(dealer)
|
||||
# self._create_random_customers(dealer)
|
||||
# self._create_randome_services(dealer)
|
||||
self._create_random_lead(dealer)
|
||||
|
||||
|
||||
# dealer = Dealer.objects.get(name="Dealer #6")
|
||||
@ -66,7 +67,7 @@ class Command(BaseCommand):
|
||||
for i in range(5):
|
||||
name = f"{fake.name()}{i}"
|
||||
email = fake.email()
|
||||
password = f"{fake.password()}{i}"
|
||||
password = "Tenhal@123"
|
||||
user = User.objects.create_user(username=email, email=email, password=password)
|
||||
user.is_staff = True
|
||||
user.save()
|
||||
@ -207,6 +208,8 @@ class Command(BaseCommand):
|
||||
first_name = fake.name()
|
||||
last_name = fake.last_name()
|
||||
email = fake.email()
|
||||
phone = fake.phone_number()
|
||||
address = fake.address()
|
||||
staff = random.choice(Staff.objects.filter(dealer=dealer))
|
||||
|
||||
make = random.choice(CarMake.objects.all())
|
||||
@ -216,7 +219,8 @@ class Command(BaseCommand):
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
email=email,
|
||||
address=fake.address(),
|
||||
phone_number=phone,
|
||||
address=address,
|
||||
lead_type="customer",
|
||||
id_car_make=make,
|
||||
id_car_model=model,
|
||||
@ -227,16 +231,18 @@ class Command(BaseCommand):
|
||||
c = Customer(
|
||||
dealer=dealer,
|
||||
title="MR",
|
||||
first_name=fake.name(),
|
||||
last_name=fake.last_name(),
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
gender="m",
|
||||
email=fake.email(),
|
||||
phone_number=fake.phone_number(),
|
||||
address=fake.address(),
|
||||
email=email,
|
||||
phone_number=phone,
|
||||
address=address,
|
||||
national_id=random.randint(1000000000, 9999999999),
|
||||
)
|
||||
c.create_user_model()
|
||||
c.create_customer_model()
|
||||
c.save()
|
||||
lead.customer = c
|
||||
lead.save()
|
||||
except Exception as e:
|
||||
pass
|
||||
@ -223,7 +223,7 @@ class CarMake(models.Model, LocalizedNameMixin):
|
||||
name = models.CharField(max_length=255, blank=True, null=True)
|
||||
slug = models.SlugField(max_length=255, unique=True, blank=True, null=True)
|
||||
arabic_name = models.CharField(max_length=255, blank=True, null=True)
|
||||
logo = models.ImageField(_("logo"), upload_to="car_make", blank=True, null=True,default="user-logo.png")
|
||||
logo = models.ImageField(_("logo"), upload_to="car_make", blank=True, null=True,default="user-logo.jpg")
|
||||
is_sa_import = models.BooleanField(default=False)
|
||||
car_type = models.SmallIntegerField(choices=CarType.choices, blank=True, null=True)
|
||||
|
||||
@ -593,7 +593,7 @@ class AdditionalServices(models.Model, LocalizedNameMixin):
|
||||
|
||||
|
||||
class Car(Base):
|
||||
|
||||
|
||||
item_model = models.OneToOneField(
|
||||
ItemModel,
|
||||
models.DO_NOTHING,
|
||||
@ -1288,7 +1288,7 @@ class Staff(models.Model, LocalizedNameMixin):
|
||||
max_length=200, blank=True, null=True, verbose_name=_("Address")
|
||||
)
|
||||
logo = models.ImageField(
|
||||
upload_to="logos/staff", blank=True, null=True, verbose_name=_("Image"),default="user-logo.png"
|
||||
upload_to="logos/staff", blank=True, null=True, verbose_name=_("Image"),default="user-logo.jpg"
|
||||
)
|
||||
thumbnail = ImageSpecField(
|
||||
source="logo",
|
||||
@ -1661,7 +1661,7 @@ class Organization(models.Model, LocalizedNameMixin):
|
||||
max_length=200, blank=True, null=True, verbose_name=_("Address")
|
||||
)
|
||||
logo = models.ImageField(
|
||||
upload_to="logos", blank=True, null=True, verbose_name=_("Logo"),default="user-logo.png"
|
||||
upload_to="logos", blank=True, null=True, verbose_name=_("Logo"),default="user-logo.jpg"
|
||||
)
|
||||
thumbnail = ImageSpecField(
|
||||
source="logo",
|
||||
@ -2481,7 +2481,7 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
email = models.EmailField(max_length=255, verbose_name=_("Email Address"))
|
||||
address = models.CharField(max_length=200, verbose_name=_("Address"))
|
||||
logo = models.ImageField(
|
||||
upload_to="logos/vendors", blank=True, null=True, verbose_name=_("Logo"),default="user-logo.png"
|
||||
upload_to="logos/vendors", blank=True, null=True, verbose_name=_("Logo"),default="user-logo.jpg"
|
||||
)
|
||||
thumbnail = ImageSpecField(
|
||||
source="logo",
|
||||
|
||||
@ -500,7 +500,7 @@ def create_item_service(sender, instance, created, **kwargs):
|
||||
"""
|
||||
if created:
|
||||
entity = instance.dealer.entity
|
||||
uom = entity.get_uom_all().get(unit_abbr=instance.uom)
|
||||
uom = entity.get_uom_all().get(name=str(instance.uom).lower())
|
||||
cogs = (
|
||||
entity.get_all_accounts()
|
||||
.filter(role=roles.COGS, active=True, role_default=True)
|
||||
@ -996,10 +996,18 @@ def car_created_notification(sender, instance, created, **kwargs):
|
||||
for accountant in accountants:
|
||||
models.Notification.objects.create(
|
||||
user=accountant,
|
||||
message=f"""
|
||||
New Car {instance.id_car_make}-{instance.id_car_model}-{instance.year}-{instance.vin} has been added to the inventory.
|
||||
<a href="{instance.get_absolute_url()}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
New Car {car_make}-{car_model}-{year}-{vin} has been added to the inventory.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(
|
||||
car_make=instance.id_car_make,
|
||||
car_model=instance.id_car_model,
|
||||
year=instance.year,
|
||||
vin=instance.vin,
|
||||
url=instance.get_absolute_url(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1014,10 +1022,17 @@ def po_fullfilled_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
New Purchase Order has been added.
|
||||
<a href="{reverse("purchase_order_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
New Purchase Order has been added.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(
|
||||
url=reverse(
|
||||
"purchase_order_detail",
|
||||
kwargs={"dealer_slug": dealer.slug, "pk": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1032,9 +1047,11 @@ def vendor_created_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
New Vendor {instance.name} has been added to dealer {instance.dealer.name}.
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
New Vendor {vendor_name} has been added to dealer {dealer_name}.
|
||||
"""
|
||||
).format(vendor_name=instance.name, dealer_name=instance.dealer.name),
|
||||
)
|
||||
|
||||
|
||||
@ -1051,10 +1068,18 @@ def sale_order_created_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
New Sale Order has been added for estimate:{instance.estimate}.
|
||||
<a href="{reverse("estimate_detail", kwargs={"dealer_slug": instance.dealer.slug, "pk": instance.estimate.pk})}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
New Sale Order has been added for estimate:{estimate_number}.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(
|
||||
estimate_number=instance.estimate.estimate_number,
|
||||
url=reverse(
|
||||
"estimate_detail",
|
||||
kwargs={"dealer_slug": instance.dealer.slug, "pk": instance.estimate.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1064,10 +1089,12 @@ def lead_created_notification(sender, instance, created, **kwargs):
|
||||
if instance.staff:
|
||||
models.Notification.objects.create(
|
||||
user=instance.staff.user,
|
||||
message=f"""
|
||||
New Lead has been added.
|
||||
<a href="{reverse("lead_detail", kwargs={"dealer_slug": instance.dealer.slug, "slug": instance.slug})}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
New Lead has been added.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(url=instance.get_absolute_url()),
|
||||
)
|
||||
|
||||
|
||||
@ -1084,11 +1111,19 @@ def estimate_in_review_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
Estimate {instance.estimate_number} is in review.
|
||||
Please review and approve it at your earliest convenience.
|
||||
<a href="{reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
Estimate {estimate_number} is in review.
|
||||
Please review and approve it at your earliest convenience.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(
|
||||
estimate_number=instance.estimate_number,
|
||||
url=reverse(
|
||||
"estimate_detail",
|
||||
kwargs={"dealer_slug": dealer.slug, "pk": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1106,10 +1141,18 @@ def estimate_in_approve_notification(sender, instance, created, **kwargs):
|
||||
return
|
||||
models.Notification.objects.create(
|
||||
user=recipient.related_object.user,
|
||||
message=f"""
|
||||
Estimate {instance.estimate_number} has been approved.
|
||||
<a href="{reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
Estimate {estimate_number} has been approved.
|
||||
<a href="{url}" target="_blank">View</a>
|
||||
"""
|
||||
).format(
|
||||
estimate_number=instance.estimate_number,
|
||||
url=reverse(
|
||||
"estimate_detail",
|
||||
kwargs={"dealer_slug": dealer.slug, "pk": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1127,10 +1170,18 @@ def bill_model_in_approve_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
Bill {instance.bill_number} is in review,please review and approve it
|
||||
<a href="{reverse("bill-detail", kwargs={"dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "bill_pk": instance.pk})}" target="_blank">View</a>.
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
Bill {bill_number} is in review,please review and approve it
|
||||
<a href="{url}" target="_blank">View</a>.
|
||||
"""
|
||||
).format(
|
||||
bill_number=instance.bill_number,
|
||||
url=reverse(
|
||||
"bill-detail",
|
||||
kwargs={"dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "bill_pk": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -1148,15 +1199,22 @@ def bill_model_after_approve_notification(sender, instance, created, **kwargs):
|
||||
for recipient in recipients:
|
||||
models.Notification.objects.create(
|
||||
user=recipient,
|
||||
message=f"""
|
||||
Bill {instance.bill_number} has been approved.
|
||||
<a href="{reverse("bill-detail", kwargs={"dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "bill_pk": instance.pk})}" target="_blank">View</a>.
|
||||
please complete the bill payment.
|
||||
""",
|
||||
message=_(
|
||||
"""
|
||||
Bill {bill_number} has been approved.
|
||||
<a href="{url}" target="_blank">View</a>.
|
||||
please complete the bill payment.
|
||||
"""
|
||||
).format(
|
||||
bill_number=instance.bill_number,
|
||||
url=reverse(
|
||||
"bill-detail",
|
||||
kwargs={"dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "bill_pk": instance.pk},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def handle_upgrade(sender, order, **kwargs):
|
||||
logger.info(f"User {order.user} upgraded to {order.plan}")
|
||||
|
||||
|
||||
@ -1157,7 +1157,7 @@ def create_user_dealer(email, password, name, arabic_name, phone, crn, vrn, addr
|
||||
user = User.objects.create(username=email, email=email)
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
|
||||
# EmailAddress.objects.create(user=user, email=email, verified=True, primary=True)
|
||||
group = Group.objects.create(name=f"{user.pk}-Admin")
|
||||
user.groups.add(group)
|
||||
for perm in Permission.objects.filter(
|
||||
|
||||
@ -2344,7 +2344,7 @@ class CustomerDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView
|
||||
estimates = entity.get_estimates().filter(customer=self.object.customer_model)
|
||||
invoices = entity.get_invoices().filter(customer=self.object.customer_model)
|
||||
context['leads']=self.object.customer_leads.all()
|
||||
|
||||
|
||||
|
||||
total = estimates.count() + invoices.count()
|
||||
|
||||
@ -6125,7 +6125,7 @@ def lead_tracking(request, dealer_slug):
|
||||
qs = models.Lead.objects.filter(dealer=dealer, staff=staff)
|
||||
else:
|
||||
qs = models.Lead.objects.filter(dealer=dealer)
|
||||
|
||||
leads=qs
|
||||
won = qs.filter(status="won")
|
||||
new = qs.filter(status="new")
|
||||
lose = qs.filter(status="lose")
|
||||
@ -6138,6 +6138,7 @@ def lead_tracking(request, dealer_slug):
|
||||
"won": won,
|
||||
"lose": lose,
|
||||
"negotiation": negotiation,
|
||||
"leads":leads
|
||||
}
|
||||
return render(request, "crm/leads/lead_tracking.html", context)
|
||||
|
||||
@ -9531,7 +9532,8 @@ def mark_all_notifications_as_read(request):
|
||||
models.Notification.objects.filter(user=request.user, is_read=False).update(
|
||||
is_read=True
|
||||
)
|
||||
return redirect(request.META.get("HTTP_REFERER"))
|
||||
messages.success(request, _("All notifications marked as read."))
|
||||
return redirect("notifications_history")
|
||||
|
||||
|
||||
@login_required
|
||||
|
||||
BIN
static/images/default-user-image/customer-logo.png
Normal file
|
After Width: | Height: | Size: 744 KiB |
BIN
static/images/default-user-image/dealer.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/images/default-user-image/staff.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
static/images/default-user-image/vendor.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 6.8 KiB |
BIN
static/images/logos/no-content-new1.jpg
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
static/images/logos/no-content-new2.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/user-logo.jpg
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
@ -6,9 +6,10 @@
|
||||
{% trans "Sign In" %}
|
||||
{% endblock head_title %}
|
||||
{% block content %}
|
||||
<section class="main mt-2">
|
||||
<div class="row flex-center ">
|
||||
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
|
||||
|
||||
<section class="main my-2">
|
||||
<div class="container" style="max-width:40rem;">
|
||||
<div class="class="row form-container" id="form-container"">
|
||||
<a class="d-flex flex-center text-decoration-none mb-4"
|
||||
href="{% url 'home' %}">
|
||||
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
|
||||
@ -77,9 +78,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pt-lg-0 pt-xl-8">
|
||||
{% include 'footer.html' %}
|
||||
</section>
|
||||
|
||||
{% include 'footer.html' %}
|
||||
|
||||
{% if LOGIN_BY_CODE_ENABLED or PASSKEY_LOGIN_ENABLED %}
|
||||
<hr>
|
||||
{% element button_group vertical=True %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{% load i18n static %}
|
||||
{% block content %}
|
||||
<section class="main my-2">
|
||||
<div class="container-fluid">
|
||||
<div class="container" style="max-width:60rem;">
|
||||
<div class="row form-container" id="form-container">
|
||||
<div class="col-12 ">
|
||||
<a class="d-flex flex-center text-decoration-none mb-4"
|
||||
@ -23,7 +23,9 @@
|
||||
<h3 class="text-body-highlight">{% trans 'Sign Up' %}</h3>
|
||||
<p class="text-body-tertiary fs-9">{% trans 'Create your account today' %}</p>
|
||||
</div>
|
||||
<div class="card theme-wizard" data-theme-wizard="data-theme-wizard">
|
||||
<div data-signals="{ form1:{email:'',password:'',confirm_password:''}, form2:{name:'',arabic_name:'',phone_number:''}, form3:{crn:'',vrn:'',address:''}, form1_valid:true, form2_valid:true, form3_valid:true, email_valid:true, password_valid:true, phone_number_valid:true }"
|
||||
class="card theme-wizard"
|
||||
data-theme-wizard="data-theme-wizard">
|
||||
<div class="card-header pt-3 pb-2 ">
|
||||
<ul class="nav justify-content-between nav-wizard nav-wizard-success"
|
||||
role="tablist">
|
||||
@ -84,7 +86,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body pt-4 pb-0">
|
||||
<div class="tab-content">
|
||||
<div class="tab-content" data-signals-current_form="1">
|
||||
<div class="tab-pane active"
|
||||
role="tabpanel"
|
||||
aria-labelledby="bootstrap-wizard-validation-tab1"
|
||||
@ -92,11 +94,57 @@
|
||||
<form class="needs-validation"
|
||||
id="wizardValidationForm1"
|
||||
novalidate="novalidate"
|
||||
data-wizard-form="1">
|
||||
{{ form1|crispy }}
|
||||
<a class="fs-10 text-decoration-none"
|
||||
href="{% url 'terms_and_privacy' %}"
|
||||
target="_blank">{{ _("Read Terms of Service and Privacy Policy") }}</a>
|
||||
data-wizard-form="1"
|
||||
data-ref-f1>
|
||||
<div class="mb-3">
|
||||
<label for="email"
|
||||
data-class="{'text-danger':!$email_valid}"
|
||||
class="form-label">
|
||||
{% trans "Email" %}
|
||||
<span data-show="!$email_valid" class="text-danger">*</span>
|
||||
</label>
|
||||
<input data-on-input="$email_valid = validateEmail($form1.email)"
|
||||
data-on-blur="$email_valid = validateEmail($form1.email)"
|
||||
data-bind-form1.email
|
||||
data-class="{'is-invalid': !$email_valid , 'is-valid': ($email_valid && $form1.email)}"
|
||||
type="email"
|
||||
class="form-control"
|
||||
id="email"
|
||||
name="email"
|
||||
required>
|
||||
<div class="invalid-feedback" data-show="!$email_valid">{% trans "Please enter a valid email address" %}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">{% trans "Password" %}</label>
|
||||
<input data-bind-form1.password
|
||||
type="password"
|
||||
data-on-input="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
|
||||
data-on-blur="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
|
||||
class="form-control"
|
||||
data-class="{'is-invalid':($form1.password.length && $form1.password.length < 8),'is-valid':$form1.password.length > 8 }"
|
||||
id="password"
|
||||
name="password"
|
||||
required>
|
||||
<div class="invalid-feedback" data-show="!$password_valid">
|
||||
{% trans "Password does not match. or length is less than 8 characters." %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirm_password" class="form-label">{% trans "Confirm Password" %}</label>
|
||||
<span class="text-danger" data-show="!$password_valid">*</span>
|
||||
<input data-bind-form1.confirm_password
|
||||
data-on-input="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
|
||||
data-on-blur="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
|
||||
type="password"
|
||||
class="form-control"
|
||||
data-class="{'is-invalid':!$password_valid,'is-valid':($password_valid&& $form1.confirm_password)}"
|
||||
id="confirm_password"
|
||||
name="confirm_password"
|
||||
required>
|
||||
<div class="invalid-feedback" data-show="!$password_valid">
|
||||
{% trans "Password does not match. or length is less than 8 characters." %}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane"
|
||||
@ -106,8 +154,39 @@
|
||||
<form class="needs-validation"
|
||||
id="wizardValidationForm2"
|
||||
novalidate="novalidate"
|
||||
data-wizard-form="2">
|
||||
{{ form2|crispy }}
|
||||
data-wizard-form="2"
|
||||
data-ref-f2>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">{% trans "Name" %}</label>
|
||||
<input data-bind-form2.name
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="name"
|
||||
name="name"
|
||||
required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="arabic_name" class="form-label">{% trans "Arabic Name" %}</label>
|
||||
<input data-bind-form2.arabic_name
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="arabic_name"
|
||||
name="arabic_name"
|
||||
required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="phone_number" class="form-label">{% trans "Phone Number" %}</label>
|
||||
<span data-show="!$phone_number_valid" class="text-danger">*</span>
|
||||
<input data-bind-form2.phone_number
|
||||
type="tel"
|
||||
data-class="{'is-invalid':!$phone_number_valid}"
|
||||
class="form-control"
|
||||
id="phone_number"
|
||||
name="phone_number"
|
||||
required
|
||||
data-on-input="$phone_number_valid = validate_sa_phone_number($form2.phone_number)">
|
||||
<div class="invalid-feedback" data-show="!$phone_number_valid">{% trans "Please enter a valid phone number" %}</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane"
|
||||
@ -117,8 +196,34 @@
|
||||
<form class="needs-validation"
|
||||
id="wizardValidationForm3"
|
||||
novalidate="novalidate"
|
||||
data-wizard-form="3">
|
||||
{{ form3|crispy }}
|
||||
data-wizard-form="3"
|
||||
data-ref-f3>
|
||||
<div class="mb-3">
|
||||
<label for="crn" class="form-label">{% trans "CRN" %}</label>
|
||||
<input data-bind-form3.crn
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="crn"
|
||||
name="crn"
|
||||
required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="vrn" class="form-label">{% trans "VRN" %}</label>
|
||||
<input data-bind-form3.vrn
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="vrn"
|
||||
name="vrn"
|
||||
required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="address" class="form-label">{% trans "Address" %}</label>
|
||||
<textarea data-bind-form3.address
|
||||
class="form-control"
|
||||
id="address"
|
||||
name="address"
|
||||
required></textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane"
|
||||
@ -146,22 +251,28 @@
|
||||
<br>
|
||||
{% trans 'anytime' %} {% trans 'anywhere' %}
|
||||
</p>
|
||||
<button class="btn btn-primary px-6" id='submit_btn'>{% trans 'Submit' %}</button>
|
||||
<button data-on-click="sendFormData()"
|
||||
class="btn btn-primary px-6"
|
||||
id='submit_btn'>{% trans 'Submit' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer border-top-0"
|
||||
<div data-computed-form1_valid="validatePassword($form1.password,$form1.confirm_password) && validateEmail($form1.email)"
|
||||
class="card-footer border-top-0"
|
||||
data-wizard-footer="data-wizard-footer">
|
||||
<div class="d-flex pager wizard list-inline mb-0">
|
||||
<button class="d-none btn btn-link ps-0"
|
||||
type="button"
|
||||
data-wizard-prev-btn="data-wizard-prev-btn">{% trans 'Previous' %}</button>
|
||||
<div class="flex-1 text-end">
|
||||
<button class="btn btn-phoenix-primary px-6 px-sm-6 next"
|
||||
type="submit"
|
||||
<button data-attr-disabled="!$form1_valid"
|
||||
data-attr-disabled="!$phone_number_valid"
|
||||
class="btn btn-phoenix-primary px-6 px-sm-6 next"
|
||||
type="button"
|
||||
id="next_btn"
|
||||
data-wizard-next-btn="data-wizard-next-btn">{% trans 'Next' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -177,160 +288,36 @@
|
||||
<script src="{% static 'js/phoenix.js' %}"></script>
|
||||
{% endblock content %}
|
||||
{% block customJS %}
|
||||
<script src="https://unpkg.com/just-validate@latest/dist/just-validate.production.min.js"></script>
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
|
||||
<script type="module"
|
||||
src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.11/bundles/datastar.js"></script>
|
||||
<script>
|
||||
const validator = new JustValidate('#wizardValidationForm1', {
|
||||
validateBeforeSubmitting: true,
|
||||
});
|
||||
const validator1 = new JustValidate('#wizardValidationForm2', {
|
||||
validateBeforeSubmitting: true,
|
||||
});
|
||||
|
||||
validator1.addField('#wizardValidationForm2 [name="phone_number"]', [
|
||||
{
|
||||
rule: 'required',
|
||||
},
|
||||
{
|
||||
rule: 'customRegexp',
|
||||
value: /^05\d{8}$/,
|
||||
errorMessage: '{% trans 'Please enter a valid phone number' %}',
|
||||
},
|
||||
{
|
||||
rule: 'maxLength',
|
||||
value: 10,
|
||||
errorMessage: '{% trans 'Please enter a valid phone number' %}',
|
||||
},
|
||||
|
||||
]);
|
||||
|
||||
validator.addField('#wizardValidationForm1 [name="email"]', [
|
||||
{
|
||||
rule: 'required',
|
||||
},
|
||||
{
|
||||
rule: 'email',
|
||||
},
|
||||
]);
|
||||
|
||||
validator.addField('#wizardValidationForm1 [name="password"]', [
|
||||
{
|
||||
rule: 'required',
|
||||
},
|
||||
{
|
||||
rule: 'minLength',
|
||||
value: 6,
|
||||
},
|
||||
|
||||
]);
|
||||
validator.addField('#wizardValidationForm1 [name="confirm_password"]', [
|
||||
{
|
||||
rule: 'required',
|
||||
},
|
||||
{
|
||||
rule: 'minLength',
|
||||
value: 6,
|
||||
errorMessage: '{% trans 'Password does not match' %}',
|
||||
},
|
||||
{
|
||||
validator: (value, context) => {
|
||||
if (value !== document.querySelector('#id_password').value) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
])
|
||||
validator.addField('#wizardValidationForm1 [name="terms"]', [
|
||||
{
|
||||
rule: 'required',
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
/*
|
||||
validator = new JustValidate('#wizardValidationForm1', {
|
||||
rules: {
|
||||
email: {
|
||||
required: true,
|
||||
email: true,
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
min: 6,
|
||||
},
|
||||
confirm_password: {
|
||||
required: true,
|
||||
min: 6,
|
||||
equalTo: '#password',
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
name: {
|
||||
required: 'Please enter your name',
|
||||
},
|
||||
email: {
|
||||
required: 'Please enter your email',
|
||||
email: 'Please enter a valid email address',
|
||||
},
|
||||
password: {
|
||||
required: 'Please enter your password',
|
||||
min: 'Password must be at least 6 characters',
|
||||
},
|
||||
confirm_password: {
|
||||
required: 'Please confirm your password',
|
||||
min: 'Password must be at least 6 characters',
|
||||
equalTo: 'Passwords do not match',
|
||||
},
|
||||
}
|
||||
})
|
||||
*/
|
||||
const url = "{% url 'account_signup' %}";
|
||||
let submit_btn = document.getElementById('submit_btn');
|
||||
const csrftoken = getCookie('csrftoken');
|
||||
|
||||
submit_btn.addEventListener('click', async () => {
|
||||
const allFormData = getAllFormData();
|
||||
|
||||
try {
|
||||
showLoading();
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrftoken,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(allFormData),
|
||||
});
|
||||
hideLoading();
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
notify("success","Account created successfully");
|
||||
setTimeout(() => {
|
||||
window.location.href = "{% url 'account_login' %}";
|
||||
}, 1000);
|
||||
} else {
|
||||
notify("error",data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
notify("error",error);
|
||||
function validatePassword(password, confirmPassword) {
|
||||
return password === confirmPassword && password.length > 7 && password !== '';
|
||||
}
|
||||
function validateEmail(email) {
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
return emailRegex.test(email) && email !== '';
|
||||
}
|
||||
function validateform2(name,arabic_name,phone_number) {
|
||||
if (name === '' || arabic_name === '' || phone_number === '' || phone_number.length < 10 || !phone_number.startsWith('056')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return true
|
||||
}
|
||||
function validate_sa_phone_number(phone_number) {
|
||||
const phone_numberRegex = /^056[0-9]{7}$/;
|
||||
return phone_numberRegex.test(phone_number) && phone_numberRegex !== '';
|
||||
}
|
||||
function getAllFormData() {
|
||||
const forms = document.querySelectorAll('form');
|
||||
const forms = document.querySelectorAll('.needs-validation');
|
||||
const formData = {};
|
||||
|
||||
forms.forEach((form, index) => {
|
||||
const formId = form.id || `form${index + 1}`;
|
||||
formData[formId] = {};
|
||||
|
||||
const formElements = form.elements;
|
||||
for (let element of formElements) {
|
||||
if (element.name) {
|
||||
formData[formId][element.name] = element.value;
|
||||
}
|
||||
}
|
||||
forms.forEach(form => {
|
||||
const fields = form.querySelectorAll('input,textarea,select');
|
||||
fields.forEach(field => {
|
||||
formData[field.name] = field.value;
|
||||
});
|
||||
});
|
||||
return formData;
|
||||
}
|
||||
@ -370,5 +357,33 @@
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
async function sendFormData() {
|
||||
const formData = getAllFormData();
|
||||
const url = "{% url 'account_signup' %}";
|
||||
const csrftoken = getCookie('csrftoken');
|
||||
try {
|
||||
showLoading();
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': '{{csrf_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
hideLoading();
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
notify("success","Account created successfully");
|
||||
setTimeout(() => {
|
||||
window.location.href = "{% url 'account_login' %}";
|
||||
}, 1000);
|
||||
} else {
|
||||
notify("error",data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
notify("error",error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock customJS %}
|
||||
@ -282,9 +282,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="pt-lg-0 pt-xl-8">
|
||||
|
||||
{% include 'footer.html' %}
|
||||
</section>
|
||||
|
||||
<script src="{% static 'js/phoenix.js' %}"></script>
|
||||
{% endblock content %}
|
||||
{% block customJS %}
|
||||
@ -307,7 +307,7 @@
|
||||
return true
|
||||
}
|
||||
function validate_sa_phone_number(phone_number) {
|
||||
const phone_numberRegex = /^056[0-9]{7}$/;
|
||||
const phone_numberRegex = /^05[0-9]{8}$/;
|
||||
return phone_numberRegex.test(phone_number) && phone_numberRegex !== '';
|
||||
}
|
||||
function getAllFormData() {
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
rel="stylesheet"
|
||||
id="user-style-default">
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
<script src="{% static 'js/jquery.min.js' %}"></script>
|
||||
|
||||
@ -79,11 +79,13 @@
|
||||
<div class="row align-items-center g-3 text-center text-xxl-start">
|
||||
<div class="col-6 col-sm-auto d-flex flex-column align-items-center text-center">
|
||||
<h5 class="fw-bolder mb-2 text-body-highlight">{{ _("Car Requested") }}</h5>
|
||||
{% if lead.id_car_make.logo %}
|
||||
<img src="{{ lead.id_car_make.logo.url }}"
|
||||
alt="Car Make Logo"
|
||||
class="img-fluid rounded mb-2"
|
||||
style="width: 60px;
|
||||
height: 60px">
|
||||
alt="Car Make Logo"
|
||||
class="img-fluid rounded mb-2"
|
||||
style="width: 60px;
|
||||
height: 60px">
|
||||
{% endif %}
|
||||
<p class="mb-0">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -65,6 +65,8 @@
|
||||
</style>
|
||||
{% endblock customCSS %}
|
||||
{% block content %}
|
||||
|
||||
{% if leads %}
|
||||
<div class="container-fluid my-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col">
|
||||
@ -168,13 +170,14 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if not new and not follow_up and not negotiation %}
|
||||
{% url 'lead_create' request.dealer.slug as create_lead_url %}
|
||||
{% include "empty-illustration-page.html" with value="lead" url=create_lead_url %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{% url 'lead_create' request.dealer.slug as create_lead_url %}
|
||||
{% include "empty-illustration-page.html" with value="lead" url=create_lead_url %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="content">
|
||||
<h2 class="mb-5">{{ _("Notifications") }}</h2>
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<a href="{% url 'mark_all_notifications_as_read' %}" hx-select-oob="#notification-counter:outerHTML" class="btn btn-phoenix-primary"><i class="far fa-envelope fs-8 me-2"></i>{{ _("Mark all as read") }}</a>
|
||||
<a href="{% url 'mark_all_notifications_as_read' %}" hx-select-oob="#toast-container:outerHTML" class="btn btn-phoenix-primary"><i class="far fa-envelope fs-8 me-2"></i>{{ _("Mark all as read") }}</a>
|
||||
</div>
|
||||
{% if notifications %}
|
||||
<div class="mx-n4 mx-lg-n6 mb-5 border-bottom">
|
||||
|
||||
@ -147,20 +147,20 @@
|
||||
<tbody class="list" id="customer-order-table-body">
|
||||
{% for lead in leads %}
|
||||
<tr>
|
||||
<td><a href="#">{{lead}} ({{ forloop.counter }})<a></td>
|
||||
<td>{{lead.opportunity}} ({{ forloop.counter }})</td>
|
||||
<td><a href="{% url 'lead_detail' request.dealer.slug lead.slug%}">{{lead}} ({{ forloop.counter }})<a></td>
|
||||
<td><a href="{$ url 'opportunity_detail' lead.opportunity.slug request.dealer.slug}">{{lead.opportunity}} ({{ forloop.counter }})</a></td>
|
||||
|
||||
<td>
|
||||
|
||||
{% for estimate in lead.customer.customer_model.estimatemodel_set.all %}
|
||||
<div class="me-2">{{estimate}}</div>
|
||||
<div class="me-2"><a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}">{{estimate}}</a></div>
|
||||
<hr>
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{% for estimate in lead.customer.customer_model.estimatemodel_set.all %}
|
||||
<div>{{estimate.sale_orders.first}}</div>
|
||||
<div><a href={% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk%}>{{estimate.sale_orders.first}}</a></div>
|
||||
<hr>
|
||||
{% endfor %}
|
||||
</td>
|
||||
@ -169,11 +169,11 @@
|
||||
|
||||
{% if invoice.is_paid %}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-success">
|
||||
<div>{{invoice}}</div>
|
||||
<div><a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug invoice.pk %}">{{invoice}}</a></div>
|
||||
</span>
|
||||
{%else%}
|
||||
<span class="badge badge-phoenix fs-10 badge-phoenix-info">
|
||||
<div>{{invoice}}</div>
|
||||
<div><a href="{% url 'invoice_detail' request.dealer.slug request.entity.slug invoice.pk %}">{{invoice}}</a></div>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
@ -182,7 +182,7 @@
|
||||
</td>
|
||||
<td>
|
||||
{% for estimate in lead.customer.customer_model.invoicemodel_set.all %}
|
||||
<div>{{estimate.itemtransactionmodel_set.first.item_model.name}}</div>
|
||||
<div><a href="#">{{estimate.itemtransactionmodel_set.first.item_model.name}}</a></div>
|
||||
<hr>
|
||||
{% endfor %}
|
||||
<td>
|
||||
|
||||
@ -121,7 +121,7 @@
|
||||
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="d-flex justify-content-between" hx-boost="false">
|
||||
<div class="mb-5 mb-md-0 mb-lg-5">
|
||||
<div class="d-sm-flex d-md-block d-lg-flex align-items-center mb-3">
|
||||
<h3 class="mb-0 me-2">{{ dealer.user.userplan.plan|capfirst }}</h3>
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
{% load static %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
.empty-state-container {
|
||||
background-color: #ffffff;
|
||||
padding: 40px;
|
||||
border-radius: 15px; /* Rounded corners */
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); /* Subtle shadow */
|
||||
padding: 50px;
|
||||
border-radius: 5px; /* Rounded corners */
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); /* Subtle shadow */
|
||||
text-align: center;
|
||||
max-width: 80rem; /* Max width for content - made wider */
|
||||
max-width: 70rem; /* Max width for content - made wider */
|
||||
width: 90%; /* Fluid width */
|
||||
margin: 10px auto; /* Added margin-top and auto for horizontal centering */
|
||||
max-height: auto; /* Added min-height to control the height */
|
||||
margin: 0px auto; /* Added margin-top and auto for horizontal centering */
|
||||
max-height: 80vh; /* Added min-height to control the height */
|
||||
display: flex; /* Use flexbox for vertical centering of content */
|
||||
flex-direction: column; /* Stack children vertically */
|
||||
justify-content: center; /* Center content vertically */
|
||||
@ -20,8 +20,8 @@
|
||||
}
|
||||
.empty-state-image {
|
||||
max-width: 50%; /* Responsive image size */
|
||||
height: auto;
|
||||
margin-bottom: 10px;
|
||||
height: auto%;
|
||||
|
||||
border-radius: 10px; /* Rounded corners for image */
|
||||
}
|
||||
.empty-state-title {
|
||||
@ -42,14 +42,19 @@
|
||||
<img src="{% static 'images/logos/no-content-new.jpg' %}" alt="No-empty-state-image" class="empty-state-image">
|
||||
|
||||
<!-- Title -->
|
||||
<h3 class="empty-state-title">No {{ value|capfirst }} Yet</h3>
|
||||
<h3 class="empty-state-title">
|
||||
{% blocktrans %}No {{ value}} Yet{% endblocktrans %}
|
||||
</h3>
|
||||
|
||||
<!-- Description -->
|
||||
<p class="empty-state-text">
|
||||
It looks like you haven't added any {{ value }} to your account.
|
||||
Click the button below to get started and add your first {{ value }}!
|
||||
{% blocktrans %}It looks like you haven't added any {{ value }} to your account.
|
||||
Click the button below to get started and add your first {{ value }}!{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<!-- Call to Action Button -->
|
||||
<a class="btn btn-lg btn-primary" href="{{ url }}">Create New {{ value|capfirst }} </a>
|
||||
<a class="btn btn-lg btn-primary" href="{{ url }}">
|
||||
<i class="fa fa-plus me-2"></i>
|
||||
{% blocktrans %}Create New {{value}}{% endblocktrans %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -547,7 +547,7 @@
|
||||
<a class="btn btn-sm btn-phoenix-danger d-flex flex-center w-100" href="{% url 'account_logout' %}"> <span class="me-2" data-feather="log-out"> </span>{% trans 'Sign Out' %}</a>
|
||||
</div>
|
||||
<div class="my-2 text-center fw-bold fs-10 text-body-quaternary">
|
||||
<a class="text-body-quaternary me-1" href="">Privacy policy</a>•<a class="text-body-quaternary mx-1" href="">Terms</a>•<a class="text-body-quaternary ms-1" href="">Cookies</a>
|
||||
<a class="text-body-quaternary me-1" href="">{% trans 'Privacy policy' %}</a>•<a class="text-body-quaternary mx-1" href="">{% trans 'Terms' %}</a>•<a class="text-body-quaternary ms-1" href="">Cookies</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="px-3">
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{% if inventory %}
|
||||
{% if inventory.total_cars > 0 %}
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-sm-12 ">
|
||||
<div class="card border h-100 w-100 p-lg-10">
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
|
||||
{% else %}
|
||||
{% url "bill-create" request.dealer.slug as create_bill_url %}
|
||||
{% url "bill-create" request.dealer.slug request.entity.slug as create_bill_url %}
|
||||
{% include "empty-illustration-page.html" with value="bill" url=create_bill_url %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@ -131,7 +131,7 @@
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
{% url 'ledger_create' request.dealer.slug as create_ledger_url %}
|
||||
{% url 'ledger_create' request.dealer.slug request.entity.slug as create_ledger_url %}
|
||||
{% include "empty-illustration-page.html" with value="ledger" url=create_ledger_url %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
|
||||
{% else %}
|
||||
{% url "estimate_create" request.dealer.slug as create_estimate_url %}
|
||||
{% include "empty-illustration-page.html" with value="customer" url=create_estimate_url %}
|
||||
{% include "empty-illustration-page.html" with value="estimate" url=create_estimate_url %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">
|
||||
{{ _("No Active Subscription,please activate your subscription.") }}<a href="{% url 'pricing_page' request.dealer.slug %}"
|
||||
{{ _("No Active Subscription,please activate your subscription.") }}<a hx-boost="false" href="{% url 'pricing_page' request.dealer.slug %}"
|
||||
class="ms-3 text-body-primary fs-9">Manage Subscription</a>
|
||||
</p>
|
||||
<button class="btn-close"
|
||||
@ -55,7 +55,7 @@
|
||||
{% if user.logo %}
|
||||
<img class="avatar-img rounded-circle"
|
||||
src="{{user.thumbnail.url}}"
|
||||
onerror="this.src='/static/user-logo.png'"
|
||||
onerror="this.src='/static/user-logo.jpg'"
|
||||
alt="Logo">
|
||||
{% endif %}
|
||||
</div>
|
||||
@ -91,8 +91,28 @@
|
||||
</section>
|
||||
|
||||
{% else %}
|
||||
{% url "user_create" request.dealer.slug as create_staff_url %}
|
||||
{% include "empty-illustration-page.html" with value="staff" url=create_staff_url %}
|
||||
|
||||
{% if request.user.userplan %}
|
||||
{% url "user_create" request.dealer.slug as create_staff_url %}
|
||||
{% include "empty-illustration-page.html" with value="staff" url=create_staff_url %}
|
||||
|
||||
{% else %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center"
|
||||
role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">
|
||||
{{ _("No Active Subscription,please activate your subscription.") }}<a href="{% url 'pricing_page' request.dealer.slug %}"
|
||||
class="ms-3 text-body-primary fs-9">Manage Subscription</a>
|
||||
</p>
|
||||
<button class="btn-close"
|
||||
type="button"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
<!DOCTYPE html>
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<html lang="{{ LANGUAGE_CODE }}"
|
||||
dir="{% if LANGUAGE_CODE == 'ar' %}
|
||||
rtl
|
||||
{% if LANGUAGE_CODE == 'ar' %}
|
||||
dir="rtl"
|
||||
{% else %}
|
||||
ltr
|
||||
{% endif %}"
|
||||
dir="ltr"
|
||||
{% endif %}
|
||||
data-bs-theme="dark"
|
||||
data-navigation-type="default"
|
||||
data-navbar-horizontal-shape="default">
|
||||
@ -78,6 +78,9 @@
|
||||
{% include 'welcome_header.html' %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
|
||||
|
||||
{% comment %}
|
||||
<script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
|
||||
<script src="{% static 'vendors/is/is.min.js' %}"></script>
|
||||
|
||||