conflicts

This commit is contained in:
Faheedkhan 2025-07-22 12:24:49 +03:00
commit aa58919c56
322 changed files with 20481 additions and 16420 deletions

1
.gitignore vendored
View File

@ -11,6 +11,7 @@ dbtest.sqlite3
db.sqlite3 db.sqlite3
db.sqlite3.backup db.sqlite3.backup
db.sqlite* db.sqlite*
new.sqlite3
*.sqlite3 *.sqlite3
media media
car*.json car*.json

View File

@ -1,4 +1,4 @@
# Generated by Django 5.2.4 on 2025-07-15 13:26 # Generated by Django 5.2.4 on 2025-07-15 11:38
import django.db.models.deletion import django.db.models.deletion
import django.utils.timezone import django.utils.timezone

View File

@ -1,4 +1,4 @@
# Generated by Django 5.2.4 on 2025-07-15 13:26 # Generated by Django 5.2.4 on 2025-07-15 11:38
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models from django.db import migrations, models

View File

@ -1,5 +1,6 @@
from django.conf import settings from django.conf import settings
def currency_context(request): def currency_context(request):
""" """
Provides a context dictionary containing the currency setting. This is typically Provides a context dictionary containing the currency setting. This is typically
@ -42,7 +43,6 @@ def breadcrumbs(request):
return {"breadcrumbs": breadcrumbs} return {"breadcrumbs": breadcrumbs}
def user_types(request): def user_types(request):
""" """
Sets various flags indicating the user's role types. Sets various flags indicating the user's role types.

View File

@ -142,6 +142,7 @@ class StaffForm(forms.ModelForm):
queryset=CustomGroup.objects.all(), queryset=CustomGroup.objects.all(),
required=True, required=True,
) )
class Meta: class Meta:
model = Staff model = Staff
fields = ["name", "arabic_name", "phone_number", "address", "logo", "group"] fields = ["name", "arabic_name", "phone_number", "address", "logo", "group"]
@ -1564,6 +1565,7 @@ class GroupForm(forms.ModelForm):
# 60 * 60, # 60 * 60,
# ) # )
# class Meta: # class Meta:
# model = Permission # model = Permission
# fields = ["name"] # fields = ["name"]
@ -1571,6 +1573,7 @@ class PermissionForm(forms.ModelForm):
""" """
Form for managing permissions with grouped checkboxes by app and model. Form for managing permissions with grouped checkboxes by app and model.
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
EXCLUDED_MODELS = [ EXCLUDED_MODELS = [
@ -1591,19 +1594,15 @@ class PermissionForm(forms.ModelForm):
"inventory.schedule", "inventory.schedule",
"inventory.activity", "inventory.activity",
"inventory.opportunity", "inventory.opportunity",
"inventory.carreservation" "inventory.carreservationinventory.customer",
"inventory.customer",
"inventory.organization", "inventory.organization",
# "inventory.salequotation", # "inventory.salequotation",
# "inventory.salequotationcar" # "inventory.salequotationcar"
"django_ledger.purchaseordermodeldjango_ledger.bankaccountmodel",
"django_ledger.purchaseordermodel"
"django_ledger.bankaccountmodel",
"django_ledger.estimatemodel", "django_ledger.estimatemodel",
"django_ledger.accountmodel", "django_ledger.accountmodel",
"django_ledger.chartofaccountmodel", "django_ledger.chartofaccountmodel",
"django_ledger.billmodel" "django_ledger.billmodeldjango_ledger.itemmodel",
"django_ledger.itemmodel",
"django_ledger.invoicemodel", "django_ledger.invoicemodel",
"django_ledger.vendormodel", "django_ledger.vendormodel",
"django_ledger.journalentrymodel" "django_ledger.journalentrymodel"
@ -1613,9 +1612,9 @@ class PermissionForm(forms.ModelForm):
permissions = cache.get( permissions = cache.get(
"permissions_queryset", "permissions_queryset",
Permission.objects.filter( Permission.objects.filter(
content_type__app_label__in=[m.split('.')[0] for m in EXCLUDED_MODELS], content_type__app_label__in=[m.split(".")[0] for m in EXCLUDED_MODELS],
content_type__model__in=[m.split('.')[1] for m in EXCLUDED_MODELS] content_type__model__in=[m.split(".")[1] for m in EXCLUDED_MODELS],
).select_related('content_type') ).select_related("content_type"),
) )
# Group permissions by app_label and model # Group permissions by app_label and model
@ -1630,11 +1629,11 @@ class PermissionForm(forms.ModelForm):
self.grouped_permissions[app_label][model].append(perm) self.grouped_permissions[app_label][model].append(perm)
# Create a multiple choice field (hidden, will use custom rendering) # Create a multiple choice field (hidden, will use custom rendering)
self.fields['permissions'] = forms.ModelMultipleChoiceField( self.fields["permissions"] = forms.ModelMultipleChoiceField(
queryset=permissions, queryset=permissions,
widget=forms.MultipleHiddenInput(), widget=forms.MultipleHiddenInput(),
required=False, required=False,
initial=self.instance.permissions.all() if self.instance.pk else [] initial=self.instance.permissions.all() if self.instance.pk else [],
) )
class Meta: class Meta:
@ -2036,8 +2035,8 @@ class CSVUploadForm(forms.Form):
) )
year = forms.IntegerField( year = forms.IntegerField(
label=_("Year"), label=_("Year"),
widget=forms.NumberInput(attrs= widget=forms.NumberInput(
{ attrs={
"class": "form-control", "class": "form-control",
"hx-get": "", "hx-get": "",
"hx-target": "#serie", "hx-target": "#serie",
@ -2101,7 +2100,8 @@ class AdditionalFinancesForm(forms.Form):
required=False, required=False,
) )
class VatRateForm(forms.ModelForm): class VatRateForm(forms.ModelForm):
class Meta: class Meta:
model = VatRate model = VatRate
fields = ['rate'] fields = ["rate"]

View File

@ -4,13 +4,46 @@ from django.core.management.base import BaseCommand
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django_ledger.models import EstimateModel, BillModel, AccountModel, LedgerModel from django_ledger.models import EstimateModel, BillModel, AccountModel, LedgerModel
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
Permission.objects.get_or_create(name="Can view crm",codename="can_view_crm",content_type=ContentType.objects.get_for_model(Lead)) Permission.objects.get_or_create(
Permission.objects.get_or_create(name="Can reassign lead",codename="can_reassign_lead",content_type=ContentType.objects.get_for_model(Lead)) name="Can view crm",
Permission.objects.get_or_create(name="Can view sales",codename="can_view_sales",content_type=ContentType.objects.get_for_model(EstimateModel)) codename="can_view_crm",
Permission.objects.get_or_create(name="Can view reports",codename="can_view_reports",content_type=ContentType.objects.get_for_model(LedgerModel)) content_type=ContentType.objects.get_for_model(Lead),
Permission.objects.get_or_create(name="Can view inventory",codename="can_view_inventory",content_type=ContentType.objects.get_for_model(Car)) )
Permission.objects.get_or_create(name="Can approve bill",codename="can_approve_billmodel",content_type=ContentType.objects.get_for_model(BillModel)) Permission.objects.get_or_create(
Permission.objects.get_or_create(name="Can view financials",codename="can_view_financials",content_type=ContentType.objects.get_for_model(AccountModel)) name="Can reassign lead",
Permission.objects.get_or_create(name="Can approve estimate",codename="can_approve_estimatemodel",content_type=ContentType.objects.get_for_model(EstimateModel)) codename="can_reassign_lead",
content_type=ContentType.objects.get_for_model(Lead),
)
Permission.objects.get_or_create(
name="Can view sales",
codename="can_view_sales",
content_type=ContentType.objects.get_for_model(EstimateModel),
)
Permission.objects.get_or_create(
name="Can view reports",
codename="can_view_reports",
content_type=ContentType.objects.get_for_model(LedgerModel),
)
Permission.objects.get_or_create(
name="Can view inventory",
codename="can_view_inventory",
content_type=ContentType.objects.get_for_model(Car),
)
Permission.objects.get_or_create(
name="Can approve bill",
codename="can_approve_billmodel",
content_type=ContentType.objects.get_for_model(BillModel),
)
Permission.objects.get_or_create(
name="Can view financials",
codename="can_view_financials",
content_type=ContentType.objects.get_for_model(AccountModel),
)
Permission.objects.get_or_create(
name="Can approve estimate",
codename="can_approve_estimatemodel",
content_type=ContentType.objects.get_for_model(EstimateModel),
)

View File

@ -135,6 +135,7 @@ class InjectDealerMiddleware:
# return redirect(reverse('verify_otp')) # return redirect(reverse('verify_otp'))
# return self.get_response(request) # return self.get_response(request)
class DealerSlugMiddleware: class DealerSlugMiddleware:
def __init__(self, get_response): def __init__(self, get_response):
self.get_response = get_response self.get_response = get_response
@ -142,19 +143,22 @@ class DealerSlugMiddleware:
def __call__(self, request): def __call__(self, request):
response = self.get_response(request) response = self.get_response(request)
return response return response
def process_view(self, request, view_func, view_args, view_kwargs): def process_view(self, request, view_func, view_args, view_kwargs):
if request.path_info.startswith('/ar/signup/') or \ if (
request.path_info.startswith('/en/signup/') or \ request.path_info.startswith("/ar/signup/")
request.path_info.startswith('/ar/login/') or \ or request.path_info.startswith("/en/signup/")
request.path_info.startswith('/en/login/') or \ or request.path_info.startswith("/ar/login/")
request.path_info.startswith('/ar/logout/') or \ or request.path_info.startswith("/en/login/")
request.path_info.startswith('/en/logout/') or \ or request.path_info.startswith("/ar/logout/")
request.path_info.startswith('/en/ledger/') or \ or request.path_info.startswith("/en/logout/")
request.path_info.startswith('/ar/ledger/') or \ or request.path_info.startswith("/en/ledger/")
request.path_info.startswith('/en/notifications/') or \ or request.path_info.startswith("/ar/ledger/")
request.path_info.startswith('/ar/notifications/') or \ or request.path_info.startswith("/en/notifications/")
request.path_info.startswith('/en/appointment/') or \ or request.path_info.startswith("/ar/notifications/")
request.path_info.startswith('/ar/appointment/'): or request.path_info.startswith("/en/appointment/")
or request.path_info.startswith("/ar/appointment/")
):
return None return None
if not request.user.is_authenticated: if not request.user.is_authenticated:
@ -164,12 +168,14 @@ class DealerSlugMiddleware:
if not dealer_slug: if not dealer_slug:
return None return None
if not hasattr(request, 'dealer') or not request.dealer: if not hasattr(request, "dealer") or not request.dealer:
logger.warning("No dealer associated with request") logger.warning("No dealer associated with request")
return None return None
if dealer_slug.lower() != request.dealer.slug.lower(): if dealer_slug.lower() != request.dealer.slug.lower():
logger.warning(f"Dealer slug mismatch: {dealer_slug} != {request.dealer.slug}") logger.warning(
f"Dealer slug mismatch: {dealer_slug} != {request.dealer.slug}"
)
raise Http404("Dealer slug mismatch") raise Http404("Dealer slug mismatch")
return None return None

View File

@ -1,4 +1,4 @@
# Generated by Django 5.2.4 on 2025-07-15 13:26 # Generated by Django 5.2.4 on 2025-07-15 11:38
import datetime import datetime
import django.core.serializers.json import django.core.serializers.json

View File

@ -84,8 +84,10 @@ class AuthorizedEntityMixin:
user_model=dealer.entity.admin, user_model=dealer.entity.admin,
authorized_superuser=self.get_superuser_authorization(), authorized_superuser=self.get_superuser_authorization(),
) )
def get_queryset(self): def get_queryset(self):
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"]) dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
self.queryset = EntityModel.objects.for_user( self.queryset = EntityModel.objects.for_user(
user_model=dealer.entity.admin).select_related('default_coa') user_model=dealer.entity.admin
).select_related("default_coa")
return super().get_queryset() return super().get_queryset()

View File

@ -18,7 +18,7 @@ from django_ledger.models import (
ItemModel, ItemModel,
CustomerModel, CustomerModel,
JournalEntryModel, JournalEntryModel,
LedgerModel LedgerModel,
) )
from django_ledger.io.io_core import get_localdate from django_ledger.io.io_core import get_localdate
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -35,7 +35,7 @@ from django_ledger.models import (
EntityManagementModel, EntityManagementModel,
PurchaseOrderModel, PurchaseOrderModel,
ItemTransactionModel, ItemTransactionModel,
BillModel BillModel,
) )
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -248,9 +248,9 @@ class CarMake(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Make") verbose_name = _("Make")
indexes = [ indexes = [
models.Index(fields=['name'], name='car_make_name_idx'), models.Index(fields=["name"], name="car_make_name_idx"),
models.Index(fields=['is_sa_import'], name='car_make_sa_import_idx'), models.Index(fields=["is_sa_import"], name="car_make_sa_import_idx"),
models.Index(fields=['car_type'], name='car_make_type_idx'), models.Index(fields=["car_type"], name="car_make_type_idx"),
] ]
@ -282,9 +282,11 @@ class CarModel(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Model") verbose_name = _("Model")
indexes = [ indexes = [
models.Index(fields=['id_car_make'], name='car_model_make_idx'), models.Index(fields=["id_car_make"], name="car_model_make_idx"),
models.Index(fields=['name'], name='car_model_name_idx'), models.Index(fields=["name"], name="car_model_name_idx"),
models.Index(fields=['id_car_make', 'name'], name='car_model_make_name_idx'), models.Index(
fields=["id_car_make", "name"], name="car_model_make_name_idx"
),
] ]
@ -321,10 +323,10 @@ class CarSerie(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Series") verbose_name = _("Series")
indexes = [ indexes = [
models.Index(fields=['id_car_model'], name='car_serie_model_idx'), models.Index(fields=["id_car_model"], name="car_serie_model_idx"),
models.Index(fields=['year_begin', 'year_end'], name='car_serie_years_idx'), models.Index(fields=["year_begin", "year_end"], name="car_serie_years_idx"),
models.Index(fields=['name'], name='car_serie_name_idx'), models.Index(fields=["name"], name="car_serie_name_idx"),
models.Index(fields=['generation_name'], name='car_serie_generation_idx'), models.Index(fields=["generation_name"], name="car_serie_generation_idx"),
] ]
@ -360,9 +362,12 @@ class CarTrim(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Trim") verbose_name = _("Trim")
indexes = [ indexes = [
models.Index(fields=['id_car_serie'], name='car_trim_serie_idx'), models.Index(fields=["id_car_serie"], name="car_trim_serie_idx"),
models.Index(fields=['start_production_year', 'end_production_year'], name='car_trim_prod_years_idx'), models.Index(
models.Index(fields=['name'], name='car_trim_name_idx'), fields=["start_production_year", "end_production_year"],
name="car_trim_prod_years_idx",
),
models.Index(fields=["name"], name="car_trim_name_idx"),
] ]
@ -385,9 +390,9 @@ class CarEquipment(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Equipment") verbose_name = _("Equipment")
indexes = [ indexes = [
models.Index(fields=['id_car_trim'], name='car_equipment_trim_idx'), models.Index(fields=["id_car_trim"], name="car_equipment_trim_idx"),
models.Index(fields=['year_begin'], name='car_equipment_year_idx'), models.Index(fields=["year_begin"], name="car_equipment_year_idx"),
models.Index(fields=['name'], name='car_equipment_name_idx'), models.Index(fields=["name"], name="car_equipment_name_idx"),
] ]
@ -421,8 +426,8 @@ class CarSpecification(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Specification") verbose_name = _("Specification")
indexes = [ indexes = [
models.Index(fields=['id_parent'], name='car_spec_parent_idx'), models.Index(fields=["id_parent"], name="car_spec_parent_idx"),
models.Index(fields=['name'], name='car_spec_name_idx'), models.Index(fields=["name"], name="car_spec_name_idx"),
] ]
@ -441,9 +446,12 @@ class CarSpecificationValue(models.Model):
class Meta: class Meta:
verbose_name = _("Specification Value") verbose_name = _("Specification Value")
indexes = [ indexes = [
models.Index(fields=['id_car_trim'], name='car_spec_val_trim_idx'), models.Index(fields=["id_car_trim"], name="car_spec_val_trim_idx"),
models.Index(fields=['id_car_specification'], name='car_spec_val_spec_idx'), models.Index(fields=["id_car_specification"], name="car_spec_val_spec_idx"),
models.Index(fields=['id_car_trim', 'id_car_specification'], name='car_spec_val_trim_spec_idx'), models.Index(
fields=["id_car_trim", "id_car_specification"],
name="car_spec_val_trim_spec_idx",
),
] ]
@ -477,8 +485,8 @@ class CarOption(models.Model, LocalizedNameMixin):
class Meta: class Meta:
verbose_name = _("Option") verbose_name = _("Option")
indexes = [ indexes = [
models.Index(fields=['id_parent'], name='car_option_parent_idx'), models.Index(fields=["id_parent"], name="car_option_parent_idx"),
models.Index(fields=['name'], name='car_option_name_idx'), models.Index(fields=["name"], name="car_option_name_idx"),
] ]
@ -500,10 +508,13 @@ class CarOptionValue(models.Model):
class Meta: class Meta:
verbose_name = _("Option Value") verbose_name = _("Option Value")
indexes = [ indexes = [
models.Index(fields=['id_car_option'], name='car_opt_val_option_idx'), models.Index(fields=["id_car_option"], name="car_opt_val_option_idx"),
models.Index(fields=['id_car_equipment'], name='car_opt_val_equipment_idx'), models.Index(fields=["id_car_equipment"], name="car_opt_val_equipment_idx"),
models.Index(fields=['is_base'], name='car_opt_val_is_base_idx'), models.Index(fields=["is_base"], name="car_opt_val_is_base_idx"),
models.Index(fields=['id_car_option', 'id_car_equipment'], name='cov_option_equipment_idx'), models.Index(
fields=["id_car_option", "id_car_equipment"],
name="cov_option_equipment_idx",
),
] ]
@ -656,7 +667,10 @@ class Car(Base):
# history = HistoricalRecords() # history = HistoricalRecords()
def get_absolute_url(self): def get_absolute_url(self):
return reverse("car_detail", kwargs={"dealer_slug": self.dealer.slug,"slug": self.slug}) return reverse(
"car_detail", kwargs={"dealer_slug": self.dealer.slug, "slug": self.slug}
)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.slug = slugify(self.vin) self.slug = slugify(self.vin)
self.hash = self.get_hash self.hash = self.get_hash
@ -666,24 +680,27 @@ class Car(Base):
verbose_name = _("Car") verbose_name = _("Car")
verbose_name_plural = _("Cars") verbose_name_plural = _("Cars")
indexes = [ indexes = [
models.Index(fields=['vin'], name='car_vin_idx'), models.Index(fields=["vin"], name="car_vin_idx"),
models.Index(fields=['year'], name='car_year_idx'), models.Index(fields=["year"], name="car_year_idx"),
models.Index(fields=['status'], name='car_status_idx'), models.Index(fields=["status"], name="car_status_idx"),
models.Index(fields=["dealer"], name="car_dealer_idx"),
models.Index(fields=['dealer'], name='car_dealer_idx'), models.Index(fields=["vendor"], name="car_vendor_idx"),
models.Index(fields=['vendor'], name='car_vendor_idx'), models.Index(fields=["id_car_make"], name="car_make_idx"),
models.Index(fields=['id_car_make'], name='car_make_idx'), models.Index(fields=["id_car_model"], name="car_model_idx"),
models.Index(fields=['id_car_model'], name='car_model_idx'), models.Index(fields=["id_car_serie"], name="car_serie_idx"),
models.Index(fields=['id_car_serie'], name='car_serie_idx'), models.Index(fields=["id_car_trim"], name="car_trim_idx"),
models.Index(fields=['id_car_trim'], name='car_trim_idx'), models.Index(
fields=["id_car_make", "id_car_model"], name="car_make_model_idx"
models.Index(fields=['id_car_make', 'id_car_model'], name='car_make_model_idx'), ),
models.Index(fields=['id_car_make', 'year'], name='car_make_year_idx'), models.Index(fields=["id_car_make", "year"], name="car_make_year_idx"),
models.Index(fields=['dealer', 'status'], name='car_dealer_status_idx'), models.Index(fields=["dealer", "status"], name="car_dealer_status_idx"),
models.Index(fields=['vendor', 'status'], name='car_vendor_status_idx'), models.Index(fields=["vendor", "status"], name="car_vendor_status_idx"),
models.Index(fields=['year', 'status'], name='car_year_status_idx'), models.Index(fields=["year", "status"], name="car_year_status_idx"),
models.Index(fields=['status'], name='car_active_status_idx', models.Index(
condition=Q(status=CarStatusChoices.AVAILABLE)), fields=["status"],
name="car_active_status_idx",
condition=Q(status=CarStatusChoices.AVAILABLE),
),
] ]
def __str__(self): def __str__(self):
@ -800,10 +817,12 @@ class Car(Base):
car=self, exterior=exterior, interior=interior car=self, exterior=exterior, interior=interior
) )
self.save() self.save()
@property @property
def logo(self): def logo(self):
return self.id_car_make.logo.url if self.id_car_make.logo else None return self.id_car_make.logo.url if self.id_car_make.logo else None
class CarTransfer(models.Model): class CarTransfer(models.Model):
car = models.ForeignKey( car = models.ForeignKey(
"Car", "Car",
@ -893,10 +912,16 @@ class CarFinance(models.Model):
max_digits=14, decimal_places=2, verbose_name=_("Cost Price") max_digits=14, decimal_places=2, verbose_name=_("Cost Price")
) )
selling_price = models.DecimalField( selling_price = models.DecimalField(
max_digits=14, decimal_places=2, verbose_name=_("Selling Price"),default=Decimal("0.00") max_digits=14,
decimal_places=2,
verbose_name=_("Selling Price"),
default=Decimal("0.00"),
) )
marked_price = models.DecimalField( marked_price = models.DecimalField(
max_digits=14, decimal_places=2, verbose_name=_("Marked Price"),default=Decimal("0.00") max_digits=14,
decimal_places=2,
verbose_name=_("Marked Price"),
default=Decimal("0.00"),
) )
discount_amount = models.DecimalField( discount_amount = models.DecimalField(
max_digits=14, max_digits=14,
@ -969,11 +994,13 @@ class CarFinance(models.Model):
verbose_name = _("Car Financial Details") verbose_name = _("Car Financial Details")
verbose_name_plural = _("Car Financial Details") verbose_name_plural = _("Car Financial Details")
indexes = [ indexes = [
models.Index(fields=['car'], name='car_finance_car_idx'), models.Index(fields=["car"], name="car_finance_car_idx"),
models.Index(fields=['cost_price'], name='car_finance_cost_price_idx'), models.Index(fields=["cost_price"], name="car_finance_cost_price_idx"),
models.Index(fields=['selling_price'], name='car_finance_selling_price_idx'), models.Index(
models.Index(fields=['marked_price'], name='car_finance_marked_price_idx'), fields=["selling_price"], name="car_finance_selling_price_idx"
models.Index(fields=['discount_amount'], name='car_finance_discount_idx'), ),
models.Index(fields=["marked_price"], name="car_finance_marked_price_idx"),
models.Index(fields=["discount_amount"], name="car_finance_discount_idx"),
] ]
@ -986,8 +1013,8 @@ class ExteriorColors(models.Model, LocalizedNameMixin):
verbose_name = _("Exterior Colors") verbose_name = _("Exterior Colors")
verbose_name_plural = _("Exterior Colors") verbose_name_plural = _("Exterior Colors")
indexes = [ indexes = [
models.Index(fields=['name'], name='exterior_color_name_idx'), models.Index(fields=["name"], name="exterior_color_name_idx"),
models.Index(fields=['arabic_name'], name='exterior_color_arabic_name_idx'), models.Index(fields=["arabic_name"], name="exterior_color_arabic_name_idx"),
] ]
def __str__(self): def __str__(self):
@ -1003,8 +1030,8 @@ class InteriorColors(models.Model, LocalizedNameMixin):
verbose_name = _("Interior Colors") verbose_name = _("Interior Colors")
verbose_name_plural = _("Interior Colors") verbose_name_plural = _("Interior Colors")
indexes = [ indexes = [
models.Index(fields=['name'], name='interior_color_name_idx'), models.Index(fields=["name"], name="interior_color_name_idx"),
models.Index(fields=['arabic_name'], name='interior_color_arabic_name_idx'), models.Index(fields=["arabic_name"], name="interior_color_arabic_name_idx"),
] ]
def __str__(self): def __str__(self):
@ -1025,9 +1052,11 @@ class CarColors(models.Model):
verbose_name_plural = _("Colors") verbose_name_plural = _("Colors")
unique_together = ("car", "exterior", "interior") unique_together = ("car", "exterior", "interior")
indexes = [ indexes = [
models.Index(fields=['exterior'], name='car_colors_exterior_idx'), models.Index(fields=["exterior"], name="car_colors_exterior_idx"),
models.Index(fields=['interior'], name='car_colors_interior_idx'), models.Index(fields=["interior"], name="car_colors_interior_idx"),
models.Index(fields=['exterior', 'interior'], name='car_colors_ext_int_combo_idx'), models.Index(
fields=["exterior", "interior"], name="car_colors_ext_int_combo_idx"
),
] ]
def __str__(self): def __str__(self):
@ -1145,7 +1174,11 @@ class Dealer(models.Model, LocalizedNameMixin):
max_length=200, blank=True, null=True, verbose_name=_("Address") max_length=200, blank=True, null=True, verbose_name=_("Address")
) )
logo = models.ImageField( logo = models.ImageField(
upload_to="logos/users", blank=True, null=True, verbose_name=_("Logo"),default="logo.png" upload_to="logos/users",
blank=True,
null=True,
verbose_name=_("Logo"),
default="logo.png",
) )
entity = models.ForeignKey( entity = models.ForeignKey(
EntityModel, on_delete=models.SET_NULL, null=True, blank=True EntityModel, on_delete=models.SET_NULL, null=True, blank=True
@ -1205,6 +1238,7 @@ class Dealer(models.Model, LocalizedNameMixin):
@property @property
def vat_rate(self): def vat_rate(self):
return VatRate.objects.get(dealer=self, is_active=True).rate return VatRate.objects.get(dealer=self, is_active=True).rate
class Meta: class Meta:
verbose_name = _("Dealer") verbose_name = _("Dealer")
verbose_name_plural = _("Dealers") verbose_name_plural = _("Dealers")
@ -1245,10 +1279,10 @@ class Staff(models.Model, LocalizedNameMixin):
upload_to="logos/staff", blank=True, null=True, verbose_name=_("Image") upload_to="logos/staff", blank=True, null=True, verbose_name=_("Image")
) )
thumbnail = ImageSpecField( thumbnail = ImageSpecField(
source='logo', source="logo",
processors=[ResizeToFill(40, 40)], processors=[ResizeToFill(40, 40)],
format='WEBP', format="WEBP",
options={'quality': 80} options={"quality": 80},
) )
active = models.BooleanField(default=True, verbose_name=_("Active")) active = models.BooleanField(default=True, verbose_name=_("Active"))
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created")) created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
@ -1301,7 +1335,9 @@ class Staff(models.Model, LocalizedNameMixin):
@property @property
def groups(self): def groups(self):
return CustomGroup.objects.select_related("group").filter(pk__in=[x.customgroup.pk for x in self.user.groups.all()]) return CustomGroup.objects.select_related("group").filter(
pk__in=[x.customgroup.pk for x in self.user.groups.all()]
)
def clear_groups(self): def clear_groups(self):
self.remove_superuser_permission() self.remove_superuser_permission()
@ -1321,12 +1357,12 @@ class Staff(models.Model, LocalizedNameMixin):
entity = self.dealer.entity entity = self.dealer.entity
if entity.managers.count() == 0: if entity.managers.count() == 0:
entity.managers.add(self.user) entity.managers.add(self.user)
def remove_superuser_permission(self): def remove_superuser_permission(self):
entity = self.dealer.entity entity = self.dealer.entity
if self.user in entity.managers.all(): if self.user in entity.managers.all():
entity.managers.remove(self.user) entity.managers.remove(self.user)
class Meta: class Meta:
verbose_name = _("Staff") verbose_name = _("Staff")
verbose_name_plural = _("Staff") verbose_name_plural = _("Staff")
@ -1979,7 +2015,7 @@ class Schedule(models.Model):
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE) dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id') content_object = GenericForeignKey("content_type", "object_id")
customer = models.ForeignKey( customer = models.ForeignKey(
CustomerModel, CustomerModel,
on_delete=models.CASCADE, on_delete=models.CASCADE,
@ -2156,7 +2192,6 @@ class Opportunity(models.Model):
# scheduled_by=self.request.user # scheduled_by=self.request.user
# ) # )
return ( return (
self.lead.get_all_schedules() self.lead.get_all_schedules()
.filter(scheduled_at__gt=timezone.now()) .filter(scheduled_at__gt=timezone.now())
.order_by("scheduled_at") .order_by("scheduled_at")
@ -2226,17 +2261,19 @@ class Notes(models.Model):
verbose_name = _("Note") verbose_name = _("Note")
verbose_name_plural = _("Notes") verbose_name_plural = _("Notes")
indexes = [ indexes = [
models.Index(fields=['dealer'], name='note_dealer_idx'), models.Index(fields=["dealer"], name="note_dealer_idx"),
models.Index(fields=['created_by'], name='note_created_by_idx'), models.Index(fields=["created_by"], name="note_created_by_idx"),
models.Index(fields=['content_type'], name='note_content_type_idx'), models.Index(fields=["content_type"], name="note_content_type_idx"),
models.Index(fields=['content_type', 'object_id'], name='note_content_object_idx'), models.Index(
fields=["content_type", "object_id"], name="note_content_object_idx"
models.Index(fields=['created'], name='note_created_date_idx'), ),
models.Index(fields=['updated'], name='note_updated_date_idx'), models.Index(fields=["created"], name="note_created_date_idx"),
models.Index(fields=["updated"], name="note_updated_date_idx"),
models.Index(fields=['dealer', 'created'], name='note_dealer_created_idx'), models.Index(fields=["dealer", "created"], name="note_dealer_created_idx"),
models.Index(fields=['content_type', 'object_id', 'created'], models.Index(
name='note_content_obj_created_idx'), fields=["content_type", "object_id", "created"],
name="note_content_obj_created_idx",
),
] ]
def __str__(self): def __str__(self):
@ -2269,17 +2306,19 @@ class Tasks(models.Model):
verbose_name = _("Task") verbose_name = _("Task")
verbose_name_plural = _("Tasks") verbose_name_plural = _("Tasks")
indexes = [ indexes = [
models.Index(fields=['dealer'], name='task_dealer_idx'), models.Index(fields=["dealer"], name="task_dealer_idx"),
models.Index(fields=['created_by'], name='task_created_by_idx'), models.Index(fields=["created_by"], name="task_created_by_idx"),
models.Index(fields=['content_type'], name='task_content_type_idx'), models.Index(fields=["content_type"], name="task_content_type_idx"),
models.Index(fields=['content_type', 'object_id'], name='task_content_object_idx'), models.Index(
fields=["content_type", "object_id"], name="task_content_object_idx"
models.Index(fields=['created'], name='task_created_date_idx'), ),
models.Index(fields=['updated'], name='task_updated_date_idx'), models.Index(fields=["created"], name="task_created_date_idx"),
models.Index(fields=["updated"], name="task_updated_date_idx"),
models.Index(fields=['dealer', 'created'], name='task_dealer_created_idx'), models.Index(fields=["dealer", "created"], name="task_dealer_created_idx"),
models.Index(fields=['content_type', 'object_id', 'created'], models.Index(
name='task_content_obj_created_idx'), fields=["content_type", "object_id", "created"],
name="task_content_obj_created_idx",
),
] ]
def __str__(self): def __str__(self):
@ -2310,15 +2349,17 @@ class Email(models.Model):
verbose_name = _("Email") verbose_name = _("Email")
verbose_name_plural = _("Emails") verbose_name_plural = _("Emails")
indexes = [ indexes = [
models.Index(fields=['created_by'], name='email_created_by_idx'), models.Index(fields=["created_by"], name="email_created_by_idx"),
models.Index(fields=['content_type'], name='email_content_type_idx'), models.Index(fields=["content_type"], name="email_content_type_idx"),
models.Index(fields=['content_type', 'object_id'], name='email_content_object_idx'), models.Index(
fields=["content_type", "object_id"], name="email_content_object_idx"
models.Index(fields=['created'], name='email_created_date_idx'), ),
models.Index(fields=['updated'], name='email_updated_date_idx'), models.Index(fields=["created"], name="email_created_date_idx"),
models.Index(fields=["updated"], name="email_updated_date_idx"),
models.Index(fields=['content_type', 'object_id', 'created'], models.Index(
name='email_content_obj_created_idx'), fields=["content_type", "object_id", "created"],
name="email_content_obj_created_idx",
),
] ]
def __str__(self): def __str__(self):
@ -2346,15 +2387,17 @@ class Activity(models.Model):
verbose_name = _("Activity") verbose_name = _("Activity")
verbose_name_plural = _("Activities") verbose_name_plural = _("Activities")
indexes = [ indexes = [
models.Index(fields=['created_by'], name='activity_created_by_idx'), models.Index(fields=["created_by"], name="activity_created_by_idx"),
models.Index(fields=['content_type'], name='activity_content_type_idx'), models.Index(fields=["content_type"], name="activity_content_type_idx"),
models.Index(fields=['content_type', 'object_id'], name='activity_content_object_idx'), models.Index(
fields=["content_type", "object_id"], name="activity_content_object_idx"
models.Index(fields=['created'], name='activity_created_date_idx'), ),
models.Index(fields=['updated'], name='activity_updated_date_idx'), models.Index(fields=["created"], name="activity_created_date_idx"),
models.Index(fields=["updated"], name="activity_updated_date_idx"),
models.Index(fields=['content_type', 'object_id', 'created'], models.Index(
name='a_content_obj_created_idx'), fields=["content_type", "object_id", "created"],
name="a_content_obj_created_idx",
),
] ]
def __str__(self): def __str__(self):
@ -2375,9 +2418,9 @@ class Notification(models.Model):
ordering = ["-created"] ordering = ["-created"]
indexes = [ indexes = [
models.Index(fields=['user'], name='notification_user_idx'), models.Index(fields=["user"], name="notification_user_idx"),
models.Index(fields=['is_read'], name='notification_is_read_idx'), models.Index(fields=["is_read"], name="notification_is_read_idx"),
models.Index(fields=['created'], name='notification_created_date_idx'), models.Index(fields=["created"], name="notification_created_date_idx"),
] ]
def __str__(self): def __str__(self):
@ -2423,7 +2466,9 @@ class Vendor(models.Model, LocalizedNameMixin):
) )
def get_absolute_url(self): def get_absolute_url(self):
return reverse("vendor_detail", kwargs={"dealer_slug":self.dealer.slug,"slug": self.slug}) return reverse(
"vendor_detail", kwargs={"dealer_slug": self.dealer.slug, "slug": self.slug}
)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.slug: if not self.slug:
@ -2444,10 +2489,10 @@ class Vendor(models.Model, LocalizedNameMixin):
verbose_name = _("Vendor") verbose_name = _("Vendor")
verbose_name_plural = _("Vendors") verbose_name_plural = _("Vendors")
indexes = [ indexes = [
models.Index(fields=['slug'], name='vendor_slug_idx'), models.Index(fields=["slug"], name="vendor_slug_idx"),
models.Index(fields=['active'], name='vendor_active_idx'), models.Index(fields=["active"], name="vendor_active_idx"),
models.Index(fields=['crn'], name='vendor_crn_idx'), models.Index(fields=["crn"], name="vendor_crn_idx"),
models.Index(fields=['vrn'], name='vendor_vrn_idx'), models.Index(fields=["vrn"], name="vendor_vrn_idx"),
] ]
def __str__(self): def __str__(self):
@ -2762,6 +2807,7 @@ class CustomGroup(models.Model):
group = models.OneToOneField( group = models.OneToOneField(
"auth.Group", verbose_name=_("Group"), on_delete=models.CASCADE "auth.Group", verbose_name=_("Group"), on_delete=models.CASCADE
) )
class Meta: class Meta:
verbose_name = _("Custom Group") verbose_name = _("Custom Group")
verbose_name_plural = _("Custom Groups") verbose_name_plural = _("Custom Groups")
@ -2855,10 +2901,17 @@ class CustomGroup(models.Model):
"journalentrymodel", "journalentrymodel",
"purchaseordermodel", "purchaseordermodel",
"ledgermodel", "ledgermodel",
"transactionmodel" "transactionmodel",
],
other_perms=[
"can_approve_estimatemodel",
"can_approve_billmodel",
"can_view_inventory",
"can_view_sales",
"can_view_crm",
"can_view_financials",
"can_view_reports",
], ],
other_perms=["can_approve_estimatemodel","can_approve_billmodel","can_view_inventory","can_view_sales","can_view_crm","can_view_financials","can_view_reports"],
) )
###################################### ######################################
###################################### ######################################
@ -2880,7 +2933,7 @@ class CustomGroup(models.Model):
"notes", "notes",
"tasks", "tasks",
"activity", "activity",
"poitemsuploaded" "poitemsuploaded",
], ],
) )
self.set_permissions( self.set_permissions(
@ -2888,8 +2941,7 @@ class CustomGroup(models.Model):
allowed_models=[], allowed_models=[],
other_perms=[ other_perms=[
"view_purchaseordermodel", "view_purchaseordermodel",
],
]
) )
###################################### ######################################
###################################### ######################################
@ -2915,8 +2967,7 @@ class CustomGroup(models.Model):
"organization", "organization",
"notes", "notes",
"tasks", "tasks",
"lead" "leadactivity",
"activity",
], ],
other_perms=[ other_perms=[
"view_car", "view_car",
@ -2959,7 +3010,6 @@ class CustomGroup(models.Model):
"view_leads", "view_leads",
"view_opportunity", "view_opportunity",
"view_customers", "view_customers",
], ],
) )
self.set_permissions( self.set_permissions(
@ -2971,18 +3021,28 @@ class CustomGroup(models.Model):
"itemmodel", "itemmodel",
"invoicemodel", "invoicemodel",
"vendormodel", "vendormodel",
"journalentrymodel", "journalentrymodel",
"purchaseordermodel", "purchaseordermodel",
"estimatemodel", "estimatemodel",
"customermodel", "customermodel",
"ledgermodel", "ledgermodel",
"transactionmodel" "transactionmodel",
],
other_perms=[
"view_billmodel",
"add_billmodel",
"change_billmodel",
"delete_billmodel",
"view_customermodel",
"view_estimatemodel",
"can_view_inventory",
"can_view_sales",
"can_view_crm",
"can_view_financials",
"can_view_reports",
], ],
other_perms=["view_billmodel","add_billmodel","change_billmodel","delete_billmodel","view_customermodel", "view_estimatemodel","can_view_inventory","can_view_sales","can_view_crm","can_view_financials","can_view_reports"],
) )
def set_permissions(self, app="inventory", allowed_models=[], other_perms=[]): def set_permissions(self, app="inventory", allowed_models=[], other_perms=[]):
try: try:
for perm in Permission.objects.filter( for perm in Permission.objects.filter(
@ -3162,7 +3222,11 @@ class PaymentHistory(models.Model):
class PoItemsUploaded(models.Model): class PoItemsUploaded(models.Model):
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, null=True, blank=True) dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, null=True, blank=True)
po = models.ForeignKey( po = models.ForeignKey(
PurchaseOrderModel, on_delete=models.CASCADE, null=True, blank=True, related_name="items" PurchaseOrderModel,
on_delete=models.CASCADE,
null=True,
blank=True,
related_name="items",
) )
item = models.ForeignKey( item = models.ForeignKey(
ItemTransactionModel, ItemTransactionModel,
@ -3182,8 +3246,11 @@ class PoItemsUploaded(models.Model):
models.Index(fields=["po"]), models.Index(fields=["po"]),
models.Index(fields=["item"]), models.Index(fields=["item"]),
] ]
def get_name(self): def get_name(self):
return self.item.item.name.split('||') return self.item.item.name.split("||")
class ExtraInfo(models.Model): class ExtraInfo(models.Model):
""" """
Stores additional information for any model with: Stores additional information for any model with:
@ -3191,20 +3258,19 @@ class ExtraInfo(models.Model):
- JSON data storage - JSON data storage
- Tracking fields - Tracking fields
""" """
dealer = models.ForeignKey( dealer = models.ForeignKey(
Dealer, Dealer,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
null=True, null=True,
blank=True, blank=True,
related_name="extra_info" related_name="extra_info",
) )
content_type = models.ForeignKey( content_type = models.ForeignKey(
ContentType, ContentType, on_delete=models.CASCADE, related_name="extra_info_primary"
on_delete=models.CASCADE,
related_name="extra_info_primary"
) )
object_id = models.CharField(max_length=255, null=True, blank=True) object_id = models.CharField(max_length=255, null=True, blank=True)
content_object = GenericForeignKey('content_type', 'object_id') content_object = GenericForeignKey("content_type", "object_id")
# Secondary GenericForeignKey (optional additional link) # Secondary GenericForeignKey (optional additional link)
related_content_type = models.ForeignKey( related_content_type = models.ForeignKey(
@ -3212,41 +3278,32 @@ class ExtraInfo(models.Model):
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
null=True, null=True,
blank=True, blank=True,
related_name="extra_info_secondary" related_name="extra_info_secondary",
) )
related_object_id = models.CharField(max_length=255, null=True, blank=True) related_object_id = models.CharField(max_length=255, null=True, blank=True)
related_object = GenericForeignKey('related_content_type', 'related_object_id') related_object = GenericForeignKey("related_content_type", "related_object_id")
# JSON Data Storage # JSON Data Storage
data = models.JSONField( data = models.JSONField(encoder=DjangoJSONEncoder, default=dict, blank=True)
encoder=DjangoJSONEncoder,
default=dict,
blank=True
)
# Metadata # Metadata
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
created_by = models.ForeignKey( created_by = models.ForeignKey(
User, User, on_delete=models.SET_NULL, null=True, related_name="created_extra_info"
on_delete=models.SET_NULL,
null=True,
related_name="created_extra_info"
) )
class Meta: class Meta:
indexes = [ indexes = [
models.Index(fields=['content_type', 'object_id']), models.Index(fields=["content_type", "object_id"]),
models.Index(fields=['related_content_type', 'related_object_id']), models.Index(fields=["related_content_type", "related_object_id"]),
] ]
verbose_name_plural = _("Extra Info") verbose_name_plural = _("Extra Info")
verbose_name = _("Extra Info") verbose_name = _("Extra Info")
def __str__(self): def __str__(self):
return f"ExtraInfo for {self.content_object} ({self.content_type})" return f"ExtraInfo for {self.content_object} ({self.content_type})"
@classmethod @classmethod
def get_sale_orders(cls, staff=None, is_dealer=False): def get_sale_orders(cls, staff=None, is_dealer=False):
if not staff and not is_dealer: if not staff and not is_dealer:
@ -3259,16 +3316,23 @@ class ExtraInfo(models.Model):
qs = cls.objects.filter( qs = cls.objects.filter(
content_type=content_type, content_type=content_type,
related_content_type=related_content_type, related_content_type=related_content_type,
related_object_id__isnull=False related_object_id__isnull=False,
) )
else: else:
qs = cls.objects.filter( qs = cls.objects.filter(
content_type=content_type, content_type=content_type,
related_content_type=related_content_type, related_content_type=related_content_type,
related_object_id=staff.pk related_object_id=staff.pk,
) )
# qs = qs.select_related("customer","estimate","invoice") # qs = qs.select_related("customer","estimate","invoice")
return [x.content_object.sale_orders.select_related("customer","estimate","invoice").first() for x in qs if x.content_object.sale_orders.first()] return [
x.content_object.sale_orders.select_related(
"customer", "estimate", "invoice"
).first()
for x in qs
if x.content_object.sale_orders.first()
]
@classmethod @classmethod
def get_invoices(cls, staff=None, is_dealer=False): def get_invoices(cls, staff=None, is_dealer=False):
if not staff and not is_dealer: if not staff and not is_dealer:
@ -3281,13 +3345,17 @@ class ExtraInfo(models.Model):
qs = cls.objects.filter( qs = cls.objects.filter(
content_type=content_type, content_type=content_type,
related_content_type=related_content_type, related_content_type=related_content_type,
related_object_id__isnull=False related_object_id__isnull=False,
) )
else: else:
qs = cls.objects.filter( qs = cls.objects.filter(
content_type=content_type, content_type=content_type,
related_content_type=related_content_type, related_content_type=related_content_type,
related_object_id=staff.pk related_object_id=staff.pk,
) )
print(qs[0].content_object.invoicemodel_set.first()) print(qs[0].content_object.invoicemodel_set.first())
return [x.content_object.invoicemodel_set.first() for x in qs if x.content_object.invoicemodel_set.first()] return [
x.content_object.invoicemodel_set.first()
for x in qs
if x.content_object.invoicemodel_set.first()
]

View File

@ -11,7 +11,7 @@ from django_ledger.forms.bill import (
InReviewBillModelUpdateForm, InReviewBillModelUpdateForm,
ApprovedBillModelUpdateForm, ApprovedBillModelUpdateForm,
AccruedAndApprovedBillModelUpdateForm, AccruedAndApprovedBillModelUpdateForm,
PaidBillModelUpdateForm PaidBillModelUpdateForm,
) )
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
from django.utils.html import format_html from django.utils.html import format_html
@ -21,11 +21,13 @@ from django.shortcuts import get_object_or_404
from django.urls import reverse from django.urls import reverse
from django_ledger.models import ItemTransactionModel from django_ledger.models import ItemTransactionModel
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django_ledger.forms.purchase_order import (ApprovedPurchaseOrderModelUpdateForm, from django_ledger.forms.purchase_order import (
ApprovedPurchaseOrderModelUpdateForm,
BasePurchaseOrderModelUpdateForm, BasePurchaseOrderModelUpdateForm,
DraftPurchaseOrderModelUpdateForm, DraftPurchaseOrderModelUpdateForm,
ReviewPurchaseOrderModelUpdateForm, ReviewPurchaseOrderModelUpdateForm,
get_po_itemtxs_formset_class) get_po_itemtxs_formset_class,
)
from django_ledger.views.purchase_order import PurchaseOrderModelModelViewQuerySetMixIn from django_ledger.views.purchase_order import PurchaseOrderModelModelViewQuerySetMixIn
from django_ledger.models import PurchaseOrderModel, EstimateModel, BillModel from django_ledger.models import PurchaseOrderModel, EstimateModel, BillModel
from django.views.generic.detail import SingleObjectMixin from django.views.generic.detail import SingleObjectMixin
@ -38,18 +40,17 @@ from django.utils.translation import gettext_lazy as _
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
class PurchaseOrderModelUpdateView(LoginRequiredMixin,
PermissionRequiredMixin, class PurchaseOrderModelUpdateView(
UpdateView): LoginRequiredMixin, PermissionRequiredMixin, UpdateView
slug_url_kwarg = 'po_pk' ):
slug_field = 'uuid' slug_url_kwarg = "po_pk"
context_object_name = 'po_model' slug_field = "uuid"
context_object_name = "po_model"
template_name = "purchase_orders/po_update.html" template_name = "purchase_orders/po_update.html"
context_object_name = "po_model" context_object_name = "po_model"
permission_required = "django_ledger.change_purchaseordermodel" permission_required = "django_ledger.change_purchaseordermodel"
extra_context = { extra_context = {"header_subtitle_icon": "uil:bill"}
'header_subtitle_icon': 'uil:bill'
}
action_update_items = False action_update_items = False
queryset = None queryset = None
@ -79,10 +80,10 @@ class PurchaseOrderModelUpdateView(LoginRequiredMixin,
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"]) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
if self.queryset is None: if self.queryset is None:
self.queryset = PurchaseOrderModel.objects.for_entity( self.queryset = PurchaseOrderModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'], entity_slug=self.kwargs["entity_slug"], user_model=dealer.entity.admin
user_model=dealer.entity.admin ).select_related("entity", "ce_model")
).select_related('entity', 'ce_model')
return super().get_queryset() return super().get_queryset()
def get_success_url(self): def get_success_url(self):
return reverse( return reverse(
"purchase_order_update", "purchase_order_update",
@ -92,6 +93,7 @@ class PurchaseOrderModelUpdateView(LoginRequiredMixin,
"po_pk": self.kwargs["po_pk"], "po_pk": self.kwargs["po_pk"],
}, },
) )
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs): def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
if self.action_update_items: if self.action_update_items:
return HttpResponseRedirect( return HttpResponseRedirect(
@ -199,78 +201,87 @@ class PurchaseOrderModelUpdateView(LoginRequiredMixin,
def get_form_kwargs(self): def get_form_kwargs(self):
if self.action_update_items: if self.action_update_items:
return { return {
'initial': self.get_initial(), "initial": self.get_initial(),
'prefix': self.get_prefix(), "prefix": self.get_prefix(),
'instance': self.object "instance": self.object,
} }
return super(PurchaseOrderModelUpdateView, self).get_form_kwargs() return super(PurchaseOrderModelUpdateView, self).get_form_kwargs()
def get_po_itemtxs_qs(self, po_model: PurchaseOrderModel): def get_po_itemtxs_qs(self, po_model: PurchaseOrderModel):
return po_model.itemtransactionmodel_set.select_related('bill_model', 'po_model').order_by('created') return po_model.itemtransactionmodel_set.select_related(
"bill_model", "po_model"
).order_by("created")
def form_valid(self, form: BasePurchaseOrderModelUpdateForm): def form_valid(self, form: BasePurchaseOrderModelUpdateForm):
po_model: PurchaseOrderModel = form.save(commit=False) po_model: PurchaseOrderModel = form.save(commit=False)
if form.has_changed(): if form.has_changed():
po_items_qs = ItemTransactionModel.objects.for_po( po_items_qs = ItemTransactionModel.objects.for_po(
entity_slug=self.kwargs['entity_slug'], entity_slug=self.kwargs["entity_slug"],
user_model=self.request.admin, user_model=self.request.admin,
po_pk=po_model.uuid, po_pk=po_model.uuid,
).select_related('bill_model') ).select_related("bill_model")
if all(['po_status' in form.changed_data, if all(
po_model.po_status == po_model.PO_STATUS_APPROVED]): [
po_items_qs.update(po_item_status=ItemTransactionModel.STATUS_NOT_ORDERED) "po_status" in form.changed_data,
po_model.po_status == po_model.PO_STATUS_APPROVED,
if 'fulfilled' in form.changed_data: ]
):
po_items_qs.update(
po_item_status=ItemTransactionModel.STATUS_NOT_ORDERED
)
if "fulfilled" in form.changed_data:
if not all([i.bill_model for i in po_items_qs]): if not all([i.bill_model for i in po_items_qs]):
messages.add_message(self.request, messages.add_message(
self.request,
messages.ERROR, messages.ERROR,
f'All PO items must be billed before marking' f"All PO items must be billed before marking"
f' PO: {po_model.po_number} as fulfilled.', f" PO: {po_model.po_number} as fulfilled.",
extra_tags='is-danger') extra_tags="is-danger",
)
return self.get(self.request) return self.get(self.request)
else: else:
if not all([i.bill_model.is_paid() for i in po_items_qs]): if not all([i.bill_model.is_paid() for i in po_items_qs]):
messages.add_message(self.request, messages.add_message(
self.request,
messages.SUCCESS, messages.SUCCESS,
f'All bills must be paid before marking' f"All bills must be paid before marking"
f' PO: {po_model.po_number} as fulfilled.', f" PO: {po_model.po_number} as fulfilled.",
extra_tags='is-success') extra_tags="is-success",
)
return self.get(self.request) return self.get(self.request)
po_items_qs.update(po_item_status=ItemTransactionModel.STATUS_RECEIVED) po_items_qs.update(po_item_status=ItemTransactionModel.STATUS_RECEIVED)
messages.add_message(self.request, messages.add_message(
self.request,
messages.SUCCESS, messages.SUCCESS,
f'{self.object.po_number} successfully updated.', f"{self.object.po_number} successfully updated.",
extra_tags='is-success') extra_tags="is-success",
)
return super().form_valid(form) return super().form_valid(form)
class BasePurchaseOrderActionActionView(
class BasePurchaseOrderActionActionView(LoginRequiredMixin, LoginRequiredMixin, PermissionRequiredMixin, RedirectView, SingleObjectMixin
PermissionRequiredMixin, ):
RedirectView, http_method_names = ["get"]
SingleObjectMixin): pk_url_kwarg = "po_pk"
http_method_names = ['get']
pk_url_kwarg = 'po_pk'
action_name = None action_name = None
commit = True commit = True
permission_required = None permission_required = None
queryset = None queryset = None
def get_queryset(self): def get_queryset(self):
dealer = get_object_or_404(Dealer, slug=self.kwargs['dealer_slug']) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
if self.queryset is None: if self.queryset is None:
self.queryset = PurchaseOrderModel.objects.for_entity( self.queryset = PurchaseOrderModel.objects.for_entity(
entity_slug=self.kwargs['entity_slug'], entity_slug=self.kwargs["entity_slug"], user_model=dealer.entity.admin
user_model=dealer.entity.admin ).select_related("entity", "ce_model")
).select_related('entity', 'ce_model')
return super().get_queryset() return super().get_queryset()
def get_redirect_url(self, dealer_slug, entity_slug, po_pk, *args, **kwargs): def get_redirect_url(self, dealer_slug, entity_slug, po_pk, *args, **kwargs):
@ -286,7 +297,9 @@ class BasePurchaseOrderActionActionView(LoginRequiredMixin,
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs): def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
# kwargs["user_model"] = dealer.entity.admin # kwargs["user_model"] = dealer.entity.admin
# Get user information for logging # Get user information for logging
user_username = request.user.username if request.user.is_authenticated else 'anonymous' user_username = (
request.user.username if request.user.is_authenticated else "anonymous"
)
dealer = get_object_or_404(Dealer, slug=dealer_slug) dealer = get_object_or_404(Dealer, slug=dealer_slug)
kwargs["user_model"] = dealer.entity.admin kwargs["user_model"] = dealer.entity.admin
@ -316,18 +329,22 @@ class BasePurchaseOrderActionActionView(LoginRequiredMixin,
) )
except ValidationError as e: except ValidationError as e:
# --- Single-line log for ValidationError --- # --- Single-line log for ValidationError ---
print(f"User {user_username} encountered a validation error " print(
f"User {user_username} encountered a validation error "
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. " f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
f"Error: {e}") f"Error: {e}"
)
logger.warning( logger.warning(
f"User {user_username} encountered a validation error " f"User {user_username} encountered a validation error "
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. " f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
f"Error: {e}" f"Error: {e}"
) )
except AttributeError as e: except AttributeError as e:
print(f"User {user_username} encountered an AttributeError " print(
f"User {user_username} encountered an AttributeError "
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. " f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
f"Error: {e}") f"Error: {e}"
)
logger.warning( logger.warning(
f"User {user_username} encountered an AttributeError " f"User {user_username} encountered an AttributeError "
f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. " f"while performing action '{self.action_name}' on Purchase Order ID: {po_model.pk}. "
@ -335,48 +352,54 @@ class BasePurchaseOrderActionActionView(LoginRequiredMixin,
) )
return response return response
class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
slug_url_kwarg = 'bill_pk' slug_url_kwarg = "bill_pk"
slug_field = 'uuid' slug_field = "uuid"
context_object_name = 'bill' context_object_name = "bill"
template_name = "bill/bill_detail.html" template_name = "bill/bill_detail.html"
extra_context = { extra_context = {"header_subtitle_icon": "uil:bill", "hide_menu": True}
'header_subtitle_icon': 'uil:bill',
'hide_menu': True
}
def get_context_data(self, *, object_list=None, **kwargs): def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs) context = super().get_context_data(object_list=object_list, **kwargs)
context["dealer"] = self.request.dealer context["dealer"] = self.request.dealer
bill_model: BillModel = self.object bill_model: BillModel = self.object
title = f'Bill {bill_model.bill_number}' title = f"Bill {bill_model.bill_number}"
context['page_title'] = title context["page_title"] = title
context['header_title'] = title context["header_title"] = title
bill_model: BillModel = self.object bill_model: BillModel = self.object
bill_items_qs, item_data = bill_model.get_itemtxs_data() bill_items_qs, item_data = bill_model.get_itemtxs_data()
context['itemtxs_qs'] = bill_items_qs context["itemtxs_qs"] = bill_items_qs
context['total_amount__sum'] = item_data['total_amount__sum'] context["total_amount__sum"] = item_data["total_amount__sum"]
if not bill_model.is_configured(): if not bill_model.is_configured():
link = format_html(f""" link = format_html(f"""
<a href="{reverse("bill-update", kwargs={ <a href="{
'dealer_slug': self.kwargs['dealer_slug'], reverse(
'entity_slug': self.kwargs['entity_slug'], "bill-update",
'bill_pk': bill_model.uuid kwargs={
})}">here</a> "dealer_slug": self.kwargs["dealer_slug"],
"entity_slug": self.kwargs["entity_slug"],
"bill_pk": bill_model.uuid,
},
)
}">here</a>
""") """)
msg = f'Bill {bill_model.bill_number} has not been fully set up. ' + \ msg = (
f'Please update or assign associated accounts {link}.' f"Bill {bill_model.bill_number} has not been fully set up. "
messages.add_message(self.request, + f"Please update or assign associated accounts {link}."
)
messages.add_message(
self.request,
message=msg, message=msg,
level=messages.WARNING, level=messages.WARNING,
extra_tags='is-danger') extra_tags="is-danger",
)
return context return context
def get_queryset(self): def get_queryset(self):
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug']) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
if self.queryset is None: if self.queryset is None:
entity_model = dealer.entity entity_model = dealer.entity
qs = entity_model.get_bills() qs = entity_model.get_bills()
@ -387,52 +410,57 @@ class BillModelDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailVie
######################################################3 ######################################################3
# BILL # BILL
class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView): class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
slug_url_kwarg = 'bill_pk' slug_url_kwarg = "bill_pk"
slug_field = 'uuid' slug_field = "uuid"
context_object_name = 'bill_model' context_object_name = "bill_model"
template_name = "bill/bill_update.html" template_name = "bill/bill_update.html"
extra_context = { extra_context = {"header_subtitle_icon": "uil:bill"}
'header_subtitle_icon': 'uil:bill' http_method_names = ["get", "post"]
}
http_method_names = ['get', 'post']
action_update_items = False action_update_items = False
queryset = None queryset = None
def get_queryset(self): def get_queryset(self):
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug']) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
if self.queryset is None: if self.queryset is None:
entity_model = dealer.entity entity_model = dealer.entity
qs = entity_model.get_bills() qs = entity_model.get_bills()
self.queryset = qs self.queryset = qs
return super().get_queryset().select_related( return (
'ledger', super()
'ledger__entity', .get_queryset()
'vendor', .select_related(
'cash_account', "ledger",
'prepaid_account', "ledger__entity",
'unearned_account', "vendor",
'cash_account__coa_model', "cash_account",
'prepaid_account__coa_model', "prepaid_account",
'unearned_account__coa_model' "unearned_account",
"cash_account__coa_model",
"prepaid_account__coa_model",
"unearned_account__coa_model",
)
) )
def get_form(self, form_class=None): def get_form(self, form_class=None):
form_class = self.get_form_class() form_class = self.get_form_class()
entity_model = self.request.dealer.entity entity_model = self.request.dealer.entity
if self.request.method == 'POST' and self.action_update_items: if self.request.method == "POST" and self.action_update_items:
return form_class( return form_class(
entity_model=entity_model, entity_model=entity_model,
user_model=self.request.admin, user_model=self.request.admin,
instance=self.object instance=self.object,
) )
form = form_class( form = form_class(
entity_model=entity_model, entity_model=entity_model,
user_model=self.request.admin, user_model=self.request.admin,
**self.get_form_kwargs() **self.get_form_kwargs(),
) )
try: try:
form.initial['amount_paid'] = self.object.get_itemtxs_data()[1]["total_amount__sum"] form.initial["amount_paid"] = self.object.get_itemtxs_data()[1][
"total_amount__sum"
]
except Exception as e: except Exception as e:
print(e) print(e)
return form return form
@ -453,54 +481,57 @@ class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateVie
return PaidBillModelUpdateForm return PaidBillModelUpdateForm
return BaseBillModelUpdateForm return BaseBillModelUpdateForm
def get_context_data(self, def get_context_data(self, *, object_list=None, itemtxs_formset=None, **kwargs):
*,
object_list=None,
itemtxs_formset=None,
**kwargs):
context = super().get_context_data(object_list=object_list, **kwargs) context = super().get_context_data(object_list=object_list, **kwargs)
dealer = get_object_or_404(Dealer,slug=self.kwargs['dealer_slug']) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
entity_model = dealer.entity entity_model = dealer.entity
bill_model: BillModel = self.object bill_model: BillModel = self.object
ledger_model = bill_model.ledger ledger_model = bill_model.ledger
title = f'Bill {bill_model.bill_number}' title = f"Bill {bill_model.bill_number}"
context['page_title'] = title context["page_title"] = title
context['header_title'] = title context["header_title"] = title
context['header_subtitle'] = bill_model.get_bill_status_display() context["header_subtitle"] = bill_model.get_bill_status_display()
if not bill_model.is_configured(): if not bill_model.is_configured():
messages.add_message( messages.add_message(
request=self.request, request=self.request,
message=f'Bill {bill_model.bill_number} must have all accounts configured.', message=f"Bill {bill_model.bill_number} must have all accounts configured.",
level=messages.ERROR, level=messages.ERROR,
extra_tags='is-danger' extra_tags="is-danger",
) )
if not bill_model.is_paid(): if not bill_model.is_paid():
if ledger_model.locked: if ledger_model.locked:
messages.add_message(self.request, messages.add_message(
self.request,
messages.ERROR, messages.ERROR,
f'Warning! This bill is locked. Must unlock before making any changes.', f"Warning! This bill is locked. Must unlock before making any changes.",
extra_tags='is-danger') extra_tags="is-danger",
)
if ledger_model.locked: if ledger_model.locked:
messages.add_message(self.request, messages.add_message(
self.request,
messages.ERROR, messages.ERROR,
f'Warning! This bill is locked. Must unlock before making any changes.', f"Warning! This bill is locked. Must unlock before making any changes.",
extra_tags='is-danger') extra_tags="is-danger",
)
if not ledger_model.is_posted(): if not ledger_model.is_posted():
messages.add_message(self.request, messages.add_message(
self.request,
messages.INFO, messages.INFO,
f'This bill has not been posted. Must post to see ledger changes.', f"This bill has not been posted. Must post to see ledger changes.",
extra_tags='is-info') extra_tags="is-info",
)
itemtxs_qs = itemtxs_formset.get_queryset() if itemtxs_formset else None itemtxs_qs = itemtxs_formset.get_queryset() if itemtxs_formset else None
if not itemtxs_formset: if not itemtxs_formset:
itemtxs_formset_class = get_bill_itemtxs_formset_class(bill_model) itemtxs_formset_class = get_bill_itemtxs_formset_class(bill_model)
itemtxs_formset = itemtxs_formset_class(entity_model=entity_model, bill_model=bill_model) itemtxs_formset = itemtxs_formset_class(
entity_model=entity_model, bill_model=bill_model
)
itemtxs_qs, itemtxs_agg = bill_model.get_itemtxs_data(queryset=itemtxs_qs) itemtxs_qs, itemtxs_agg = bill_model.get_itemtxs_data(queryset=itemtxs_qs)
has_po = any(i.po_model_id for i in itemtxs_qs) has_po = any(i.po_model_id for i in itemtxs_qs)
@ -509,9 +540,9 @@ class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateVie
itemtxs_formset.can_delete = False itemtxs_formset.can_delete = False
itemtxs_formset.has_po = has_po itemtxs_formset.has_po = has_po
context['itemtxs_formset'] = itemtxs_formset context["itemtxs_formset"] = itemtxs_formset
context['total_amount__sum'] = itemtxs_agg['total_amount__sum'] context["total_amount__sum"] = itemtxs_agg["total_amount__sum"]
context['has_po'] = has_po context["has_po"] = has_po
return context return context
def get_success_url(self): def get_success_url(self):
@ -523,23 +554,28 @@ class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateVie
"bill_pk": self.kwargs["bill_pk"], "bill_pk": self.kwargs["bill_pk"],
}, },
) )
def form_valid(self, form): def form_valid(self, form):
form.save(commit=False) form.save(commit=False)
messages.add_message(self.request, messages.add_message(
self.request,
messages.SUCCESS, messages.SUCCESS,
f'Bill {self.object.bill_number} successfully updated.', f"Bill {self.object.bill_number} successfully updated.",
extra_tags='is-success') extra_tags="is-success",
)
return super().form_valid(form) return super().form_valid(form)
def get(self, request, dealer_slug, entity_slug, bill_pk, *args, **kwargs): def get(self, request, dealer_slug, entity_slug, bill_pk, *args, **kwargs):
if self.action_update_items: if self.action_update_items:
return HttpResponseRedirect( return HttpResponseRedirect(
redirect_to=reverse('bill-update', redirect_to=reverse(
"bill-update",
kwargs={ kwargs={
'dealer_slug': dealer_slug, "dealer_slug": dealer_slug,
'entity_slug': entity_slug, "entity_slug": entity_slug,
'bill_pk': bill_pk "bill_pk": bill_pk,
}) },
)
) )
return super(BillModelUpdateView, self).get(request, *args, **kwargs) return super(BillModelUpdateView, self).get(request, *args, **kwargs)
@ -614,10 +650,11 @@ class BillModelUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateVie
) )
class BaseBillActionView(
class BaseBillActionView(LoginRequiredMixin,PermissionRequiredMixin, RedirectView, SingleObjectMixin): LoginRequiredMixin, PermissionRequiredMixin, RedirectView, SingleObjectMixin
http_method_names = ['get'] ):
pk_url_kwarg = 'bill_pk' http_method_names = ["get"]
pk_url_kwarg = "bill_pk"
action_name = None action_name = None
commit = True commit = True
permission_required = "django_ledger.change_billmodel" permission_required = "django_ledger.change_billmodel"
@ -631,7 +668,6 @@ class BaseBillActionView(LoginRequiredMixin,PermissionRequiredMixin, RedirectVie
self.queryset = qs self.queryset = qs
return super().get_queryset() return super().get_queryset()
def get_redirect_url(self, dealer_slug, entity_slug, bill_pk, *args, **kwargs): def get_redirect_url(self, dealer_slug, entity_slug, bill_pk, *args, **kwargs):
return reverse( return reverse(
"bill-update", "bill-update",
@ -642,58 +678,56 @@ class BaseBillActionView(LoginRequiredMixin,PermissionRequiredMixin, RedirectVie
}, },
) )
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"]) dealer = get_object_or_404(Dealer, slug=self.kwargs["dealer_slug"])
kwargs['user_model'] = dealer.entity.admin kwargs["user_model"] = dealer.entity.admin
if not self.action_name: if not self.action_name:
raise ImproperlyConfigured('View attribute action_name is required.') raise ImproperlyConfigured("View attribute action_name is required.")
response = super(BaseBillActionView, self).get(request, *args, **kwargs) response = super(BaseBillActionView, self).get(request, *args, **kwargs)
bill_model: BillModel = self.get_object() bill_model: BillModel = self.get_object()
try: try:
getattr(bill_model, self.action_name)(commit=self.commit, **kwargs) getattr(bill_model, self.action_name)(commit=self.commit, **kwargs)
except ValidationError as e: except ValidationError as e:
messages.add_message(request, messages.add_message(
message=e.message, request, message=e.message, level=messages.ERROR, extra_tags="is-danger"
level=messages.ERROR, )
extra_tags='is-danger')
return response return response
class InventoryListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): class InventoryListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
template_name = 'django_ledger/inventory/inventory_list.html' template_name = "django_ledger/inventory/inventory_list.html"
context_object_name = 'inventory_list' context_object_name = "inventory_list"
http_method_names = ['get'] http_method_names = ["get"]
def get_context_data(self, *, object_list=None, **kwargs): def get_context_data(self, *, object_list=None, **kwargs):
context = super(InventoryListView, self).get_context_data(**kwargs) context = super(InventoryListView, self).get_context_data(**kwargs)
qs = self.get_queryset() qs = self.get_queryset()
# evaluates the queryset... # evaluates the queryset...
context['qs_count'] = qs.count() context["qs_count"] = qs.count()
# ordered inventory... # ordered inventory...
ordered_qs = qs.is_ordered() ordered_qs = qs.is_ordered()
context['inventory_ordered'] = ordered_qs context["inventory_ordered"] = ordered_qs
# in transit inventory... # in transit inventory...
in_transit_qs = qs.in_transit() in_transit_qs = qs.in_transit()
context['inventory_in_transit'] = in_transit_qs context["inventory_in_transit"] = in_transit_qs
# on hand inventory... # on hand inventory...
received_qs = qs.is_received() received_qs = qs.is_received()
context['inventory_received'] = received_qs context["inventory_received"] = received_qs
context['page_title'] = _('Inventory') context["page_title"] = _("Inventory")
context['header_title'] = _('Inventory Status') context["header_title"] = _("Inventory Status")
context['header_subtitle'] = _('Ordered/In Transit/On Hand') context["header_subtitle"] = _("Ordered/In Transit/On Hand")
context['header_subtitle_icon'] = 'ic:round-inventory' context["header_subtitle_icon"] = "ic:round-inventory"
return context return context
def get_queryset(self): def get_queryset(self):
if self.queryset is None: if self.queryset is None:
self.queryset = ItemTransactionModel.objects.inventory_pipeline_aggregate( self.queryset = ItemTransactionModel.objects.inventory_pipeline_aggregate(
entity_slug=self.kwargs['entity_slug'], entity_slug=self.kwargs["entity_slug"],
) )
return super().get_queryset() return super().get_queryset()

View File

@ -18,7 +18,7 @@ from django_ledger.models import (
AccountModel, AccountModel,
PurchaseOrderModel, PurchaseOrderModel,
EstimateModel, EstimateModel,
BillModel BillModel,
) )
from . import models from . import models
from django.utils.timezone import now from django.utils.timezone import now
@ -27,6 +27,7 @@ from django_q.tasks import async_task
# logging # logging
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
User = get_user_model() User = get_user_model()
@ -94,7 +95,9 @@ def create_car_location(sender, instance, created, **kwargs):
try: try:
if created: if created:
# Log that the signal was triggered for a new car # Log that the signal was triggered for a new car
logger.debug(f"Post-save signal triggered for new Car (VIN: {instance.vin}). Attempting to create CarLocation.") logger.debug(
f"Post-save signal triggered for new Car (VIN: {instance.vin}). Attempting to create CarLocation."
)
if instance.dealer is None: if instance.dealer is None:
# Log the critical data integrity error before raising # Log the critical data integrity error before raising
@ -122,7 +125,7 @@ def create_car_location(sender, instance, created, **kwargs):
logger.error( logger.error(
f"Failed to create CarLocation for car (VIN: {instance.vin}). " f"Failed to create CarLocation for car (VIN: {instance.vin}). "
f"An unexpected error occurred: {e}", f"An unexpected error occurred: {e}",
exc_info=True exc_info=True,
) )
print(f"Failed to create CarLocation for car {instance.vin}: {e}") print(f"Failed to create CarLocation for car {instance.vin}: {e}")
@ -196,9 +199,7 @@ def create_dealer_groups(sender, instance, created, **kwargs):
# async_task("inventory.tasks.create_groups",instance.slug) # async_task("inventory.tasks.create_groups",instance.slug)
def create_groups(): def create_groups():
for group_name in ["Inventory", "Accountant", "Sales", "Manager"]: for group_name in ["Inventory", "Accountant", "Sales", "Manager"]:
group= Group.objects.create( group = Group.objects.create(name=f"{instance.slug}_{group_name}")
name=f"{instance.slug}_{group_name}"
)
group_manager = models.CustomGroup.objects.create( group_manager = models.CustomGroup.objects.create(
name=group_name, dealer=instance, group=group name=group_name, dealer=instance, group=group
) )
@ -936,12 +937,16 @@ def update_finance_cost(sender, instance, created, **kwargs):
# else: # else:
# save_journal(instance,ledger,vendor) # save_journal(instance,ledger,vendor)
@receiver(post_save, sender=PurchaseOrderModel) @receiver(post_save, sender=PurchaseOrderModel)
def create_po_item_upload(sender, instance, created, **kwargs): def create_po_item_upload(sender, instance, created, **kwargs):
if instance.po_status == "fulfilled": if instance.po_status == "fulfilled":
for item in instance.get_itemtxs_data()[0]: for item in instance.get_itemtxs_data()[0]:
dealer = models.Dealer.objects.get(entity=instance.entity) dealer = models.Dealer.objects.get(entity=instance.entity)
models.PoItemsUploaded.objects.create(dealer=dealer,po=instance, item=item, status="fulfilled") models.PoItemsUploaded.objects.create(
dealer=dealer, po=instance, item=item, status="fulfilled"
)
@receiver(post_save, sender=models.Staff) @receiver(post_save, sender=models.Staff)
def add_service_to_staff(sender, instance, created, **kwargs): def add_service_to_staff(sender, instance, created, **kwargs):
@ -949,15 +954,22 @@ def add_service_to_staff(sender,instance,created,**kwargs):
for service in Service.objects.all(): for service in Service.objects.all():
instance.staff_member.services_offered.add(service) instance.staff_member.services_offered.add(service)
########################################################## ##########################################################
######################Notification######################## ######################Notification########################
########################################################## ##########################################################
@receiver(post_save, sender=PurchaseOrderModel) @receiver(post_save, sender=PurchaseOrderModel)
def create_po_fulfilled_notification(sender, instance, created, **kwargs): def create_po_fulfilled_notification(sender, instance, created, **kwargs):
if instance.po_status == "fulfilled": if instance.po_status == "fulfilled":
dealer = models.Dealer.objects.get(entity=instance.entity) dealer = models.Dealer.objects.get(entity=instance.entity)
accountants = models.CustomGroup.objects.filter(dealer=dealer,name="Inventory").first().group.user_set.exclude(email=dealer.user.email).distinct() accountants = (
models.CustomGroup.objects.filter(dealer=dealer, name="Inventory")
.first()
.group.user_set.exclude(email=dealer.user.email)
.distinct()
)
for accountant in accountants: for accountant in accountants:
models.Notification.objects.create( models.Notification.objects.create(
user=accountant, user=accountant,
@ -967,11 +979,18 @@ def create_po_fulfilled_notification(sender,instance,created,**kwargs):
""", """,
) )
@receiver(post_save, sender=models.Car) @receiver(post_save, sender=models.Car)
def car_created_notification(sender, instance, created, **kwargs): def car_created_notification(sender, instance, created, **kwargs):
if created: if created:
accountants = (
accountants = models.CustomGroup.objects.filter(dealer=instance.dealer,name__in=["Manager","Accountant"]).first().group.user_set.all().distinct() models.CustomGroup.objects.filter(
dealer=instance.dealer, name__in=["Manager", "Accountant"]
)
.first()
.group.user_set.all()
.distinct()
)
for accountant in accountants: for accountant in accountants:
models.Notification.objects.create( models.Notification.objects.create(
user=accountant, user=accountant,
@ -982,29 +1001,30 @@ def car_created_notification(sender, instance, created, **kwargs):
) )
@receiver(post_save, sender=PurchaseOrderModel) @receiver(post_save, sender=PurchaseOrderModel)
def po_fullfilled_notification(sender, instance, created, **kwargs): def po_fullfilled_notification(sender, instance, created, **kwargs):
if instance.is_fulfilled(): if instance.is_fulfilled():
dealer = models.Dealer.objects.get(entity=instance.entity) dealer = models.Dealer.objects.get(entity=instance.entity)
recipients = User.objects.filter( recipients = User.objects.filter(
groups__customgroup__dealer=instance.dealer, groups__customgroup__dealer=instance.dealer,
groups__customgroup__name__in=["Manager", "Inventory"] groups__customgroup__name__in=["Manager", "Inventory"],
).distinct() ).distinct()
for recipient in recipients: for recipient in recipients:
models.Notification.objects.create( models.Notification.objects.create(
user=recipient, user=recipient,
message=f""" message=f"""
New Purchase Order has been added. New Purchase Order has been added.
<a href="{reverse('purchase_order_detail',kwargs={'dealer_slug':dealer.slug,'pk':instance.pk})}" target="_blank">View</a> <a href="{reverse("purchase_order_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
""", """,
) )
@receiver(post_save, sender=models.Vendor) @receiver(post_save, sender=models.Vendor)
def vendor_created_notification(sender, instance, created, **kwargs): def vendor_created_notification(sender, instance, created, **kwargs):
if created: if created:
recipients = User.objects.filter( recipients = User.objects.filter(
groups__customgroup__dealer=instance.dealer, groups__customgroup__dealer=instance.dealer,
groups__customgroup__name__in=["Manager", "Inventory"] groups__customgroup__name__in=["Manager", "Inventory"],
).distinct() ).distinct()
for recipient in recipients: for recipient in recipients:
@ -1015,19 +1035,27 @@ def vendor_created_notification(sender, instance, created, **kwargs):
""", """,
) )
@receiver(post_save, sender=models.SaleOrder) @receiver(post_save, sender=models.SaleOrder)
def sale_order_created_notification(sender, instance, created, **kwargs): def sale_order_created_notification(sender, instance, created, **kwargs):
if created: if created:
recipients = models.CustomGroup.objects.filter(dealer=instance.dealer,name="Accountant").first().group.user_set.exclude(email=instance.dealer.user.email).distinct() recipients = (
models.CustomGroup.objects.filter(dealer=instance.dealer, name="Accountant")
.first()
.group.user_set.exclude(email=instance.dealer.user.email)
.distinct()
)
for recipient in recipients: for recipient in recipients:
models.Notification.objects.create( models.Notification.objects.create(
user=recipient, user=recipient,
message=f""" message=f"""
New Sale Order has been added for estimate:{instance.estimate}. 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> <a href="{reverse("estimate_detail", kwargs={"dealer_slug": instance.dealer.slug, "pk": instance.estimate.pk})}" target="_blank">View</a>
""", """,
) )
@receiver(post_save, sender=models.Lead) @receiver(post_save, sender=models.Lead)
def lead_created_notification(sender, instance, created, **kwargs): def lead_created_notification(sender, instance, created, **kwargs):
if created: if created:
@ -1036,22 +1064,31 @@ def lead_created_notification(sender, instance, created, **kwargs):
user=instance.staff.user, user=instance.staff.user,
message=f""" message=f"""
New Lead has been added. New Lead has been added.
<a href="{reverse('lead_detail',kwargs={'dealer_slug':instance.dealer.slug,'slug':instance.slug})}" target="_blank">View</a> <a href="{reverse("lead_detail", kwargs={"dealer_slug": instance.dealer.slug, "slug": instance.slug})}" target="_blank">View</a>
""", """,
) )
@receiver(post_save, sender=EstimateModel) @receiver(post_save, sender=EstimateModel)
def estimate_in_review_notification(sender, instance, created, **kwargs): def estimate_in_review_notification(sender, instance, created, **kwargs):
if instance.is_review(): if instance.is_review():
dealer = models.Dealer.objects.get(entity=instance.entity) dealer = models.Dealer.objects.get(entity=instance.entity)
recipients = models.CustomGroup.objects.filter(dealer=dealer,name="Manager").first().group.user_set.exclude(email=dealer.user.email).distinct() recipients = (
models.CustomGroup.objects.filter(dealer=dealer, name="Manager")
.first()
.group.user_set.exclude(email=dealer.user.email)
.distinct()
)
for recipient in recipients: for recipient in recipients:
models.Notification.objects.create( models.Notification.objects.create(
user=recipient, user=recipient,
message=f""" message=f"""
Estimate {instance.estimate_number} is in review. Estimate {instance.estimate_number} is in review.
Please review and approve it at your earliest convenience. 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> <a href="{reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
""") """,
)
@receiver(post_save, sender=EstimateModel) @receiver(post_save, sender=EstimateModel)
def estimate_in_approve_notification(sender, instance, created, **kwargs): def estimate_in_approve_notification(sender, instance, created, **kwargs):
@ -1068,37 +1105,49 @@ def estimate_in_approve_notification(sender, instance, created, **kwargs):
user=recipient.related_object.user, user=recipient.related_object.user,
message=f""" message=f"""
Estimate {instance.estimate_number} has been approved. Estimate {instance.estimate_number} has been approved.
<a href="{reverse('estimate_detail', kwargs={'dealer_slug': dealer.slug, 'pk': instance.pk})}" target="_blank">View</a> <a href="{reverse("estimate_detail", kwargs={"dealer_slug": dealer.slug, "pk": instance.pk})}" target="_blank">View</a>
""" """,
) )
@receiver(post_save, sender=BillModel) @receiver(post_save, sender=BillModel)
def bill_model_in_approve_notification(sender, instance, created, **kwargs): def bill_model_in_approve_notification(sender, instance, created, **kwargs):
if instance.is_review(): if instance.is_review():
dealer = models.Dealer.objects.get(entity=instance.ledger.entity) dealer = models.Dealer.objects.get(entity=instance.ledger.entity)
recipients = models.CustomGroup.objects.filter(dealer=dealer,name="Manager").first().group.user_set.exclude(email=dealer.user.email).distinct() recipients = (
models.CustomGroup.objects.filter(dealer=dealer, name="Manager")
.first()
.group.user_set.exclude(email=dealer.user.email)
.distinct()
)
for recipient in recipients: for recipient in recipients:
models.Notification.objects.create( models.Notification.objects.create(
user=recipient, user=recipient,
message=f""" message=f"""
Bill {instance.bill_number} is in review,please review and approve it 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>. <a href="{reverse("bill-detail", kwargs={"dealer_slug": dealer.slug, "entity_slug": dealer.entity.slug, "bill_pk": instance.pk})}" target="_blank">View</a>.
""" """,
) )
@receiver(post_save, sender=BillModel) @receiver(post_save, sender=BillModel)
def bill_model_after_approve_notification(sender, instance, created, **kwargs): def bill_model_after_approve_notification(sender, instance, created, **kwargs):
if instance.is_approved(): if instance.is_approved():
dealer = models.Dealer.objects.get(entity=instance.ledger.entity) dealer = models.Dealer.objects.get(entity=instance.ledger.entity)
recipients = models.CustomGroup.objects.filter(dealer=dealer,name="Accountant").first().group.user_set.exclude(email=dealer.user.email).distinct() recipients = (
models.CustomGroup.objects.filter(dealer=dealer, name="Accountant")
.first()
.group.user_set.exclude(email=dealer.user.email)
.distinct()
)
for recipient in recipients: for recipient in recipients:
models.Notification.objects.create( models.Notification.objects.create(
user=recipient, user=recipient,
message=f""" message=f"""
Bill {instance.bill_number} has been approved. 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>. <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. please complete the bill payment.
""" """,
) )

View File

@ -11,6 +11,7 @@ from django.utils.translation import gettext_lazy as _
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
def create_settings(pk): def create_settings(pk):
instance = Dealer.objects.get(pk=pk) instance = Dealer.objects.get(pk=pk)
@ -1126,6 +1127,7 @@ def create_make_accounts(entity, coa, makes, name, role, balance_type):
) )
return acc return acc
def send_email(from_, to_, subject, message): def send_email(from_, to_, subject, message):
subject = subject subject = subject
message = message message = message
@ -1174,4 +1176,3 @@ def create_user_dealer(email, password, name, arabic_name, phone, crn, vrn, addr
# instance.user.groups.add(group) # instance.user.groups.add(group)
# transaction.on_commit(run) # transaction.on_commit(run)

View File

@ -54,7 +54,6 @@ def period_navigation(context, base_url: str):
kwargs["dealer_slug"] = dealer_slug kwargs["dealer_slug"] = dealer_slug
kwargs["entity_slug"] = entity_slug kwargs["entity_slug"] = entity_slug
if context["view"].kwargs.get("ledger_pk"): if context["view"].kwargs.get("ledger_pk"):
kwargs["ledger_pk"] = context["view"].kwargs.get("ledger_pk") kwargs["ledger_pk"] = context["view"].kwargs.get("ledger_pk")
@ -475,8 +474,8 @@ def po_item_formset_table(context, po_model, itemtxs_formset,user):
def bill_item_formset_table(context, item_formset): def bill_item_formset_table(context, item_formset):
for item in item_formset: for item in item_formset:
if item: if item:
item.initial['quantity'] = item.instance.po_quantity item.initial["quantity"] = item.instance.po_quantity
item.initial['unit_cost'] = item.instance.po_unit_cost item.initial["unit_cost"] = item.instance.po_unit_cost
# print(item.instance.po_quantity) # print(item.instance.po_quantity)
# print(item.instance.po_unit_cost) # print(item.instance.po_unit_cost)
# print(item.instance.po_total_amount) # print(item.instance.po_total_amount)
@ -661,7 +660,6 @@ def inventory_table(context, queryset):
return ctx return ctx
@register.filter @register.filter
def count_checked(permissions, group_permission_ids): def count_checked(permissions, group_permission_ids):
"""Count how many permissions are checked from the allowed list""" """Count how many permissions are checked from the allowed list"""
@ -669,10 +667,8 @@ def count_checked(permissions, group_permission_ids):
return 0 return 0
return sum(1 for perm in permissions if perm.id in group_permission_ids) return sum(1 for perm in permissions if perm.id in group_permission_ids)
# @register.filter # @register.filter
# def count_checked(permissions, group_permission_ids): # def count_checked(permissions, group_permission_ids):
# """Count how many permissions are checked from the allowed list""" # """Count how many permissions are checked from the allowed list"""
# return sum(1 for perm in permissions if perm.id in group_permission_ids) # return sum(1 for perm in permissions if perm.id in group_permission_ids)

View File

@ -472,5 +472,3 @@ class AuthenticationTest(TestCase):
# self.assertEqual(finance_data["total_additionals"], Decimal("180")) # self.assertEqual(finance_data["total_additionals"], Decimal("180"))
# self.assertEqual(finance_data["additionals"][0]["name"], "Service") # self.assertEqual(finance_data["additionals"][0]["name"], "Service")
# self.assertEqual(finance_data["vat"], Decimal("0.20")) # self.assertEqual(finance_data["vat"], Decimal("0.20"))

View File

@ -12,7 +12,6 @@ urlpatterns = [
path("signup/", views.dealer_signup, name="account_signup"), path("signup/", views.dealer_signup, name="account_signup"),
path("", views.HomeView.as_view(), name="home"), path("", views.HomeView.as_view(), name="home"),
path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"), path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"),
# Tasks # Tasks
path("legal/", views.terms_and_privacy, name="terms_and_privacy"), path("legal/", views.terms_and_privacy, name="terms_and_privacy"),
# path('tasks/<int:task_id>/detail/', views.task_detail, name='task_detail'), # path('tasks/<int:task_id>/detail/', views.task_detail, name='task_detail'),
@ -20,7 +19,11 @@ urlpatterns = [
# path("user/<int:pk>/settings/", views.UserSettingsView.as_view(), name="user_settings"), # path("user/<int:pk>/settings/", views.UserSettingsView.as_view(), name="user_settings"),
path("<slug:dealer_slug>/pricing/", views.pricing_page, name="pricing_page"), path("<slug:dealer_slug>/pricing/", views.pricing_page, name="pricing_page"),
path("<slug:dealer_slug>/submit_plan/", views.submit_plan, name="submit_plan"), path("<slug:dealer_slug>/submit_plan/", views.submit_plan, name="submit_plan"),
path("<slug:dealer_slug>/payment-callback/", views.payment_callback, name="payment_callback"), path(
"<slug:dealer_slug>/payment-callback/",
views.payment_callback,
name="payment_callback",
),
# #
path( path(
"<slug:dealer_slug>/dealers/activity/", "<slug:dealer_slug>/dealers/activity/",
@ -32,7 +35,11 @@ urlpatterns = [
views.DealerSettingsView, views.DealerSettingsView,
name="dealer_settings", name="dealer_settings",
), ),
path("<slug:dealer_slug>/dealers/assign-car-makes/", views.assign_car_makes, name="assign_car_makes"), path(
"<slug:dealer_slug>/dealers/assign-car-makes/",
views.assign_car_makes,
name="assign_car_makes",
),
path( path(
"dashboards/manager/", "dashboards/manager/",
views.ManagerDashboard.as_view(), views.ManagerDashboard.as_view(),
@ -59,9 +66,15 @@ urlpatterns = [
# path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'), # path('dealers/<int:pk>/delete/', views.DealerDeleteView.as_view(), name='dealer_delete'),
# CRM URLs # CRM URLs
path( path(
"<slug:dealer_slug>/customers/create/", views.CustomerCreateView.as_view(), name="customer_create" "<slug:dealer_slug>/customers/create/",
views.CustomerCreateView.as_view(),
name="customer_create",
),
path(
"<slug:dealer_slug>/customers/",
views.CustomerListView.as_view(),
name="customer_list",
), ),
path("<slug:dealer_slug>/customers/", views.CustomerListView.as_view(), name="customer_list"),
path( path(
"<slug:dealer_slug>/customers/<slug:slug>/", "<slug:dealer_slug>/customers/<slug:slug>/",
views.CustomerDetailView.as_view(), views.CustomerDetailView.as_view(),
@ -78,7 +91,9 @@ urlpatterns = [
name="customer_update", name="customer_update",
), ),
path( path(
"<slug:dealer_slug>/customers/<slug:slug>/delete/", views.delete_customer, name="customer_delete" "<slug:dealer_slug>/customers/<slug:slug>/delete/",
views.delete_customer,
name="customer_delete",
), ),
path( path(
"<slug:dealer_slug>/customers/<slug:slug>/opportunities/create/", "<slug:dealer_slug>/customers/<slug:slug>/opportunities/create/",
@ -94,21 +109,39 @@ urlpatterns = [
views.LeadDetailView.as_view(), views.LeadDetailView.as_view(),
name="lead_detail", name="lead_detail",
), ),
path("<slug:dealer_slug>/update-lead-actions/", views.update_lead_actions, name="update_lead_actions"), path(
path("<slug:dealer_slug>/crm/leads/lead_tracking/", views.lead_tracking, name="lead_tracking"), "<slug:dealer_slug>/update-lead-actions/",
views.update_lead_actions,
name="update_lead_actions",
),
path(
"<slug:dealer_slug>/crm/leads/lead_tracking/",
views.lead_tracking,
name="lead_tracking",
),
path("<slug:dealer_slug>/crm/leads/lead_view/", views.lead_view, name="lead_view"), path("<slug:dealer_slug>/crm/leads/lead_view/", views.lead_view, name="lead_view"),
path("<slug:dealer_slug>/crm/leads/", views.LeadListView.as_view(), name="lead_list"), path(
"<slug:dealer_slug>/crm/leads/", views.LeadListView.as_view(), name="lead_list"
),
path( path(
"<slug:dealer_slug>/crm/leads/<slug:slug>/update/", "<slug:dealer_slug>/crm/leads/<slug:slug>/update/",
views.LeadUpdateView.as_view(), views.LeadUpdateView.as_view(),
name="lead_update", name="lead_update",
), ),
path("<slug:dealer_slug>/crm/leads/<slug:slug>/delete/", views.LeadDeleteView, name="lead_delete"),
path( path(
"<slug:dealer_slug>/crm/leads/<slug:slug>/lead-convert/", views.lead_convert, name="lead_convert" "<slug:dealer_slug>/crm/leads/<slug:slug>/delete/",
views.LeadDeleteView,
name="lead_delete",
), ),
path( path(
"<slug:dealer_slug>/crm/leads/<int:pk>/delete-note/", views.delete_note, name="delete_note_to_lead" "<slug:dealer_slug>/crm/leads/<slug:slug>/lead-convert/",
views.lead_convert,
name="lead_convert",
),
path(
"<slug:dealer_slug>/crm/leads/<int:pk>/delete-note/",
views.delete_note,
name="delete_note_to_lead",
), ),
path( path(
"<slug:dealer_slug>/crm/<int:pk>/update-note/", "<slug:dealer_slug>/crm/<int:pk>/update-note/",
@ -216,9 +249,11 @@ urlpatterns = [
# Notifications # Notifications
path("notifications/stream/", views.sse_stream, name="sse_stream"), path("notifications/stream/", views.sse_stream, name="sse_stream"),
path("notifications/fetch/", views.fetch_notifications, name="fetch_notifications"), path("notifications/fetch/", views.fetch_notifications, name="fetch_notifications"),
path(
path("notifications/list/", views.NotificationListView.as_view(), name="notifications_history"), "notifications/list/",
views.NotificationListView.as_view(),
name="notifications_history",
),
path( path(
"notifications/<int:notification_id>/mark_as_read/", "notifications/<int:notification_id>/mark_as_read/",
views.mark_notification_as_read, views.mark_notification_as_read,
@ -235,9 +270,19 @@ urlpatterns = [
####################################################### #######################################################
# Vendor URLs # Vendor URLs
####################################################### #######################################################
path("<slug:dealer_slug>/vendors/create/", views.VendorCreateView.as_view(), name="vendor_create"), path(
path("<slug:dealer_slug>/vendors", views.VendorListView.as_view(), name="vendor_list"), "<slug:dealer_slug>/vendors/create/",
path("<slug:dealer_slug>/vendors/<slug:slug>/", views.vendorDetailView, name="vendor_detail"), views.VendorCreateView.as_view(),
name="vendor_create",
),
path(
"<slug:dealer_slug>/vendors", views.VendorListView.as_view(), name="vendor_list"
),
path(
"<slug:dealer_slug>/vendors/<slug:slug>/",
views.vendorDetailView,
name="vendor_detail",
),
path( path(
"<slug:dealer_slug>/vendors/<slug:slug>/update/", "<slug:dealer_slug>/vendors/<slug:slug>/update/",
views.VendorUpdateView.as_view(), views.VendorUpdateView.as_view(),
@ -447,26 +492,99 @@ urlpatterns = [
# ), # ),
# Users URLs # Users URLs
path("<slug:dealer_slug>/user/", views.UserListView.as_view(), name="user_list"), path("<slug:dealer_slug>/user/", views.UserListView.as_view(), name="user_list"),
path("<slug:dealer_slug>/user/create/", views.UserCreateView.as_view(), name="user_create"), path(
path("<slug:dealer_slug>/user/<slug:slug>/", views.UserDetailView.as_view(), name="user_detail"), "<slug:dealer_slug>/user/create/",
path("<slug:dealer_slug>/user/<slug:slug>/groups/", views.UserGroupView, name="user_groups"), views.UserCreateView.as_view(),
path("<slug:dealer_slug>/user/<slug:slug>/update/", views.UserUpdateView.as_view(), name="user_update"), name="user_create",
path("<slug:dealer_slug>/user/<slug:slug>/confirm/", views.UserDeleteview, name="user_delete"), ),
path("<slug:dealer_slug>/group/create/", views.GroupCreateView.as_view(), name="group_create"), path(
path("<slug:dealer_slug>/group/<int:pk>/update/", views.GroupUpdateView.as_view(), name="group_update"), "<slug:dealer_slug>/user/<slug:slug>/",
path("<slug:dealer_slug>/group/<int:pk>/", views.GroupDetailView.as_view(), name="group_detail"), views.UserDetailView.as_view(),
name="user_detail",
),
path(
"<slug:dealer_slug>/user/<slug:slug>/groups/",
views.UserGroupView,
name="user_groups",
),
path(
"<slug:dealer_slug>/user/<slug:slug>/update/",
views.UserUpdateView.as_view(),
name="user_update",
),
path(
"<slug:dealer_slug>/user/<slug:slug>/confirm/",
views.UserDeleteview,
name="user_delete",
),
path(
"<slug:dealer_slug>/group/create/",
views.GroupCreateView.as_view(),
name="group_create",
),
path(
"<slug:dealer_slug>/group/<int:pk>/update/",
views.GroupUpdateView.as_view(),
name="group_update",
),
path(
"<slug:dealer_slug>/group/<int:pk>/",
views.GroupDetailView.as_view(),
name="group_detail",
),
path("<slug:dealer_slug>/group/", views.GroupListView.as_view(), name="group_list"), path("<slug:dealer_slug>/group/", views.GroupListView.as_view(), name="group_list"),
path("<slug:dealer_slug>/group/<int:pk>/confirm/", views.GroupDeleteview, name="group_delete"), path(
path("<slug:dealer_slug>/group/<int:pk>/permission/", views.GroupPermissionView, name="group_permission"), "<slug:dealer_slug>/group/<int:pk>/confirm/",
path("<slug:dealer_slug>/organizations/create/", views.OrganizationCreateView.as_view(), name="organization_create"), views.GroupDeleteview,
path("<slug:dealer_slug>/organizations/", views.OrganizationListView.as_view(), name="organization_list"), name="group_delete",
path("<slug:dealer_slug>/organizations/<slug:slug>/", views.OrganizationDetailView.as_view(), name="organization_detail"), ),
path("<slug:dealer_slug>/organizations/<slug:slug>/update/", views.OrganizationUpdateView.as_view(), name="organization_update"), path(
path("<slug:dealer_slug>/organizations/<slug:slug>/delete/", views.OrganizationDeleteView, name="organization_delete"), "<slug:dealer_slug>/group/<int:pk>/permission/",
path("representatives/", views.RepresentativeListView.as_view(), name="representative_list"), views.GroupPermissionView,
path("representatives/<int:pk>/", views.RepresentativeDetailView.as_view(), name="representative_detail"), name="group_permission",
path("representatives/create/", views.RepresentativeCreateView.as_view(),name="representative_create"), ),
path("representatives/<int:pk>/update/", path(
"<slug:dealer_slug>/organizations/create/",
views.OrganizationCreateView.as_view(),
name="organization_create",
),
path(
"<slug:dealer_slug>/organizations/",
views.OrganizationListView.as_view(),
name="organization_list",
),
path(
"<slug:dealer_slug>/organizations/<slug:slug>/",
views.OrganizationDetailView.as_view(),
name="organization_detail",
),
path(
"<slug:dealer_slug>/organizations/<slug:slug>/update/",
views.OrganizationUpdateView.as_view(),
name="organization_update",
),
path(
"<slug:dealer_slug>/organizations/<slug:slug>/delete/",
views.OrganizationDeleteView,
name="organization_delete",
),
path(
"representatives/",
views.RepresentativeListView.as_view(),
name="representative_list",
),
path(
"representatives/<int:pk>/",
views.RepresentativeDetailView.as_view(),
name="representative_detail",
),
path(
"representatives/create/",
views.RepresentativeCreateView.as_view(),
name="representative_create",
),
path(
"representatives/<int:pk>/update/",
views.RepresentativeUpdateView.as_view(), views.RepresentativeUpdateView.as_view(),
name="representative_update", name="representative_update",
), ),
@ -475,9 +593,15 @@ urlpatterns = [
views.RepresentativeDeleteView.as_view(), views.RepresentativeDeleteView.as_view(),
name="representative_delete", name="representative_delete",
), ),
path("<slug:dealer_slug>/ledgers/<slug:entity_slug>/", views.LedgerModelListView.as_view(), name="ledger_list"),
path( path(
"<slug:dealer_slug>/ledgers/<slug:entity_slug>/create/", views.LedgerModelCreateView.as_view(), name="ledger_create" "<slug:dealer_slug>/ledgers/<slug:entity_slug>/",
views.LedgerModelListView.as_view(),
name="ledger_list",
),
path(
"<slug:dealer_slug>/ledgers/<slug:entity_slug>/create/",
views.LedgerModelCreateView.as_view(),
name="ledger_create",
), ),
path( path(
"<slug:dealer_slug>/ledgers/<slug:entity_slug>/detail/<uuid:pk>/", "<slug:dealer_slug>/ledgers/<slug:entity_slug>/detail/<uuid:pk>/",
@ -698,7 +822,6 @@ urlpatterns = [
views.update_estimate_additionals, views.update_estimate_additionals,
name="update_estimate_additionals", name="update_estimate_additionals",
), ),
############################################### ###############################################
# Invoice # Invoice
############################################### ###############################################
@ -771,7 +894,9 @@ urlpatterns = [
# path('sales/journal/<uuid:pk>/create/', views.JournalEntryCreateView.as_view(), name='journal_create'), # path('sales/journal/<uuid:pk>/create/', views.JournalEntryCreateView.as_view(), name='journal_create'),
# Items # Items
path( path(
"<slug:dealer_slug>/items/services/", views.ItemServiceListView.as_view(), name="item_service_list" "<slug:dealer_slug>/items/services/",
views.ItemServiceListView.as_view(),
name="item_service_list",
), ),
path( path(
"<slug:dealer_slug>/items/services/create/", "<slug:dealer_slug>/items/services/create/",
@ -884,7 +1009,6 @@ urlpatterns = [
views.BillModelActionForceMigrateView.as_view(), views.BillModelActionForceMigrateView.as_view(),
name="bill-action-force-migrate", name="bill-action-force-migrate",
), ),
# orders # orders
path("orders/", views.OrderListView.as_view(), name="order_list_view"), path("orders/", views.OrderListView.as_view(), name="order_list_view"),
# BALANCE SHEET Reports... # BALANCE SHEET Reports...
@ -1013,7 +1137,11 @@ urlpatterns = [
), ),
# Admin Management... # Admin Management...
path("<slug:dealer_slug>/management/", views.management_view, name="management"), path("<slug:dealer_slug>/management/", views.management_view, name="management"),
path("<slug:dealer_slug>/management/user_management/", views.user_management, name="user_management"), path(
"<slug:dealer_slug>/management/user_management/",
views.user_management,
name="user_management",
),
path( path(
"<slug:dealer_slug>/management/<str:content_type>/<slug:slug>/activate_account/", "<slug:dealer_slug>/management/<str:content_type>/<slug:slug>/activate_account/",
views.activate_account, views.activate_account,

View File

@ -27,8 +27,10 @@ from django_ledger.models.transactions import TransactionModel
from django_ledger.models.journal_entry import JournalEntryModel from django_ledger.models.journal_entry import JournalEntryModel
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def make_random_password( def make_random_password(
length=10, allowed_chars="abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789" length=10, allowed_chars="abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
): ):
@ -68,10 +70,7 @@ def get_jwt_token():
return response.text return response.text
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
# logging for error # logging for error
logger.error( logger.error(f"HTTP error fetching JWT token from {url}: ", exc_info=True)
f"HTTP error fetching JWT token from {url}: ",
exc_info=True
)
print(f"Error obtaining JWT token: {e}") print(f"Error obtaining JWT token: {e}")
return None return None
@ -239,7 +238,7 @@ def reserve_car(car, request):
f"Error reserving car {car.pk} ('{car.id_car_make} {car.id_car_model}') " f"Error reserving car {car.pk} ('{car.id_car_make} {car.id_car_model}') "
f"for user {request.user} . " f"for user {request.user} . "
f"Error: {e}", f"Error: {e}",
exc_info=True exc_info=True,
) )
messages.error(request, f"Error reserving car: {e}") messages.error(request, f"Error reserving car: {e}")
@ -1002,7 +1001,11 @@ class CarFinanceCalculator:
self.vat_rate = self._get_vat_rate() self.vat_rate = self._get_vat_rate()
self.item_transactions = self._get_item_transactions() self.item_transactions = self._get_item_transactions()
self.additional_services = self._get_additional_services() self.additional_services = self._get_additional_services()
self.extra_info = models.ExtraInfo.objects.get(dealer=self.dealer,content_type=ContentType.objects.get_for_model(model),object_id=model.pk) self.extra_info = models.ExtraInfo.objects.get(
dealer=self.dealer,
content_type=ContentType.objects.get_for_model(model),
object_id=model.pk,
)
def _get_vat_rate(self): def _get_vat_rate(self):
vat = models.VatRate.objects.filter(dealer=self.dealer, is_active=True).first() vat = models.VatRate.objects.filter(dealer=self.dealer, is_active=True).first()
@ -1294,10 +1297,9 @@ def handle_account_process(invoice, amount, finance_data):
except Exception as e: except Exception as e:
logger.error( logger.error(
f"Error updating item_model.for_inventory for car {car.vin} (Invoice {invoice.invoice_number}): {e}", f"Error updating item_model.for_inventory for car {car.vin} (Invoice {invoice.invoice_number}): {e}",
exc_info=True exc_info=True,
) )
car.finances.is_sold = True car.finances.is_sold = True
car.finances.save() car.finances.save()
car.item_model.save() car.item_model.save()
@ -1372,6 +1374,7 @@ def create_make_accounts(dealer):
active=True, active=True,
) )
def handle_payment(request, order): def handle_payment(request, order):
url = "https://api.moyasar.com/v1/payments" url = "https://api.moyasar.com/v1/payments"
callback_url = request.build_absolute_uri( callback_url = request.build_absolute_uri(

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
// static/js/formSubmitHandler.js
document.addEventListener('DOMContentLoaded', function() {
// Initialize all forms with submit buttons
const forms = document.querySelectorAll('form');
forms.forEach(form => {
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
// Store original button HTML
if (!submitBtn.dataset.originalHtml) {
submitBtn.dataset.originalHtml = submitBtn.innerHTML;
}
form.addEventListener('submit', function(e) {
// Only proceed if form is valid
if (form.checkValidity()) {
disableSubmitButton(submitBtn);
}
});
}
});
});
/**
* Disable and show loading state on submit button
* @param {HTMLElement} button - The submit button element
*/
function disableSubmitButton(button) {
button.disabled = true;
button.innerHTML = `
<span class="submit-spinner">
<i class="fas fa-spinner fa-spin me-1"></i>
</span>
<span class="submit-text">${button.dataset.savingText || 'Processing...'}</span>
`;
button.classList.add('submitting');
}
/**
* Reset submit button to original state
* @param {HTMLElement} button - The submit button element
*/
function resetSubmitButton(button) {
if (button.dataset.originalHtml) {
button.innerHTML = button.dataset.originalHtml;
}
button.disabled = false;
button.classList.remove('submitting');
}

View File

@ -45,7 +45,7 @@
} }
.form-control, .form-select { .form-control, .form-select {
/* text-align: center; */ text-align: center;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View File

@ -6,29 +6,54 @@
<title>Access Forbidden</title> <title>Access Forbidden</title>
<meta name="description" content="" /> <meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" /> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'assets/img/favicons/favicon-32x32.png' %}" /> sizes="180x180"
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'assets/img/favicons/favicon-16x16.png' %}" /> href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" />
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/img/favicons/favicon.ico' %}" /> <link rel="icon"
<link rel="manifest" href="{% static 'assets/img/favicons/manifest.json' %}" /> type="image/png"
<meta name="msapplication-TileImage" content="{% static 'assets/img/favicons/mstile-150x150.png' %}" /> sizes="32x32"
href="{% static 'assets/img/favicons/favicon-32x32.png' %}" />
<link rel="icon"
type="image/png"
sizes="16x16"
href="{% static 'assets/img/favicons/favicon-16x16.png' %}" />
<link rel="shortcut icon"
type="image/x-icon"
href="{% static 'assets/img/favicons/favicon.ico' %}" />
<link rel="manifest"
href="{% static 'assets/img/favicons/manifest.json' %}" />
<meta name="msapplication-TileImage"
content="{% static 'assets/img/favicons/mstile-150x150.png' %}" />
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
<script src="{% static 'assets/js/config.js' %}"></script> <script src="{% static 'assets/js/config.js' %}"></script>
<!-- =============================================== --> <!-- =============================================== -->
<!-- Stylesheets --> <!-- Stylesheets -->
<!-- =============================================== --> <!-- =============================================== -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet" /> rel="stylesheet" />
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" /> <link href="{% static 'vendors/simplebar/simplebar.min.css' %}"
<link href="{% static 'assets/css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl" /> rel="stylesheet" />
<link href="{% static 'assets/css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default" /> <link rel="stylesheet"
<link href="{% static 'assets/css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl" /> href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" />
<link href="{% static 'assets/css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default" /> <link href="{% static 'assets/css/theme-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-rtl" />
<link href="{% static 'assets/css/theme.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-default" />
<link href="{% static 'assets/css/user-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-rtl" />
<link href="{% static 'assets/css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default" />
<style> <style>
body, html { body, html {
height: 100%; height: 100%;
@ -53,7 +78,6 @@
} }
</style> </style>
</head> </head>
<body> <body>
<main class="main" id="top"> <main class="main" id="top">
<div class="px-3"> <div class="px-3">
@ -61,21 +85,28 @@
<div class="col-12 col-xl-10 col-xxl-8"> <div class="col-12 col-xl-10 col-xxl-8">
<div class="row justify-content-center align-items-center g-5"> <div class="row justify-content-center align-items-center g-5">
<div class="col-12 col-lg-6 text-center order-lg-1"> <div class="col-12 col-lg-6 text-center order-lg-1">
<img class="img-fluid w-md-50 w-lg-100 d-light-none" src="{% static 'images/spot-illustrations/dark_403-illustration.png' %}" alt="" width="540" /> <img class="img-fluid w-md-50 w-lg-100 d-light-none"
src="{% static 'images/spot-illustrations/dark_403-illustration.png' %}"
alt=""
width="540" />
</div> </div>
<div class="col-12 col-lg-6 text-center text-lg-start"> <div class="col-12 col-lg-6 text-center text-lg-start">
<img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none" src="{% static 'images/spot-illustrations/403.png' %}" alt="" /> <img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
src="{% static 'images/spot-illustrations/403.png' %}"
alt="" />
<h2 class="text-body-secondary fw-bolder mb-3">Access Forbidden!</h2> <h2 class="text-body-secondary fw-bolder mb-3">Access Forbidden!</h2>
<p class="text-body mb-5"> <p class="text-body mb-5">
Halt! Thou art endeavouring to trespass upon a realm not granted unto thee.<br class="d-none d-md-block d-lg-none" />granted unto thee. Halt! Thou art endeavouring to trespass upon a realm not granted unto thee.
</p><a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a> <br class="d-none d-md-block d-lg-none" />
granted unto thee.
</p>
<a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/phoenix.js' %}"></script> <script src="{% static 'js/phoenix.js' %}"></script>
<script src="{% static 'vendors/popper/popper.min.js' %}"></script> <script src="{% static 'vendors/popper/popper.min.js' %}"></script>

View File

@ -6,29 +6,54 @@
<title>Access Forbidden</title> <title>Access Forbidden</title>
<meta name="description" content="" /> <meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" /> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'assets/img/favicons/favicon-32x32.png' %}" /> sizes="180x180"
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'assets/img/favicons/favicon-16x16.png' %}" /> href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" />
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/img/favicons/favicon.ico' %}" /> <link rel="icon"
<link rel="manifest" href="{% static 'assets/img/favicons/manifest.json' %}" /> type="image/png"
<meta name="msapplication-TileImage" content="{% static 'assets/img/favicons/mstile-150x150.png' %}" /> sizes="32x32"
href="{% static 'assets/img/favicons/favicon-32x32.png' %}" />
<link rel="icon"
type="image/png"
sizes="16x16"
href="{% static 'assets/img/favicons/favicon-16x16.png' %}" />
<link rel="shortcut icon"
type="image/x-icon"
href="{% static 'assets/img/favicons/favicon.ico' %}" />
<link rel="manifest"
href="{% static 'assets/img/favicons/manifest.json' %}" />
<meta name="msapplication-TileImage"
content="{% static 'assets/img/favicons/mstile-150x150.png' %}" />
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
<script src="{% static 'assets/js/config.js' %}"></script> <script src="{% static 'assets/js/config.js' %}"></script>
<!-- =============================================== --> <!-- =============================================== -->
<!-- Stylesheets --> <!-- Stylesheets -->
<!-- =============================================== --> <!-- =============================================== -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet" /> rel="stylesheet" />
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" /> <link href="{% static 'vendors/simplebar/simplebar.min.css' %}"
<link href="{% static 'assets/css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl" /> rel="stylesheet" />
<link href="{% static 'assets/css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default" /> <link rel="stylesheet"
<link href="{% static 'assets/css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl" /> href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" />
<link href="{% static 'assets/css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default" /> <link href="{% static 'assets/css/theme-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-rtl" />
<link href="{% static 'assets/css/theme.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-default" />
<link href="{% static 'assets/css/user-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-rtl" />
<link href="{% static 'assets/css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default" />
<style> <style>
body, html { body, html {
height: 100%; height: 100%;
@ -53,7 +78,6 @@
} }
</style> </style>
</head> </head>
<body> <body>
<main class="main" id="top"> <main class="main" id="top">
<div class="px-3"> <div class="px-3">
@ -61,19 +85,28 @@
<div class="col-12 col-xl-10 col-xxl-8"> <div class="col-12 col-xl-10 col-xxl-8">
<div class="row justify-content-center align-items-center g-5"> <div class="row justify-content-center align-items-center g-5">
<div class="col-12 col-lg-6 text-center order-lg-1"> <div class="col-12 col-lg-6 text-center order-lg-1">
<img class="img-fluid w-md-50 w-lg-100 d-light-none" src="{% static 'images/spot-illustrations/dark_500-illustration.png' %}" alt="" width="540" /> <img class="img-fluid w-md-50 w-lg-100 d-light-none"
src="{% static 'images/spot-illustrations/dark_500-illustration.png' %}"
alt=""
width="540" />
</div> </div>
<div class="col-12 col-lg-6 text-center text-lg-start"> <div class="col-12 col-lg-6 text-center text-lg-start">
<img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none" src="{% static 'images/spot-illustrations/500.png' %}" alt="" /> <img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
src="{% static 'images/spot-illustrations/500.png' %}"
alt="" />
<h2 class="text-body-secondary fw-bolder mb-3">Page Missing!</h2> <h2 class="text-body-secondary fw-bolder mb-3">Page Missing!</h2>
<p class="text-body mb-5">But no worries! Our ostrich is looking everywhere <br class="d-none d-sm-block" />while you wait safely. </p><a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a> <p class="text-body mb-5">
But no worries! Our ostrich is looking everywhere
<br class="d-none d-sm-block" />
while you wait safely.
</p>
<a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/phoenix.js' %}"></script> <script src="{% static 'js/phoenix.js' %}"></script>
<script src="{% static 'vendors/popper/popper.min.js' %}"></script> <script src="{% static 'vendors/popper/popper.min.js' %}"></script>

View File

@ -6,29 +6,54 @@
<title>Access Forbidden</title> <title>Access Forbidden</title>
<meta name="description" content="" /> <meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" /> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'assets/img/favicons/favicon-32x32.png' %}" /> sizes="180x180"
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'assets/img/favicons/favicon-16x16.png' %}" /> href="{% static 'assets/img/favicons/apple-touch-icon.png' %}" />
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/img/favicons/favicon.ico' %}" /> <link rel="icon"
<link rel="manifest" href="{% static 'assets/img/favicons/manifest.json' %}" /> type="image/png"
<meta name="msapplication-TileImage" content="{% static 'assets/img/favicons/mstile-150x150.png' %}" /> sizes="32x32"
href="{% static 'assets/img/favicons/favicon-32x32.png' %}" />
<link rel="icon"
type="image/png"
sizes="16x16"
href="{% static 'assets/img/favicons/favicon-16x16.png' %}" />
<link rel="shortcut icon"
type="image/x-icon"
href="{% static 'assets/img/favicons/favicon.ico' %}" />
<link rel="manifest"
href="{% static 'assets/img/favicons/manifest.json' %}" />
<meta name="msapplication-TileImage"
content="{% static 'assets/img/favicons/mstile-150x150.png' %}" />
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
<script src="{% static 'assets/js/config.js' %}"></script> <script src="{% static 'assets/js/config.js' %}"></script>
<!-- =============================================== --> <!-- =============================================== -->
<!-- Stylesheets --> <!-- Stylesheets -->
<!-- =============================================== --> <!-- =============================================== -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet" /> rel="stylesheet" />
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" /> <link href="{% static 'vendors/simplebar/simplebar.min.css' %}"
<link href="{% static 'assets/css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl" /> rel="stylesheet" />
<link href="{% static 'assets/css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default" /> <link rel="stylesheet"
<link href="{% static 'assets/css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl" /> href="https://unicons.iconscout.com/release/v4.0.8/css/line.css" />
<link href="{% static 'assets/css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default" /> <link href="{% static 'assets/css/theme-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-rtl" />
<link href="{% static 'assets/css/theme.min.css' %}"
type="text/css"
rel="stylesheet"
id="style-default" />
<link href="{% static 'assets/css/user-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-rtl" />
<link href="{% static 'assets/css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default" />
<style> <style>
body, html { body, html {
height: 100%; height: 100%;
@ -53,7 +78,6 @@
} }
</style> </style>
</head> </head>
<body> <body>
<main class="main" id="top"> <main class="main" id="top">
<div class="px-3"> <div class="px-3">
@ -61,19 +85,24 @@
<div class="col-12 col-xl-10 col-xxl-8"> <div class="col-12 col-xl-10 col-xxl-8">
<div class="row justify-content-center align-items-center g-5"> <div class="row justify-content-center align-items-center g-5">
<div class="col-12 col-lg-6 text-center order-lg-1"> <div class="col-12 col-lg-6 text-center order-lg-1">
<img class="img-fluid w-md-50 w-lg-100 d-light-none" src="{% static 'images/spot-illustrations/dark_404-illustration.png' %}" alt="" width="540" /> <img class="img-fluid w-md-50 w-lg-100 d-light-none"
src="{% static 'images/spot-illustrations/dark_404-illustration.png' %}"
alt=""
width="540" />
</div> </div>
<div class="col-12 col-lg-6 text-center text-lg-start"> <div class="col-12 col-lg-6 text-center text-lg-start">
<img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none" src="{% static 'images/spot-illustrations/404.png' %}" alt="" /> <img class="img-fluid mb-6 w-50 w-lg-75 d-dark-none"
src="{% static 'images/spot-illustrations/404.png' %}"
alt="" />
<h2 class="text-body-secondary fw-bolder mb-3">Unknow error!</h2> <h2 class="text-body-secondary fw-bolder mb-3">Unknow error!</h2>
<p class="text-body mb-5">But relax! Our cat is here to play you some music.</p><a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a> <p class="text-body mb-5">But relax! Our cat is here to play you some music.</p>
<a class="btn btn-lg btn-phoenix-primary" href="{% url 'home' %}">Go Home</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</main> </main>
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
<script src="{% static 'js/phoenix.js' %}"></script> <script src="{% static 'js/phoenix.js' %}"></script>
<script src="{% static 'vendors/popper/popper.min.js' %}"></script> <script src="{% static 'vendors/popper/popper.min.js' %}"></script>

View File

@ -1,6 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% load i18n %} {% load i18n %}
{% load allauth account %} {% load allauth account %}
{% block head_title %} {% block head_title %}
@ -10,25 +9,34 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% translate "Enter Sign-In Code" %}</h3> <h3 class="mb-4">{% translate "Enter Sign-In Code" %}</h3>
</div> </div>
{% setvar email_link %} {% setvar email_link %}
<a href="mailto:{{ email }}">{{ email }}</a> <a href="mailto:{{ email }}">{{ email }}</a>
{% endsetvar %} {% endsetvar %}
<p> <p>
{% blocktranslate %}Weve sent a code to {{ email_link }}. The code expires shortly, so please enter it soon.{% endblocktranslate %} {% blocktranslate %}Weve sent a code to {{ email_link }}. The code expires shortly, so please enter it soon.{% endblocktranslate %}
</p> </p>
<form method="post" action="{% url 'account_confirm_login_code' %}" class="form needs-validation" novalidate> <form method="post"
action="{% url 'account_confirm_login_code' %}"
class="form needs-validation"
novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}

View File

@ -8,22 +8,26 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Email Addresses" %}</h3> <h3 class="mb-4">{% trans "Email Addresses" %}</h3>
</div> </div>
{% if emailaddresses %} {% if emailaddresses %}
<p> <p>{% trans 'The following email addresses are associated with your account:' %}</p>
{% trans 'The following email addresses are associated with your account:' %}
</p>
{% url 'account_email' as email_url %} {% url 'account_email' as email_url %}
<form action="{{ email_url }}" method="POST" class="form email list"> <form action="{{ email_url }}" method="POST" class="form email list">
{% csrf_token %} {% csrf_token %}
@ -31,7 +35,12 @@
{% for radio in emailaddress_radios %} {% for radio in emailaddress_radios %}
{% with emailaddress=radio.emailaddress %} {% with emailaddress=radio.emailaddress %}
<label for="{{ radio.id }}"> <label for="{{ radio.id }}">
<input type="radio" name="email" checked="{{ radio.checked }}" value="{{ emailaddress.email }}" id="{{ radio.id }}" class="form-check-input mb-3" /> <input type="radio"
name="email"
checked="{{ radio.checked }}"
value="{{ emailaddress.email }}"
id="{{ radio.id }}"
class="form-check-input mb-3" />
{{ emailaddress.email }} {{ emailaddress.email }}
{% if emailaddress.verified %} {% if emailaddress.verified %}
<span class="badge badge-phoenix badge-phoenix-success verified">{% translate "Verified" %}</span> <span class="badge badge-phoenix badge-phoenix-success verified">{% translate "Verified" %}</span>
@ -46,31 +55,33 @@
{% endfor %} {% endfor %}
</div> </div>
<div class="mt-2 mb-6"> <div class="mt-2 mb-6">
<button type="submit" name="action_primary" class="btn btn-sm btn-phoenix-primary">{% trans 'Make Primary' %}</button> <button type="submit"
<button type="submit" name="action_send" class="btn btn-sm btn-phoenix-secondary">{% trans 'Re-send Verification' %}</button> name="action_primary"
<button type="submit" name="action_remove" class="btn btn-sm btn-phoenix-danger delete">{% trans 'Remove' %}</button> class="btn btn-sm btn-phoenix-primary">{% trans 'Make Primary' %}</button>
<button type="submit"
name="action_send"
class="btn btn-sm btn-phoenix-secondary">
{% trans 'Re-send Verification' %}
</button>
<button type="submit"
name="action_remove"
class="btn btn-sm btn-phoenix-danger delete">{% trans 'Remove' %}</button>
</div> </div>
</form> </form>
{% else %} {% else %}
{% include "account/snippets/warn_no_email.html" %} {% include "account/snippets/warn_no_email.html" %}
{% endif %} {% endif %}
{% if can_add_email %} {% if can_add_email %}
<p class="fs-8 fw-bold text-start"> <p class="fs-8 fw-bold text-start">{% trans "Add Email Address" %}</p>
{% trans "Add Email Address" %}
</p>
{% url 'account_email' as action_url %} {% url 'account_email' as action_url %}
<form action="{{ action_url }}" method="POST" class="form email add"> <form action="{{ action_url }}" method="POST" class="form email add">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button class="btn btn-sm btn-phoenix-success w-100" type="submit" name="action_add"> <button class="btn btn-sm btn-phoenix-success w-100"
{% trans "Add Email" %} type="submit"
</button> name="action_add">{% trans "Add Email" %}</button>
</form> </form>
{% endif %} {% endif %}
<script> <script>
(function() { (function() {
var message = "{% trans 'Do you really want to remove the selected email address?' %}"; var message = "{% trans 'Do you really want to remove the selected email address?' %}";

View File

@ -9,18 +9,24 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Confirm Email Address" %}</h3> <h3 class="mb-4">{% trans "Confirm Email Address" %}</h3>
</div> </div>
{% if confirmation %} {% if confirmation %}
{% user_display confirmation.email_address.user as user_display %} {% user_display confirmation.email_address.user as user_display %}
{% if can_confirm %} {% if can_confirm %}
@ -31,11 +37,8 @@
<form class="form" action="{{ action_url }}" method="post"> <form class="form" action="{{ action_url }}" method="post">
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
<button class="btn btn-sm btn-phoenix-primary" type="submit"> <button class="btn btn-sm btn-phoenix-primary" type="submit">{% trans 'Confirm' %}</button>
{% trans 'Confirm' %}
</button>
</form> </form>
{% else %} {% else %}
<p> <p>
{% blocktrans %}Unable to confirm {{ email }} because it is already confirmed by a different account.{% endblocktrans %} {% blocktrans %}Unable to confirm {{ email }} because it is already confirmed by a different account.{% endblocktrans %}

View File

@ -1,44 +1,65 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en-US" dir="ltr" data-navigation-type="default" data-navbar-horizontal-shape="default"> <html lang="en-US"
dir="ltr"
data-navigation-type="default"
data-navbar-horizontal-shape="default">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- ===============================================--> <!-- ===============================================-->
<!-- Document Title--> <!-- Document Title-->
<!-- ===============================================--> <!-- ===============================================-->
<title>Phoenix</title> <title>Phoenix</title>
<!-- ===============================================--> <!-- ===============================================-->
<!-- Favicons--> <!-- Favicons-->
<!-- ===============================================--> <!-- ===============================================-->
<link rel="apple-touch-icon" sizes="180x180" href="../../../assets/img/favicons/apple-touch-icon.png"> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="32x32" href="../../../assets/img/favicons/favicon-32x32.png"> sizes="180x180"
<link rel="icon" type="image/png" sizes="16x16" href="../../../assets/img/favicons/favicon-16x16.png"> href="../../../assets/img/favicons/apple-touch-icon.png">
<link rel="shortcut icon" type="image/x-icon" href="../../../assets/img/favicons/favicon.ico"> <link rel="icon"
type="image/png"
sizes="32x32"
href="../../../assets/img/favicons/favicon-32x32.png">
<link rel="icon"
type="image/png"
sizes="16x16"
href="../../../assets/img/favicons/favicon-16x16.png">
<link rel="shortcut icon"
type="image/x-icon"
href="../../../assets/img/favicons/favicon.ico">
<link rel="manifest" href="../../../assets/img/favicons/manifest.json"> <link rel="manifest" href="../../../assets/img/favicons/manifest.json">
<meta name="msapplication-TileImage" content="../../../assets/img/favicons/mstile-150x150.png"> <meta name="msapplication-TileImage"
content="../../../assets/img/favicons/mstile-150x150.png">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<script src="../../../vendors/simplebar/simplebar.min.js"></script> <script src="../../../vendors/simplebar/simplebar.min.js"></script>
<script src="../../../assets/js/config.js"></script> <script src="../../../assets/js/config.js"></script>
<!-- ===============================================--> <!-- ===============================================-->
<!-- Stylesheets--> <!-- Stylesheets-->
<!-- ===============================================--> <!-- ===============================================-->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
rel="stylesheet">
<link href="../../../vendors/simplebar/simplebar.min.css" rel="stylesheet"> <link href="../../../vendors/simplebar/simplebar.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> <link rel="stylesheet"
<link href="../../../assets/css/theme-rtl.min.css" type="text/css" rel="stylesheet" id="style-rtl"> href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
<link href="../../../assets/css/theme.min.css" type="text/css" rel="stylesheet" id="style-default"> <link href="../../../assets/css/theme-rtl.min.css"
<link href="../../../assets/css/user-rtl.min.css" type="text/css" rel="stylesheet" id="user-style-rtl"> type="text/css"
<link href="../../../assets/css/user.min.css" type="text/css" rel="stylesheet" id="user-style-default"> rel="stylesheet"
id="style-rtl">
<link href="../../../assets/css/theme.min.css"
type="text/css"
rel="stylesheet"
id="style-default">
<link href="../../../assets/css/user-rtl.min.css"
type="text/css"
rel="stylesheet"
id="user-style-rtl">
<link href="../../../assets/css/user.min.css"
type="text/css"
rel="stylesheet"
id="user-style-default">
<script> <script>
var phoenixIsRTL = window.config.config.phoenixIsRTL; var phoenixIsRTL = window.config.config.phoenixIsRTL;
if (phoenixIsRTL) { if (phoenixIsRTL) {
@ -55,10 +76,7 @@
} }
</script> </script>
</head> </head>
<body> <body>
<!-- ===============================================--> <!-- ===============================================-->
<!-- Main Content--> <!-- Main Content-->
<!-- ===============================================--> <!-- ===============================================-->
@ -67,14 +85,26 @@
<div class="row flex-center min-vh-100 py-5"> <div class="row flex-center min-vh-100 py-5">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<div class="text-center mb-5"> <div class="text-center mb-5">
<div class="avatar avatar-4xl mb-4"><img class="rounded-circle" src="../../../assets/img/team/30.webp" alt="" /></div> <div class="avatar avatar-4xl mb-4">
<h2 class="text-body-highlight"> <span class="fw-normal">Hello </span>John Smith</h2> <img class="rounded-circle" src="../../../assets/img/team/30.webp" alt="" />
</div>
<h2 class="text-body-highlight">
<span class="fw-normal">Hello</span>John Smith
</h2>
<p class="text-body-tertiary">Enter your password to access the admin</p> <p class="text-body-tertiary">Enter your password to access the admin</p>
</div> </div>
<div class="position-relative" data-password="data-password"> <div class="position-relative" data-password="data-password">
<input class="form-control mb-3" id="password" type="password" placeholder="Enter Password" data-password-input="data-password-input" /> <input class="form-control mb-3"
<button class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary" data-password-toggle="data-password-toggle"><span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span></button> id="password"
</div><a class="btn btn-phoenix-primary w-100" href="../../../index.html">Sign In</a> type="password"
placeholder="Enter Password"
data-password-input="data-password-input" />
<button class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary"
data-password-toggle="data-password-toggle">
<span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span>
</button>
</div>
<a class="btn btn-phoenix-primary w-100" href="../../../index.html">Sign In</a>
</div> </div>
</div> </div>
</div> </div>
@ -95,77 +125,164 @@
<div class="row-fluid support-chat"> <div class="row-fluid support-chat">
<div class="card bg-body-emphasis"> <div class="card bg-body-emphasis">
<div class="card-header d-flex flex-between-center px-4 py-3 border-bottom border-translucent"> <div class="card-header d-flex flex-between-center px-4 py-3 border-bottom border-translucent">
<h5 class="mb-0 d-flex align-items-center gap-2">Demo widget<span class="fa-solid fa-circle text-success fs-11"></span></h5> <h5 class="mb-0 d-flex align-items-center gap-2">
Demo widget<span class="fa-solid fa-circle text-success fs-11"></span>
</h5>
<div class="btn-reveal-trigger"> <div class="btn-reveal-trigger">
<button class="btn btn-link p-0 dropdown-toggle dropdown-caret-none transition-none d-flex" type="button" id="support-chat-dropdown" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h text-body"></span></button> <button class="btn btn-link p-0 dropdown-toggle dropdown-caret-none transition-none d-flex"
<div class="dropdown-menu dropdown-menu-end py-2" aria-labelledby="support-chat-dropdown"><a class="dropdown-item" href="#!">Request a callback</a><a class="dropdown-item" href="#!">Search in chat</a><a class="dropdown-item" href="#!">Show history</a><a class="dropdown-item" href="#!">Report to Admin</a><a class="dropdown-item btn-support-chat" href="#!">Close Support</a></div> type="button"
id="support-chat-dropdown"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h text-body"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2"
aria-labelledby="support-chat-dropdown">
<a class="dropdown-item" href="#!">Request a callback</a><a class="dropdown-item" href="#!">Search in chat</a><a class="dropdown-item" href="#!">Show history</a><a class="dropdown-item" href="#!">Report to Admin</a><a class="dropdown-item btn-support-chat" href="#!">Close Support</a>
</div>
</div> </div>
</div> </div>
<div class="card-body chat p-0"> <div class="card-body chat p-0">
<div class="d-flex flex-column-reverse scrollbar h-100 p-3"> <div class="d-flex flex-column-reverse scrollbar h-100 p-3">
<div class="text-end mt-6"><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> <div class="text-end mt-6">
<p class="mb-0 fw-semibold fs-9">I need help with something</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> href="#!">
<p class="mb-0 fw-semibold fs-9">I cant reorder a product I previously ordered</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <p class="mb-0 fw-semibold fs-9">I need help with something</p>
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> <span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
<p class="mb-0 fw-semibold fs-9">How do I place an order?</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> </a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
</a><a class="false d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> href="#!">
<p class="mb-0 fw-semibold fs-9">My payment method not working</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <p class="mb-0 fw-semibold fs-9">I cant reorder a product I previously ordered</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
href="#!">
<p class="mb-0 fw-semibold fs-9">How do I place an order?</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a><a class="false d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
href="#!">
<p class="mb-0 fw-semibold fs-9">My payment method not working</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a> </a>
</div> </div>
<div class="text-center mt-auto"> <div class="text-center mt-auto">
<div class="avatar avatar-3xl status-online"><img class="rounded-circle border border-3 border-light-subtle" src="../../../assets/img/team/30.webp" alt="" /></div> <div class="avatar avatar-3xl status-online">
<img class="rounded-circle border border-3 border-light-subtle"
src="../../../assets/img/team/30.webp"
alt="" />
</div>
<h5 class="mt-2 mb-3">Eric</h5> <h5 class="mt-2 mb-3">Eric</h5>
<p class="text-center text-body-emphasis mb-0">Ask us anything well get back to you here or by email within 24 hours.</p> <p class="text-center text-body-emphasis mb-0">
Ask us anything well get back to you here or by email within 24 hours.
</p>
</div> </div>
</div> </div>
</div> </div>
<div class="card-footer d-flex align-items-center gap-2 border-top border-translucent ps-3 pe-4 py-3"> <div class="card-footer d-flex align-items-center gap-2 border-top border-translucent ps-3 pe-4 py-3">
<div class="d-flex align-items-center flex-1 gap-3 border border-translucent rounded-pill px-4"> <div class="d-flex align-items-center flex-1 gap-3 border border-translucent rounded-pill px-4">
<input class="form-control outline-none border-0 flex-1 fs-9 px-0" type="text" placeholder="Write message" /> <input class="form-control outline-none border-0 flex-1 fs-9 px-0"
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0" for="supportChatPhotos"><span class="fa-solid fa-image"></span></label> type="text"
placeholder="Write message" />
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0"
for="supportChatPhotos">
<span class="fa-solid fa-image"></span>
</label>
<input class="d-none" type="file" accept="image/*" id="supportChatPhotos" /> <input class="d-none" type="file" accept="image/*" id="supportChatPhotos" />
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0" for="supportChatAttachment"> <span class="fa-solid fa-paperclip"></span></label> <label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0"
for="supportChatAttachment">
<span class="fa-solid fa-paperclip"></span>
</label>
<input class="d-none" type="file" id="supportChatAttachment" /> <input class="d-none" type="file" id="supportChatAttachment" />
</div> </div>
<button class="btn p-0 border-0 send-btn"><span class="fa-solid fa-paper-plane fs-9"></span></button> <button class="btn p-0 border-0 send-btn">
<span class="fa-solid fa-paper-plane fs-9"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
<button class="btn btn-support-chat p-0 border border-translucent"><span class="fs-8 btn-text text-primary text-nowrap">Chat demo</span><span class="ping-icon-wrapper mt-n4 ms-n6 mt-sm-0 ms-sm-2 position-absolute position-sm-relative"><span class="ping-icon-bg"></span><span class="fa-solid fa-circle ping-icon"></span></span><span class="fa-solid fa-headset text-primary fs-8 d-sm-none"></span><span class="fa-solid fa-chevron-down text-primary fs-7"></span></button> <button class="btn btn-support-chat p-0 border border-translucent">
<span class="fs-8 btn-text text-primary text-nowrap">Chat demo</span><span class="ping-icon-wrapper mt-n4 ms-n6 mt-sm-0 ms-sm-2 position-absolute position-sm-relative"><span class="ping-icon-bg"></span><span class="fa-solid fa-circle ping-icon"></span></span><span class="fa-solid fa-headset text-primary fs-8 d-sm-none"></span><span class="fa-solid fa-chevron-down text-primary fs-7"></span>
</button>
</div> </div>
</main> </main>
<!-- ===============================================--> <!-- ===============================================-->
<!-- End of Main Content--> <!-- End of Main Content-->
<!-- ===============================================--> <!-- ===============================================-->
<div class="offcanvas offcanvas-end settings-panel border-0"
id="settings-offcanvas"
<div class="offcanvas offcanvas-end settings-panel border-0" id="settings-offcanvas" tabindex="-1" aria-labelledby="settings-offcanvas"> tabindex="-1"
aria-labelledby="settings-offcanvas">
<div class="offcanvas-header align-items-start border-bottom flex-column border-translucent"> <div class="offcanvas-header align-items-start border-bottom flex-column border-translucent">
<div class="pt-1 w-100 mb-6 d-flex justify-content-between align-items-start"> <div class="pt-1 w-100 mb-6 d-flex justify-content-between align-items-start">
<div> <div>
<h5 class="mb-2 me-2 lh-sm"><span class="fas fa-palette me-2 fs-8"></span>Theme Customizer</h5> <h5 class="mb-2 me-2 lh-sm">
<span class="fas fa-palette me-2 fs-8"></span>Theme Customizer
</h5>
<p class="mb-0 fs-9">Explore different styles according to your preferences</p> <p class="mb-0 fs-9">Explore different styles according to your preferences</p>
</div> </div>
<button class="btn p-1 fw-bolder" type="button" data-bs-dismiss="offcanvas" aria-label="Close"><span class="fas fa-times fs-8"> </span></button> <button class="btn p-1 fw-bolder"
type="button"
data-bs-dismiss="offcanvas"
aria-label="Close">
<span class="fas fa-times fs-8"></span>
</button>
</div> </div>
<button class="btn btn-phoenix-secondary w-100" data-theme-control="reset"><span class="fas fa-arrows-rotate me-2 fs-10"></span>Reset to default</button> <button class="btn btn-phoenix-secondary w-100" data-theme-control="reset">
<span class="fas fa-arrows-rotate me-2 fs-10"></span>Reset to default
</button>
</div> </div>
<div class="offcanvas-body scrollbar px-card" id="themeController"> <div class="offcanvas-body scrollbar px-card" id="themeController">
<div class="setting-panel-item mt-0"> <div class="setting-panel-item mt-0">
<h5 class="setting-panel-item-title">Color Scheme</h5> <h5 class="setting-panel-item-title">Color Scheme</h5>
<div class="row gx-2"> <div class="row gx-2">
<div class="col-4"> <div class="col-4">
<input class="btn-check" id="themeSwitcherLight" name="theme-color" type="radio" value="light" data-theme-control="phoenixTheme" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="themeSwitcherLight"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype mb-0" src="../../../assets/img/generic/default-light.png" alt=""/></span><span class="label-text">Light</span></label> id="themeSwitcherLight"
name="theme-color"
type="radio"
value="light"
data-theme-control="phoenixTheme" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="themeSwitcherLight">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype mb-0"
src="../../../assets/img/generic/default-light.png"
alt="" />
</span><span class="label-text">Light</span>
</label>
</div> </div>
<div class="col-4"> <div class="col-4">
<input class="btn-check" id="themeSwitcherDark" name="theme-color" type="radio" value="dark" data-theme-control="phoenixTheme" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="themeSwitcherDark"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype mb-0" src="../../../assets/img/generic/default-dark.png" alt=""/></span><span class="label-text"> Dark</span></label> id="themeSwitcherDark"
name="theme-color"
type="radio"
value="dark"
data-theme-control="phoenixTheme" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="themeSwitcherDark">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype mb-0"
src="../../../assets/img/generic/default-dark.png"
alt="" />
</span><span class="label-text">Dark</span>
</label>
</div> </div>
<div class="col-4"> <div class="col-4">
<input class="btn-check" id="themeSwitcherAuto" name="theme-color" type="radio" value="auto" data-theme-control="phoenixTheme" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="themeSwitcherAuto"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype mb-0" src="../../../assets/img/generic/auto.png" alt=""/></span><span class="label-text"> Auto</span></label> id="themeSwitcherAuto"
name="theme-color"
type="radio"
value="auto"
data-theme-control="phoenixTheme" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="themeSwitcherAuto">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype mb-0"
src="../../../assets/img/generic/auto.png"
alt="" />
</span><span class="label-text">Auto</span>
</label>
</div> </div>
</div> </div>
</div> </div>
@ -173,7 +290,9 @@
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h5 class="setting-panel-item-title mb-1">RTL</h5> <h5 class="setting-panel-item-title mb-1">RTL</h5>
<div class="form-check form-switch mb-0"> <div class="form-check form-switch mb-0">
<input class="form-check-input ms-auto" type="checkbox" data-theme-control="phoenixIsRTL" /> <input class="form-check-input ms-auto"
type="checkbox"
data-theme-control="phoenixIsRTL" />
</div> </div>
</div> </div>
<p class="mb-0 text-body-tertiary">Change text direction</p> <p class="mb-0 text-body-tertiary">Change text direction</p>
@ -182,7 +301,9 @@
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h5 class="setting-panel-item-title mb-1">Support Chat</h5> <h5 class="setting-panel-item-title mb-1">Support Chat</h5>
<div class="form-check form-switch mb-0"> <div class="form-check form-switch mb-0">
<input class="form-check-input ms-auto" type="checkbox" data-theme-control="phoenixSupportChat" /> <input class="form-check-input ms-auto"
type="checkbox"
data-theme-control="phoenixSupportChat" />
</div> </div>
</div> </div>
<p class="mb-0 text-body-tertiary">Toggle support chat</p> <p class="mb-0 text-body-tertiary">Toggle support chat</p>
@ -191,79 +312,266 @@
<h5 class="setting-panel-item-title">Navigation Type</h5> <h5 class="setting-panel-item-title">Navigation Type</h5>
<div class="row gx-2"> <div class="row gx-2">
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarPositionVertical" name="navigation-type" type="radio" value="vertical" data-theme-control="phoenixNavbarPosition" data-page-url="../../../documentation/layouts/vertical-navbar.html" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarPositionVertical"> <span class="rounded d-block"><img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/default-light.png" alt=""/><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/default-dark.png" alt=""/></span><span class="label-text">Vertical</span></label> id="navbarPositionVertical"
name="navigation-type"
type="radio"
value="vertical"
data-theme-control="phoenixNavbarPosition"
data-page-url="../../../documentation/layouts/vertical-navbar.html"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarPositionVertical">
<span class="rounded d-block">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/default-light.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/default-dark.png"
alt="" />
</span><span class="label-text">Vertical</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarPositionHorizontal" name="navigation-type" type="radio" value="horizontal" data-theme-control="phoenixNavbarPosition" data-page-url="../../../documentation/layouts/horizontal-navbar.html" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarPositionHorizontal"> <span class="rounded d-block"><img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/top-default.png" alt=""/><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/top-default-dark.png" alt=""/></span><span class="label-text"> Horizontal</span></label> id="navbarPositionHorizontal"
name="navigation-type"
type="radio"
value="horizontal"
data-theme-control="phoenixNavbarPosition"
data-page-url="../../../documentation/layouts/horizontal-navbar.html"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarPositionHorizontal">
<span class="rounded d-block">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/top-default.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/top-default-dark.png"
alt="" />
</span><span class="label-text">Horizontal</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarPositionCombo" name="navigation-type" type="radio" value="combo" data-theme-control="phoenixNavbarPosition" disabled="disabled" data-page-url="../../../documentation/layouts/combo-navbar.html" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarPositionCombo"> <span class="rounded d-block"><img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/nav-combo-light.png" alt=""/><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/nav-combo-dark.png" alt=""/></span><span class="label-text"> Combo</span></label> id="navbarPositionCombo"
name="navigation-type"
type="radio"
value="combo"
data-theme-control="phoenixNavbarPosition"
disabled="disabled"
data-page-url="../../../documentation/layouts/combo-navbar.html" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarPositionCombo">
<span class="rounded d-block">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/nav-combo-light.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/nav-combo-dark.png"
alt="" />
</span><span class="label-text">Combo</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarPositionTopDouble" name="navigation-type" type="radio" value="dual-nav" data-theme-control="phoenixNavbarPosition" disabled="disabled" data-page-url="../../../documentation/layouts/dual-nav.html" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarPositionTopDouble"> <span class="rounded d-block"><img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/dual-light.png" alt=""/><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/dual-dark.png" alt=""/></span><span class="label-text"> Dual nav</span></label> id="navbarPositionTopDouble"
name="navigation-type"
type="radio"
value="dual-nav"
data-theme-control="phoenixNavbarPosition"
disabled="disabled"
data-page-url="../../../documentation/layouts/dual-nav.html" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarPositionTopDouble">
<span class="rounded d-block">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/dual-light.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/dual-dark.png"
alt="" />
</span><span class="label-text">Dual nav</span>
</label>
</div> </div>
</div> </div>
<p class="text-warning-dark font-medium"> <span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update navigation type in this page</p> <p class="text-warning-dark font-medium">
<span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update navigation type in this page
</p>
</div> </div>
<div class="setting-panel-item"> <div class="setting-panel-item">
<h5 class="setting-panel-item-title">Vertical Navbar Appearance</h5> <h5 class="setting-panel-item-title">Vertical Navbar Appearance</h5>
<div class="row gx-2"> <div class="row gx-2">
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbar-style-default" type="radio" name="config.name" value="default" data-theme-control="phoenixNavbarVerticalStyle" disabled="disabled" /> <input class="btn-check"
<label class="btn d-block w-100 btn-navbar-style fs-9" for="navbar-style-default"> <img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/default-light.png" alt="" /><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/default-dark.png" alt="" /><span class="label-text d-dark-none"> Default</span><span class="label-text d-light-none">Default</span></label> id="navbar-style-default"
type="radio"
name="config.name"
value="default"
data-theme-control="phoenixNavbarVerticalStyle"
disabled="disabled" />
<label class="btn d-block w-100 btn-navbar-style fs-9"
for="navbar-style-default">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/default-light.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/default-dark.png"
alt="" />
<span class="label-text d-dark-none">Default</span><span class="label-text d-light-none">Default</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbar-style-dark" type="radio" name="config.name" value="darker" data-theme-control="phoenixNavbarVerticalStyle" disabled="disabled" /> <input class="btn-check"
<label class="btn d-block w-100 btn-navbar-style fs-9" for="navbar-style-dark"> <img class="img-fluid img-prototype d-dark-none" src="../../../assets/img/generic/vertical-darker.png" alt="" /><img class="img-fluid img-prototype d-light-none" src="../../../assets/img/generic/vertical-lighter.png" alt="" /><span class="label-text d-dark-none"> Darker</span><span class="label-text d-light-none">Lighter</span></label> id="navbar-style-dark"
type="radio"
name="config.name"
value="darker"
data-theme-control="phoenixNavbarVerticalStyle"
disabled="disabled" />
<label class="btn d-block w-100 btn-navbar-style fs-9"
for="navbar-style-dark">
<img class="img-fluid img-prototype d-dark-none"
src="../../../assets/img/generic/vertical-darker.png"
alt="" />
<img class="img-fluid img-prototype d-light-none"
src="../../../assets/img/generic/vertical-lighter.png"
alt="" />
<span class="label-text d-dark-none">Darker</span><span class="label-text d-light-none">Lighter</span>
</label>
</div> </div>
</div> </div>
<p class="text-warning-dark font-medium"> <span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update vertical navbar appearance in this page</p> <p class="text-warning-dark font-medium">
<span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update vertical navbar appearance in this page
</p>
</div> </div>
<div class="setting-panel-item"> <div class="setting-panel-item">
<h5 class="setting-panel-item-title">Horizontal Navbar Shape</h5> <h5 class="setting-panel-item-title">Horizontal Navbar Shape</h5>
<div class="row gx-2"> <div class="row gx-2">
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarShapeDefault" name="navbar-shape" type="radio" value="default" data-theme-control="phoenixNavbarTopShape" data-page-url="../../../documentation/layouts/horizontal-navbar.html" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarShapeDefault"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype d-dark-none mb-0" src="../../../assets/img/generic/top-default.png" alt=""/><img class="img-fluid img-prototype d-light-none mb-0" src="../../../assets/img/generic/top-default-dark.png" alt=""/></span><span class="label-text">Default</span></label> id="navbarShapeDefault"
name="navbar-shape"
type="radio"
value="default"
data-theme-control="phoenixNavbarTopShape"
data-page-url="../../../documentation/layouts/horizontal-navbar.html"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarShapeDefault">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype d-dark-none mb-0"
src="../../../assets/img/generic/top-default.png"
alt="" />
<img class="img-fluid img-prototype d-light-none mb-0"
src="../../../assets/img/generic/top-default-dark.png"
alt="" />
</span><span class="label-text">Default</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarShapeSlim" name="navbar-shape" type="radio" value="slim" data-theme-control="phoenixNavbarTopShape" data-page-url="../../../documentation/layouts/horizontal-navbar.html#horizontal-navbar-slim" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarShapeSlim"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype d-dark-none mb-0" src="../../../assets/img/generic/top-slim.png" alt=""/><img class="img-fluid img-prototype d-light-none mb-0" src="../../../assets/img/generic/top-slim-dark.png" alt=""/></span><span class="label-text"> Slim</span></label> id="navbarShapeSlim"
name="navbar-shape"
type="radio"
value="slim"
data-theme-control="phoenixNavbarTopShape"
data-page-url="../../../documentation/layouts/horizontal-navbar.html#horizontal-navbar-slim"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarShapeSlim">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype d-dark-none mb-0"
src="../../../assets/img/generic/top-slim.png"
alt="" />
<img class="img-fluid img-prototype d-light-none mb-0"
src="../../../assets/img/generic/top-slim-dark.png"
alt="" />
</span><span class="label-text">Slim</span>
</label>
</div> </div>
</div> </div>
<p class="text-warning-dark font-medium"> <span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update horizontal navbar shape in this page</p> <p class="text-warning-dark font-medium">
<span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update horizontal navbar shape in this page
</p>
</div> </div>
<div class="setting-panel-item"> <div class="setting-panel-item">
<h5 class="setting-panel-item-title">Horizontal Navbar Appearance</h5> <h5 class="setting-panel-item-title">Horizontal Navbar Appearance</h5>
<div class="row gx-2"> <div class="row gx-2">
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarTopDefault" name="navbar-top-style" type="radio" value="default" data-theme-control="phoenixNavbarTopStyle" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarTopDefault"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype d-dark-none mb-0" src="../../../assets/img/generic/top-default.png" alt=""/><img class="img-fluid img-prototype d-light-none mb-0" src="../../../assets/img/generic/top-style-darker.png" alt=""/></span><span class="label-text">Default</span></label> id="navbarTopDefault"
name="navbar-top-style"
type="radio"
value="default"
data-theme-control="phoenixNavbarTopStyle"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarTopDefault">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype d-dark-none mb-0"
src="../../../assets/img/generic/top-default.png"
alt="" />
<img class="img-fluid img-prototype d-light-none mb-0"
src="../../../assets/img/generic/top-style-darker.png"
alt="" />
</span><span class="label-text">Default</span>
</label>
</div> </div>
<div class="col-6"> <div class="col-6">
<input class="btn-check" id="navbarTopDarker" name="navbar-top-style" type="radio" value="darker" data-theme-control="phoenixNavbarTopStyle" disabled="disabled" /> <input class="btn-check"
<label class="btn d-inline-block btn-navbar-style fs-9" for="navbarTopDarker"> <span class="mb-2 rounded d-block"><img class="img-fluid img-prototype d-dark-none mb-0" src="../../../assets/img/generic/navbar-top-style-light.png" alt=""/><img class="img-fluid img-prototype d-light-none mb-0" src="../../../assets/img/generic/top-style-lighter.png" alt=""/></span><span class="label-text d-dark-none">Darker</span><span class="label-text d-light-none">Lighter</span></label> id="navbarTopDarker"
name="navbar-top-style"
type="radio"
value="darker"
data-theme-control="phoenixNavbarTopStyle"
disabled="disabled" />
<label class="btn d-inline-block btn-navbar-style fs-9"
for="navbarTopDarker">
<span class="mb-2 rounded d-block">
<img class="img-fluid img-prototype d-dark-none mb-0"
src="../../../assets/img/generic/navbar-top-style-light.png"
alt="" />
<img class="img-fluid img-prototype d-light-none mb-0"
src="../../../assets/img/generic/top-style-lighter.png"
alt="" />
</span><span class="label-text d-dark-none">Darker</span><span class="label-text d-light-none">Lighter</span>
</label>
</div> </div>
</div> </div>
<p class="text-warning-dark font-medium"> <span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update horizontal navbar appearance in this page</p> <p class="text-warning-dark font-medium">
</div><a class="bun btn-primary d-grid mb-3 text-white mt-5 btn btn-primary" href="https://themes.getbootstrap.com/product/phoenix-admin-dashboard-webapp-template/" target="_blank">Purchase template</a> <span class="fa-solid fa-triangle-exclamation me-2 text-warning"></span>You can't update horizontal navbar appearance in this page
</p>
</div> </div>
</div><a class="card setting-toggle" href="#settings-offcanvas" data-bs-toggle="offcanvas"> <a class="bun btn-primary d-grid mb-3 text-white mt-5 btn btn-primary"
href="https://themes.getbootstrap.com/product/phoenix-admin-dashboard-webapp-template/"
target="_blank">Purchase template</a>
</div>
</div>
<a class="card setting-toggle"
href="#settings-offcanvas"
data-bs-toggle="offcanvas">
<div class="card-body d-flex align-items-center px-2 py-1"> <div class="card-body d-flex align-items-center px-2 py-1">
<div class="position-relative rounded-start" style="height:34px;width:28px"> <div class="position-relative rounded-start"
<div class="settings-popover"><span class="ripple"><span class="fa-spin position-absolute all-0 d-flex flex-center"><span class="icon-spin position-absolute all-0 d-flex flex-center"> style="height:34px;
<svg width="20" height="20" viewBox="0 0 20 20" fill="#ffffff" xmlns="http://www.w3.org/2000/svg"> width:28px">
<path d="M19.7369 12.3941L19.1989 12.1065C18.4459 11.7041 18.0843 10.8487 18.0843 9.99495C18.0843 9.14118 18.4459 8.28582 19.1989 7.88336L19.7369 7.59581C19.9474 7.47484 20.0316 7.23291 19.9474 7.03131C19.4842 5.57973 18.6843 4.28943 17.6738 3.20075C17.5053 3.03946 17.2527 2.99914 17.0422 3.12011L16.393 3.46714C15.6883 3.84379 14.8377 3.74529 14.1476 3.3427C14.0988 3.31422 14.0496 3.28621 14.0002 3.25868C13.2568 2.84453 12.7055 2.10629 12.7055 1.25525V0.70081C12.7055 0.499202 12.5371 0.297594 12.2845 0.257272C10.7266 -0.105622 9.16879 -0.0653007 7.69516 0.257272C7.44254 0.297594 7.31623 0.499202 7.31623 0.70081V1.23474C7.31623 2.09575 6.74999 2.8362 5.99824 3.25599C5.95774 3.27861 5.91747 3.30159 5.87744 3.32493C5.15643 3.74527 4.26453 3.85902 3.53534 3.45302L2.93743 3.12011C2.72691 2.99914 2.47429 3.03946 2.30587 3.20075C1.29538 4.28943 0.495411 5.57973 0.0322686 7.03131C-0.051939 7.23291 0.0322686 7.47484 0.242788 7.59581L0.784376 7.8853C1.54166 8.29007 1.92694 9.13627 1.92694 9.99495C1.92694 10.8536 1.54166 11.6998 0.784375 12.1046L0.242788 12.3941C0.0322686 12.515 -0.051939 12.757 0.0322686 12.9586C0.495411 14.4102 1.29538 15.7005 2.30587 16.7891C2.47429 16.9504 2.72691 16.9907 2.93743 16.8698L3.58669 16.5227C4.29133 16.1461 5.14131 16.2457 5.8331 16.6455C5.88713 16.6767 5.94159 16.7074 5.99648 16.7375C6.75162 17.1511 7.31623 17.8941 7.31623 18.7552V19.2891C7.31623 19.4425 7.41373 19.5959 7.55309 19.696C7.64066 19.7589 7.74815 19.7843 7.85406 19.8046C9.35884 20.0925 10.8609 20.0456 12.2845 19.7729C12.5371 19.6923 12.7055 19.4907 12.7055 19.2891V18.7346C12.7055 17.8836 13.2568 17.1454 14.0002 16.7312C14.0496 16.7037 14.0988 16.6757 14.1476 16.6472C14.8377 16.2446 15.6883 16.1461 16.393 16.5227L17.0422 16.8698C17.2527 16.9907 17.5053 16.9504 17.6738 16.7891C18.7264 15.7005 19.4842 14.4102 19.9895 12.9586C20.0316 12.757 19.9474 12.515 19.7369 12.3941ZM10.0109 13.2005C8.1162 13.2005 6.64257 11.7893 6.64257 9.97478C6.64257 8.20063 8.1162 6.74905 10.0109 6.74905C11.8634 6.74905 13.3792 8.20063 13.3792 9.97478C13.3792 11.7893 11.8634 13.2005 10.0109 13.2005Z" fill="#2A7BE4"></path> <div class="settings-popover">
</svg></span></span></span></div> <span class="ripple"><span class="fa-spin position-absolute all-0 d-flex flex-center"><span class="icon-spin position-absolute all-0 d-flex flex-center">
</div><small class="text-uppercase text-body-tertiary fw-bold py-2 pe-2 ps-1 rounded-end">customize</small> <svg width="20"
height="20"
viewBox="0 0 20 20"
fill="#ffffff"
xmlns="http://www.w3.org/2000/svg">
<path d="M19.7369 12.3941L19.1989 12.1065C18.4459 11.7041 18.0843 10.8487 18.0843 9.99495C18.0843 9.14118 18.4459 8.28582 19.1989 7.88336L19.7369 7.59581C19.9474 7.47484 20.0316 7.23291 19.9474 7.03131C19.4842 5.57973 18.6843 4.28943 17.6738 3.20075C17.5053 3.03946 17.2527 2.99914 17.0422 3.12011L16.393 3.46714C15.6883 3.84379 14.8377 3.74529 14.1476 3.3427C14.0988 3.31422 14.0496 3.28621 14.0002 3.25868C13.2568 2.84453 12.7055 2.10629 12.7055 1.25525V0.70081C12.7055 0.499202 12.5371 0.297594 12.2845 0.257272C10.7266 -0.105622 9.16879 -0.0653007 7.69516 0.257272C7.44254 0.297594 7.31623 0.499202 7.31623 0.70081V1.23474C7.31623 2.09575 6.74999 2.8362 5.99824 3.25599C5.95774 3.27861 5.91747 3.30159 5.87744 3.32493C5.15643 3.74527 4.26453 3.85902 3.53534 3.45302L2.93743 3.12011C2.72691 2.99914 2.47429 3.03946 2.30587 3.20075C1.29538 4.28943 0.495411 5.57973 0.0322686 7.03131C-0.051939 7.23291 0.0322686 7.47484 0.242788 7.59581L0.784376 7.8853C1.54166 8.29007 1.92694 9.13627 1.92694 9.99495C1.92694 10.8536 1.54166 11.6998 0.784375 12.1046L0.242788 12.3941C0.0322686 12.515 -0.051939 12.757 0.0322686 12.9586C0.495411 14.4102 1.29538 15.7005 2.30587 16.7891C2.47429 16.9504 2.72691 16.9907 2.93743 16.8698L3.58669 16.5227C4.29133 16.1461 5.14131 16.2457 5.8331 16.6455C5.88713 16.6767 5.94159 16.7074 5.99648 16.7375C6.75162 17.1511 7.31623 17.8941 7.31623 18.7552V19.2891C7.31623 19.4425 7.41373 19.5959 7.55309 19.696C7.64066 19.7589 7.74815 19.7843 7.85406 19.8046C9.35884 20.0925 10.8609 20.0456 12.2845 19.7729C12.5371 19.6923 12.7055 19.4907 12.7055 19.2891V18.7346C12.7055 17.8836 13.2568 17.1454 14.0002 16.7312C14.0496 16.7037 14.0988 16.6757 14.1476 16.6472C14.8377 16.2446 15.6883 16.1461 16.393 16.5227L17.0422 16.8698C17.2527 16.9907 17.5053 16.9504 17.6738 16.7891C18.7264 15.7005 19.4842 14.4102 19.9895 12.9586C20.0316 12.757 19.9474 12.515 19.7369 12.3941ZM10.0109 13.2005C8.1162 13.2005 6.64257 11.7893 6.64257 9.97478C6.64257 8.20063 8.1162 6.74905 10.0109 6.74905C11.8634 6.74905 13.3792 8.20063 13.3792 9.97478C13.3792 11.7893 11.8634 13.2005 10.0109 13.2005Z" fill="#2A7BE4">
</path>
</svg>
</span></span></span>
</div>
</div>
<small class="text-uppercase text-body-tertiary fw-bold py-2 pe-2 ps-1 rounded-end">customize</small>
</div> </div>
</a> </a>
<!-- ===============================================--> <!-- ===============================================-->
<!-- JavaScripts--> <!-- JavaScripts-->
<!-- ===============================================--> <!-- ===============================================-->
@ -277,7 +585,5 @@
<script src="../../../vendors/feather-icons/feather.min.js"></script> <script src="../../../vendors/feather-icons/feather.min.js"></script>
<script src="../../../vendors/dayjs/dayjs.min.js"></script> <script src="../../../vendors/dayjs/dayjs.min.js"></script>
<script src="../../../assets/js/phoenix.js"></script> <script src="../../../assets/js/phoenix.js"></script>
</body> </body>
</html> </html>

View File

@ -7,49 +7,67 @@
{% endblock head_title %} {% endblock head_title %}
{% block content %} {% block content %}
<section class="main mt-2"> <section class="main mt-2">
<div class="row flex-center "> <div class="row flex-center ">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Sign In" %}</h3> <h3 class="mb-4">{% trans "Sign In" %}</h3>
{% if not SOCIALACCOUNT_ONLY %} {% if not SOCIALACCOUNT_ONLY %}
<form method="post"
action="{% url 'account_login' %}"
<form method="post" action="{% url 'account_login' %}" class="form needs-validation" novalidate > class="form needs-validation"
novalidate>
{% csrf_token %} {% csrf_token %}
<div class="mb-3 "> <div class="mb-3 ">
<label class="form-label" for="id_login">{{ _("Email") }}</label> <label class="form-label" for="id_login">{{ _("Email") }}</label>
<div class="form-icon-container"> <div class="form-icon-container">
<input type="email" name="login" id="id_login" class="form-control form-icon-input placeholder-center" placeholder="{{ _("Email") }}" required > <input type="email"
name="login"
id="id_login"
class="form-control form-icon-input placeholder-center"
placeholder="{{ _("Email") }}"
required>
<span class="fas fa-user text-body fs-9 form-icon"></span> <span class="fas fa-user text-body fs-9 form-icon"></span>
</div> </div>
</div> </div>
<div class="mb-3 "> <div class="mb-3 ">
<label class="form-label" for="id_password">{{ _("Password") }}</label> <label class="form-label" for="id_password">{{ _("Password") }}</label>
<div class="form-icon-container"> <div class="form-icon-container">
<input type="password" name="password" id="id_password" class="form-control form-icon-input placeholder-center" placeholder="{{ _("Password") }}" required > <input type="password"
name="password"
id="id_password"
class="form-control form-icon-input placeholder-center"
placeholder="{{ _("Password") }}"
required>
<span class="fas fa-key text-body fs-9 form-icon"></span> <span class="fas fa-key text-body fs-9 form-icon"></span>
</div> </div>
</div> </div>
<div class="form-group form-check"> <div class="form-group form-check">
<input type="checkbox" name="remember" id="id_remember" class="form-check-input"> <input type="checkbox"
name="remember"
id="id_remember"
class="form-check-input">
<label class="form-check-label mb-0 fs-9" for="id_remember">{{ _("Remember Me") }}</label> <label class="form-check-label mb-0 fs-9" for="id_remember">{{ _("Remember Me") }}</label>
</div> </div>
<button type="submit" class="btn btn-phoenix-primary btn-sm w-100">{% trans "Sign In" %}</button> <button type="submit" class="btn btn-phoenix-primary btn-sm w-100">{% trans "Sign In" %}</button>
<div class="text-start mt-1"> <div class="text-start mt-1">
<a class="fs-9" href="{% url 'account_reset_password' %}">{{ _("Forgot Password?") }}</a> <a class="fs-9" href="{% url 'account_reset_password' %}">{{ _("Forgot Password?") }}</a>
</div> </div>
{% include 'partials/form_errors.html' %} {% include 'partials/form_errors.html' %}
</form> </form>
<div class="text-center my-3 fs-9"> <div class="text-center my-3 fs-9">
{% trans 'If you have not created an account yet, then please' %} {% trans 'If you have not created an account yet, then please' %}
@ -58,12 +76,10 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</section> </section>
<section class="pt-lg-0 pt-xl-8"> <section class="pt-lg-0 pt-xl-8">
{% include 'footer.html' %} {% include 'footer.html' %}
</section> </section>
{% if LOGIN_BY_CODE_ENABLED or PASSKEY_LOGIN_ENABLED %} {% if LOGIN_BY_CODE_ENABLED or PASSKEY_LOGIN_ENABLED %}
<hr> <hr>
{% element button_group vertical=True %} {% element button_group vertical=True %}
@ -82,9 +98,7 @@
{% if SOCIALACCOUNT_ENABLED %} {% if SOCIALACCOUNT_ENABLED %}
{% include "socialaccount/snippets/login.html" with page_layout="entrance" %} {% include "socialaccount/snippets/login.html" with page_layout="entrance" %}
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}
{% block extra_body %} {% block extra_body %}
{{ block.super }} {{ block.super }}
{% if PASSKEY_LOGIN_ENABLED %} {% if PASSKEY_LOGIN_ENABLED %}

View File

@ -1,7 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% block title %}{{ _("Sign Out") }}{% endblock title %} {% block title %}
{{ _("Sign Out") }}
{% endblock title %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
@ -26,5 +27,4 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -1,14 +1,20 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static %} {% load i18n static %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="row flex-center min-vh-50 py-5"> <div class="row flex-center min-vh-50 py-5">
<div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4"> <div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<div class="px-xxl-5"> <div class="px-xxl-5">
@ -17,17 +23,16 @@
<p class="text-body-tertiary mb-0"> <p class="text-body-tertiary mb-0">
{{ _("An email containing a 6-digit verification code has been sent to your email.") }} {{ _("An email containing a 6-digit verification code has been sent to your email.") }}
</p> </p>
<form class="verification-form" method="POST"> <form class="verification-form" method="POST">
{% csrf_token %} {% csrf_token %}
<div class="d-flex align-items-center gap-2 mb-3"> <div class="d-flex align-items-center gap-2 mb-3">
<input class="form-control px-2 text-center" type="number" name="otp_code" required maxlength="6" /> <input class="form-control px-2 text-center"
type="number"
name="otp_code"
required
maxlength="6" />
</div> </div>
<button class="btn btn-phoenix-primary w-100 mb-5" type="submit"> <button class="btn btn-phoenix-primary w-100 mb-5" type="submit">{{ _("Verify") }}</button>
{{ _("Verify") }}
</button>
<a class="fs-9" href="">{{ _("Didnt receive the code") }}</a> <a class="fs-9" href="">{{ _("Didnt receive the code") }}</a>
</form> </form>
</div> </div>

View File

@ -8,18 +8,28 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Change Password" %}</h3> <h3 class="mb-4">{% trans "Change Password" %}</h3>
</div> </div>
<form method="post" action="{% url 'account_change_password' %}" class="form needs-validation" novalidate> <form method="post"
action="{% url 'account_change_password' %}"
class="form needs-validation"
novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}

View File

@ -8,26 +8,34 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Password Reset" %}</h3> <h3 class="mb-4">{% trans "Password Reset" %}</h3>
</div> </div>
{% if user.is_authenticated %} {% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %} {% include "account/snippets/already_logged_in.html" %}
{% endif %} {% endif %}
<p> <p>
{% trans "Forgotten your password? Enter your email address below, and we'll send you an email allowing you to reset it." %} {% trans "Forgotten your password? Enter your email address below, and we'll send you an email allowing you to reset it." %}
</p> </p>
<form method="post"
<form method="post" action="{% url 'account_reset_password' %}" class="form needs-validation" novalidate> action="{% url 'account_reset_password' %}"
class="form needs-validation"
novalidate>
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-phoenix-primary btn-sm w-100">{% trans 'Reset My Password' %}</button> <button type="submit" class="btn btn-phoenix-primary btn-sm w-100">{% trans 'Reset My Password' %}</button>

View File

@ -9,18 +9,24 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Password Reset" %}</h3> <h3 class="mb-4">{% trans "Password Reset" %}</h3>
</div> </div>
{% if user.is_authenticated %} {% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %} {% include "account/snippets/already_logged_in.html" %}
{% endif %} {% endif %}

View File

@ -9,11 +9,18 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
@ -26,7 +33,6 @@
{% endif %} {% endif %}
</h3> </h3>
</div> </div>
{% if token_fail %} {% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %} {% url 'account_reset_password' as passwd_reset_url %}
<p> <p>

View File

@ -8,20 +8,27 @@
<div class="row "> <div class="row ">
<div class="row flex-center min-vh-50"> <div class="row flex-center min-vh-50">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="mb-4">{% trans "Change Password" %}</h3> <h3 class="mb-4">{% trans "Change Password" %}</h3>
<p class="fs-9 fw-bold text-success">{% trans 'Your password is now changed.' %} <span class="far fa-check-circle ms-1"></span></p> <p class="fs-9 fw-bold text-success">
{% trans 'Your password is now changed.' %} <span class="far fa-check-circle ms-1"></span>
</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,79 +1,168 @@
{% extends "welcome_base.html" %} {% extends "welcome_base.html" %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% load i18n static %} {% load i18n static %}
{% block content %} {% block content %}
<section class="main my-2"> <section class="main my-2">
<div class="container-fluid"> <div class="container-fluid">
<div class="row form-container" id="form-container"> <div class="row form-container" id="form-container">
<div class="col-12 ">
<div class="col-12 "><a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="text-body-highlight">{% trans 'Sign Up' %}</h3> <h3 class="text-body-highlight">{% trans 'Sign Up' %}</h3>
<p class="text-body-tertiary fs-9">{% trans 'Create your account today' %}</p> <p class="text-body-tertiary fs-9">{% trans 'Create your account today' %}</p>
</div> </div>
<div class="card theme-wizard" data-theme-wizard="data-theme-wizard"> <div class="card theme-wizard" data-theme-wizard="data-theme-wizard">
<div class="card-header pt-3 pb-2 "> <div class="card-header pt-3 pb-2 ">
<ul class="nav justify-content-between nav-wizard nav-wizard-success" role="tablist"> <ul class="nav justify-content-between nav-wizard nav-wizard-success"
<li class="nav-item" role="presentation"><a class="nav-link active fw-semibold" href="#bootstrap-wizard-validation-tab1" data-bs-toggle="tab" data-wizard-step="1" aria-selected="true" role="tab"> role="tablist">
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-lock"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Access' %}</span></div> <li class="nav-item" role="presentation">
</a></li> <a class="nav-link active fw-semibold"
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab2" data-bs-toggle="tab" data-wizard-step="2" aria-selected="false" tabindex="-1" role="tab"> href="#bootstrap-wizard-validation-tab1"
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-user"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Account' %}</span></div> data-bs-toggle="tab"
</a></li> data-wizard-step="1"
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab3" data-bs-toggle="tab" data-wizard-step="3" aria-selected="false" tabindex="-1" role="tab"> aria-selected="true"
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><svg class="fa fa-file-lines"></svg></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Extra' %}</span></div> role="tab">
</a></li> <div class="text-center d-inline-block">
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab4" data-bs-toggle="tab" data-wizard-step="4" aria-selected="false" tabindex="-1" role="tab"> <span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-lock"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Access' %}</span>
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-check"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Done' %}</span></div> </div>
</a></li> </a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab2"
data-bs-toggle="tab"
data-wizard-step="2"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-user"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Account' %}</span>
</div>
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab3"
data-bs-toggle="tab"
data-wizard-step="3"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle">
<svg class="fa fa-file-lines">
</svg>
</span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Extra' %}</span>
</div>
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab4"
data-bs-toggle="tab"
data-wizard-step="4"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-check"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Done' %}</span>
</div>
</a>
</li>
</ul> </ul>
</div> </div>
<div class="card-body pt-4 pb-0"> <div class="card-body pt-4 pb-0">
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab1" id="bootstrap-wizard-validation-tab1"> <div class="tab-pane active"
<form class="needs-validation" id="wizardValidationForm1" novalidate="novalidate" data-wizard-form="1"> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab1"
id="bootstrap-wizard-validation-tab1">
<form class="needs-validation"
id="wizardValidationForm1"
novalidate="novalidate"
data-wizard-form="1">
{{ form1|crispy }} {{ form1|crispy }}
<a class="fs-10 text-decoration-none" href="{% url 'terms_and_privacy' %}" target="_blank">{{ _("Read Terms of Service and Privacy Policy")}}</a> <a class="fs-10 text-decoration-none"
href="{% url 'terms_and_privacy' %}"
target="_blank">{{ _("Read Terms of Service and Privacy Policy") }}</a>
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab2" id="bootstrap-wizard-validation-tab2"> <div class="tab-pane"
<form class="needs-validation" id="wizardValidationForm2" novalidate="novalidate" data-wizard-form="2"> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab2"
id="bootstrap-wizard-validation-tab2">
<form class="needs-validation"
id="wizardValidationForm2"
novalidate="novalidate"
data-wizard-form="2">
{{ form2|crispy }} {{ form2|crispy }}
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab3" id="bootstrap-wizard-validation-tab3"> <div class="tab-pane"
<form class="needs-validation" id="wizardValidationForm3" novalidate="novalidate" data-wizard-form="3"> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab3"
id="bootstrap-wizard-validation-tab3">
<form class="needs-validation"
id="wizardValidationForm3"
novalidate="novalidate"
data-wizard-form="3">
{{ form3|crispy }} {{ form3|crispy }}
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab4" id="bootstrap-wizard-validation-tab4"> <div class="tab-pane"
role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab4"
id="bootstrap-wizard-validation-tab4">
<div class="row flex-center pb-8 pt-4 gx-3 gy-4"> <div class="row flex-center pb-8 pt-4 gx-3 gy-4">
<div class="col-12 col-sm-auto"> <div class="col-12 col-sm-auto">
<div class="text-center text-sm-start"><img class="d-dark-none" src="{% static 'images/spot-illustrations/38.webp' %}" alt="" width="220"><img class="d-light-none" src="{% static 'images/spot-illustrations/dark_38.webp' %}" alt="" width="220"></div> <div class="text-center text-sm-start">
<img class="d-dark-none"
src="{% static 'images/spot-illustrations/38.webp' %}"
alt=""
width="220">
<img class="d-light-none"
src="{% static 'images/spot-illustrations/dark_38.webp' %}"
alt=""
width="220">
</div>
</div> </div>
<div class="col-12 col-sm-auto"> <div class="col-12 col-sm-auto">
<div class="text-center text-sm-start"> <div class="text-center text-sm-start">
<h5 class="mb-3">{% trans 'You are all set!' %}</h5> <h5 class="mb-3">{% trans 'You are all set!' %}</h5>
<p class="text-body-emphasis fs-9">{% trans 'Now you can access your account' %}<br>{% trans 'anytime' %} {% trans 'anywhere' %}</p><button class="btn btn-primary px-6" id='submit_btn'>{% trans 'Submit' %}</button> <p class="text-body-emphasis fs-9">
{% trans 'Now you can access your account' %}
<br>
{% trans 'anytime' %} {% trans 'anywhere' %}
</p>
<button class="btn btn-primary px-6" id='submit_btn'>{% trans 'Submit' %}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="card-footer border-top-0" data-wizard-footer="data-wizard-footer"> <div class="card-footer border-top-0"
data-wizard-footer="data-wizard-footer">
<div class="d-flex pager wizard list-inline mb-0"> <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> <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"> <div class="flex-1 text-end">
<button class="btn btn-phoenix-primary px-6 px-sm-6 next" type="submit" data-wizard-next-btn="data-wizard-next-btn">{% trans 'Next' %}</button> <button class="btn btn-phoenix-primary px-6 px-sm-6 next"
type="submit"
data-wizard-next-btn="data-wizard-next-btn">{% trans 'Next' %}</button>
</div> </div>
</div> </div>
</div> </div>
@ -87,7 +176,6 @@
</section> </section>
<script src="{% static 'js/phoenix.js' %}"></script> <script src="{% static 'js/phoenix.js' %}"></script>
{% endblock content %} {% endblock content %}
{% block customJS %} {% block customJS %}
<script src="https://unpkg.com/just-validate@latest/dist/just-validate.production.min.js"></script> <script src="https://unpkg.com/just-validate@latest/dist/just-validate.production.min.js"></script>
<script> <script>
@ -283,5 +371,4 @@
return cookieValue; return cookieValue;
} }
</script> </script>
{% endblock customJS %} {% endblock customJS %}

View File

@ -1,69 +1,109 @@
{% extends "welcome_base.html" %} {% extends "welcome_base.html" %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% load i18n static %} {% load i18n static %}
{% block content %} {% block content %}
<section class="main my-2"> <section class="main my-2">
<div class="container" style="max-width:60rem;"> <div class="container" style="max-width:60rem;">
<div class="row form-container" id="form-container"> <div class="row form-container" id="form-container">
<div class="col-12 ">
<div class="col-12 "><a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<div class="text-center"> <div class="text-center">
<h3 class="text-body-highlight">{% trans 'Sign Up' %}</h3> <h3 class="text-body-highlight">{% trans 'Sign Up' %}</h3>
<p class="text-body-tertiary fs-9">{% trans 'Create your account today' %}</p> <p class="text-body-tertiary fs-9">{% trans 'Create your account today' %}</p>
</div> </div>
<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 }"
<div class="card theme-wizard"
data-signals="{ data-theme-wizard="data-theme-wizard">
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 "> <div class="card-header pt-3 pb-2 ">
<ul class="nav justify-content-between nav-wizard nav-wizard-success" role="tablist"> <ul class="nav justify-content-between nav-wizard nav-wizard-success"
<li class="nav-item" role="presentation"><a class="nav-link active fw-semibold" href="#bootstrap-wizard-validation-tab1" data-bs-toggle="tab" data-wizard-step="1" aria-selected="true" role="tab"> role="tablist">
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-lock"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Access' %}</span></div> <li class="nav-item" role="presentation">
</a></li> <a class="nav-link active fw-semibold"
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab2" data-bs-toggle="tab" data-wizard-step="2" aria-selected="false" tabindex="-1" role="tab"> href="#bootstrap-wizard-validation-tab1"
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-user"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Account' %}</span></div> data-bs-toggle="tab"
</a></li> data-wizard-step="1"
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab3" data-bs-toggle="tab" data-wizard-step="3" aria-selected="false" tabindex="-1" role="tab"> aria-selected="true"
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><svg class="fa fa-file-lines"></svg></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Extra' %}</span></div> role="tab">
</a></li> <div class="text-center d-inline-block">
<li class="nav-item" role="presentation"><a class="nav-link fw-semibold" href="#bootstrap-wizard-validation-tab4" data-bs-toggle="tab" data-wizard-step="4" aria-selected="false" tabindex="-1" role="tab"> <span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-lock"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Access' %}</span>
<div class="text-center d-inline-block"><span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-check"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Done' %}</span></div> </div>
</a></li> </a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab2"
data-bs-toggle="tab"
data-wizard-step="2"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-user"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Account' %}</span>
</div>
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab3"
data-bs-toggle="tab"
data-wizard-step="3"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle">
<svg class="fa fa-file-lines">
</svg>
</span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Extra' %}</span>
</div>
</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link fw-semibold"
href="#bootstrap-wizard-validation-tab4"
data-bs-toggle="tab"
data-wizard-step="4"
aria-selected="false"
tabindex="-1"
role="tab">
<div class="text-center d-inline-block">
<span class="nav-item-circle-parent"><span class="nav-item-circle"><span class="fa fa-check"></span></span></span><span class="d-none d-md-block mt-1 fs-9">{% trans 'Done' %}</span>
</div>
</a>
</li>
</ul> </ul>
</div> </div>
<div class="card-body pt-4 pb-0"> <div class="card-body pt-4 pb-0">
<div class="tab-content" data-signals-current_form="1"> <div class="tab-content" data-signals-current_form="1">
<div class="tab-pane active" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab1" id="bootstrap-wizard-validation-tab1"> <div class="tab-pane active"
<form class="needs-validation" id="wizardValidationForm1" novalidate="novalidate" data-wizard-form="1" data-ref-f1> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab1"
id="bootstrap-wizard-validation-tab1">
<form class="needs-validation"
id="wizardValidationForm1"
novalidate="novalidate"
data-wizard-form="1"
data-ref-f1>
<div class="mb-3"> <div class="mb-3">
<label <label for="email"
for="email"
data-class="{'text-danger':!$email_valid}" data-class="{'text-danger':!$email_valid}"
class="form-label">{% trans "Email"%} class="form-label">
<span {% trans "Email" %}
data-show="!$email_valid" <span data-show="!$email_valid" class="text-danger">*</span>
class="text-danger">*</span>
</label> </label>
<input <input data-on-input="$email_valid = validateEmail($form1.email)"
data-on-input="$email_valid = validateEmail($form1.email)"
data-on-blur="$email_valid = validateEmail($form1.email)" data-on-blur="$email_valid = validateEmail($form1.email)"
data-bind-form1.email data-bind-form1.email
data-class="{'is-invalid': !$email_valid , 'is-valid': ($email_valid && $form1.email)}" data-class="{'is-invalid': !$email_valid , 'is-valid': ($email_valid && $form1.email)}"
@ -72,14 +112,11 @@
id="email" id="email"
name="email" name="email"
required> required>
<div class="invalid-feedback" data-show="!$email_valid"> <div class="invalid-feedback" data-show="!$email_valid">{% trans "Please enter a valid email address" %}</div>
{% trans "Please enter a valid email address" %}
</div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="password" class="form-label">{% trans "Password" %}</label> <label for="password" class="form-label">{% trans "Password" %}</label>
<input <input data-bind-form1.password
data-bind-form1.password
type="password" type="password"
data-on-input="$password_valid = validatePassword($form1.password,$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)" data-on-blur="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
@ -93,9 +130,9 @@
</div> </div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="confirm_password" class="form-label">{% trans "Confirm Password" %}</label><span class="text-danger" data-show="!$password_valid">*</span> <label for="confirm_password" class="form-label">{% trans "Confirm Password" %}</label>
<input <span class="text-danger" data-show="!$password_valid">*</span>
data-bind-form1.confirm_password <input data-bind-form1.confirm_password
data-on-input="$password_valid = validatePassword($form1.password,$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)" data-on-blur="$password_valid = validatePassword($form1.password,$form1.confirm_password)"
type="password" type="password"
@ -110,63 +147,133 @@
</div> </div>
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab2" id="bootstrap-wizard-validation-tab2"> <div class="tab-pane"
<form class="needs-validation" id="wizardValidationForm2" novalidate="novalidate" data-wizard-form="2" data-ref-f2> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab2"
id="bootstrap-wizard-validation-tab2">
<form class="needs-validation"
id="wizardValidationForm2"
novalidate="novalidate"
data-wizard-form="2"
data-ref-f2>
<div class="mb-3"> <div class="mb-3">
<label for="name" class="form-label">{% trans "Name" %}</label> <label for="name" class="form-label">{% trans "Name" %}</label>
<input data-bind-form2.name type="text" class="form-control" id="name" name="name" required> <input data-bind-form2.name
type="text"
class="form-control"
id="name"
name="name"
required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="arabic_name" class="form-label">{% trans "Arabic Name" %}</label> <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> <input data-bind-form2.arabic_name
type="text"
class="form-control"
id="arabic_name"
name="arabic_name"
required>
</div> </div>
<div class="mb-3"> <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> <label for="phone_number" class="form-label">{% trans "Phone Number" %}</label>
<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 <span data-show="!$phone_number_valid" class="text-danger">*</span>
data-on-input="$phone_number_valid = validate_sa_phone_number($form2.phone_number)" <input data-bind-form2.phone_number
> type="tel"
<div class="invalid-feedback" data-show="!$phone_number_valid"> data-class="{'is-invalid':!$phone_number_valid}"
{% trans "Please enter a valid phone number" %} class="form-control"
</div> 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> </div>
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab3" id="bootstrap-wizard-validation-tab3"> <div class="tab-pane"
<form class="needs-validation" id="wizardValidationForm3" novalidate="novalidate" data-wizard-form="3" data-ref-f3> role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab3"
id="bootstrap-wizard-validation-tab3">
<form class="needs-validation"
id="wizardValidationForm3"
novalidate="novalidate"
data-wizard-form="3"
data-ref-f3>
<div class="mb-3"> <div class="mb-3">
<label for="crn" class="form-label">{% trans "CRN" %}</label> <label for="crn" class="form-label">{% trans "CRN" %}</label>
<input data-bind-form3.crn type="text" class="form-control" id="crn" name="crn" required> <input data-bind-form3.crn
type="text"
class="form-control"
id="crn"
name="crn"
required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="vrn" class="form-label">{% trans "VRN" %}</label> <label for="vrn" class="form-label">{% trans "VRN" %}</label>
<input data-bind-form3.vrn type="text" class="form-control" id="vrn" name="vrn" required> <input data-bind-form3.vrn
type="text"
class="form-control"
id="vrn"
name="vrn"
required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="address" class="form-label">{% trans "Address" %}</label> <label for="address" class="form-label">{% trans "Address" %}</label>
<textarea data-bind-form3.address class="form-control" id="address" name="address" required></textarea> <textarea data-bind-form3.address
class="form-control"
id="address"
name="address"
required></textarea>
</div> </div>
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab4" id="bootstrap-wizard-validation-tab4"> <div class="tab-pane"
role="tabpanel"
aria-labelledby="bootstrap-wizard-validation-tab4"
id="bootstrap-wizard-validation-tab4">
<div class="row flex-center pb-8 pt-4 gx-3 gy-4"> <div class="row flex-center pb-8 pt-4 gx-3 gy-4">
<div class="col-12 col-sm-auto"> <div class="col-12 col-sm-auto">
<div class="text-center text-sm-start"><img class="d-dark-none" src="{% static 'images/spot-illustrations/38.webp' %}" alt="" width="220"><img class="d-light-none" src="{% static 'images/spot-illustrations/dark_38.webp' %}" alt="" width="220"></div> <div class="text-center text-sm-start">
<img class="d-dark-none"
src="{% static 'images/spot-illustrations/38.webp' %}"
alt=""
width="220">
<img class="d-light-none"
src="{% static 'images/spot-illustrations/dark_38.webp' %}"
alt=""
width="220">
</div>
</div> </div>
<div class="col-12 col-sm-auto"> <div class="col-12 col-sm-auto">
<div class="text-center text-sm-start"> <div class="text-center text-sm-start">
<h5 class="mb-3">{% trans 'You are all set!' %}</h5> <h5 class="mb-3">{% trans 'You are all set!' %}</h5>
<p class="text-body-emphasis fs-9">{% trans 'Now you can access your account' %}<br>{% trans 'anytime' %} {% trans 'anywhere' %}</p><button data-on-click="sendFormData()" class="btn btn-primary px-6" id='submit_btn'>{% trans 'Submit' %}</button> <p class="text-body-emphasis fs-9">
{% trans 'Now you can access your account' %}
<br>
{% trans 'anytime' %} {% trans 'anywhere' %}
</p>
<button data-on-click="sendFormData()"
class="btn btn-primary px-6"
id='submit_btn'>{% trans 'Submit' %}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<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 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"> <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> <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"> <div class="flex-1 text-end">
<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> <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>
</div> </div>
</div> </div>
@ -180,12 +287,11 @@
</section> </section>
<script src="{% static 'js/phoenix.js' %}"></script> <script src="{% static 'js/phoenix.js' %}"></script>
{% endblock content %} {% endblock content %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/main.js' %}"></script> <script src="{% static 'js/main.js' %}"></script>
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script> <script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
<script type="module"
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.11/bundles/datastar.js"></script> src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.11/bundles/datastar.js"></script>
<script> <script>
function validatePassword(password, confirmPassword) { function validatePassword(password, confirmPassword) {
return password === confirmPassword && password.length > 7 && password !== ''; return password === confirmPassword && password.length > 7 && password !== '';

View File

@ -1,18 +1,25 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% load allauth i18n static %} {% load allauth i18n static %}
{% block title %}
{% block title %}{{ _("Sign Up") }}{% endblock title %} {{ _("Sign Up") }}
{% endblock title %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="row min-vh-100 text-center"> <div class="row min-vh-100 text-center">
<div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3"> <div class="col-sm-10 col-md-8 col-lg-5 col-xl-5 col-xxl-3">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<div class="d-flex align-items-center fw-bolder fs-3 d-inline-block"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</div> </div>
</a> </a>
@ -24,70 +31,72 @@
{% if PASSKEY_SIGNUP_ENABLED %} {% if PASSKEY_SIGNUP_ENABLED %}
<hr class="my-4"> <hr class="my-4">
<div class="d-grid gap-2"> <div class="d-grid gap-2">
<a href="{{ signup_by_passkey_url }}" class="btn btn-outline-primary btn-lg"> <a href="{{ signup_by_passkey_url }}"
{{ _("Sign up using a passkey") }} class="btn btn-outline-primary btn-lg">{{ _("Sign up using a passkey") }}</a>
</a>
</div> </div>
{% endif %} {% endif %}
<!-- Social Signup --> <!-- Social Signup -->
{% if SOCIALACCOUNT_ENABLED %} {% if SOCIALACCOUNT_ENABLED %}
{% include "socialaccount/snippets/login.html" with page_layout="entrance" %} {% include "socialaccount/snippets/login.html" with page_layout="entrance" %}
{% endif %} {% endif %}
<!-- Sign Up Form --> <!-- Sign Up Form -->
{% if not SOCIALACCOUNT_ONLY %} {% if not SOCIALACCOUNT_ONLY %}
<form method="post" action="{% url 'account_signup' %}" class="needs-validation" novalidate> <form method="post"
action="{% url 'account_signup' %}"
class="needs-validation"
novalidate>
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
<div class="mb-3"> <div class="mb-3">
<label for="id_email" class="form-label">{{ form.email.label }}</label> <label for="id_email" class="form-label">{{ form.email.label }}</label>
<input type="email" class="form-control" id="id_email" name="email" placeholder="name@example.com"> <input type="email"
{% if form.email.errors %} class="form-control"
<div class="text-danger">{{ form.email.errors|striptags }}</div> id="id_email"
{% endif %} name="email"
placeholder="name@example.com">
{% if form.email.errors %}<div class="text-danger">{{ form.email.errors|striptags }}</div>{% endif %}
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="id_password1" class="form-label">{{ form.password1.label }}</label> <label for="id_password1" class="form-label">{{ form.password1.label }}</label>
<div class="position-relative" data-password="data-password"> <div class="position-relative" data-password="data-password">
<input type="password" class="form-control form-icon-input pe-6" id="id_password1" name="password1" data-password-input="data-password-input" placeholder="Password"> <input type="password"
<a class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary" data-password-toggle="data-password-toggle"><span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span></a> class="form-control form-icon-input pe-6"
id="id_password1"
name="password1"
data-password-input="data-password-input"
placeholder="Password">
<a class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary"
data-password-toggle="data-password-toggle"><span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span></a>
</div> </div>
{% if form.password1.errors %} {% if form.password1.errors %}<div class="text-danger">{{ form.password1.errors|striptags }}</div>{% endif %}
<div class="text-danger">{{ form.password1.errors|striptags }}</div>
{% endif %}
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="id_password2" class="form-label">{{ form.password2.label }}</label> <label for="id_password2" class="form-label">{{ form.password2.label }}</label>
<div class="position-relative" data-password="data-password"> <div class="position-relative" data-password="data-password">
<input type="password" class="form-control form-icon-input pe-6" id="id_password2" name="password2" data-password-input="data-password-input" placeholder="Confirm Password"> <input type="password"
<a class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary" data-password-toggle="data-password-toggle"><span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span></a> class="form-control form-icon-input pe-6"
id="id_password2"
name="password2"
data-password-input="data-password-input"
placeholder="Confirm Password">
<a class="btn px-3 py-0 h-100 position-absolute top-0 end-0 fs-7 text-body-tertiary"
data-password-toggle="data-password-toggle"><span class="uil uil-eye show"></span><span class="uil uil-eye-slash hide"></span></a>
</div> </div>
{% if form.password2.errors %} {% if form.password2.errors %}<div class="text-danger">{{ form.password2.errors|striptags }}</div>{% endif %}
<div class="text-danger">{{ form.password2.errors|striptags }}</div>
{% endif %}
</div> </div>
<div class="form-check mb-3"> <div class="form-check mb-3">
<input class="form-check-input" id="termsService" type="checkbox" /> <input class="form-check-input" id="termsService" type="checkbox" />
<label class="form-label fs-9 text-transform-none" for="termsService">I accept the <a href="">terms </a>and <a href="">privacy policy</a></label> <label class="form-label fs-9 text-transform-none" for="termsService">
I accept the <a href="">terms</a>and <a href="">privacy policy</a>
</label>
</div> </div>
<button type="submit" class="btn btn-phoenix-primary w-100 mb-3">{{ _("Sign Up") }}</button> <button type="submit" class="btn btn-phoenix-primary w-100 mb-3">{{ _("Sign Up") }}</button>
<div class="text-center">{% trans 'Already have an account?' %}<a class="fw-bold" href="{% url 'account_login' %}"> {{ _("Sign In") }}</a></div> <div class="text-center">
{% trans 'Already have an account?' %}<a class="fw-bold" href="{% url 'account_login' %}">{{ _("Sign In") }}</a>
</div>
</form> </form>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -2,10 +2,8 @@
{% load account %} {% load account %}
{% load allauth %} {% load allauth %}
{% user_display user as user_display %} {% user_display user as user_display %}
<div class="alert alert-phoenix-danger d-flex fs-9" role="alert"> <div class="alert alert-phoenix-danger d-flex fs-9" role="alert">
<span class="fas fa-info-circle fs-8 me-3"></span> <span class="fas fa-info-circle fs-8 me-3"></span>
<strong>{% trans 'Note' %}:</strong> <strong>{% trans 'Note' %}:</strong>
{% blocktranslate %}You are already logged in as {{ user_display }}.{% endblocktranslate %} {% blocktranslate %}You are already logged in as {{ user_display }}.{% endblocktranslate %}
</div> </div>

View File

@ -10,36 +10,22 @@
{% csrf_token %} {% csrf_token %}
<div class="col-12 col-xl-8"> <div class="col-12 col-xl-8">
<div class=" mb-4"> <div class=" mb-4">
<div class="row gx-3 mb-4 gy-6 gy-sm-3"> <div class="row gx-3 mb-4 gy-6 gy-sm-3">
<div class="col-12 col-sm-8"> <div class="col-12 col-sm-8">
<h4 class="mb-4">Default Invoice Accounts</h4> <h4 class="mb-4">Default Invoice Accounts</h4>
<div class="form-icon-container mb-3"> <div class="form-icon-container mb-3">{{ form.invoice_cash_account|as_crispy_field }}</div>
{{ form.invoice_cash_account|as_crispy_field }} <div class="form-icon-container mb-3">{{ form.invoice_prepaid_account|as_crispy_field }}</div>
</div> <div class="form-icon-container mb-3">{{ form.invoice_unearned_account|as_crispy_field }}</div>
<div class="form-icon-container mb-3">
{{ form.invoice_prepaid_account|as_crispy_field }}
</div>
<div class="form-icon-container mb-3">
{{ form.invoice_unearned_account|as_crispy_field }}
</div>
</div> </div>
</div> </div>
<div class="row gx-3 mb-4 gy-6 gy-sm-3"> <div class="row gx-3 mb-4 gy-6 gy-sm-3">
<div class="col-12 col-sm-8"> <div class="col-12 col-sm-8">
<h4 class="mb-4">Default Bill Accounts</h4> <h4 class="mb-4">Default Bill Accounts</h4>
<div class="form-icon-container mb-3"> <div class="form-icon-container mb-3">{{ form.bill_cash_account|as_crispy_field }}</div>
{{ form.bill_cash_account|as_crispy_field }} <div class="form-icon-container mb-3">{{ form.bill_prepaid_account|as_crispy_field }}</div>
</div> <div class="form-icon-container mb-3">{{ form.bill_unearned_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>
</div>
<div class="text-start mb-6"> <div class="text-start mb-6">
<div> <div>
<button type="submit" class="btn btn-phoenix-primary">Update</button> <button type="submit" class="btn btn-phoenix-primary">Update</button>

View File

@ -4,22 +4,24 @@
{% block head_title %} {% block head_title %}
{% trans "Verify Your Email Address" %} {% trans "Verify Your Email Address" %}
{% endblock head_title %} {% endblock head_title %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="row flex-center min-vh-50 py-5"> <div class="row flex-center min-vh-50 py-5">
<div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4"> <div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<h3> <h3>{% trans "Verify Your Email Address" %}</h3>
{% trans "Verify Your Email Address" %}
</h3>
<p> <p>
{% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %}
</p> </p>

View File

@ -8,16 +8,20 @@
<div class="row"> <div class="row">
<div class="row flex-center min-vh-50 py-5"> <div class="row flex-center min-vh-50 py-5">
<div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4"> <div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<h3> <h3>{% trans "Verify Your Email Address" %}</h3>
{% trans "Verify Your Email Address" %}
</h3>
<p> <p>
{% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %} {% blocktrans %}We have sent an email to you for verification. Follow the link provided to finalize the signup process. If you do not see the verification email in your main inbox, check your spam folder. Please contact us if you do not receive the verification email within a few minutes.{% endblocktrans %}
</p> </p>

View File

@ -8,16 +8,20 @@
<div class="row"> <div class="row">
<div class="row flex-center min-vh-50 py-5"> <div class="row flex-center min-vh-50 py-5">
<div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4"> <div class="col-sm-10 col-md-8 col-lg-5 col-xxl-4">
<a class="d-flex flex-center text-decoration-none mb-4" href="{% url 'home' %}"> <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"> <div class="d-flex align-items-center fw-bolder fs-3 d-inline-block">
<img class="d-dark-none" src="{% static 'images/logos/logo-d.png' %}" alt="{% trans 'home' %}" width="58" /> <img class="d-dark-none"
<img class="d-light-none" src="{% static 'images/logos/logo.png' %}" alt="{% trans 'home' %}" width="58" /> src="{% static 'images/logos/logo-d.png' %}"
alt="{% trans 'home' %}"
width="58" />
<img class="d-light-none"
src="{% static 'images/logos/logo.png' %}"
alt="{% trans 'home' %}"
width="58" />
</div> </div>
</a> </a>
<h3> <h3>{% trans "Verify Your Email Address" %}</h3>
{% trans "Verify Your Email Address" %}
</h3>
{% url 'account_email' as email_url %} {% url 'account_email' as email_url %}
<p> <p>
{% blocktrans %}This part of the site requires us to verify that {% blocktrans %}This part of the site requires us to verify that

View File

@ -1,7 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n custom_filters %} {% load i18n custom_filters %}
{% block title %}{% trans "Accounts" %}{% endblock title %} {% block title %}
{% trans "Accounts" %}
{% endblock title %}
{% block accounts %} {% block accounts %}
<a class="nav-link active fw-bold"> <a class="nav-link active fw-bold">
{% trans "Accounts"|capfirst %} {% trans "Accounts"|capfirst %}
@ -10,18 +11,17 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row mt-4"> <div class="row mt-4">
<div class="d-flex justify-content-between mb-2"> <div class="d-flex justify-content-between mb-2">
<h3 class=""><i class="fas fa-right-to-bracket me-2"></i> {% trans "Audit Log Dashboard" %}</h3> <h3 class="">
<i class="fas fa-right-to-bracket me-2"></i> {% trans "Audit Log Dashboard" %}
</h3>
</div> </div>
<!-- Log Type Tabs --> <!-- Log Type Tabs -->
<div class="mb-4"> <div class="mb-4">
{% include 'admin_management/nav.html' %} {% include 'admin_management/nav.html' %}
<div class="tab-content p-3 border border-top-0 rounded-bottom"
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent"> id="accountTypeTabsContent">
<!-- modellogs Tab --> <!-- modellogs Tab -->
{% if page_obj %} {% if page_obj %}
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">
<table class= "table align-items-center table-flush table-hover"> <table class= "table align-items-center table-flush table-hover">
@ -37,38 +37,23 @@
<tbody class="list"> <tbody class="list">
{% for event in page_obj.object_list %} {% for event in page_obj.object_list %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle product white-space-nowrap">{{ event.datetime }}</td> <td class="align-middle product white-space-nowrap">{{ event.datetime }}</td>
<td class="align-middle product white-space-nowrap">{{ event.user.username|default:"N/A" }}</td> <td class="align-middle product white-space-nowrap">{{ event.user.username|default:"N/A" }}</td>
<td class="align-middle product white-space-nowrap">{{ event.get_login_type_display }}</td> <td class="align-middle product white-space-nowrap">{{ event.get_login_type_display }}</td>
<td class="align-middle product white-space-nowrap">{{ event.username }}</td> <td class="align-middle product white-space-nowrap">{{ event.username }}</td>
<td class="align-middle product white-space-nowrap">{{ event.remote_ip }}</td> <td class="align-middle product white-space-nowrap">{{ event.remote_ip }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="d-flex justify-content-end mt-3"> <div class="d-flex justify-content-end mt-3">
<div class="d-flex"> <div class="d-flex">{% include 'partials/pagination.html' with q='loginEvents' %}</div>
{% include 'partials/pagination.html' with q='loginEvents' %}
</div> </div>
</div>
{% else %} {% else %}
<p>No authentication audit events found.</p> <p>No authentication audit events found.</p>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,4 +1,3 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
@ -16,37 +15,27 @@
</form> </form>
</div> </div>
</div> {% endcomment %} </div> {% endcomment %}
<!----> <!---->
<div class="row justify-content-center mt-5 mb-3"> <div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10"> <div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-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"> <h3 class="mb-0 fs-4 text-center text-white">{% trans 'Activate Account' %}</h3>
{% trans 'Activate Account'%}
</h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body bg-light-subtle">
<p class="text-center">Are you sure you want to activate this account "{{ obj.email }}"?</p> <p class="text-center">Are you sure you want to activate this account "{{ obj.email }}"?</p>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
<hr class="my-2"> <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">{{ _("Activate") }}</button> <button class="btn btn-lg btn-phoenix-primary md-me-2" type="submit">{{ _("Activate") }}</button>
<a class="btn btn-lg btn-phoenix-danger mx-2" href="{% url 'user_management' request.dealer.slug %}">Cancel</a> <a class="btn btn-lg btn-phoenix-danger mx-2"
href="{% url 'user_management' request.dealer.slug %}">Cancel</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!----> <!---->
{% endblock %} {% endblock %}

View File

@ -1,6 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{%block title%} {%trans 'Admin Management' %} {%endblock%} {% block title %}
{% trans 'Admin Management' %} {% endblock %}
{% block content %} {% block content %}
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-4 g-4 mt-10"> <div class="row row-cols-1 row-cols-sm-2 row-cols-md-4 g-4 mt-10">
<div class="col"> <div class="col">
@ -24,6 +25,4 @@
</a> </a>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -1,7 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n custom_filters %} {% load i18n custom_filters %}
{% block title %}{% trans "Accounts" %}{% endblock title %} {% block title %}
{% trans "Accounts" %}
{% endblock title %}
{% block accounts %} {% block accounts %}
<a class="nav-link active fw-bold"> <a class="nav-link active fw-bold">
{% trans "Accounts"|capfirst %} {% trans "Accounts"|capfirst %}
@ -10,18 +11,17 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row mt-4"> <div class="row mt-4">
<div class="d-flex justify-content-between mb-2"> <div class="d-flex justify-content-between mb-2">
<h3 class=""><i class="fas fa-history me-2"></i>{% trans "Audit Log Dashboard" %}</h3> <h3 class="">
<i class="fas fa-history me-2"></i>{% trans "Audit Log Dashboard" %}
</h3>
</div> </div>
<!-- Log Type Tabs --> <!-- Log Type Tabs -->
<div class="mb-4"> <div class="mb-4">
{% include 'admin_management/nav.html' %} {% include 'admin_management/nav.html' %}
<div class="tab-content p-3 border border-top-0 rounded-bottom"
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent"> id="accountTypeTabsContent">
<!-- modellogs Tab --> <!-- modellogs Tab -->
{% if page_obj %} {% if page_obj %}
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">
<table class="table align-items-center table-flush table-hover mt-3"> <table class="table align-items-center table-flush table-hover mt-3">
@ -33,9 +33,12 @@
<th>{% trans "Model" %}</th> <th>{% trans "Model" %}</th>
<th>{% trans "Object ID" %}</th> <th>{% trans "Object ID" %}</th>
<th>{% trans "Object Representation" %}</th> <th>{% trans "Object Representation" %}</th>
<th>{% trans "Field" %}</th> {# Dedicated column for field name #} <th>{% trans "Field" %}</th>
<th>{% trans "Old Value" %}</th> {# Dedicated column for old value #} {# Dedicated column for field name #}
<th>{% trans "New Value" %}</th> {# Dedicated column for new value #} <th>{% trans "Old Value" %}</th>
{# Dedicated column for old value #}
<th>{% trans "New Value" %}</th>
{# Dedicated column for new value #}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -46,38 +49,37 @@
<tr> <tr>
{# Display common event details using rowspan for the first change #} {# Display common event details using rowspan for the first change #}
{% if forloop.first %} {% if forloop.first %}
<td rowspan="{{ event.field_changes|length }}"> <td rowspan="{{ event.field_changes|length }}">{{ event.datetime|date:"Y-m-d H:i:s" }}</td>
{{ event.datetime|date:"Y-m-d H:i:s" }} <td rowspan="{{ event.field_changes|length }}">{{ event.user.username|default:"Anonymous" }}</td>
</td> <td rowspan="{{ event.field_changes|length }}">{{ event.event_type_display }}</td>
<td rowspan="{{ event.field_changes|length }}"> <td rowspan="{{ event.field_changes|length }}">{{ event.model_name|title }}</td>
{{ event.user.username|default:"Anonymous" }} <td rowspan="{{ event.field_changes|length }}">{{ event.object_id }}</td>
</td> <td rowspan="{{ event.field_changes|length }}">{{ event.object_repr }}</td>
<td rowspan="{{ event.field_changes|length }}">
{{ event.event_type_display }}
</td>
<td rowspan="{{ event.field_changes|length }}">
{{ event.model_name|title }}
</td>
<td rowspan="{{ event.field_changes|length }}">
{{ event.object_id }}
</td>
<td rowspan="{{ event.field_changes|length }}">
{{ event.object_repr }}
</td>
{% endif %} {% endif %}
{# Display the specific field change details in their own columns #} {# Display the specific field change details in their own columns #}
<td><strong>{{ change.field }}</strong></td> <td>
<strong>{{ change.field }}</strong>
</td>
<td> <td>
{% if change.old is not None %} {% if change.old is not None %}
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.old }}</pre> <pre style="white-space: pre-wrap;
word-break: break-all;
font-size: 0.85em;
background-color: #f8f9fa;
padding: 5px;
border-radius: 3px">{{ change.old }}</pre>
{% else %} {% else %}
(None) (None)
{% endif %} {% endif %}
</td> </td>
<td> <td>
{% if change.new is not None %} {% if change.new is not None %}
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.new }}</pre> <pre style="white-space: pre-wrap;
word-break: break-all;
font-size: 0.85em;
background-color: #f8f9fa;
padding: 5px;
border-radius: 3px">{{ change.new }}</pre>
{% else %} {% else %}
(None) (None)
{% endif %} {% endif %}
@ -108,26 +110,14 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="d-flex justify-content-end mt-3"> <div class="d-flex justify-content-end mt-3">
<div class="d-flex"> <div class="d-flex">{% include 'partials/pagination.html' with q='userActions' %}</div>
{% include 'partials/pagination.html' with q='userActions' %}
</div> </div>
</div>
{% else %} {% else %}
<p>{% trans "No model change audit events found." %}</p> <p>{% trans "No model change audit events found." %}</p>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,6 +1,5 @@
{% load i18n %} {% load i18n %}
<ul class="nav nav-tabs" id="accountTypeTabs" role="tablist"> <ul class="nav nav-tabs" id="accountTypeTabs" role="tablist">
<li class="nav-item me-3" role="presentation"> <li class="nav-item me-3" role="presentation">
<a href="{% url 'audit_log_dashboard' request.dealer.slug %}?q=userActions"> <a href="{% url 'audit_log_dashboard' request.dealer.slug %}?q=userActions">
<i class="fas fa-history me-2"></i>{% trans "User Actions" %} <i class="fas fa-history me-2"></i>{% trans "User Actions" %}

View File

@ -14,38 +14,31 @@
</form> </form>
</div> </div>
</div> {% endcomment %} </div> {% endcomment %}
<!----> <!---->
<div class="row justify-content-center mt-5 mb-3"> <div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10"> <div class="col-lg-8 col-md-10">
<div class="card shadow-sm border-0 rounded-3"> <div class="card shadow-sm border-0 rounded-3">
<div class="card-header bg-gray-200 py-3 border-0 rounded-top-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"> <h3 class="mb-0 fs-4 text-center text-white">{% trans 'Delete Account' %}</h3>
{% trans 'Delete Account'%}
</h3>
</div> </div>
<div class="card-body bg-light-subtle"> <div class="card-body bg-light-subtle">
<p class="lead text-center">Are you sure you want to delete this account "{{ obj.email }}"? This will delete all associated information for this user.</p> <p class="lead text-center">
Are you sure you want to delete this account "{{ obj.email }}"? This will delete all associated information for this user.
</p>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
<hr class="my-2"> <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-danger md-me-2" type="submit"><i class="fas fa-trash me-2"></i>{{ _("Delete Permenantly") }}</button> <button class="btn btn-lg btn-phoenix-danger md-me-2" type="submit">
<a class="btn btn-lg btn-phoenix-secondary mx-2" href="{% url 'user_management' request.dealer.slug %}"><i class="fas fa-ban me-2"></i>Cancel</a> <i class="fas fa-trash me-2"></i>{{ _("Delete Permenantly") }}
</button>
<a class="btn btn-lg btn-phoenix-secondary mx-2"
href="{% url 'user_management' request.dealer.slug %}"><i class="fas fa-ban me-2"></i>Cancel</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!----> <!---->
{% endblock %} {% endblock %}

View File

@ -1,7 +1,8 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n custom_filters %} {% load i18n custom_filters %}
{% block title %}{% trans "Accounts" %}{% endblock title %} {% block title %}
{% trans "Accounts" %}
{% endblock title %}
{% block accounts %} {% block accounts %}
<a class="nav-link active fw-bold"> <a class="nav-link active fw-bold">
{% trans "Accounts"|capfirst %} {% trans "Accounts"|capfirst %}
@ -10,16 +11,16 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row mt-4"> <div class="row mt-4">
<div class="d-flex justify-content-between mb-2"> <div class="d-flex justify-content-between mb-2">
<h3 class=""><i class="fas fa-file-alt me-2"></i> {% trans "Audit Log Dashboard" %}</h3> <h3 class="">
<i class="fas fa-file-alt me-2"></i> {% trans "Audit Log Dashboard" %}
</h3>
</div> </div>
<!-- Log Type Tabs --> <!-- Log Type Tabs -->
<div class="mb-4"> <div class="mb-4">
{% include 'admin_management/nav.html' %} {% include 'admin_management/nav.html' %}
<div class="tab-content p-3 border border-top-0 rounded-bottom"
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent"> id="accountTypeTabsContent">
<!-- modellogs Tab --> <!-- modellogs Tab -->
{% if page_obj %} {% if page_obj %}
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">
@ -36,34 +37,23 @@
<tbody class="list"> <tbody class="list">
{% for event in page_obj.object_list %} {% for event in page_obj.object_list %}
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="align-middle product white-space-nowrap">{{ event.datetime }}</td> <td class="align-middle product white-space-nowrap">{{ event.datetime }}</td>
<td class="align-middle product white-space-nowrap">{{ event.user.username|default:"Anonymous" }}</td> <td class="align-middle product white-space-nowrap">{{ event.user.username|default:"Anonymous" }}</td>
<td class="align-middle product white-space-nowrap">{{ event.url }}</td> <td class="align-middle product white-space-nowrap">{{ event.url }}</td>
<td class="align-middle product white-space-nowrap">{{ event.method }}</td> <td class="align-middle product white-space-nowrap">{{ event.method }}</td>
<td class="align-middle product white-space-nowrap">{{ event.remote_ip }}</td> <td class="align-middle product white-space-nowrap">{{ event.remote_ip }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="d-flex justify-content-end mt-3"> <div class="d-flex justify-content-end mt-3">
<div class="d-flex"> <div class="d-flex">{% include 'partials/pagination.html' with q='userRequests' %}</div>
{% include 'partials/pagination.html' with q='userRequests' %}
</div>
</div> </div>
{% else %} {% else %}
<p>No request audit events found.</p> <p>No request audit events found.</p>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,14 +1,14 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static humanize %} {% load i18n static humanize %}
{% block title %} {% block title %}
{% trans 'User Management' %} {% trans 'User Management' %}
{% endblock title %} {% endblock title %}
{% block content %} {% block content %}
<section class="pt-5 pb-9"> <section class="pt-5 pb-9">
<div class="row"> <div class="row">
<h2 class="mb-4"><i class="fa-solid fa-people-roof me-1"></i> {% trans 'User Management' %}</h2> <h2 class="mb-4">
<i class="fa-solid fa-people-roof me-1"></i> {% trans 'User Management' %}
</h2>
<div class="row g-3 justify-content-between mb-4"> <div class="row g-3 justify-content-between mb-4">
<div class="col-12"> <div class="col-12">
<h3 class="mb-3">{% trans 'Customers' %}</h3> <h3 class="mb-3">{% trans 'Customers' %}</h3>
@ -16,12 +16,22 @@
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-flush table-hover">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-body-highlight">
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('First Name') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Last Name') }}</th> scope="col"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th> style="width:20%">{{ _("First Name") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase " scope="col" style="width:15%;">{{ _('Status') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Created date') }}</th> scope="col"
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th> style="width:20%">{{ _("Last Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:20%">{{ _("Email") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Status") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Created date") }}</th>
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _("Actions") }}</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="leal-tables-body"> <tbody class="list" id="leal-tables-body">
@ -32,16 +42,15 @@
<td class="ps-0">{{ customer.email }}</td> <td class="ps-0">{{ customer.email }}</td>
<td class="ps-0"> <td class="ps-0">
{% if customer.active %} {% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }} <span class="fas fa-check-circle text-success"></span> {{ _("Active") }}
{% else %} {% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }} <span class="fas fa-times-circle text-danger"></span> {{ _("Inactive") }}
{% endif %} {% endif %}
</td> </td>
<td class="ps-0">{{ customer.created|naturalday|capfirst }}</td> <td class="ps-0">{{ customer.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end"> <td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
data-boundary="window" data-boundary="window"
@ -51,9 +60,13 @@
<span class="fas fa-ellipsis-h fs-10"></span> <span class="fas fa-ellipsis-h fs-10"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' request.dealer.slug 'customer' customer.slug %}"><button class="dropdown-item text-primary">{% trans "Activate" %}</button></a> <a href="{% url 'activate_account' request.dealer.slug 'customer' customer.slug %}">
<button class="dropdown-item text-primary">{% trans "Activate" %}</button>
</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' request.dealer.slug 'customer' customer.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a> <a href="{% url 'permenant_delete_account' request.dealer.slug 'customer' customer.slug %}">
<button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button>
</a>
</div> </div>
</div> </div>
</td> </td>
@ -80,12 +93,22 @@
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-flush table-hover">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-body-highlight">
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th> scope="col"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th> style="width:20%">{{ _("Name") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase " scope="col" style="width:15%;">{{ _('Status') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th> scope="col"
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th> style="width:20%">{{ _("Arabic Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:20%">{{ _("Email") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Status") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Create date") }}</th>
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _("Actions") }}</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="leal-tables-body"> <tbody class="list" id="leal-tables-body">
@ -96,16 +119,15 @@
<td class="ps-0">{{ organization.email }}</td> <td class="ps-0">{{ organization.email }}</td>
<td class="ps-0"> <td class="ps-0">
{% if customer.active %} {% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }} <span class="fas fa-check-circle text-success"></span> {{ _("Active") }}
{% else %} {% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }} <span class="fas fa-times-circle text-danger"></span> {{ _("Inactive") }}
{% endif %} {% endif %}
</td> </td>
<td class="ps-0">{{ organization.created|naturalday|capfirst }}</td> <td class="ps-0">{{ organization.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end"> <td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
data-boundary="window" data-boundary="window"
@ -115,9 +137,13 @@
<span class="fas fa-ellipsis-h fs-10"></span> <span class="fas fa-ellipsis-h fs-10"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' request.dealer.slug 'organization' organization.slug %}"><button class="dropdown-item text-primary">{% trans "Activate" %}</button></a> <a href="{% url 'activate_account' request.dealer.slug 'organization' organization.slug %}">
<button class="dropdown-item text-primary">{% trans "Activate" %}</button>
</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' request.dealer.slug 'organization' organization.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a> <a href="{% url 'permenant_delete_account' request.dealer.slug 'organization' organization.slug %}">
<button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button>
</a>
</div> </div>
</div> </div>
</td> </td>
@ -144,12 +170,22 @@
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-flush table-hover">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-body-highlight">
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th> scope="col"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th> style="width:20%">{{ _("Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:15%;">{{ _('Status') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th> scope="col"
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th> style="width:20%">{{ _("Arabic Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:20%">{{ _("Email") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:15%">{{ _("Status") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Create date") }}</th>
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _("Actions") }}</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="leal-tables-body"> <tbody class="list" id="leal-tables-body">
@ -160,16 +196,15 @@
<td class="ps-0">{{ vendor.email }}</td> <td class="ps-0">{{ vendor.email }}</td>
<td class="ps-0"> <td class="ps-0">
{% if customer.active %} {% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }} <span class="fas fa-check-circle text-success"></span> {{ _("Active") }}
{% else %} {% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }} <span class="fas fa-times-circle text-danger"></span> {{ _("Inactive") }}
{% endif %} {% endif %}
</td> </td>
<td class="ps-0">{{ vendor.created_at|naturalday|capfirst }}</td> <td class="ps-0">{{ vendor.created_at|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end"> <td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
data-boundary="window" data-boundary="window"
@ -179,9 +214,13 @@
<span class="fas fa-ellipsis-h fs-10"></span> <span class="fas fa-ellipsis-h fs-10"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' request.dealer.slug 'vendor' vendor.slug %}"><button class="dropdown-item text-primary">{% trans "Activate" %}</button></a> <a href="{% url 'activate_account' request.dealer.slug 'vendor' vendor.slug %}">
<button class="dropdown-item text-primary">{% trans "Activate" %}</button>
</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' request.dealer.slug 'vendor' vendor.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a> <a href="{% url 'permenant_delete_account' request.dealer.slug 'vendor' vendor.slug %}">
<button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button>
</a>
</div> </div>
</div> </div>
</td> </td>
@ -208,12 +247,22 @@
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-flush table-hover">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-body-highlight">
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Name') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Arabic Name') }}</th> scope="col"
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:20%;">{{ _('Email') }}</th> style="width:20%">{{ _("Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0" scope="col" style="width:15%;">{{ _('Status') }}</th> <th class="sort white-space-nowrap align-middle text-uppercase ps-0"
<th class="sort align-middle ps-4 pe-5 text-uppercase" scope="col" style="width:15%;">{{ _('Create date') }}</th> scope="col"
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _('Actions') }}</th> style="width:20%">{{ _("Arabic Name") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:20%">{{ _("Email") }}</th>
<th class="sort white-space-nowrap align-middle text-uppercase ps-0"
scope="col"
style="width:15%">{{ _("Status") }}</th>
<th class="sort align-middle ps-4 pe-5 text-uppercase"
scope="col"
style="width:15%">{{ _("Create date") }}</th>
<th class="sort text-end align-middle pe-0 ps-4" scope="col">{{ _("Actions") }}</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="leal-tables-body"> <tbody class="list" id="leal-tables-body">
@ -224,16 +273,15 @@
<td class="ps-0">{{ obj.email }}</td> <td class="ps-0">{{ obj.email }}</td>
<td class="ps-0"> <td class="ps-0">
{% if obj.active %} {% if obj.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }} <span class="fas fa-check-circle text-success"></span> {{ _("Active") }}
{% else %} {% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }} <span class="fas fa-times-circle text-danger"></span> {{ _("Inactive") }}
{% endif %} {% endif %}
</td> </td>
<td class="ps-0">{{ obj.created|naturalday|capfirst }}</td> <td class="ps-0">{{ obj.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end"> <td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
data-boundary="window" data-boundary="window"
@ -243,9 +291,13 @@
<span class="fas fa-ellipsis-h fs-10"></span> <span class="fas fa-ellipsis-h fs-10"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' request.dealer.slug 'staff' obj.slug %}"><button class="dropdown-item text-primary">{% trans "Activate" %}</button></a> <a href="{% url 'activate_account' request.dealer.slug 'staff' obj.slug %}">
<button class="dropdown-item text-primary">{% trans "Activate" %}</button>
</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' request.dealer.slug 'staff' obj.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a> <a href="{% url 'permenant_delete_account' request.dealer.slug 'staff' obj.slug %}">
<button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button>
</a>
</div> </div>
</div> </div>
</td> </td>
@ -268,4 +320,3 @@
</div> </div>
</section> </section>
{% endblock %} {% endblock %}

View File

@ -1,10 +1,8 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block title %}{{ page_title }}{% endblock %} {% block title %}{{ page_title }}{% endblock %}
{% block description %}{{ page_description }}{% endblock %} {% block description %}{{ page_description }}{% endblock %}
{% block content %} {% block content %}
<div class="container py-5"> <div class="container py-5">
<div class="card bg-body"> <div class="card bg-body">
@ -81,7 +79,6 @@
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<span class="icon-saudi_riyal text-primary"></span> <span class="icon-saudi_riyal text-primary"></span>
<strong class="me-2">{% trans 'Service price' %}:</strong> {{ appointment.get_appointment_amount_to_pay_text }} <strong class="me-2">{% trans 'Service price' %}:</strong> {{ appointment.get_appointment_amount_to_pay_text }}
</div> </div>
@ -91,9 +88,11 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js"
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js" crossorigin="anonymous"></script> crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js"
crossorigin="anonymous"></script>
{% endblock %} {% endblock %}

View File

@ -2,7 +2,9 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/verification_code.css' %}"/> <link rel="stylesheet"
type="text/css"
href="{% static 'css/verification_code.css' %}" />
{% endblock %} {% endblock %}
{% block title %} {% block title %}
{% trans 'Enter Verification Code' %} {% trans 'Enter Verification Code' %}
@ -19,7 +21,8 @@
<form method="post" <form method="post"
action="{% url 'appointment:email_change_verification_code' %}"> action="{% url 'appointment:email_change_verification_code' %}">
{% csrf_token %} {% csrf_token %}
<label>{% trans 'Code' %}: <label>
{% trans 'Code' %}:
<input type="text" name="code" placeholder="X1Y2Z3" required> <input type="text" name="code" placeholder="X1Y2Z3" required>
</label> </label>
<button class="btn btn-phoenix-primary" type="submit">{% trans 'Submit' %}</button> <button class="btn btn-phoenix-primary" type="submit">{% trans 'Submit' %}</button>
@ -29,7 +32,15 @@
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -1,21 +1,22 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/app_admin/days_off.css' %}"/> <link rel="stylesheet"
type="text/css"
href="{% static 'css/app_admin/days_off.css' %}" />
<!-- jQuery UI CSS --> <!-- jQuery UI CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.css" <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.css"
integrity="sha512-lCk0aEL6CvAGQvaZ47hoq1v/hNsunE8wD4xmmBelkJjg51DauW6uVdaWEJlwgAE6PxcY7/SThs1T4+IMwwpN7w==" integrity="sha512-lCk0aEL6CvAGQvaZ47hoq1v/hNsunE8wD4xmmBelkJjg51DauW6uVdaWEJlwgAE6PxcY7/SThs1T4+IMwwpN7w=="
crossorigin="anonymous" referrerpolicy="no-referrer"/> crossorigin="anonymous"
referrerpolicy="no-referrer" />
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<section class="content content-wrapper"> <section class="content content-wrapper">
<div class="days-off-form-wrapper"> <div class="days-off-form-wrapper">
<div class="do-form-content"> <div class="do-form-content">
<h2>{% trans "Manage Days Off" %}</h2> <h2>{% trans "Manage Days Off" %}</h2>
<form method="post" action=""> <form method="post" action="">
{% csrf_token %} {% csrf_token %}
<!-- Staff Member --> <!-- Staff Member -->
@ -26,60 +27,66 @@
}); });
</script> </script>
{% endif %} {% endif %}
{% if days_off_form.staff_member %} {% if days_off_form.staff_member %}
<div class="form-group"> <div class="form-group">
<label for="{{ days_off_form.staff_member.id_for_label }}">{% trans 'Staff Member' %}:</label> <label for="{{ days_off_form.staff_member.id_for_label }}">{% trans 'Staff Member' %}:</label>
{{ days_off_form.staff_member }} {{ days_off_form.staff_member }}
</div> </div>
{% endif %} {% endif %}
<!-- Start Date Display (read-only) --> <!-- Start Date Display (read-only) -->
<div class="form-group"> <div class="form-group">
<label for="{{ day_off_form.start_date.id_for_label }}_display">{% trans 'Start date' %}:</label> <label for="{{ day_off_form.start_date.id_for_label }}_display">{% trans 'Start date' %}:</label>
<input type="text" id="{{ day_off_form.start_date.id_for_label }}_display" <input type="text"
id="{{ day_off_form.start_date.id_for_label }}_display"
class="datepicker-display" class="datepicker-display"
value="{{ day_off_form.start_date.value }}" readonly> value="{{ day_off_form.start_date.value }}"
readonly>
<!-- Actual value to be submitted --> <!-- Actual value to be submitted -->
<input type="hidden" id="{{ day_off_form.start_date.id_for_label }}" <input type="hidden"
name="{{ day_off_form.start_date.name }}" class="datepicker-actual" id="{{ day_off_form.start_date.id_for_label }}"
name="{{ day_off_form.start_date.name }}"
class="datepicker-actual"
value="{{ day_off_form.start_date.value }}"> value="{{ day_off_form.start_date.value }}">
</div> </div>
<!-- End Date Display (read-only) --> <!-- End Date Display (read-only) -->
<div class="form-group"> <div class="form-group">
<label for="{{ day_off_form.end_date.id_for_label }}_display">{% trans 'End date' %}:</label> <label for="{{ day_off_form.end_date.id_for_label }}_display">{% trans 'End date' %}:</label>
<input type="text" id="{{ day_off_form.end_date.id_for_label }}_display" <input type="text"
id="{{ day_off_form.end_date.id_for_label }}_display"
class="datepicker-display" class="datepicker-display"
value="{{ day_off_form.end_date.value }}" readonly> value="{{ day_off_form.end_date.value }}"
readonly>
<!-- Actual value to be submitted --> <!-- Actual value to be submitted -->
<input type="hidden" id="{{ day_off_form.end_date.id_for_label }}" <input type="hidden"
name="{{ day_off_form.end_date.name }}" class="datepicker-actual" id="{{ day_off_form.end_date.id_for_label }}"
name="{{ day_off_form.end_date.name }}"
class="datepicker-actual"
value="{{ day_off_form.end_date.value }}"> value="{{ day_off_form.end_date.value }}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="{{ day_off_form.description.id_for_label }}">{% trans 'Description' %}:</label> <label for="{{ day_off_form.description.id_for_label }}">{% trans 'Description' %}:</label>
<input type="text" id="{{ day_off_form.description.id_for_label }}" <input type="text"
name="{{ day_off_form.description.name }}" value="{{ day_off_form.description.value }}"> id="{{ day_off_form.description.id_for_label }}"
name="{{ day_off_form.description.name }}"
value="{{ day_off_form.description.value }}">
</div> </div>
<button type="submit" class="btn btn-phoenix-primary">{% trans "Submit" %}</button> <button type="submit" class="btn btn-phoenix-primary">{% trans "Submit" %}</button>
</form> </form>
<div class="row-form-errors" style="margin: 10px 0"> <div class="row-form-errors" style="margin: 10px 0">
{% if days_off_form.errors %} {% if days_off_form.errors %}<div class="alert alert-danger">{{ days_off_form.errors }}</div>{% endif %}
<div class="alert alert-danger">
{{ days_off_form.errors }}
</div> </div>
{% endif %}
</div>
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@ -89,15 +96,16 @@
</div> </div>
</section> </section>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<!-- JS --> <!-- JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.js"
integrity="sha512-ynDTbjF5rUHsWBjz7nsljrrSWqLTPJaORzSe5aGCFxOigRZRmwM05y+kuCtxaoCSzVGB1Ky3XeRZsDhbSLdzXQ==" integrity="sha512-ynDTbjF5rUHsWBjz7nsljrrSWqLTPJaORzSe5aGCFxOigRZRmwM05y+kuCtxaoCSzVGB1Ky3XeRZsDhbSLdzXQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
$.datepicker._defaults.monthNamesShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]; $.datepicker._defaults.monthNamesShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"];

View File

@ -2,11 +2,7 @@
{% load crispy_forms_filters custom_filters %} {% load crispy_forms_filters custom_filters %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %}{% endblock %}
{% block customCSS %}
{% endblock %}
{% block content %} {% block content %}
{% translate "Confirm Deletion" as modal_title %} {% translate "Confirm Deletion" as modal_title %}
{% translate "Delete" as delete_btn_modal %} {% translate "Delete" as delete_btn_modal %}
@ -15,98 +11,65 @@
<h3 class="mb-3">{{ page_title }}</h3> <h3 class="mb-3">{{ page_title }}</h3>
<form class="form" method="post" enctype="multipart/form-data"> <form class="form" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<!-- Name Field --> <!-- Name Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.name|add_class:"form-control form-control-sm" }} {{ form.name|add_class:"form-control form-control-sm" }}
<label for="{{ form.name.id_for_label }}">{{ _("Name") }}</label> <label for="{{ form.name.id_for_label }}">{{ _("Name") }}</label>
{% if form.name.errors %} {% if form.name.errors %}<div class="alert alert-danger mt-2">{{ form.name.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.name.errors }}
</div> </div>
{% endif %}
</div>
<!-- Description Field --> <!-- Description Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.description|add_class:"form-control form-control-sm" }} {{ form.description|add_class:"form-control form-control-sm" }}
<label for="{{ form.description.id_for_label }}">{{ _("Description") }}</label> <label for="{{ form.description.id_for_label }}">{{ _("Description") }}</label>
{% if form.description.errors %} {% if form.description.errors %}<div class="alert alert-danger mt-2">{{ form.description.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.description.errors }}
</div> </div>
{% endif %}
</div>
<!-- Duration Field --> <!-- Duration Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.duration|add_class:"form-control form-control-sm" }} {{ form.duration|add_class:"form-control form-control-sm" }}
<label for="{{ form.duration.id_for_label }}">{{ _("Duration") }}</label> <label for="{{ form.duration.id_for_label }}">{{ _("Duration") }}</label>
{% if form.duration.errors %} {% if form.duration.errors %}<div class="alert alert-danger mt-2">{{ form.duration.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.duration.errors }}
</div> </div>
{% endif %}
</div>
<!-- Price Field --> <!-- Price Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.price|add_class:"form-control form-control-sm" }} {{ form.price|add_class:"form-control form-control-sm" }}
<label for="{{ form.price.id_for_label }}">{{ _("Price") }}</label> <label for="{{ form.price.id_for_label }}">{{ _("Price") }}</label>
{% if form.price.errors %} {% if form.price.errors %}<div class="alert alert-danger mt-2">{{ form.price.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.price.errors }}
</div> </div>
{% endif %}
</div>
<!-- Down Payment Field --> <!-- Down Payment Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.down_payment|add_class:"form-control form-control-sm" }} {{ form.down_payment|add_class:"form-control form-control-sm" }}
<label for="{{ form.down_payment.id_for_label }}">{{ _("Down Payment") }}</label> <label for="{{ form.down_payment.id_for_label }}">{{ _("Down Payment") }}</label>
{% if form.down_payment.errors %} {% if form.down_payment.errors %}<div class="alert alert-danger mt-2">{{ form.down_payment.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.down_payment.errors }}
</div> </div>
{% endif %}
</div>
<!-- Image Field --> <!-- Image Field -->
<div class="mb-3"> <div class="mb-3">
<label for="{{ form.image.id_for_label }}" class="form-label">{{ _("Image") }}</label> <label for="{{ form.image.id_for_label }}" class="form-label">{{ _("Image") }}</label>
{{ form.image }} {{ form.image }}
{% if form.image.errors %} {% if form.image.errors %}<div class="alert alert-danger mt-2">{{ form.image.errors }}</div>{% endif %}
<div class="alert alert-danger mt-2">
{{ form.image.errors }}
</div> </div>
{% endif %}
</div>
<!-- Currency Field --> <!-- Currency Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<select name="currency" id="id_currency" class="form-select form-control-sm"> <select name="currency" id="id_currency" class="form-select form-control-sm">
<option class="icon-saudi_riyal" value="SAR"><span class="icon-saudi_riyal"></span></option> <option class="icon-saudi_riyal" value="SAR">
<span class="icon-saudi_riyal"></span>
</option>
</select> </select>
<label for="id_currency"> <span class="icon-saudi_riyal"></span></label> <label for="id_currency">
{% if form.currency.errors %} <span class="icon-saudi_riyal"></span>
<div class="alert alert-danger mt-2"> </label>
{{ form.currency.errors }} {% if form.currency.errors %}<div class="alert alert-danger mt-2">{{ form.currency.errors }}</div>{% endif %}
</div> </div>
{% endif %}
</div>
<!-- Background Color Field --> <!-- Background Color Field -->
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input type="color" value="#000000" id="{{ form.background_color.id_for_label }}" class="form-control form-control-sm" > <input type="color"
value="#000000"
id="{{ form.background_color.id_for_label }}"
class="form-control form-control-sm">
<label for="{{ form.background_color.id_for_label }}">{{ _("Background Color") }}</label> <label for="{{ form.background_color.id_for_label }}">{{ _("Background Color") }}</label>
{% if form.background_color.errors %} {% if form.background_color.errors %}
<div class="alert alert-danger mt-2"> <div class="alert alert-danger mt-2">{{ form.background_color.errors }}</div>
{{ form.background_color.errors }}
</div>
{% endif %} {% endif %}
</div> </div>
{% if btn_text %} {% if btn_text %}
<button type="submit" class="btn btn-sm btn-phoenix-primary">{{ btn_text }}</button> <button type="submit" class="btn btn-sm btn-phoenix-primary">{{ btn_text }}</button>
{% else %} {% else %}
@ -126,14 +89,11 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</form> </form>
</div> </div>
</div> </div>
{% include 'modal/confirm_modal.html' %} {% include 'modal/confirm_modal.html' %}
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/modal/show_modal.js' %}"></script> <script src="{% static 'js/modal/show_modal.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -1,11 +1,11 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/app_admin/staff_member.css' %}"/> <link rel="stylesheet"
type="text/css"
href="{% static 'css/app_admin/staff_member.css' %}" />
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<section class="main-container"> <section class="main-container">
<div class="container-fluid"> <div class="container-fluid">
@ -25,54 +25,55 @@
</small> </small>
</div> </div>
{% endif %} {% endif %}
<div class="form-group"> <div class="form-group">
{{ form.services_offered.label_tag }} {{ form.services_offered.label_tag }}
{{ form.services_offered.errors }} {{ form.services_offered.errors }}
{{ form.services_offered }} {{ form.services_offered }}
<br><small>{% trans 'Hold down “Control”, or “Command” on a Mac, to select more than one.' %}</small> <br>
<small>{% trans 'Hold down “Control”, or “Command” on a Mac, to select more than one.' %}</small>
</div> </div>
<div class="form-group"> <div class="form-group">
{{ form.slot_duration.label_tag }} {{ form.slot_duration.label_tag }}
{{ form.slot_duration }} {{ form.slot_duration }}
<small>{{ form.slot_duration.help_text }}</small> <small>{{ form.slot_duration.help_text }}</small>
</div> </div>
<div class="form-group"> <div class="form-group">
{{ form.lead_time.label_tag }} {{ form.lead_time.label_tag }}
{{ form.lead_time }} {{ form.lead_time }}
<small>{{ form.lead_time.help_text }}</small> <small>{{ form.lead_time.help_text }}</small>
</div> </div>
<div class="form-group"> <div class="form-group">
{{ form.finish_time.label_tag }} {{ form.finish_time.label_tag }}
{{ form.finish_time }} {{ form.finish_time }}
<small>{{ form.finish_time.help_text }}</small> <small>{{ form.finish_time.help_text }}</small>
</div> </div>
<div class="form-group"> <div class="form-group">
{{ form.appointment_buffer_time.label_tag }} {{ form.appointment_buffer_time.label_tag }}
{{ form.appointment_buffer_time }} {{ form.appointment_buffer_time }}
<small>{{ form.appointment_buffer_time.help_text }}</small> <small>{{ form.appointment_buffer_time.help_text }}</small>
</div> </div>
<div class="form-check"> <div class="form-check">
{{ form.work_on_saturday }} {{ form.work_on_saturday }}
{{ form.work_on_saturday.label_tag }} {{ form.work_on_saturday.label_tag }}
</div> </div>
<div class="form-check"> <div class="form-check">
{{ form.work_on_sunday }} {{ form.work_on_sunday }}
{{ form.work_on_sunday.label_tag }} {{ form.work_on_sunday.label_tag }}
</div> </div>
<button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-primary">{% trans 'Save' %}</button>
</form> </form>
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@ -81,7 +82,6 @@
</div> </div>
</section> </section>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -1,40 +1,39 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %}{% endblock %}
{% block customCSS %}
{% endblock %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h3 class="mb-3">{% trans 'Staff Personal Information' %}</h3> <h3 class="mb-3">{% trans 'Staff Personal Information' %}</h3>
<form id="updatePersonalInfoForm" method="post" action=""> <form id="updatePersonalInfoForm" method="post" action="">
{% csrf_token %} {% csrf_token %}
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.first_name }} {{ form.first_name }}
<label for="first_name">{{ _("First Name") }}</label> <label for="first_name">{{ _("First Name") }}</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.last_name }} {{ form.last_name }}
<label for="last_name">{{ _("Last Name") }}</label> <label for="last_name">{{ _("Last Name") }}</label>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
{{ form.email }} {{ form.email }}
<label for="email">{{ _("Email") }}</label> <label for="email">{{ _("Email") }}</label>
</div> </div>
<button type="submit" class="btn btn-phoenix-primary">{{ btn_text }}</button> <button type="submit" class="btn btn-phoenix-primary">{{ btn_text }}</button>
</form> </form>
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@ -42,7 +41,6 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -2,70 +2,107 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% load custom_filters %} {% load custom_filters %}
{% block customCSS %}<!-- additional CSS -->{% endblock %}
{% block customCSS %}
<!-- additional CSS -->
{% endblock %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h3>{% trans "Manage Working Hours" %}</h3> <h3>{% trans "Manage Working Hours" %}</h3>
<form class="form" method="post" action="" id="workingHoursForm" <form class="form"
data-action="{% if working_hours_instance %}update{% else %}create{% endif %}" method="post"
action=""
id="workingHoursForm"
data-action="{% if working_hours_instance %}
update
{% else %}
create
{% endif %}"
data-working-hours-id=" data-working-hours-id="
{% if working_hours_instance %}{{ working_hours_instance.id }}{% else %}0{% endif %}" {% if working_hours_instance %}
data-staff-user-id="{% if staff_user_id %}{{ staff_user_id }}{% else %}0{% endif %}"> {{ working_hours_instance.id }}
{% else %}
0
{% endif %}"
data-staff-user-id="{% if staff_user_id %}
{{ staff_user_id }}
{% else %}
0
{% endif %}">
{% csrf_token %} {% csrf_token %}
{% if working_hours_form.staff_member %} {% if working_hours_form.staff_member %}
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="form-label" for="{{ working_hours_form.staff_member.id_for_label }}">{% trans 'Staff Member' %}:</label> <label class="form-label"
for="{{ working_hours_form.staff_member.id_for_label }}">
{% trans 'Staff Member' %}:
</label>
{{ working_hours_form.staff_member }} {{ working_hours_form.staff_member }}
</div> </div>
{% endif %} {% endif %}
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="form-label" for="{{ working_hours_form.day_of_week.id_for_label }}">{% trans 'Day of Week' %}:</label> <label class="form-label"
for="{{ working_hours_form.day_of_week.id_for_label }}">{% trans 'Day of Week' %}:</label>
{{ working_hours_form.day_of_week|add_class:"form-select form-select-sm" }} {{ working_hours_form.day_of_week|add_class:"form-select form-select-sm" }}
</div> </div>
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="form-label" for="{{ working_hours_form.start_time.id_for_label }}">{% trans 'Start time' %}:</label> <label class="form-label"
<div class="input-group time24hr" id="start-timepicker" data-target-input="nearest"> for="{{ working_hours_form.start_time.id_for_label }}">{% trans 'Start time' %}:</label>
<input type="text" class="form-control form-control-sm datetimepicker-input" data-toggle="datetimepicker" <div class="input-group time24hr"
data-target="#start-timepicker" name="{{ working_hours_form.start_time.name }}" id="start-timepicker"
data-target-input="nearest">
<input type="text"
class="form-control form-control-sm datetimepicker-input"
data-toggle="datetimepicker"
data-target="#start-timepicker"
name="{{ working_hours_form.start_time.name }}"
value="{{ working_hours_form.start_time.value|default:'09:00 AM' }}" value="{{ working_hours_form.start_time.value|default:'09:00 AM' }}"
id="{{ working_hours_form.start_time.id_for_label }}"> id="{{ working_hours_form.start_time.id_for_label }}">
<div class="input-group-text" data-toggle="datetimepicker" data-target="#start-timepicker"><i class="far fa-clock"></i></div> <div class="input-group-text"
data-toggle="datetimepicker"
data-target="#start-timepicker">
<i class="far fa-clock"></i>
</div>
</div> </div>
</div> </div>
<div class="form-group mb-3"> <div class="form-group mb-3">
<label class="form-label" for="{{ working_hours_form.end_time.id_for_label }}">{% trans 'End time' %}:</label> <label class="form-label"
<div class="input-group date" id="end-timepicker" data-target-input="nearest"> for="{{ working_hours_form.end_time.id_for_label }}">{% trans 'End time' %}:</label>
<input type="text" class="form-control form-control-sm datetimepicker-input" data-toggle="datetimepicker" <div class="input-group date"
data-target="#end-timepicker" name="{{ working_hours_form.end_time.name }}" id="end-timepicker"
data-target-input="nearest">
<input type="text"
class="form-control form-control-sm datetimepicker-input"
data-toggle="datetimepicker"
data-target="#end-timepicker"
name="{{ working_hours_form.end_time.name }}"
value="{{ working_hours_form.end_time.value|default:'05:00 PM' }}" value="{{ working_hours_form.end_time.value|default:'05:00 PM' }}"
id="{{ working_hours_form.end_time.id_for_label }}"> id="{{ working_hours_form.end_time.id_for_label }}">
<div class="input-group-text" data-toggle="datetimepicker" data-target="#end-timepicker"><i class="far fa-clock"></i></div> <div class="input-group-text"
data-toggle="datetimepicker"
data-target="#end-timepicker">
<i class="far fa-clock"></i>
</div>
</div> </div>
</div> </div>
<button type="submit" class="btn btn-sm btn-phoenix-primary">{{ button_text }}</button> <button type="submit" class="btn btn-sm btn-phoenix-primary">{{ button_text }}</button>
<input type="hidden" id="addWorkingHoursUrl" <input type="hidden"
id="addWorkingHoursUrl"
value="{% url 'appointment:add_working_hours_id' staff_user_id|default:user.id %}"> value="{% url 'appointment:add_working_hours_id' staff_user_id|default:user.id %}">
<input type="hidden" id="updateWorkingHoursUrl" <input type="hidden"
id="updateWorkingHoursUrl"
value="{% url 'appointment:update_working_hours_id' working_hours_id|default:0 staff_user_id|default:user.id %}"> value="{% url 'appointment:update_working_hours_id' working_hours_id|default:0 staff_user_id|default:user.id %}">
</form> </form>
{% include 'modal/error_modal.html' %} {% include 'modal/error_modal.html' %}
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@ -75,19 +112,22 @@
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<!-- JS --> <!-- JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js"
integrity="sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ==" integrity="sha512-TPh2Oxlg1zp+kz3nFA0C5vVC6leG/6mm1z9+mA81MI5eaUVqasPLO8Cuk4gMF4gUfP5etR73rgU/8PNMsSesoQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.min.js"
integrity="sha512-7rusk8kGPFynZWu26OKbTeI+QPoYchtxsmPeBqkHIEXJxeun4yJ4ISYe7C6sz9wdxeE1Gk3VxsIWgCZTc+vX3g==" integrity="sha512-7rusk8kGPFynZWu26OKbTeI+QPoYchtxsmPeBqkHIEXJxeun4yJ4ISYe7C6sz9wdxeE1Gk3VxsIWgCZTc+vX3g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js"
integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg==" integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.39.0/js/tempusdominus-bootstrap-4.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.39.0/js/tempusdominus-bootstrap-4.min.js"
integrity="sha512-k6/Bkb8Fxf/c1Tkyl39yJwcOZ1P4cRrJu77p83zJjN2Z55prbFHxPs9vN7q3l3+tSMGPDdoH51AEU8Vgo1cgAA==" integrity="sha512-k6/Bkb8Fxf/c1Tkyl39yJwcOZ1P4cRrJu77p83zJjN2Z55prbFHxPs9vN7q3l3+tSMGPDdoH51AEU8Vgo1cgAA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script type="text/javascript"> <script type="text/javascript">
const addWorkingHoursUrl = $('#addWorkingHoursUrl').val(); const addWorkingHoursUrl = $('#addWorkingHoursUrl').val();
const updateWorkingHoursUrl = $('#updateWorkingHoursUrl').val(); const updateWorkingHoursUrl = $('#updateWorkingHoursUrl').val();
@ -163,4 +203,3 @@
<script src="{% static 'js/modal/error_modal.js' %}"></script> <script src="{% static 'js/modal/error_modal.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block title %} {% block title %}
{% trans 'Service List' %} {% trans 'Service List' %}
{% endblock %} {% endblock %}
@ -29,7 +28,13 @@
<tbody> <tbody>
{% for service in services %} {% for service in services %}
<tr> <tr>
<td><img class="rounded-soft" src="{{ service.get_image_url }}" alt="" style="width: 35px; height: 35px;"/></td> <td>
<img class="rounded-soft"
src="{{ service.get_image_url }}"
alt=""
style="width: 35px;
height: 35px" />
</td>
<td>{{ service.name }}</td> <td>{{ service.name }}</td>
<td>{{ service.get_duration }}</td> <td>{{ service.get_duration }}</td>
<td>{{ service.get_price_text }}</td> <td>{{ service.get_price_text }}</td>
@ -64,11 +69,8 @@
</div> </div>
{% include 'modal/confirm_modal.html' %} {% include 'modal/confirm_modal.html' %}
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/modal/show_modal.js' %}"></script> <script src="{% static 'js/modal/show_modal.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -1,18 +1,16 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customMetaTag %} {% block customMetaTag %}<meta name="csrf-token" content="{{ csrf_token }}">{% endblock %}
<meta name="csrf-token" content="{{ csrf_token }}">
{% endblock %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/appt-common.css' %}"/> <link rel="stylesheet"
<link rel="stylesheet" type="text/css" href="{% static 'css/app_admin/admin.css' %}"/> type="text/css"
href="{% static 'css/appt-common.css' %}" />
<link rel="stylesheet"
type="text/css"
href="{% static 'css/app_admin/admin.css' %}" />
{% endblock %} {% endblock %}
{% block title %} {% block title %}{{ page_title }}{% endblock %}
{{ page_title }}
{% endblock %}
{% block content %} {% block content %}
<section class="content content-wrapper"> <section class="content content-wrapper">
<div class="container"> <div class="container">
@ -20,40 +18,49 @@
<div id="calendar" class="calendarbox"></div> <div id="calendar" class="calendarbox"></div>
<div id="event-list-container" class="event-list-container"></div> <div id="event-list-container" class="event-list-container"></div>
</div> </div>
{% include 'modal/event_details_modal.html' %} {% include 'modal/event_details_modal.html' %}
{% include 'modal/error_modal.html' %} {% include 'modal/error_modal.html' %}
<div class="messages" style="margin: 20px 0"> <div class="messages" style="margin: 20px 0">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
</section> </section>
<div id="customContextMenu" style="display: none; position: absolute; z-index: 1000;"> <div id="customContextMenu"
style="display: none;
<a id="newAppointmentOption" class="btn btn-sm btn-phoenix-success rounded-pill me-1 mb-1" href="#">{{ _("New Appointment")}}</a> position: absolute;
z-index: 1000">
<a id="newAppointmentOption"
class="btn btn-sm btn-phoenix-success rounded-pill me-1 mb-1"
href="#">{{ _("New Appointment") }}</a>
</div> </div>
{% include 'modal/confirm_modal.html' %} {% include 'modal/confirm_modal.html' %}
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js"
integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg==" integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js"
integrity="sha512-t/mY3un180WRfsSkWy4Yi0tAxEDGcY2rAEx873hb5BrkvLA0QLk54+SjfYgFBBoCdJDV1H86M8uyZdJhAOHeyA==" integrity="sha512-t/mY3un180WRfsSkWy4Yi0tAxEDGcY2rAEx873hb5BrkvLA0QLk54+SjfYgFBBoCdJDV1H86M8uyZdJhAOHeyA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js"
integrity="sha512-JCQkxdym6GmQ+AFVioDUq8dWaWN6tbKRhRyHvYZPupQ6DxpXzkW106FXS1ORgo/m3gxtt5lHRMqSdm2OfPajtg==" integrity="sha512-JCQkxdym6GmQ+AFVioDUq8dWaWN6tbKRhRyHvYZPupQ6DxpXzkW106FXS1ORgo/m3gxtt5lHRMqSdm2OfPajtg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script> <script>
const timezone = "{{ timezone }}"; const timezone = "{{ timezone }}";
const locale = "{{ locale }}"; const locale = "{{ locale }}";
@ -88,12 +95,10 @@
const noServiceOfferedTxt = "{% trans "You don't offer any service. Add new service from your profile." %}"; const noServiceOfferedTxt = "{% trans "You don't offer any service. Add new service from your profile." %}";
const noStaffMemberTxt = "{% trans "No staff members found." %}"; const noStaffMemberTxt = "{% trans "No staff members found." %}";
</script> </script>
<script src="{% static 'js/modal/error_modal.js' %}"></script> <script src="{% static 'js/modal/error_modal.js' %}"></script>
<script src="{% static 'js/app_admin/staff_index.js' %}"></script> <script src="{% static 'js/app_admin/staff_index.js' %}"></script>
<script src="{% static 'js/modal/show_modal.js' %}"></script> <script src="{% static 'js/modal/show_modal.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
<script> <script>
function createCommonInputFields(appointment, servicesDropdown, isEditMode, defaultStartTime, staffDropdown) { function createCommonInputFields(appointment, servicesDropdown, isEditMode, defaultStartTime, staffDropdown) {
const startTimeValue = isEditMode ? moment(appointment.start_time).format('HH:mm:ss') : defaultStartTime; const startTimeValue = isEditMode ? moment(appointment.start_time).format('HH:mm:ss') : defaultStartTime;

View File

@ -1,26 +1,17 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}{% endblock %}
{% block title %}{{ _("Staff Members List") }}{% endblock %}
{% endblock %}
{% block title %}
{{ _("Staff Members List")}}
{% endblock %}
{% block description %} {% block description %}
{% trans 'List of all staff members' %}. {% trans 'List of all staff members' %}.
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h3 class="section-header-itm">{% trans 'Staff Members' %}</h3> <h3 class="section-header-itm">{% trans 'Staff Members' %}</h3>
<div class="buttons-container section-header-itm"> <div class="buttons-container section-header-itm">
<a href="{{ btn_staff_me_link }}" <a href="{{ btn_staff_me_link }}" class="btn btn-sm btn-phoenix-info">{{ btn_staff_me }}</a>
class="btn btn-sm btn-phoenix-info">
{{ btn_staff_me }}
</a>
<a href="{% url 'appointment:add_staff_member_info' %}" <a href="{% url 'appointment:add_staff_member_info' %}"
class="btn btn-sm btn-phoenix-success">{{ _("Add") }} class="btn btn-sm btn-phoenix-success">{{ _("Add") }}
<i class="fas fa-add"></i> <i class="fas fa-add"></i>
@ -53,16 +44,12 @@
<td colspan="3">{% trans 'No staff members found' %}.</td> <td colspan="3">{% trans 'No staff members found' %}.</td>
</tr> </tr>
{% endfor %} {% endfor %}
<small> <small>{% trans "PS: Remove means, deleting the staff status of the user. The user account is still active." %}</small>
{% trans "PS: Remove means, deleting the staff status of the user. The user account is still active." %}
</small>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -1,28 +1,26 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}{% endblock %}
{% block title %}{{ page_title }}{% endblock %}
{% endblock %} {% block description %}{{ page_description }}{% endblock %}
{% block title %}
{{ page_title }}
{% endblock %}
{% block description %}
{{ page_description }}
{% endblock %}
{% block content %} {% block content %}
<div class="row mt-4"> <div class="row mt-4">
<div class="col-6"> <div class="col-6">
{% translate "Confirm Deletion" as modal_title %} {% translate "Confirm Deletion" as modal_title %}
{% translate "Delete" as delete_btn_modal %} {% translate "Delete" as delete_btn_modal %}
<h3>{% trans 'Personal Information' %}</h3> <h3>{% trans 'Personal Information' %}</h3>
<!-- Display fields from PersonalInformationForm --> <!-- Display fields from PersonalInformationForm -->
<div class="section-content"> <div class="section-content">
<p><strong>{% trans 'First name' %}:</strong> {{ user.first_name }}</p> <p>
<p><strong>{% trans 'Last name' %}:</strong> {{ user.last_name }}</p> <strong>{% trans 'First name' %}:</strong> {{ user.first_name }}
<p><strong>{% trans 'Email' %}:</strong> {{ user.email }}</p> </p>
<p>
<strong>{% trans 'Last name' %}:</strong> {{ user.last_name }}
</p>
<p>
<strong>{% trans 'Email' %}:</strong> {{ user.email }}
</p>
</div> </div>
<a href="{% url 'appointment:update_user_info' user.id %}" <a href="{% url 'appointment:update_user_info' user.id %}"
class="btn btn-sm btn-phoenix-primary"> class="btn btn-sm btn-phoenix-primary">
@ -30,32 +28,34 @@
</a> </a>
</div> </div>
</div> </div>
<!-- Appointment Information Section --> <!-- Appointment Information Section -->
<div class="row mt-4"> <div class="row mt-4">
<div class="col-6"> <div class="col-6">
<h3>{% trans 'Appointments Information' %}</h3> <h3>{% trans 'Appointments Information' %}</h3>
<small> <small>{{ service_msg }}</small>
{{ service_msg }}
</small>
{% if staff_member %} {% if staff_member %}
<div class="section-content"> <div class="section-content">
<p> <p>
<strong>{% trans 'Slot duration' %}:</strong> {{ staff_member.get_slot_duration_text }} <strong>{% trans 'Slot duration' %}:</strong> {{ staff_member.get_slot_duration_text }}
<i class="fas fa-info-circle" data-toggle="tooltip" <i class="fas fa-info-circle"
data-toggle="tooltip"
title="{{ slot_duration_help_text }}"></i> title="{{ slot_duration_help_text }}"></i>
</p> </p>
<p><strong>{% trans 'General start time' %}:</strong> {{ staff_member.get_lead_time }}</p> <p>
<p><strong>{% trans 'General end time' %}:</strong> {{ staff_member.get_finish_time }}</p> <strong>{% trans 'General start time' %}:</strong> {{ staff_member.get_lead_time }}
</p>
<p>
<strong>{% trans 'General end time' %}:</strong> {{ staff_member.get_finish_time }}
</p>
<p> <p>
<strong>{% trans 'Weekend days you work' %}:</strong> {{ staff_member.get_weekend_days_worked_text }} <strong>{% trans 'Weekend days you work' %}:</strong> {{ staff_member.get_weekend_days_worked_text }}
</p> </p>
<p> <p>
<strong>{% trans 'Appointment buffer time' %}:</strong> {{ staff_member.get_appointment_buffer_time_text }} <strong>{% trans 'Appointment buffer time' %}:</strong> {{ staff_member.get_appointment_buffer_time_text }}
<i class="fas fa-info-circle" data-toggle="tooltip" title="{{ buffer_time_help_text }}"></i> <i class="fas fa-info-circle"
data-toggle="tooltip"
title="{{ buffer_time_help_text }}"></i>
</p> </p>
</div> </div>
<a href="{% url 'appointment:update_staff_other_info' staff_member.user.id %}" <a href="{% url 'appointment:update_staff_other_info' staff_member.user.id %}"
class="btn btn-sm section-content-button modify-btn button-color-blue btn-phoenix-primary"> class="btn btn-sm section-content-button modify-btn button-color-blue btn-phoenix-primary">
@ -72,7 +72,6 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
<!-- Days Off Information Section --> <!-- Days Off Information Section -->
<section class="profile"> <section class="profile">
<div class="container"> <div class="container">
@ -140,7 +139,6 @@
</div> </div>
</div> </div>
</section> </section>
<!-- Working Hours Information Section --> <!-- Working Hours Information Section -->
<section class="profile"> <section class="profile">
<div class="container"> <div class="container">
@ -165,7 +163,6 @@
<tbody> <tbody>
{% for working_hour in working_hours %} {% for working_hour in working_hours %}
<tr> <tr>
{% if working_hour.day_of_week == 0 %} {% if working_hour.day_of_week == 0 %}
<td>{{ _("Sunday") }}</td> <td>{{ _("Sunday") }}</td>
{% elif working_hour.day_of_week == 1 %} {% elif working_hour.day_of_week == 1 %}
@ -181,7 +178,6 @@
{% elif working_hour.day_of_week == 6 %} {% elif working_hour.day_of_week == 6 %}
<td>{{ _("Saturday") }}</td> <td>{{ _("Saturday") }}</td>
{% endif %} {% endif %}
<td>{{ working_hour.start_time|time:"g:i A" }}</td> <td>{{ working_hour.start_time|time:"g:i A" }}</td>
<td>{{ working_hour.end_time|time:"g:i A" }}</td> <td>{{ working_hour.end_time|time:"g:i A" }}</td>
<td> <td>
@ -224,7 +220,6 @@
</div> </div>
</div> </div>
</section> </section>
<!-- Service Information Section --> <!-- Service Information Section -->
<section class="profile"> <section class="profile">
<div class="container"> <div class="container">
@ -265,17 +260,11 @@
</div> </div>
</div> </div>
</section> </section>
{% include 'modal/confirm_modal.html' %} {% include 'modal/confirm_modal.html' %}
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<!-- Bootstrap's JS and CSS (if not already included) --> <!-- Bootstrap's JS and CSS (if not already included) -->
<!-- Our custom modal JS --> <!-- Our custom modal JS -->
<script src="{% static 'js/modal/show_modal.js' %}"></script> <script src="{% static 'js/modal/show_modal.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/js-utils.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -2,7 +2,9 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/appointments-user-details.css' %}"/> <link rel="stylesheet"
type="text/css"
href="{% static 'css/appointments-user-details.css' %}" />
{% endblock %} {% endblock %}
{% block title %} {% block title %}
{% translate 'Client Information' %} - {{ ar.get_service_name }} {% translate 'Client Information' %} - {{ ar.get_service_name }}
@ -22,9 +24,7 @@
{% csrf_token %} {% csrf_token %}
<div class="appointment-user-info"> <div class="appointment-user-info">
<div class="appointment-user-info-title"> <div class="appointment-user-info-title">
<div class="title"> <div class="title">{% trans "Fill out your details" %}</div>
{% trans "Fill out your details" %}
</div>
</div> </div>
<hr class="second-part"> <hr class="second-part">
<div class="user-info-input"> <div class="user-info-input">
@ -37,10 +37,14 @@
</div> </div>
</div> </div>
<div class="name-email"> <div class="name-email">
<label for="{{ form.name.id_for_label }}" class="name">{% trans "Full Name" %} *<br> <label for="{{ form.name.id_for_label }}" class="name">
{% trans "Full Name" %} *
<br>
{{ client_data_form.name }} {{ client_data_form.name }}
</label> </label>
<label for="{{ form.email.id_for_label }}" class="email">{% trans "Email" %} *<br> <label for="{{ form.email.id_for_label }}" class="email">
{% trans "Email" %} *
<br>
{{ client_data_form.email }} {{ client_data_form.email }}
</label> </label>
</div> </div>
@ -52,19 +56,22 @@
</div> </div>
<div class="phone-number"> <div class="phone-number">
<label for="{{ form.phone.id_for_label }}"> <label for="{{ form.phone.id_for_label }}">
{% trans "Phone" %} *<br> {% trans "Phone" %} *
<br>
</label> </label>
<div class="phone-input-container"> <div class="phone-input-container">{{ form.phone }}</div>
{{ form.phone }}
</div>
</div> </div>
<div class="address"> <div class="address">
<label for="{{ form.address.id_for_label }}">{% trans "City and State" %} * :<br> <label for="{{ form.address.id_for_label }}">
{% trans "City and State" %} * :
<br>
{{ form.address }} {{ form.address }}
</label> </label>
</div> </div>
<div class="additional-information"> <div class="additional-information">
<label for="{{ form.additional_info.id_for_label }}">{% trans 'Additional Information' %}<br> <label for="{{ form.additional_info.id_for_label }}">
{% trans 'Additional Information' %}
<br>
{{ form.additional_info }} {{ form.additional_info }}
</label> </label>
</div> </div>
@ -73,18 +80,14 @@
</div> </div>
<div class="service-description-and-pay"> <div class="service-description-and-pay">
<div class="service-details-title">{% trans "Service Details" %}</div> <div class="service-details-title">{% trans "Service Details" %}</div>
<hr class="second-part"> <hr class="second-part">
<div class="service-description-content"> <div class="service-description-content">
<div class="item-name">{{ ar.get_service_name }}</div> <div class="item-name">{{ ar.get_service_name }}</div>
<div id="service-datetime-chosen" <div id="service-datetime-chosen" class="service-datetime-chosen">
class="service-datetime-chosen">
{{ ar.date }}&nbsp;{% trans "at" %}&nbsp;{{ ar.start_time }} {{ ar.date }}&nbsp;{% trans "at" %}&nbsp;{{ ar.start_time }}
</div> </div>
<div>{{ ar.service.get_duration }}</div> <div>{{ ar.service.get_duration }}</div>
</div> </div>
<hr class="second-part"> <hr class="second-part">
{% if ar.is_a_paid_service %} {% if ar.is_a_paid_service %}
{% if APPOINTMENT_PAYMENT_URL %} {% if APPOINTMENT_PAYMENT_URL %}
@ -95,12 +98,13 @@
<div>${{ ar.get_service_price }}</div> <div>${{ ar.get_service_price }}</div>
</div> </div>
<div class="payment-options"> <div class="payment-options">
<button type="submit" class="btn btn-phoenix-primary btn-pay-full" name="payment_type" <button type="submit"
value="full"> class="btn btn-phoenix-primary btn-pay-full"
{% trans "Pay" %} name="payment_type"
</button> value="full">{% trans "Pay" %}</button>
{% if ar.accepts_down_payment %} {% if ar.accepts_down_payment %}
<button type="submit" class="btn btn-phoenix-primary btn-pay-down-payment" <button type="submit"
class="btn btn-phoenix-primary btn-pay-down-payment"
name="payment_type" name="payment_type"
value="down"> value="down">
{% trans "Down Payment" %} (${{ ar.get_service_down_payment }}) {% trans "Down Payment" %} (${{ ar.get_service_down_payment }})
@ -109,16 +113,16 @@
</div> </div>
</div> </div>
{% else %} {% else %}
<button type="submit" class="btn btn-phoenix-primary btn-submit-appointment" name="payment_type" <button type="submit"
value="full"> class="btn btn-phoenix-primary btn-submit-appointment"
{% trans "Finish" %} name="payment_type"
</button> value="full">{% trans "Finish" %}</button>
{% endif %} {% endif %}
{% else %} {% else %}
<button type="submit" class="btn btn-phoenix-primary btn-submit-appointment" name="payment_type" <button type="submit"
value="full"> class="btn btn-phoenix-primary btn-submit-appointment"
{% trans "Finish" %} name="payment_type"
</button> value="full">{% trans "Finish" %}</button>
{% endif %} {% endif %}
</div> </div>
</form> </form>

View File

@ -2,40 +2,38 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/appt-common.css' %}"/> <link rel="stylesheet"
<link rel="stylesheet" type="text/css" href="{% static 'css/appointments.css' %}"/> type="text/css"
{% endblock %} href="{% static 'css/appt-common.css' %}" />
{% block title %} <link rel="stylesheet"
{{ page_title }} type="text/css"
{% endblock %} href="{% static 'css/appointments.css' %}" />
{% block description %}
{{ page_description }}
{% endblock %} {% endblock %}
{% block title %}{{ page_title }}{% endblock %}
{% block description %}{{ page_description }}{% endblock %}
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-xl-12"> <div class="col-xl-12">
<h3 class="page-title"> <h3 class="page-title">
{% if page_header %}{{ page_header }}{% else %}{{ service.name }}{% endif %} </h3> {% if page_header %}
{{ page_header }}
{% else %}
{{ service.name }}
{% endif %}
</h3>
<small class="page-description"> <small class="page-description">
{% trans "Check out our availability and book the date and time that works for you" %} {% trans "Check out our availability and book the date and time that works for you" %}
</small> </small>
<hr> <hr>
<div class="djangoAppt_page-body"> <div class="djangoAppt_page-body">
<div class="djangoAppt_appointment-calendar"> <div class="djangoAppt_appointment-calendar">
<div class="djangoAppt_appointment-calendar-title-timezone"> <div class="djangoAppt_appointment-calendar-title-timezone">
<div class="djangoAppt_title"> <div class="djangoAppt_title">{% trans "Select a date and time" %}</div>
{% trans "Select a date and time" %} <div class="djangoAppt_timezone-details">{% trans "Timezone" %}:&nbsp;{{ timezoneTxt }}</div>
</div>
<div class="djangoAppt_timezone-details">
{% trans "Timezone" %}:&nbsp;{{ timezoneTxt }}
</div>
</div> </div>
<hr class="djangoAppt_second-part"> <hr class="djangoAppt_second-part">
<div class="djangoAppt_calendar-and-slot"> <div class="djangoAppt_calendar-and-slot">
<div class="djangoAppt_calendar" id="calendar"> <div class="djangoAppt_calendar" id="calendar"></div>
</div>
<div class="djangoAppt_slot"> <div class="djangoAppt_slot">
<div class="djangoAppt_date_chosen">{{ date_chosen }}</div> <div class="djangoAppt_date_chosen">{{ date_chosen }}</div>
<div class="slot-container"> <div class="slot-container">
@ -44,27 +42,29 @@
<!-- Slot list will be updated dynamically by the AJAX request --> <!-- Slot list will be updated dynamically by the AJAX request -->
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
{% if rescheduled_date %} {% if rescheduled_date %}
<div class="form-group" style="margin-top: 10px"> <div class="form-group" style="margin-top: 10px">
<label for="reason_for_rescheduling">{% trans "Reason for rescheduling" %}:</label> <label for="reason_for_rescheduling">{% trans "Reason for rescheduling" %}:</label>
<textarea name="reason_for_rescheduling" id="reason_for_rescheduling" <textarea name="reason_for_rescheduling"
class="form-control" rows="1" required></textarea> id="reason_for_rescheduling"
class="form-control"
rows="1"
required></textarea>
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="djangoAppt_service-description"> <div class="djangoAppt_service-description">
<form method="post" action="{% url 'appointment:appointment_request_submit' %}" <form method="post"
action="{% url 'appointment:appointment_request_submit' %}"
class="appointment-form"> class="appointment-form">
{% csrf_token %} {% csrf_token %}
<div class="staff-members-list"> <div class="staff-members-list">
<label class="djangoAppt_item-name" for="staff_id">{{ label }}</label> <label class="djangoAppt_item-name" for="staff_id">{{ label }}</label>
<select name="staff_member" id="staff_id"> <select name="staff_member" id="staff_id">
{% if not staff_member %} {% if not staff_member %}
<option value="none" <option value="none" selected>{% trans 'Please select a staff member' %}</option>
selected>{% trans 'Please select a staff member' %}</option>
{% endif %} {% endif %}
{% for sf in all_staff_members %} {% for sf in all_staff_members %}
<option value="{{ sf.id }}" <option value="{{ sf.id }}"
@ -72,7 +72,6 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div>{% trans "Service Details" %}</div> <div>{% trans "Service Details" %}</div>
<hr class="djangoAppt_second-part"> <hr class="djangoAppt_second-part">
<div class="djangoAppt_service-description-content"> <div class="djangoAppt_service-description-content">
@ -89,25 +88,34 @@
</div> </div>
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.js"
integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg==" integrity="sha512-3CuraBvy05nIgcoXjVN33mACRyI89ydVHg7y/HMN9wcTVbHeur0SeBzweSd/rxySapO7Tmfu68+JlKkLTnDFNg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js"
integrity="sha512-t/mY3un180WRfsSkWy4Yi0tAxEDGcY2rAEx873hb5BrkvLA0QLk54+SjfYgFBBoCdJDV1H86M8uyZdJhAOHeyA==" integrity="sha512-t/mY3un180WRfsSkWy4Yi0tAxEDGcY2rAEx873hb5BrkvLA0QLk54+SjfYgFBBoCdJDV1H86M8uyZdJhAOHeyA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js" <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/6.1.10/index.global.min.js"
integrity="sha512-JCQkxdym6GmQ+AFVioDUq8dWaWN6tbKRhRyHvYZPupQ6DxpXzkW106FXS1ORgo/m3gxtt5lHRMqSdm2OfPajtg==" integrity="sha512-JCQkxdym6GmQ+AFVioDUq8dWaWN6tbKRhRyHvYZPupQ6DxpXzkW106FXS1ORgo/m3gxtt5lHRMqSdm2OfPajtg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script> crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<script> <script>
const timezone = "{{ timezoneTxt }}"; const timezone = "{{ timezoneTxt }}";
const locale = "{{ locale }}"; const locale = "{{ locale }}";

View File

@ -2,19 +2,19 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" type="text/css" href="{% static 'css/thank_you.css' %}"/> <link rel="stylesheet"
{% endblock %} type="text/css"
{% block title %} href="{% static 'css/thank_you.css' %}" />
{{ page_title }}
{% endblock %}
{% block description %}
{{ page_description }}
{% endblock %} {% endblock %}
{% block title %}{{ page_title }}{% endblock %}
{% block description %}{{ page_description }}{% endblock %}
{% block body %} {% block body %}
<div class="container content-body-apd"> <div class="container content-body-apd">
<div class="main-content"> <div class="main-content">
<h1 class="thank-you-title">{% trans "See you soon" %} !</h1> <h1 class="thank-you-title">{% trans "See you soon" %} !</h1>
<p class="thank-you-message">{% trans "We've successfully scheduled your appointment! Please check your email for all the details" %}.</p> <p class="thank-you-message">
{% trans "We've successfully scheduled your appointment! Please check your email for all the details" %}.
</p>
<p class="appointment-details-title">{% trans "Appointment details" %}:</p> <p class="appointment-details-title">{% trans "Appointment details" %}:</p>
<ul class="appointment-details"> <ul class="appointment-details">
<li>{% trans 'Service' %}: {{ appointment.get_service_name }}</li> <li>{% trans 'Service' %}: {{ appointment.get_service_name }}</li>
@ -24,7 +24,15 @@
</ul> </ul>
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -1,39 +1,39 @@
{% extends BASE_TEMPLATE %} {% extends BASE_TEMPLATE %}
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block customCSS %} {% block customCSS %}
<link rel="stylesheet" href="{% static 'css/verification_code.css' %}"> <link rel="stylesheet" href="{% static 'css/verification_code.css' %}">
{% endblock %} {% endblock %}
{% block title %}
{% block title %}{% trans 'Enter Verification Code' %}{% endblock %} {% trans 'Enter Verification Code' %}
{% block description %}{% trans 'Enter Verification Code' %}{% endblock %} {% endblock %}
{% block description %}
{% trans 'Enter Verification Code' %}
{% endblock %}
{% block body %} {% block body %}
<div class="vcode-container"> <div class="vcode-container">
<div class="vcode-card"> <div class="vcode-card">
<h1 class="vcode-title">{% trans 'Enter Verification Code' %}</h1> <h1 class="vcode-title">{% trans 'Enter Verification Code' %}</h1>
<p class="vcode-instruction">{% trans "We've sent a verification code to your email. Please enter it below" %}:</p> <p class="vcode-instruction">{% trans "We've sent a verification code to your email. Please enter it below" %}:</p>
<form method="post" class="vcode-form"> <form method="post" class="vcode-form">
{% csrf_token %} {% csrf_token %}
<div class="vcode-input-group"> <div class="vcode-input-group">
<label for="verification-code" class="vcode-label">{% trans 'Code' %}:</label> <label for="verification-code" class="vcode-label">{% trans 'Code' %}:</label>
<input type="text" id="verification-code" name="code" class="vcode-input" required> <input type="text"
id="verification-code"
name="code"
class="vcode-input"
required>
</div> </div>
<button type="submit" class="vcode-button">{% trans 'Submit' %}</button> <button type="submit" class="vcode-button">{% trans 'Submit' %}</button>
</form> </form>
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="vcode-alert vcode-alert-{% if message.tags %}{{ message.tags }}{% endif %}"> <div class="vcode-alert vcode-alert-
{{ message }} {% if message.tags %}{{ message.tags }}{% endif %}">{{ message }}</div>
</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %}{% endblock %}
{% block customJS %}
{% endblock %}

View File

@ -62,12 +62,22 @@
<div class="main-content"> <div class="main-content">
<div class="confirmation-message"> <div class="confirmation-message">
<h1>{% trans "Rescheduling Successful" %}</h1> <h1>{% trans "Rescheduling Successful" %}</h1>
<p>{% trans "Your appointment rescheduling request has been successfully submitted. Please check your email and click on the confirmation link to finalize the rescheduling process." %}</p> <p>
{% trans "Your appointment rescheduling request has been successfully submitted. Please check your email and click on the confirmation link to finalize the rescheduling process." %}
</p>
<a href="/">{% trans "Go to Homepage" %}</a> <a href="/">{% trans "Go to Homepage" %}</a>
</div> </div>
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -91,7 +91,6 @@
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
<!-- Password Reset Form --> <!-- Password Reset Form -->
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}

View File

@ -37,12 +37,18 @@
{% block body %} {% block body %}
<div class="container"> <div class="container">
<h1 class="title">{{ page_title }}</h1> <h1 class="title">{{ page_title }}</h1>
<p class="message"> <p class="message">{{ page_message }}</p>
{{ page_message }}
</p>
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-dismissible {% if message.tags %}alert-{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}danger{% else %}{{ message.tags }}{% endif %}{% endif %}" <div class="alert alert-dismissible
{% if message.tags %}
alert-
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
danger
{% else %}
{{ message.tags }}
{% endif %}
{% endif %}"
role="alert">{{ message }}</div> role="alert">{{ message }}</div>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@ -1,88 +1,97 @@
{% load static %} {% load i18n %} {% load static %}
{% load i18n %}
<!DOCTYPE html> <!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}" <html lang="{{ LANGUAGE_CODE }}"
dir="{% if LANGUAGE_CODE == 'ar' %}rtl{% else %}ltr{% endif %}" dir="{% if LANGUAGE_CODE == 'ar' %}
rtl
{% else %}
ltr
{% endif %}"
data-bs-theme="" data-bs-theme=""
data-navigation-type="default" data-navigation-type="default"
data-navbar-horizontal-shape="default"> data-navbar-horizontal-shape="default">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Haikal - The Backbone of Car Qar: An innovative car inventory management system designed to streamline dealership operations. Manage inventory, sales, transfers, and accounting seamlessly with advanced analytics and intuitive tools. Inspired by Arabic origins, Haikal empowers businesses with precision and efficiency."> <meta name="description"
content="Haikal - The Backbone of Car Qar: An innovative car inventory management system designed to streamline dealership operations. Manage inventory, sales, transfers, and accounting seamlessly with advanced analytics and intuitive tools. Inspired by Arabic origins, Haikal empowers businesses with precision and efficiency.">
<title>{% block title %}{% trans 'HAIKAL' %}{% endblock %}</title> <title>
{% block title %}
{% trans 'HAIKAL' %}
{% endblock %}
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'images/favicons/apple-touch-icon.png' %}"> </title>
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'images/favicons/favicon-32x32.png' %}"> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'images/favicons/favicon-16x16.png' %}"> sizes="180x180"
<link rel="shortcut icon" type="image/x-icon" href="{% static 'images/favicons/favicon.ico' %}"> href="{% static 'images/favicons/apple-touch-icon.png' %}">
<link rel="icon"
type="image/png"
sizes="32x32"
href="{% static 'images/favicons/favicon-32x32.png' %}">
<link rel="icon"
type="image/png"
sizes="16x16"
href="{% static 'images/favicons/favicon-16x16.png' %}">
<link rel="shortcut icon"
type="image/x-icon"
href="{% static 'images/favicons/favicon.ico' %}">
<link rel="manifest" href="{% static 'images/favicons/manifest.json' %}"> <link rel="manifest" href="{% static 'images/favicons/manifest.json' %}">
<meta name="msapplication-TileImage" content="{% static 'images/logos/logo-d.png' %}"> <meta name="msapplication-TileImage"
content="{% static 'images/logos/logo-d.png' %}">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script>
<script src="{% static 'js/config.js' %}"></script> <script src="{% static 'js/config.js' %}"></script>
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script> <script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
<!-- ===============================================--> <!-- ===============================================-->
<!-- Stylesheets--> <!-- Stylesheets-->
<!-- ===============================================--> <!-- ===============================================-->
<link href="{% static 'vendors/mapbox-gl/mapbox-gl.css' %}"
rel="stylesheet">
<link href="{% static 'vendors/mapbox-gl/mapbox-gl.css' %}" rel="stylesheet"> <link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}"
<link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}" rel="stylesheet"> rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet"> rel="stylesheet">
<link href="{% static 'vendors/simplebar/simplebar.min.css' %}"
rel="stylesheet">
<link href="{% static 'css/sweetalert2.min.css' %}" rel="stylesheet"> <link href="{% static 'css/sweetalert2.min.css' %}" rel="stylesheet">
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> <link rel="stylesheet"
href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
{% if LANGUAGE_CODE == 'en' %} {% if LANGUAGE_CODE == 'en' %}
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default"> <link href="{% static 'css/theme.min.css' %}"
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default"> type="text/css"
rel="stylesheet"
id="style-default">
<link href="{% static 'css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default">
{% else %} {% else %}
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl"> <link href="{% static 'css/theme-rtl.min.css' %}"
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl"> type="text/css"
rel="stylesheet"
id="style-rtl">
<link href="{% static 'css/user-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-rtl">
{% endif %} {% endif %}
</head> </head>
<body> <body>
{% include 'messages.html' %} {% include 'messages.html' %}
<main class="main" id="top"> <main class="main" id="top">
<div class="content"> <div class="content">
{% block content %}<!-- Main content goes here -->{% endblock %}
{% block content %}
<!-- Main content goes here -->
{% endblock %}
</div> </div>
</main> </main>
<!-- ===============================================--> <!-- ===============================================-->
<!-- End of Main Content--> <!-- End of Main Content-->
<!-- ===============================================--> <!-- ===============================================-->
<script> <script></script>
{% block customJS %}
{% endblock customJS %}
</script>
{% block customJS %}{% endblock customJS %}
<!-- ===============================================--> <!-- ===============================================-->
<!-- JavaScripts--> <!-- JavaScripts-->
<!-- ===============================================--> <!-- ===============================================-->
@ -102,5 +111,4 @@
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script> <script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script> <script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
</body> </body>
</html> </html>

View File

@ -2,7 +2,11 @@
<!DOCTYPE html> <!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}" <html lang="{{ LANGUAGE_CODE }}"
dir="{% if LANGUAGE_CODE == 'ar' %}rtl{% else %}ltr{% endif %}" dir="{% if LANGUAGE_CODE == 'ar' %}
rtl
{% else %}
ltr
{% endif %}"
data-bs-theme="" data-bs-theme=""
data-navigation-type="default" data-navigation-type="default"
data-navbar-horizontal-shape="default"> data-navbar-horizontal-shape="default">
@ -10,22 +14,30 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Haikal - The Backbone of Car Qar: An innovative car inventory management system designed to streamline dealership operations. Manage inventory, sales, transfers, and accounting seamlessly with advanced analytics and intuitive tools. Inspired by Arabic origins, Haikal empowers businesses with precision and efficiency."> <meta name="description"
content="Haikal - The Backbone of Car Qar: An innovative car inventory management system designed to streamline dealership operations. Manage inventory, sales, transfers, and accounting seamlessly with advanced analytics and intuitive tools. Inspired by Arabic origins, Haikal empowers businesses with precision and efficiency.">
<title> <title>
{% block title %} {% block title %}{% endblock %}
{% block description %}{% endblock %}
{% endblock %}
{% block description %}
{% endblock %}
</title> </title>
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'images/favicons/apple-touch-icon.png' %}"> <link rel="apple-touch-icon"
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'images/favicons/favicon-32x32.png' %}"> sizes="180x180"
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'images/favicons/favicon-16x16.png' %}"> href="{% static 'images/favicons/apple-touch-icon.png' %}">
<link rel="shortcut icon" type="image/x-icon" href="{% static 'images/favicons/favicon.ico' %}"> <link rel="icon"
type="image/png"
sizes="32x32"
href="{% static 'images/favicons/favicon-32x32.png' %}">
<link rel="icon"
type="image/png"
sizes="16x16"
href="{% static 'images/favicons/favicon-16x16.png' %}">
<link rel="shortcut icon"
type="image/x-icon"
href="{% static 'images/favicons/favicon.ico' %}">
<link rel="manifest" href="{% static 'images/favicons/manifest.json' %}"> <link rel="manifest" href="{% static 'images/favicons/manifest.json' %}">
<meta name="msapplication-TileImage" content="{% static 'images/logos/logo-d.png' %}"> <meta name="msapplication-TileImage"
content="{% static 'images/logos/logo-d.png' %}">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
{% comment %} <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'vendors/simplebar/simplebar.min.js' %}"></script> {% endcomment %}
<script src="{% static 'js/config.js' %}"></script> <script src="{% static 'js/config.js' %}"></script>
<script src="{% static 'js/sweetalert2.all.min.js' %}"></script> <script src="{% static 'js/sweetalert2.all.min.js' %}"></script>
@ -33,68 +45,68 @@
{% comment %} <link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}" rel="stylesheet"> {% endcomment %} {% comment %} <link href="{% static 'vendors/swiper/swiper-bundle.min.css' %}" rel="stylesheet"> {% endcomment %}
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;600;700;800;900&amp;display=swap"
rel="stylesheet">
{% comment %} <link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet"> {% endcomment %} {% comment %} <link href="{% static 'vendors/simplebar/simplebar.min.css' %}" rel="stylesheet"> {% endcomment %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@emran-alhaddad/saudi-riyal-font/index.css"> <link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@emran-alhaddad/saudi-riyal-font/index.css">
{% comment %} <link href="{% static 'vendors/flatpickr/flatpickr.min.css' %}" rel="stylesheet"> {% endcomment %} {% comment %} <link href="{% static 'vendors/flatpickr/flatpickr.min.css' %}" rel="stylesheet"> {% endcomment %}
<link href="{% static 'css/custom.css' %}" rel="stylesheet"> <link href="{% static 'css/custom.css' %}" rel="stylesheet">
{% comment %} <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> {% endcomment %} {% comment %} <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css"> {% endcomment %}
{% if LANGUAGE_CODE == 'ar' %} {% if LANGUAGE_CODE == 'ar' %}
<link href="{% static 'css/theme-rtl.min.css' %}" type="text/css" rel="stylesheet" id="style-rtl"> <link href="{% static 'css/theme-rtl.min.css' %}"
<link href="{% static 'css/user-rtl.min.css' %}" type="text/css" rel="stylesheet" id="user-style-rtl"> type="text/css"
rel="stylesheet"
id="style-rtl">
<link href="{% static 'css/user-rtl.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-rtl">
{% else %} {% else %}
<link href="{% static 'css/theme.min.css' %}" type="text/css" rel="stylesheet" id="style-default"> <link href="{% static 'css/theme.min.css' %}"
<link href="{% static 'css/user.min.css' %}" type="text/css" rel="stylesheet" id="user-style-default"> type="text/css"
rel="stylesheet"
id="style-default">
<link href="{% static 'css/user.min.css' %}"
type="text/css"
rel="stylesheet"
id="user-style-default">
{% endif %} {% endif %}
<script src="{% static 'js/main.js' %}"></script> <script src="{% static 'js/main.js' %}"></script>
<script src="{% static 'js/jquery.min.js' %}"></script> <script src="{% static 'js/jquery.min.js' %}"></script>
{% comment %} <script src="{% static 'js/echarts.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'js/echarts.js' %}"></script> {% endcomment %}
{% block customCSS %}{% endblock %}
{% block customCSS %}
{% endblock %}
</head> </head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'> <body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
{% include "toast-alert.html" %} {% include "toast-alert.html" %}
<main class="main" id="top"> <main class="main" id="top">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
{% include 'header.html' %} {% include 'header.html' %}
{% endif %} {% endif %}
<div class="content"> <div class="content">
{% include "plans/expiration_messages.html" %} {% include "plans/expiration_messages.html" %}
{% block period_navigation %} {% block period_navigation %}
{% endblock period_navigation %} {% endblock period_navigation %}
{% block content %} {% block content %}
{% endblock content %} {% endblock content %}
{% block body %} {% block body %}
{% endblock body %} {% endblock body %}
{% include 'footer.html' %} {% include 'footer.html' %}
</div> </div>
</main> </main>
{% comment %} <script src="{% static 'js/djetler.bundle.js' %}"></script> {% comment %} <script src="{% static 'js/djetler.bundle.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> {% endcomment %} <script src="{% static 'js/js-utils.js' %}"></script> {% endcomment %}
{% comment %} <script src="{% static 'js/modal/show_modal.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'js/modal/show_modal.js' %}"></script> {% endcomment %}
<!-- ===============================================--> <!-- ===============================================-->
<!-- JavaScripts--> <!-- JavaScripts-->
<!-- ===============================================--> <!-- ===============================================-->
<script src="{% static 'vendors/popper/popper.min.js' %}"></script> <script src="{% static 'vendors/popper/popper.min.js' %}"></script>
<!--1--> <!--1-->
<script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script> <script src="{% static 'vendors/bootstrap/bootstrap.min.js' %}"></script>
{% comment %} <script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script> {% comment %} <script src="{% static 'vendors/anchorjs/anchor.min.js' %}"></script>
<script src="{% static 'vendors/is/is.min.js' %}"></script> {% endcomment %} <script src="{% static 'vendors/is/is.min.js' %}"></script> {% endcomment %}
<!--2--> <!--2-->
<script src="{% static 'vendors/fontawesome/all.min.js' %}"></script> <script src="{% static 'vendors/fontawesome/all.min.js' %}"></script>
<script src="{% static 'vendors/lodash/lodash.min.js' %}"></script> <script src="{% static 'vendors/lodash/lodash.min.js' %}"></script>
{% comment %} <script src="{% static 'vendors/list.js/list.min.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'vendors/list.js/list.min.js' %}"></script> {% endcomment %}
<script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script> <script src="{% static 'vendors/feather-icons/feather.min.js' %}"></script>
@ -106,13 +118,12 @@
{% comment %} <script src="{% static 'js/travel-agency-dashboard.js' %}"></script> {% comment %} <script src="{% static 'js/travel-agency-dashboard.js' %}"></script>
<script src="{% static 'js/crm-dashboard.js' %}"></script> <script src="{% static 'js/crm-dashboard.js' %}"></script>
<script src="{% static 'js/projectmanagement-dashboard.js' %}"></script> {% endcomment %} <script src="{% static 'js/projectmanagement-dashboard.js' %}"></script> {% endcomment %}
{% comment %} <script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'vendors/mapbox-gl/mapbox-gl.js' %}"></script> {% endcomment %}
{% comment %} <script src="{% static 'vendors/turf.min.js' %}"></script> {% endcomment %} {% comment %} <script src="{% static 'vendors/turf.min.js' %}"></script> {% endcomment %}
<script src="{% static 'vendors/htmx.min.js' %}"></script> <script src="{% static 'vendors/htmx.min.js' %}"></script>
<script src="{% static 'js/formSubmitHandler.js' %}"></script>
{% comment %} <script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script> {% comment %} <script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
<script src="{% static 'vendors/flatpickr/flatpickr.min.js' %}"></script> {% endcomment %} <script src="{% static 'vendors/flatpickr/flatpickr.min.js' %}"></script> {% endcomment %}
<script> <script>
{% if entity_slug %} {% if entity_slug %}
let entitySlug = "{{ view.kwargs.entity_slug }}" let entitySlug = "{{ view.kwargs.entity_slug }}"
@ -129,8 +140,6 @@
datePickers.forEach(dp => djLedger.getCalendar(dp.attributes.id.value, dateNavigationUrl)) datePickers.forEach(dp => djLedger.getCalendar(dp.attributes.id.value, dateNavigationUrl))
{% endif %} {% endif %}
</script> </script>
{% block customJS %} {% block customJS %}{% endblock %}
{% endblock %}
</body> </body>
</html> </html>

View File

@ -10,7 +10,6 @@
{% block content %} {% block content %}
<!----> <!---->
<div class="row justify-content-center mt-5 mb-3"> <div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10"> <div class="col-lg-8 col-md-10">
@ -60,9 +59,6 @@
</div> </div>
</div> </div>
</div>
</div> </div>
<!----> <!---->
{% endblock %} {% endblock %}

View File

@ -3,9 +3,7 @@
{% load static %} {% load static %}
{% load django_ledger %} {% load django_ledger %}
{% load custom_filters %} {% load custom_filters %}
{% block title %}Bill Details - {{ block.super }}{% endblock %} {% block title %}Bill Details - {{ block.super }}{% endblock %}
{% block customCSS %} {% block customCSS %}
<style> <style>
/* Optional custom overrides for Bootstrap 5 */ /* Optional custom overrides for Bootstrap 5 */
@ -34,24 +32,19 @@
</style> </style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="row mt-3 mb-2"> <div class="row mt-3 mb-2">
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<div class="row"> <div class="row">
<div class="col-12 mb-3"> <div class="col-12 mb-3">
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body"> <div class="card-body">
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %} {% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill entity_slug=view.kwargs.entity_slug style='bill-detail' %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="card shadow-sm "> <div class="card shadow-sm ">
<div class="card-header pb-0"> <div class="card-header pb-0">
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
@ -66,10 +59,7 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-md-9"> <div class="col-12 col-md-9">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@ -82,9 +72,7 @@
<h6 class="text-uppercase text-xs text-muted mb-2"> <h6 class="text-uppercase text-xs text-muted mb-2">
{% trans 'Cash Account' %}: {% trans 'Cash Account' %}:
<a href="{% url 'account_detail' request.dealer.slug bill.cash_account.uuid %}" <a href="{% url 'account_detail' request.dealer.slug bill.cash_account.uuid %}"
class="text-decoration-none ms-1"> class="text-decoration-none ms-1">{{ bill.cash_account.code }}</a>
{{ bill.cash_account.code }}
</a>
</h6> </h6>
<h4 class="mb-0" id="djl-bill-detail-amount-paid"> <h4 class="mb-0" id="djl-bill-detail-amount-paid">
{% currency_symbol %}{{ bill.get_amount_cash | absolute | currency_format }} {% currency_symbol %}{{ bill.get_amount_cash | absolute | currency_format }}
@ -122,20 +110,14 @@
</div> </div>
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<div class="border rounded p-3"> <div class="border rounded p-3">
<h6 class="text-uppercase text-xs text-muted mb-2"> <h6 class="text-uppercase text-xs text-muted mb-2">{% trans 'Accrued' %} {{ bill.get_progress | percentage }}</h6>
{% trans 'Accrued' %} {{ bill.get_progress | percentage }} <h4 class="mb-0">{% currency_symbol %}{{ bill.get_amount_earned | currency_format }}</h4>
</h6>
<h4 class="mb-0">
{% currency_symbol %}{{ bill.get_amount_earned | currency_format }}
</h4>
</div> </div>
</div> </div>
{% else %} {% else %}
<div class="col-12 col-md-3 offset-md-6"> <div class="col-12 col-md-3 offset-md-6">
<div class="border rounded p-3"> <div class="border rounded p-3">
<h6 class="text-uppercase text-xs text-muted mb-2"> <h6 class="text-uppercase text-xs text-muted mb-2">{% trans 'You Still Owe' %}</h6>
{% trans 'You Still Owe' %}
</h6>
<h4 class="text-danger mb-0" id="djl-bill-detail-amount-owed"> <h4 class="text-danger mb-0" id="djl-bill-detail-amount-owed">
{% currency_symbol %}{{ bill.get_amount_open | currency_format }} {% currency_symbol %}{{ bill.get_amount_open | currency_format }}
</h4> </h4>
@ -146,12 +128,8 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="card mb-3 shadow-sm"> <div class="card mb-3 shadow-sm">
<div class="card-header pb-0"> <div class="card-header pb-0">
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
@ -184,23 +162,17 @@
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<span class="text-xs font-weight-bold"> <span class="text-xs font-weight-bold">
{% if bill_item.entity_unit %} {% if bill_item.entity_unit %}{{ bill_item.entity_unit }}{% endif %}
{{ bill_item.entity_unit }}
{% endif %}
</span> </span>
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<span class="text-xs font-weight-bold"> <span class="text-xs font-weight-bold">{{ bill_item.unit_cost | currency_format }}</span>
{{ bill_item.unit_cost | currency_format }}
</span>
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<span class="text-xs font-weight-bold">{{ bill_item.quantity }}</span> <span class="text-xs font-weight-bold">{{ bill_item.quantity }}</span>
</td> </td>
<td class="align-middle white-space-nowrap"> <td class="align-middle white-space-nowrap">
<span class="text-xs font-weight-bold"> <span class="text-xs font-weight-bold">{{ bill_item.total_amount | currency_format }}</span>
{{ bill_item.total_amount | currency_format }}
</span>
</td> </td>
<td class="align-items-start white-space-nowrap pe-2"> <td class="align-items-start white-space-nowrap pe-2">
{% if bill_item.po_model_id %} {% if bill_item.po_model_id %}
@ -218,11 +190,11 @@
<tfoot> <tfoot>
<tr> <tr>
<td colspan="3"></td> <td colspan="3"></td>
<td class="text-end"><strong>{% trans 'Total' %}</strong></td>
<td class="text-end"> <td class="text-end">
<strong> <strong>{% trans 'Total' %}</strong>
{% currency_symbol %}{{ total_amount__sum | currency_format }} </td>
</strong> <td class="text-end">
<strong>{% currency_symbol %}{{ total_amount__sum | currency_format }}</strong>
</td> </td>
<td></td> <td></td>
</tr> </tr>
@ -231,12 +203,8 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12">
<div class="card mb-3 shadow-sm"> <div class="card mb-3 shadow-sm">
<div class="card-header pb-0"> <div class="card-header pb-0">
<div class="d-flex align-items-center mb-2"> <div class="d-flex align-items-center mb-2">
@ -244,19 +212,11 @@
<h5 class="mb-0">{% trans 'Bill Transactions' %}</h5> <h5 class="mb-0">{% trans 'Bill Transactions' %}</h5>
</div> </div>
</div> </div>
<div class="card-body px-0 pt-0 pb-2 table-responsive"> <div class="card-body px-0 pt-0 pb-2 table-responsive">{% transactions_table bill %}</div>
{% transactions_table bill %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
{% include "bill/includes/mark_as.html" %} {% include "bill/includes/mark_as.html" %}
{% endblock %} {% endblock %}

View File

@ -4,27 +4,20 @@
{% load django_ledger %} {% load django_ledger %}
{% load custom_filters %} {% load custom_filters %}
{% load widget_tweaks crispy_forms_filters %} {% load widget_tweaks crispy_forms_filters %}
{% block content %} {% block content %}
<div class="container py-4"> <div class="container py-4">
<div class="row g-2"> <div class="row g-2">
<!-- Bill Form --> <!-- Bill Form -->
<div class="col-12"> <div class="col-12">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="card mb-2"> <div class="card mb-2">
<div class="card-body"> <div class="card-body">
{% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %} {% include 'bill/includes/card_bill.html' with dealer_slug=request.dealer.slug bill=bill_model style='bill-detail' entity_slug=view.kwargs.entity_slug %}
<form action="{% url 'bill-update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}"
<form action="{% url 'bill-update' dealer_slug=request.dealer.slug entity_slug=view.kwargs.entity_slug bill_pk=bill_model.uuid %}" method="post"> method="post">
{% csrf_token %} {% csrf_token %}
<div class="mb-3">{{ form|crispy }}</div>
<div class="mb-3">
{{ form|crispy }}
</div>
<button type="submit" class="btn btn-phoenix-primary mb-2 me-2"> <button type="submit" class="btn btn-phoenix-primary mb-2 me-2">
<i class="fas fa-save me-2"></i>{% trans 'Save Bill' %} <i class="fas fa-save me-2"></i>{% trans 'Save Bill' %}
</button> </button>
@ -32,27 +25,14 @@
class="btn btn-phoenix-secondary mb-2"> class="btn btn-phoenix-secondary mb-2">
<i class="fas fa-arrow-left me-2"></i>{% trans 'Back to Bill Detail' %} <i class="fas fa-arrow-left me-2"></i>{% trans 'Back to Bill Detail' %}
</a> </a>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Bill Item Formset --> <!-- Bill Item Formset -->
<div class="col-12"> <div class="col-12">{% bill_item_formset_table itemtxs_formset %}</div>
{% bill_item_formset_table itemtxs_formset %}
</div>
</div> </div>
</div> </div>
{% include "bill/includes/mark_as.html" %} {% include "bill/includes/mark_as.html" %}

View File

@ -1,13 +1,11 @@
{% load django_ledger %} {% load django_ledger %}
{% load i18n %} {% load i18n %}
<div id="djl-bill-card-widget" class=""> <div id="djl-bill-card-widget" class="">
{% if not create_bill %} {% if not create_bill %}
{% if style == 'dashboard' %} {% if style == 'dashboard' %}
<!-- Dashboard Style Card --> <!-- Dashboard Style Card -->
<div class=""> <div class="">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3 text-primary"> <div class="d-flex justify-content-between align-items-center mb-3 text-primary">
<h6 class="text-uppercase text-primary mb-0"> <h6 class="text-uppercase text-primary mb-0">
<i class="fas fa-file-invoice me-2"></i>{% trans 'Bill' %} <i class="fas fa-file-invoice me-2"></i>{% trans 'Bill' %}
@ -16,7 +14,6 @@
</div> </div>
<h4 class="card-title">{{ bill.vendor.vendor_name }}</h4> <h4 class="card-title">{{ bill.vendor.vendor_name }}</h4>
<p class="text-sm text-muted mb-4">{{ bill.vendor.address_1 }}</p> <p class="text-sm text-muted mb-4">{{ bill.vendor.address_1 }}</p>
{% if not bill.is_past_due %} {% if not bill.is_past_due %}
<p class="text-info mb-2"> <p class="text-info mb-2">
<i class="fas fa-clock me-2"></i>{% trans 'Due in' %}: {{ bill.date_due | timeuntil }} <i class="fas fa-clock me-2"></i>{% trans 'Due in' %}: {{ bill.date_due | timeuntil }}
@ -26,7 +23,6 @@
<i class="fas fa-exclamation-triangle me-2"></i>{% trans 'Past Due' %}: {{ bill.date_due | timesince }} {% trans 'ago' %} <i class="fas fa-exclamation-triangle me-2"></i>{% trans 'Past Due' %}: {{ bill.date_due | timesince }} {% trans 'ago' %}
</p> </p>
{% endif %} {% endif %}
<div class="d-flex align-items-center mb-3"> <div class="d-flex align-items-center mb-3">
<span class="me-2">{% trans 'Accrued' %}:</span> <span class="me-2">{% trans 'Accrued' %}:</span>
{% if bill.accrue %} {% if bill.accrue %}
@ -35,7 +31,6 @@
<i class="fas fa-times-circle text-danger me-2"></i> <i class="fas fa-times-circle text-danger me-2"></i>
{% endif %} {% endif %}
</div> </div>
<div class="mb-4"> <div class="mb-4">
<p class="text-danger fw-bold mb-1"> <p class="text-danger fw-bold mb-1">
{% trans 'Amount Due' %}: {% currency_symbol %}{{ bill.get_amount_open | currency_format }} {% trans 'Amount Due' %}: {% currency_symbol %}{{ bill.get_amount_open | currency_format }}
@ -43,70 +38,48 @@
<p class="text-success mb-1"> <p class="text-success mb-1">
{% trans 'Amount Paid' %}: {% currency_symbol %}{{ bill.amount_paid | currency_format }} {% trans 'Amount Paid' %}: {% currency_symbol %}{{ bill.amount_paid | currency_format }}
</p> </p>
<p class="mb-1"> <p class="mb-1">{% trans 'Progress' %}: {{ bill.get_progress | percentage }}</p>
{% trans 'Progress' %}: {{ bill.get_progress | percentage }}
</p>
<div class="progress mt-2"> <div class="progress mt-2">
<div class="progress-bar bg-success" <div class="progress-bar bg-success"
role="progressbar" role="progressbar"
style="width: {{ bill.get_progress_percent }}%" style="width: {{ bill.get_progress_percent }}%"
aria-valuenow="{{ bill.get_progress_percent }}" aria-valuenow="{{ bill.get_progress_percent }}"
aria-valuemin="0" aria-valuemin="0"
aria-valuemax="100"> aria-valuemax="100"></div>
</div> </div>
</div> </div>
</div>
<!-- Modal Action --> <!-- Modal Action -->
{% modal_action bill 'get' entity_slug %} {% modal_action bill 'get' entity_slug %}
<div class="d-grid gap-2 d-md-flex justify-content-md-end"> <div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{% url 'django_ledger:bill-detail' entity_slug=entity_slug bill_pk=bill.uuid %}" <a href="{% url 'django_ledger:bill-detail' entity_slug=entity_slug bill_pk=bill.uuid %}"
class="btn btn-sm btn-phoenix-primary me-md-2"> class="btn btn-sm btn-phoenix-primary me-md-2">{% trans 'View' %}</a>
{% trans 'View' %}
</a>
{% if perms.django_ledger.change_billmodel %} {% if perms.django_ledger.change_billmodel %}
<a href="{% url 'django_ledger:bill-update' entity_slug=entity_slug bill_pk=bill.uuid %}" <a href="{% url 'django_ledger:bill-update' entity_slug=entity_slug bill_pk=bill.uuid %}"
class="btn btn-sm btn-phoenix-warning me-md-2"> class="btn btn-sm btn-phoenix-warning me-md-2">{% trans 'Update' %}</a>
{% trans 'Update' %}
</a>
{% if bill.can_pay %} {% if bill.can_pay %}
<button onclick="djLedger.toggleModal('{{ bill.get_html_id }}')" <button onclick="djLedger.toggleModal('{{ bill.get_html_id }}')"
class="btn btn-sm btn-phoenix-info"> class="btn btn-sm btn-phoenix-info">{% trans 'Mark as Paid' %}</button>
{% trans 'Mark as Paid' %}
</button>
{% endif %} {% endif %}
{% if bill.can_cancel %} {% if bill.can_cancel %}
<button onclick="djLedger.toggleModal('{{ bill.get_html_id }}')" <button onclick="djLedger.toggleModal('{{ bill.get_html_id }}')"
class="btn btn-sm btn-phoenix-danger"> class="btn btn-sm btn-phoenix-danger">{% trans 'Cancel' %}</button>
{% trans 'Cancel' %}
</button>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
{% elif style == 'bill-detail' %} {% elif style == 'bill-detail' %}
<!-- Detail Style Card --> <!-- Detail Style Card -->
<div class=""> <div class="">
<div class="card-header p-2 bg-{{ bill.get_status_badge_color }}"> <div class="card-header p-2 bg-{{ bill.get_status_badge_color }}">
<div class="d-flex align-items-center justify-content-center mb-2 text-primary"> <div class="d-flex align-items-center justify-content-center mb-2 text-primary">
<i class="fas fa-file-invoice me-3 "></i> <i class="fas fa-file-invoice me-3 "></i>
<h4 class="mb-0 text-primary me-2"> <h4 class="mb-0 text-primary me-2">{% trans 'Bill' %} {{ bill.bill_number }}</h4>
{% trans 'Bill' %} {{ bill.bill_number }}
</h4>
</div> </div>
<a href="{% url 'bill_list' request.dealer.slug %}" <a href="{% url 'bill_list' request.dealer.slug %}"
class="btn btn-phoenix-primary mb-2"> class="btn btn-phoenix-primary mb-2">
<i class="fas fa-long-arrow-alt-left me-2"></i>{% trans 'Back to Bill List' %} <i class="fas fa-long-arrow-alt-left me-2"></i>{% trans 'Back to Bill List' %}
</a> </a>
</div> </div>
<div class="card-body p-2 text-center"> <div class="card-body p-2 text-center">
{% if bill.is_draft %} {% if bill.is_draft %}
@ -189,8 +162,7 @@
style="width: {{ bill.get_progress_percent }}%" style="width: {{ bill.get_progress_percent }}%"
aria-valuenow="{{ bill.get_progress_percent }}" aria-valuenow="{{ bill.get_progress_percent }}"
aria-valuemin="0" aria-valuemin="0"
aria-valuemax="100"> aria-valuemax="100"></div>
</div>
</div> </div>
</div> </div>
{% if bill.xref %} {% if bill.xref %}
@ -221,9 +193,7 @@
<span class="fw-bold">{% trans 'Bill Amount' %}:</span> <span class="fw-bold">{% trans 'Bill Amount' %}:</span>
{% currency_symbol %}{{ bill.amount_due | currency_format }} {% currency_symbol %}{{ bill.amount_due | currency_format }}
</p> </p>
<p class="text-danger fw-bold"> <p class="text-danger fw-bold">{{ bill.get_bill_status_display | upper }}</p>
{{ bill.get_bill_status_display | upper }}
</p>
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -231,7 +201,8 @@
<div class="d-flex flex-wrap gap-2 mt-2"> <div class="d-flex flex-wrap gap-2 mt-2">
<!-- Update Button --> <!-- Update Button -->
{% if perms.django_ledger.change_billmodel %} {% if perms.django_ledger.change_billmodel %}
<button class="btn btn-phoenix-primary" {% if not request.is_accountant %} disabled {% endif %}> <button class="btn btn-phoenix-primary"
{% if not request.is_accountant %}disabled{% endif %}>
<a href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}"> <a href="{% url 'bill-update' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill.uuid %}">
<i class="fas fa-edit me-2"></i>{% trans 'Update' %} <i class="fas fa-edit me-2"></i>{% trans 'Update' %}
</a> </a>
@ -291,13 +262,11 @@
</div> </div>
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% else %} {% else %}
<!-- Create Bill Card --> <!-- Create Bill Card -->
{% if perms.django_ledger.add_billmodel %} {% if perms.django_ledger.add_billmodel %}
<div class=" bg-light"> <div class=" bg-light">
<div class="card-body text-center p-5"> <div class="card-body text-center p-5">
<a href="{% url 'django_ledger:bill-create' entity_slug=entity_slug %}" <a href="{% url 'django_ledger:bill-create' entity_slug=entity_slug %}"
class="text-primary"> class="text-primary">
@ -309,7 +278,6 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
<style> <style>
.card-footer .btn-link { .card-footer .btn-link {
padding: 1rem; padding: 1rem;
@ -320,7 +288,6 @@
background-color: rgba(0,0,0,0.03); background-color: rgba(0,0,0,0.03);
} }
</style> </style>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
window.showPOModal = function(title, actionUrl, buttonText) { window.showPOModal = function(title, actionUrl, buttonText) {

View File

@ -1,9 +1,7 @@
{% load trans from i18n %} {% load trans from i18n %}
{% load django_ledger %} {% load django_ledger %}
{% if style == 'card_1' %} {% if style == 'card_1' %}
<div class="card h-100" style="height: 25rem;"> <div class="card h-100" style="height: 25rem;">
<div class="card-body overflow-auto"> <div class="card-body overflow-auto">
{% if notes_html %} {% if notes_html %}
{{ notes_html|safe }} {{ notes_html|safe }}

View File

@ -1,19 +1,21 @@
{% load i18n %} {% load i18n %}
{% load django_ledger %} {% load django_ledger %}
<div class="card " id="djl-vendor-card-widget"> <div class="card " id="djl-vendor-card-widget">
<div class="card-header"> <div class="card-header">
<h2 class="card-title d-flex align-items-center text-primary"> <h2 class="card-title d-flex align-items-center text-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-person-lines-fill me-2" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-person-lines-fill me-2"
viewBox="0 0 16 16">
<path d="M6 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-5 6s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zM11 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zm-1 0a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-5 0a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zM2 3a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4A.5.5 0 0 1 2 3zm9.854 2.854a.5.5 0 0 1 0-.708l3-3a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0zM2.5 14.5c0-.827.673-1.5 1.5-1.5h7c.827 0 1.5.673 1.5 1.5s-.673 1.5-1.5 1.5h-7c-.827 0-1.5-.673-1.5-1.5z" /> <path d="M6 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-5 6s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zM11 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zm-1 0a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-5 0a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zM2 3a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4A.5.5 0 0 1 2 3zm9.854 2.854a.5.5 0 0 1 0-.708l3-3a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0zM2.5 14.5c0-.827.673-1.5 1.5-1.5h7c.827 0 1.5.673 1.5 1.5s-.673 1.5-1.5 1.5h-7c-.827 0-1.5-.673-1.5-1.5z" />
</svg> </svg>
{% trans 'Vendor Info' %} {% trans 'Vendor Info' %}
</h2> </h2>
</div> </div>
<div class="card-body"> <div class="card-body">
<h4 class="card-title fw-bold mb-3">{{ vendor.vendor_name }}</h4> <h4 class="card-title fw-bold mb-3">{{ vendor.vendor_name }}</h4>
<p class="card-text mb-0"> <p class="card-text mb-0">
{% if vendor.address_1 %}<span class="d-block">{{ vendor.address_1 }}</span>{% endif %} {% if vendor.address_1 %}<span class="d-block">{{ vendor.address_1 }}</span>{% endif %}
{% if vendor.address_2 %}<span class="d-block">{{ vendor.address_2 }}</span>{% endif %} {% if vendor.address_2 %}<span class="d-block">{{ vendor.address_2 }}</span>{% endif %}

View File

@ -4,7 +4,10 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="POModalTitle"></h5> <h5 class="modal-title" id="POModalTitle"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"></button>
</div> </div>
<div class="modal-body" id="POModalBody"> <div class="modal-body" id="POModalBody">
<!-- Content will be inserted here by JavaScript --> <!-- Content will be inserted here by JavaScript -->

View File

@ -2,8 +2,8 @@
{% load static %} {% load static %}
{% load django_ledger %} {% load django_ledger %}
{% load widget_tweaks %} {% load widget_tweaks %}
<form action="{% url 'bill-update-items' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill_pk %}"
<form action="{% url 'bill-update-items' dealer_slug=dealer_slug entity_slug=entity_slug bill_pk=bill_pk %}" method="post"> method="post">
<div class="container-fluid py-4"> <div class="container-fluid py-4">
<!-- Page Header --> <!-- Page Header -->
<div class="row mb-4"> <div class="row mb-4">
@ -15,14 +15,12 @@
<hr class="my-3"> <hr class="my-3">
</div> </div>
</div> </div>
<!-- Form Content --> <!-- Form Content -->
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
{% csrf_token %} {% csrf_token %}
{{ item_formset.non_form_errors }} {{ item_formset.non_form_errors }}
{{ item_formset.management_form }} {{ item_formset.management_form }}
<!-- Card Container --> <!-- Card Container -->
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body p-0"> <div class="card-body p-0">
@ -47,30 +45,22 @@
<!-- Item Column --> <!-- Item Column -->
<td> <td>
<div class="d-flex flex-column ms-2"> <div class="d-flex flex-column ms-2">
{% for hidden_field in f.hidden_fields %} {% for hidden_field in f.hidden_fields %}{{ hidden_field }}{% endfor %}
{{ hidden_field }}
{% endfor %}
{{ f.item_model|add_class:"form-control" }} {{ f.item_model|add_class:"form-control" }}
{% if f.errors %} {% if f.errors %}<span class="text-danger text-xs">{{ f.errors }}</span>{% endif %}
<span class="text-danger text-xs">{{ f.errors }}</span>
{% endif %}
</div> </div>
</td> </td>
<!-- PO Quantity --> <!-- PO Quantity -->
<td class="text-center"> <td class="text-center">
<span class="text-muted text-xs"> <span class="text-muted text-xs">
{% if f.instance.po_quantity %}{{ f.instance.po_quantity }}{% endif %} {% if f.instance.po_quantity %}{{ f.instance.po_quantity }}{% endif %}
</span> </span>
</td> </td>
<!-- PO Amount --> <!-- PO Amount -->
<td class="text-center"> <td class="text-center">
{% if f.instance.po_total_amount %} {% if f.instance.po_total_amount %}
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<span class="text-xs font-weight-bold"> <span class="text-xs font-weight-bold">{% currency_symbol %}{{ f.instance.po_total_amount | currency_format }}</span>
{% currency_symbol %}{{ f.instance.po_total_amount | currency_format }}
</span>
<a class="btn btn-sm btn-phoenix-info mt-1" <a class="btn btn-sm btn-phoenix-info mt-1"
href="{% url 'purchase_order_detail' dealer_slug entity_slug f.instance.po_model_id %}"> href="{% url 'purchase_order_detail' dealer_slug entity_slug f.instance.po_model_id %}">
{% trans 'View PO' %} {% trans 'View PO' %}
@ -78,54 +68,38 @@
</div> </div>
{% endif %} {% endif %}
</td> </td>
<!-- Quantity --> <!-- Quantity -->
<td class="text-center"> <td class="text-center">
<div class="input-group input-group-sm w-100"> <div class="input-group input-group-sm w-100">{{ f.quantity|add_class:"form-control" }}</div>
{{ f.quantity|add_class:"form-control" }}
</div>
</td> </td>
<!-- Unit Cost --> <!-- Unit Cost -->
<td class="text-center"> <td class="text-center">
<div class="input-group input-group-sm w-100"> <div class="input-group input-group-sm w-100">{{ f.unit_cost|add_class:"form-control" }}</div>
{{ f.unit_cost|add_class:"form-control" }}
</div>
</td> </td>
<!-- Entity Unit --> <!-- Entity Unit -->
<td class="text-center"> <td class="text-center">{{ f.entity_unit|add_class:"form-control" }}</td>
{{ f.entity_unit|add_class:"form-control" }}
</td>
<!-- Total Amount --> <!-- Total Amount -->
<td class="text-end"> <td class="text-end">
<span class="text-xs font-weight-bold"> <span class="text-xs font-weight-bold">
<span>{% currency_symbol %}</span>{{ f.instance.total_amount | currency_format }} <span>{% currency_symbol %}</span>{{ f.instance.total_amount | currency_format }}
</span> </span>
</td> </td>
<!-- Delete Checkbox --> <!-- Delete Checkbox -->
<td class="text-center"> <td class="text-center">
{% if item_formset.can_delete %} {% if item_formset.can_delete %}<div class="form-check d-flex justify-content-center">{{ f.DELETE }}</div>{% endif %}
<div class="form-check d-flex justify-content-center">
{{ f.DELETE }}
</div>
{% endif %}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
<!-- Footer Total --> <!-- Footer Total -->
<tfoot class="total-row"> <tfoot class="total-row">
<tr> <tr>
<td colspan="5"></td> <td colspan="5"></td>
<td class="text-end"><strong>{% trans 'Total' %}</strong></td>
<td class="text-end"> <td class="text-end">
<strong> <strong>{% trans 'Total' %}</strong>
{% currency_symbol %}{{ total_amount__sum | currency_format }} </td>
</strong> <td class="text-end">
<strong>{% currency_symbol %}{{ total_amount__sum | currency_format }}</strong>
</td> </td>
<td></td> <td></td>
</tr> </tr>
@ -136,7 +110,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Action Buttons --> <!-- Action Buttons -->
<div class="row mt-4"> <div class="row mt-4">
<div class="col-12"> <div class="col-12">

View File

@ -1,8 +1,6 @@
{% load django_ledger %} {% load django_ledger %}
{% load i18n %} {% load i18n %}
<div class="table-container"> <div class="table-container">
<table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75"> <table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75">
<thead> <thead>
<tr> <tr>
@ -23,17 +21,16 @@
<td>{{ bill.get_bill_status_display }}</td> <td>{{ bill.get_bill_status_display }}</td>
<td>{{ bill.get_status_action_date }}</td> <td>{{ bill.get_status_action_date }}</td>
<td>{{ bill.vendor.vendor_name }}</td> <td>{{ bill.vendor.vendor_name }}</td>
<td id="{{ bill.get_html_amount_due_id }}"> <td id="{{ bill.get_html_amount_due_id }}">{% currency_symbol %}{{ bill.amount_due | currency_format }}</td>
{% currency_symbol %}{{ bill.amount_due | currency_format }}</td> <td id="{{ bill.get_html_amount_paid_id }}">{% currency_symbol %}{{ bill.amount_paid | currency_format }}</td>
<td id="{{ bill.get_html_amount_paid_id }}">
{% currency_symbol %}{{ bill.amount_paid | currency_format }}</td>
<td class="has-text-centered"> <td class="has-text-centered">
{% if bill.is_past_due %} {% if bill.is_past_due %}
<span class="icon is-small has-text-danger">{% icon 'bi:check-circle-fill' 24 %}</span> <span class="icon is-small has-text-danger">{% icon 'bi:check-circle-fill' 24 %}</span>
{% endif %} {% endif %}
</td> </td>
<td class="has-text-centered"> <td class="has-text-centered">
<div class="dropdown is-right is-hoverable" id="bill-action-{{ bill.uuid }}"> <div class="dropdown is-right is-hoverable"
id="bill-action-{{ bill.uuid }}">
<div class="dropdown-trigger"> <div class="dropdown-trigger">
<button class="button is-small is-rounded is-outlined is-dark" <button class="button is-small is-rounded is-outlined is-dark"
aria-haspopup="true" aria-haspopup="true"
@ -56,5 +53,4 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,8 +1,6 @@
{% load i18n %} {% load i18n %}
{% load django_ledger %} {% load django_ledger %}
{% if style == 'detail' %} {% if style == 'detail' %}
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
@ -17,23 +15,31 @@
</tr> </tr>
</thead> </thead>
<tbody class="fs-9"> <tbody class="fs-9">
{% for transaction_model in transaction_model_qs %} {% for transaction_model in transaction_model_qs %}
<tr> <tr>
<td class=" white-space-nowrap align-middle ps-2" scope="col">{{ transaction_model.timestamp }}</td> <td class=" white-space-nowrap align-middle ps-2" scope="col">{{ transaction_model.timestamp }}</td>
<td class=" white-space-nowrap align-middle" scope="col">{{ transaction_model.account_code }}</td> <td class=" white-space-nowrap align-middle" scope="col">{{ transaction_model.account_code }}</td>
<td class=" white-space-nowrap align-middle" scope="col">{{ transaction_model.account_name }}</td> <td class=" white-space-nowrap align-middle" scope="col">{{ transaction_model.account_name }}</td>
<td class=" white-space-nowrap align-middle" scope="col">{% if transaction_model.entity_unit_name %}{{ transaction_model.entity_unit_name }}{% endif %}</td> <td class=" white-space-nowrap align-middle" scope="col">
<td class=" white-space-nowrap align-middle" scope="col">{% if transaction_model.is_credit %}{{ transaction_model.amount | currency_format }}{% endif %}</td> {% if transaction_model.entity_unit_name %}{{ transaction_model.entity_unit_name }}{% endif %}
<td class=" white-space-nowrap align-middle" scope="col">{% if transaction_model.is_debit %}{{ transaction_model.amount | currency_format }}{% endif %}</td> </td>
<td class=" white-space-nowrap align-middle pe-2" scope="col">{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}</td> <td class=" white-space-nowrap align-middle" scope="col">
{% if transaction_model.is_credit %}{{ transaction_model.amount | currency_format }}{% endif %}
</td>
<td class=" white-space-nowrap align-middle" scope="col">
{% if transaction_model.is_debit %}{{ transaction_model.amount | currency_format }}{% endif %}
</td>
<td class=" white-space-nowrap align-middle pe-2" scope="col">
{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="fw-bold"> <tr class="fw-bold">
<td class=" white-space-nowrap align-middle" colspan="3"></td> <td class=" white-space-nowrap align-middle" colspan="3"></td>
<td class=" white-space-nowrap align-middle" scope="col">{% trans 'Total' %}</td> <td class=" white-space-nowrap align-middle" scope="col">{% trans 'Total' %}</td>
<td class=" white-space-nowrap align-middle" scope="col">{% currency_symbol %}{{ total_credits | currency_format }}</td> <td class=" white-space-nowrap align-middle" scope="col">
{% currency_symbol %}{{ total_credits | currency_format }}
</td>
<td class=" white-space-nowrap align-middle" scope="col">{% currency_symbol %}{{ total_debits | currency_format }}</td> <td class=" white-space-nowrap align-middle" scope="col">{% currency_symbol %}{{ total_debits | currency_format }}</td>
<td class=" white-space-nowrap align-middle" scope="col"></td> <td class=" white-space-nowrap align-middle" scope="col"></td>
</tr> </tr>
@ -56,9 +62,15 @@
<tr> <tr>
<td class=" white-space-nowrap align-middle ps-2">{{ transaction_model.account_code }}</td> <td class=" white-space-nowrap align-middle ps-2">{{ transaction_model.account_code }}</td>
<td class=" white-space-nowrap align-middle">{{ transaction_model.account_name }}</td> <td class=" white-space-nowrap align-middle">{{ transaction_model.account_name }}</td>
<td class=" white-space-nowrap align-middle">{% if transaction_model.is_credit %}{{ transaction_model.amount | currency_format }}{% endif %}</td> <td class=" white-space-nowrap align-middle">
<td class=" white-space-nowrap align-middle">{% if transaction_model.is_debit %}{{ transaction_model.amount | currency_format }}{% endif %}</td> {% if transaction_model.is_credit %}{{ transaction_model.amount | currency_format }}{% endif %}
<td class=" white-space-nowrap align-middle pe-2">{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}</td> </td>
<td class=" white-space-nowrap align-middle">
{% if transaction_model.is_debit %}{{ transaction_model.amount | currency_format }}{% endif %}
</td>
<td class=" white-space-nowrap align-middle pe-2">
{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="fw-bold"> <tr class="fw-bold">
@ -72,4 +84,3 @@
</table> </table>
</div> </div>
{% endif %} {% endif %}

View File

@ -2,42 +2,83 @@
<div class="row-fluid support-chat"> <div class="row-fluid support-chat">
<div class="card bg-body-emphasis"> <div class="card bg-body-emphasis">
<div class="card-header d-flex flex-between-center px-4 py-3 border-bottom border-translucent"> <div class="card-header d-flex flex-between-center px-4 py-3 border-bottom border-translucent">
<h5 class="mb-0 d-flex align-items-center gap-2">Demo widget<span class="fa-solid fa-circle text-success fs-11"></span></h5> <h5 class="mb-0 d-flex align-items-center gap-2">
Demo widget<span class="fa-solid fa-circle text-success fs-11"></span>
</h5>
<div class="btn-reveal-trigger"> <div class="btn-reveal-trigger">
<button class="btn btn-link p-0 dropdown-toggle dropdown-caret-none transition-none d-flex" type="button" id="support-chat-dropdown" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h text-body"></span></button> <button class="btn btn-link p-0 dropdown-toggle dropdown-caret-none transition-none d-flex"
<div class="dropdown-menu dropdown-menu-end py-2" aria-labelledby="support-chat-dropdown"><a class="dropdown-item" href="#!">Request a callback</a><a class="dropdown-item" href="#!">Search in chat</a><a class="dropdown-item" href="#!">Show history</a><a class="dropdown-item" href="#!">Report to Admin</a><a class="dropdown-item btn-support-chat" href="#!">Close Support</a></div> type="button"
id="support-chat-dropdown"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h text-body"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2"
aria-labelledby="support-chat-dropdown">
<a class="dropdown-item" href="#!">Request a callback</a><a class="dropdown-item" href="#!">Search in chat</a><a class="dropdown-item" href="#!">Show history</a><a class="dropdown-item" href="#!">Report to Admin</a><a class="dropdown-item btn-support-chat" href="#!">Close Support</a>
</div>
</div> </div>
</div> </div>
<div class="card-body chat p-0"> <div class="card-body chat p-0">
<div class="d-flex flex-column-reverse scrollbar h-100 p-3"> <div class="d-flex flex-column-reverse scrollbar h-100 p-3">
<div class="text-end mt-6"><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> <div class="text-end mt-6">
<p class="mb-0 fw-semibold fs-9">I need help with something</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> href="#!">
<p class="mb-0 fw-semibold fs-9">I cant reorder a product I previously ordered</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <p class="mb-0 fw-semibold fs-9">I need help with something</p>
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> <span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
<p class="mb-0 fw-semibold fs-9">How do I place an order?</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> </a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
</a><a class="false d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3" href="#!"> href="#!">
<p class="mb-0 fw-semibold fs-9">My payment method not working</p><span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span> <p class="mb-0 fw-semibold fs-9">I cant reorder a product I previously ordered</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a><a class="mb-2 d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
href="#!">
<p class="mb-0 fw-semibold fs-9">How do I place an order?</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a><a class="false d-inline-flex align-items-center text-decoration-none text-body-emphasis bg-body-hover rounded-pill border border-primary py-2 ps-4 pe-3"
href="#!">
<p class="mb-0 fw-semibold fs-9">My payment method not working</p>
<span class="fa-solid fa-paper-plane text-primary fs-9 ms-3"></span>
</a> </a>
</div> </div>
<div class="text-center mt-auto"> <div class="text-center mt-auto">
<div class="avatar avatar-3xl status-online"><img class="rounded-circle border border-3 border-light-subtle" src="{% static 'images/team/40x40/30.webp' %}" alt="" /></div> <div class="avatar avatar-3xl status-online">
<img class="rounded-circle border border-3 border-light-subtle"
src="{% static 'images/team/40x40/30.webp' %}"
alt="" />
</div>
<h5 class="mt-2 mb-3">Eric</h5> <h5 class="mt-2 mb-3">Eric</h5>
<p class="text-center text-body-emphasis mb-0">Ask us anything well get back to you here or by email within 24 hours.</p> <p class="text-center text-body-emphasis mb-0">
Ask us anything well get back to you here or by email within 24 hours.
</p>
</div> </div>
</div> </div>
</div> </div>
<div class="card-footer d-flex align-items-center gap-2 border-top border-translucent ps-3 pe-4 py-3"> <div class="card-footer d-flex align-items-center gap-2 border-top border-translucent ps-3 pe-4 py-3">
<div class="d-flex align-items-center flex-1 gap-3 border border-translucent rounded-pill px-4"> <div class="d-flex align-items-center flex-1 gap-3 border border-translucent rounded-pill px-4">
<input class="form-control outline-none border-0 flex-1 fs-9 px-0" type="text" placeholder="Write message" /> <input class="form-control outline-none border-0 flex-1 fs-9 px-0"
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0" for="supportChatPhotos"><span class="fa-solid fa-image"></span></label> type="text"
placeholder="Write message" />
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0"
for="supportChatPhotos">
<span class="fa-solid fa-image"></span>
</label>
<input class="d-none" type="file" accept="image/*" id="supportChatPhotos" /> <input class="d-none" type="file" accept="image/*" id="supportChatPhotos" />
<label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0" for="supportChatAttachment"> <span class="fa-solid fa-paperclip"></span></label> <label class="btn btn-link d-flex p-0 text-body-quaternary fs-9 border-0"
for="supportChatAttachment">
<span class="fa-solid fa-paperclip"></span>
</label>
<input class="d-none" type="file" id="supportChatAttachment" /> <input class="d-none" type="file" id="supportChatAttachment" />
</div> </div>
<button class="btn p-0 border-0 send-btn"><span class="fa-solid fa-paper-plane fs-9"></span></button> <button class="btn p-0 border-0 send-btn">
<span class="fa-solid fa-paper-plane fs-9"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
<button class="btn btn-support-chat p-0 border border-translucent"><span class="fs-8 btn-text text-primary text-nowrap">Chat demo</span><span class="ping-icon-wrapper mt-n4 ms-n6 mt-sm-0 ms-sm-2 position-absolute position-sm-relative"><span class="ping-icon-bg"></span><span class="fa-solid fa-circle ping-icon"></span></span><span class="fa-solid fa-headset text-primary fs-8 d-sm-none"></span><span class="fa-solid fa-chevron-down text-primary fs-7"></span></button> <button class="btn btn-support-chat p-0 border border-translucent">
<span class="fs-8 btn-text text-primary text-nowrap">Chat demo</span><span class="ping-icon-wrapper mt-n4 ms-n6 mt-sm-0 ms-sm-2 position-absolute position-sm-relative"><span class="ping-icon-bg"></span><span class="fa-solid fa-circle ping-icon"></span></span><span class="fa-solid fa-headset text-primary fs-8 d-sm-none"></span><span class="fa-solid fa-chevron-down text-primary fs-7"></span>
</button>
</div> </div>

View File

@ -1,16 +1,24 @@
{% load static i18n crispy_forms_tags %} {% load static i18n crispy_forms_tags %}
<!-- activity Modal --> <!-- activity Modal -->
<div class="modal fade" id="activityModal" tabindex="-1" aria-labelledby="activityModalLabel" aria-hidden="true"> <div class="modal fade"
id="activityModal"
tabindex="-1"
aria-labelledby="activityModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-md"> <div class="modal-dialog modal-md">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0"> <div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
<h4 class="modal-title" id="noteModalLabel">{% trans 'Activity' %}</h4> <h4 class="modal-title" id="noteModalLabel">{% trans 'Activity' %}</h4>
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"> <button class="btn p-0 text-body-quaternary fs-6"
data-bs-dismiss="modal"
aria-label="Close">
<span class="fas fa-times"></span> <span class="fas fa-times"></span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_activity' dealer_slug=request.dealer.slug content_type=content_type slug=slug %}" method="post" class="add_activity_form"> <form action="{% url 'add_activity' dealer_slug=request.dealer.slug content_type=content_type slug=slug %}"
method="post"
class="add_activity_form">
{% csrf_token %} {% csrf_token %}
<div class="mb-2 form-group"> <div class="mb-2 form-group">
<select class="form-select" name="activity_type" id="activity_type"> <select class="form-select" name="activity_type" id="activity_type">

View File

@ -1,7 +1,6 @@
{% load i18n %} {% load i18n %}
{% if date_navigation_url %} {% if date_navigation_url %}
<button id="{{ date_picker_id }}" data-baseurl="{{ date_navigation_url }}" <button id="{{ date_picker_id }}"
data-baseurl="{{ date_navigation_url }}"
class="btn btn-sm btn-phoenix-primary">{% trans 'Select Date' %}</button> class="btn btn-sm btn-phoenix-primary">{% trans 'Select Date' %}</button>
{% endif %} {% endif %}

View File

@ -1,15 +1,23 @@
{% load i18n crispy_forms_tags %} {% load i18n crispy_forms_tags %}
<div class="modal fade" id="noteModal" tabindex="-1" aria-labelledby="noteModalLabel" aria-hidden="true"> <div class="modal fade"
id="noteModal"
tabindex="-1"
aria-labelledby="noteModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-md"> <div class="modal-dialog modal-md">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0"> <div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
<h4 class="modal-title" id="noteModalLabel">{% trans 'Note' %}</h4> <h4 class="modal-title" id="noteModalLabel">{% trans 'Note' %}</h4>
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"> <button class="btn p-0 text-body-quaternary fs-6"
data-bs-dismiss="modal"
aria-label="Close">
<span class="fas fa-times"></span> <span class="fas fa-times"></span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_note' request.dealer.slug content_type slug %}" method="post" class="add_note_form"> <form action="{% url 'add_note' request.dealer.slug content_type slug %}"
method="post"
class="add_note_form">
{% csrf_token %} {% csrf_token %}
{{ note_form|crispy }} {{ note_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>
@ -18,7 +26,6 @@
</div> </div>
</div> </div>
</div> </div>
<script> <script>
function updateNote(e) { function updateNote(e) {
let url = e.getAttribute('data-url') let url = e.getAttribute('data-url')

View File

@ -1,15 +1,23 @@
{% load i18n crispy_forms_filters %} {% load i18n crispy_forms_filters %}
<div class="modal fade" id="scheduleModal" tabindex="-1" aria-labelledby="taskModalLabel" aria-hidden="true"> <div class="modal fade"
id="scheduleModal"
tabindex="-1"
aria-labelledby="taskModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-md"> <div class="modal-dialog modal-md">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0"> <div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
<h4 class="modal-title" id="taskModalLabel">{% trans 'Schedule' %}</h4> <h4 class="modal-title" id="taskModalLabel">{% trans 'Schedule' %}</h4>
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"> <button class="btn p-0 text-body-quaternary fs-6"
data-bs-dismiss="modal"
aria-label="Close">
<span class="fas fa-times"></span> <span class="fas fa-times"></span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'schedule_event' request.dealer.slug content_type slug %}" method="post" class="add_schedule_form"> <form action="{% url 'schedule_event' request.dealer.slug content_type slug %}"
method="post"
class="add_schedule_form">
{% csrf_token %} {% csrf_token %}
{{ schedule_form|crispy }} {{ schedule_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>

View File

@ -6,17 +6,25 @@
opacity: 0.7; opacity: 0.7;
} }
</style> </style>
<div class="modal fade" id="taskModal" tabindex="-1" aria-labelledby="taskModalLabel" aria-hidden="true"> <div class="modal fade"
id="taskModal"
tabindex="-1"
aria-labelledby="taskModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-md"> <div class="modal-dialog modal-md">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0"> <div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
<h4 class="modal-title" id="taskModalLabel">{% trans 'Task' %}</h4> <h4 class="modal-title" id="taskModalLabel">{% trans 'Task' %}</h4>
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"> <button class="btn p-0 text-body-quaternary fs-6"
data-bs-dismiss="modal"
aria-label="Close">
<span class="fas fa-times"></span> <span class="fas fa-times"></span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form action="{% url 'add_task' request.dealer.slug content_type slug %}" method="post" class="add_task_form"> <form action="{% url 'add_task' request.dealer.slug content_type slug %}"
method="post"
class="add_task_form">
{% csrf_token %} {% csrf_token %}
{{ staff_task_form|crispy }} {{ staff_task_form|crispy }}
<button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button> <button type="submit" class="btn btn-phoenix-success w-100">{% trans 'Save' %}</button>

View File

@ -1,6 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static crispy_forms_filters %} {% load i18n static crispy_forms_filters %}
{% block content %} {% block content %}
<h1>Add Activity to {{ lead.first_name }} {{ lead.last_name }}</h1> <h1>Add Activity to {{ lead.first_name }} {{ lead.last_name }}</h1>
<form method="post"> <form method="post">

View File

@ -4,7 +4,5 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Title</title> <title>Title</title>
</head> </head>
<body> <body></body>
</body>
</html> </html>

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static humanize %} {% load i18n static humanize %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block customCSS %} {% block customCSS %}
<style> <style>
.main-tab li:last-child { .main-tab li:last-child {
@ -42,7 +41,9 @@
<div class="col-12 col-md-auto"> <div class="col-12 col-md-auto">
<div class="d-flex"> <div class="d-flex">
<div class="flex-1 d-md-none"> <div class="flex-1 d-md-none">
<button class="btn px-3 btn-phoenix-secondary text-body-tertiary me-2"><span class="fa-solid fa-bars"></span></button> <button class="btn px-3 btn-phoenix-secondary text-body-tertiary me-2">
<span class="fa-solid fa-bars"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -55,7 +56,9 @@
<div class="lead-details" data-breakpoint="md"> <div class="lead-details" data-breakpoint="md">
<div class="d-flex justify-content-between align-items-center mb-2 d-md-none"> <div class="d-flex justify-content-between align-items-center mb-2 d-md-none">
<h3 class="mb-0">{{ _("Lead Details") }}</h3> <h3 class="mb-0">{{ _("Lead Details") }}</h3>
<button class="btn p-0" ><span class="uil uil-times fs-7"></span></button> <button class="btn p-0">
<span class="uil uil-times fs-7"></span>
</button>
</div> </div>
<div class="card mb-2"> <div class="card mb-2">
<div class="card-body"> <div class="card-body">
@ -63,14 +66,16 @@
<div class="col-6 col-sm-auto flex-1"> <div class="col-6 col-sm-auto flex-1">
<h3 class="fw-bolder mb-2">{{ lead.first_name }} {{ lead.last_name }}</h3> <h3 class="fw-bolder mb-2">{{ lead.first_name }} {{ lead.last_name }}</h3>
{% if lead.staff %} {% if lead.staff %}
<p class="fs-8 mb-0 white-space-nowrap fw-bold">{{ _("Assigned to")}}: <span class="fw-light">{{ lead.staff }}</span></p> <p class="fs-8 mb-0 white-space-nowrap fw-bold">
{{ _("Assigned to") }}: <span class="fw-light">{{ lead.staff }}</span>
</p>
{% else %} {% else %}
<p class="mb-0 fw-bold">{{ _("Not Assigned") }}</p> <p class="mb-0 fw-bold">{{ _("Not Assigned") }}</p>
{% endif %} {% endif %}
</div> </div>
<div class="col-6 col-sm-auto flex-1"> <div class="col-6 col-sm-auto flex-1">
<h5 class="text-body-highlight mb-0 text-end">
<h5 class="text-body-highlight mb-0 text-end">{{ _("Status")}} {{ _("Status") }}
{% if lead.status == "new" %} {% if lead.status == "new" %}
<span class="badge badge-phoenix badge-phoenix-primary"><span class="badge-label">{{ _("New") }}</span><span class="fa fa-bell ms-1"></span></span> <span class="badge badge-phoenix badge-phoenix-primary"><span class="badge-label">{{ _("New") }}</span><span class="fa fa-bell ms-1"></span></span>
{% elif lead.status == "contacted" %} {% elif lead.status == "contacted" %}
@ -92,7 +97,11 @@
<div class="row align-items-center g-3 text-center text-xxl-start"> <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"> <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> <h5 class="fw-bolder mb-2 text-body-highlight">{{ _("Car Requested") }}</h5>
<img src="{{ lead.id_car_make.logo.url }}" alt="Car Make Logo" class="img-fluid rounded mb-2" style="width: 60px; height: 60px;"> <img src="{{ lead.id_car_make.logo.url }}"
alt="Car Make Logo"
class="img-fluid rounded mb-2"
style="width: 60px;
height: 60px">
<p class="mb-0">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</p> <p class="mb-0">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</p>
</div> </div>
</div> </div>
@ -105,7 +114,8 @@
<h5 class="fw-bolder mb-2 text-body-highlight">{{ _("Related Records") }}</h5> <h5 class="fw-bolder mb-2 text-body-highlight">{{ _("Related Records") }}</h5>
<h6 class="fw-bolder mb-2 text-body-highlight">{{ _("Opportunity") }}</h6> <h6 class="fw-bolder mb-2 text-body-highlight">{{ _("Opportunity") }}</h6>
{% if lead.opportunity %} {% if lead.opportunity %}
<a href="{% url 'opportunity_detail' request.dealer.slug lead.opportunity.slug %}" class="">{{ lead.opportunity }}</a> <a href="{% url 'opportunity_detail' request.dealer.slug lead.opportunity.slug %}"
class="">{{ lead.opportunity }}</a>
{% else %} {% else %}
<p>{{ _("No Opportunity") }}</p> <p>{{ _("No Opportunity") }}</p>
{% endif %} {% endif %}
@ -116,25 +126,29 @@
<div class="card mb-2"> <div class="card mb-2">
<div class="card-body"> <div class="card-body">
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-envelope-alt"> </span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-envelope-alt"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Email") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Email") }}</h5>
</div> </div>
<span class="text-body-secondary">{{ lead.email }}</span> <span class="text-body-secondary">{{ lead.email }}</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-phone"> </span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-phone"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Phone") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Phone") }}</h5>
</div> </div>
<span class="text-body-secondary">{{ lead.phone_number }}</span> <span class="text-body-secondary">{{ lead.phone_number }}</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-clock"></span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-clock"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Created") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Created") }}</h5>
</div> </div>
<span class="text-body-secondary">{{ lead.created|naturalday|capfirst }}</span> <span class="text-body-secondary">{{ lead.created|naturalday|capfirst }}</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-file-check-alt"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source") }}</h5>
</div> </div>
{% if lead.source == 'REFERRALS' %} {% if lead.source == 'REFERRALS' %}
@ -163,13 +177,15 @@
<span class="text-body-secondary">{{ lead.source|upper }}</span> <span class="text-body-secondary">{{ lead.source|upper }}</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-file-check-alt"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Channel") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Channel") }}</h5>
</div> </div>
<span class="text-body-secondary">{{ lead.channel|upper }}</span> <span class="text-body-secondary">{{ lead.channel|upper }}</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-estate"></span> <div class="d-flex align-items-center mb-1">
<span class="me-2 uil uil-estate"></span>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Address") }}</h5> <h5 class="text-body-highlight fw-bold mb-0">{{ _("Address") }}</h5>
</div> </div>
<span class="text-body-secondary">{{ lead.address }}</span> <span class="text-body-secondary">{{ lead.address }}</span>
@ -182,39 +198,104 @@
</div> </div>
<div class="col-md-7 col-lg-7 col-xl-8"> <div class="col-md-7 col-lg-7 col-xl-8">
<div class="d-flex w-100 gap-5"> <div class="d-flex w-100 gap-5">
<div class="kanban-header bg-success w-50 text-white fw-bold"><i class="fa-solid fa-circle-check me-2"></i>{{lead.status|capfirst}} <br> &nbsp; <small>{% trans "Current Stage" %}</small></div> <div class="kanban-header bg-success w-50 text-white fw-bold">
<div class="kanban-header bg-secondary w-50 text-white fw-bold"><i class="fa-solid fa-circle-info me-2"></i>{{lead.next_action|capfirst}} <br> &nbsp; <small>{% trans "Next Action" %} :</small>&nbsp; <small>{{lead.next_action_date|naturalday|capfirst}}</small></div> <i class="fa-solid fa-circle-check me-2"></i>{{ lead.status|capfirst }}
<br>
&nbsp; <small>{% trans "Current Stage" %}</small>
</div> </div>
<ul class="nav main-tab nav-underline fs-9 deal-details scrollbar flex-nowrap w-100 pb-1 mb-6 justify-content-end mt-5" id="myTab" role="tablist" style="overflow-y: hidden;"> <div class="kanban-header bg-secondary w-50 text-white fw-bold">
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link active" id="tasks-tab" data-bs-toggle="tab" href="#tab-tasks" role="tab" aria-controls="tab-tasks" aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Tasks") }}</a></li> <i class="fa-solid fa-circle-info me-2"></i>{{ lead.next_action|capfirst }}
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="notes-tab" data-bs-toggle="tab" href="#tab-notes" role="tab" aria-controls="tab-notes" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-clipboard me-2 tab-icon-color fs-8"></span>{{ _("Notes") }}</a></li> <br>
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="emails-tab" data-bs-toggle="tab" href="#tab-emails" role="tab" aria-controls="tab-emails" aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Emails") }}</a></li> &nbsp; <small>{% trans "Next Action" %} :</small>&nbsp; <small>{{ lead.next_action_date|naturalday|capfirst }}</small>
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="activity-tab" data-bs-toggle="tab" href="#tab-activity" role="tab" aria-controls="tab-activity" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Activity") }}</a></li> </div>
<li class="nav-item text-nowrap me-2" role="presentation"><a class="nav-link" id="opportunity-tab" data-bs-toggle="tab" href="#tab-opportunity" role="tab" aria-controls="tab-opportunity" aria-selected="false" tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Opportunities") }}</a></li> </div>
<ul class="nav main-tab nav-underline fs-9 deal-details scrollbar flex-nowrap w-100 pb-1 mb-6 justify-content-end mt-5"
id="myTab"
role="tablist"
style="overflow-y: hidden">
<li class="nav-item text-nowrap me-2" role="presentation">
<a class="nav-link active"
id="tasks-tab"
data-bs-toggle="tab"
href="#tab-tasks"
role="tab"
aria-controls="tab-tasks"
aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Tasks") }}</a>
</li>
<li class="nav-item text-nowrap me-2" role="presentation">
<a class="nav-link"
id="notes-tab"
data-bs-toggle="tab"
href="#tab-notes"
role="tab"
aria-controls="tab-notes"
aria-selected="false"
tabindex="-1"> <span class="fa-solid fa-clipboard me-2 tab-icon-color fs-8"></span>{{ _("Notes") }}</a>
</li>
<li class="nav-item text-nowrap me-2" role="presentation">
<a class="nav-link"
id="emails-tab"
data-bs-toggle="tab"
href="#tab-emails"
role="tab"
aria-controls="tab-emails"
aria-selected="true"> <span class="fa-solid fa-envelope me-2 tab-icon-color fs-8"></span>{{ _("Emails") }}</a>
</li>
<li class="nav-item text-nowrap me-2" role="presentation">
<a class="nav-link"
id="activity-tab"
data-bs-toggle="tab"
href="#tab-activity"
role="tab"
aria-controls="tab-activity"
aria-selected="false"
tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Activity") }}</a>
</li>
<li class="nav-item text-nowrap me-2" role="presentation">
<a class="nav-link"
id="opportunity-tab"
data-bs-toggle="tab"
href="#tab-opportunity"
role="tab"
aria-controls="tab-opportunity"
aria-selected="false"
tabindex="-1"> <span class="fa-solid fa-chart-line me-2 tab-icon-color fs-8"></span>{{ _("Opportunities") }}</a>
</li>
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
<li class="nav-item text-nowrap ml-auto" role="presentation"> <li class="nav-item text-nowrap ml-auto" role="presentation">
{% if perms.inventory.can_reassign_lead %} {% if perms.inventory.can_reassign_lead %}
<button class="btn btn-phoenix-primary btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#exampleModal"> <i class="fa-solid fa-user-plus me-2"></i> Reassign Lead</button> <button class="btn btn-phoenix-primary btn-sm"
type="button"
data-bs-toggle="modal"
data-bs-target="#exampleModal">
<i class="fa-solid fa-user-plus me-2"></i> Reassign Lead
</button>
{% endif %} {% endif %}
<button class="btn btn-phoenix-primary btn-sm" onclick="openActionModal('{{ lead.id }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')"> <button class="btn btn-phoenix-primary btn-sm"
onclick="openActionModal('{{ lead.id }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')">
<i class="fa-solid fa-user-plus me-2"></i> <i class="fa-solid fa-user-plus me-2"></i>
{% trans "Update Actions" %} {% trans "Update Actions" %}
</button> </button>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<form class="modal-content" action="{% url 'lead_transfer' request.dealer.slug lead.slug %}" method="post"> <form class="modal-content"
action="{% url 'lead_transfer' request.dealer.slug lead.slug %}"
method="post">
{% csrf_token %} {% csrf_token %}
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Reassign Lead To Another Employee</h5> <h5 class="modal-title" id="exampleModalLabel">Reassign Lead To Another Employee</h5>
<button class="btn btn-close p-1" type="button" data-bs-dismiss="modal" aria-label="Close"></button> <button class="btn btn-close p-1"
</div> type="button"
<div class="modal-body"> data-bs-dismiss="modal"
{{transfer_form|crispy}} aria-label="Close"></button>
</div> </div>
<div class="modal-body">{{ transfer_form|crispy }}</div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-phoenix-primary" type="submit">Save</button> <button class="btn btn-phoenix-primary" type="submit">Save</button>
<button class="btn btn-phoenix-secondary" type="button" data-bs-dismiss="modal">Cancel</button> <button class="btn btn-phoenix-secondary"
type="button"
data-bs-dismiss="modal">Cancel</button>
</div> </div>
</form> </form>
</div> </div>
@ -224,11 +305,15 @@
{% endif %} {% endif %}
</ul> </ul>
<div class="tab-content" id="myTabContent"> <div class="tab-content" id="myTabContent">
<div class="tab-pane fade" id="tab-activity" role="tabpanel" aria-labelledby="activity-tab"> <div class="tab-pane fade"
id="tab-activity"
role="tabpanel"
aria-labelledby="activity-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-4" id="s crollspyTask">{{ _("Activities") }} <span class="fw-light fs-7">({{ activities.count}})</span></h3> <h3 class="mb-4" id="s crollspyTask">
{% if perms.inventory.change_lead%} {{ _("Activities") }} <span class="fw-light fs-7">({{ activities.count }})</span>
{% endif %} </h3>
{% if perms.inventory.change_lead %}{% endif %}
</div> </div>
<div class="row justify-content-between align-items-md-center hover-actions-trigger btn-reveal-trigger border-translucent py-3 gx-0 border-top"> <div class="row justify-content-between align-items-md-center hover-actions-trigger btn-reveal-trigger border-translucent py-3 gx-0 border-top">
<div class="col-12 col-lg-auto"> <div class="col-12 col-lg-auto">
@ -265,9 +350,13 @@
<div class="d-flex mb-2"> <div class="d-flex mb-2">
<h6 class="lh-sm mb-0 me-2 text-body-secondary timeline-item-title">{{ activity.activity_type|capfirst }}</h6> <h6 class="lh-sm mb-0 me-2 text-body-secondary timeline-item-title">{{ activity.activity_type|capfirst }}</h6>
</div> </div>
<p class="text-body-quaternary fs-9 mb-0 text-nowrap timeline-time"><span class="fa-regular fa-clock me-1"></span>{{ activity.created|naturalday|capfirst }}</p> <p class="text-body-quaternary fs-9 mb-0 text-nowrap timeline-time">
<span class="fa-regular fa-clock me-1"></span>{{ activity.created|naturalday|capfirst }}
</p>
</div> </div>
<h6 class="fs-10 fw-normal mb-3">{{ _("created by") }} <a class="fw-semibold" href="#!">{{ activity.created_by }}</a></h6> <h6 class="fs-10 fw-normal mb-3">
{{ _("created by") }} <a class="fw-semibold" href="#!">{{ activity.created_by }}</a>
</h6>
<p class="fs-9 text-body-secondary w-sm-60 mb-5">{{ activity.notes }}</p> <p class="fs-9 text-body-secondary w-sm-60 mb-5">{{ activity.notes }}</p>
</div> </div>
</div> </div>
@ -277,22 +366,35 @@
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="tab-opportunity" role="tabpanel" aria-labelledby="opportunity-tab"> <div class="tab-pane fade"
id="tab-opportunity"
role="tabpanel"
aria-labelledby="opportunity-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-4" id="scrollspyTask">{{ _("Opportunities") }} <span class="fw-light fs-7">({{ lead.get_opportunities.count}})</span></h3> <h3 class="mb-4" id="scrollspyTask">
{{ _("Opportunities") }} <span class="fw-light fs-7">({{ lead.get_opportunities.count }})</span>
</h3>
{% if perms.inventory.add_opportunity %} {% if perms.inventory.add_opportunity %}
<a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}" class="btn btn-phoenix-primary btn-sm" type="button"> <i class="fa-solid fa-plus me-2"></i>{{ _("Add Opportunity") }}</a> <a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}"
class="btn btn-phoenix-primary btn-sm"
type="button"> <i class="fa-solid fa-plus me-2"></i>{{ _("Add Opportunity") }}</a>
{% endif %} {% endif %}
</div> </div>
<div class="border-top border-bottom border-translucent"
<div class="border-top border-bottom border-translucent" id="leadDetailsTable"> id="leadDetailsTable">
<div class="table-responsive scrollbar mx-n1 px-1"> <div class="table-responsive scrollbar mx-n1 px-1">
<table class="table fs-9 mb-0"> <table class="table fs-9 mb-0">
<thead> <thead>
<tr> <tr>
<th class="align-middle pe-6 text-uppercase text-start" scope="col" style="width:40%;">{{ _("Car") }}</th> <th class="align-middle pe-6 text-uppercase text-start"
<th class="align-middle text-start text-uppercase" scope="col" style="width:20%;">{{ _("Probability")}}</th> scope="col"
<th class="align-middle text-start text-uppercase white-space-nowrap" scope="col" style="width:20%;">{{ _("Priority")}}</th> style="width:40%">{{ _("Car") }}</th>
<th class="align-middle text-start text-uppercase"
scope="col"
style="width:20%">{{ _("Probability") }}</th>
<th class="align-middle text-start text-uppercase white-space-nowrap"
scope="col"
style="width:20%">{{ _("Priority") }}</th>
<th class="align-middle pe-0 text-end" scope="col" style="width:10%;"></th> <th class="align-middle pe-0 text-end" scope="col" style="width:10%;"></th>
</tr> </tr>
</thead> </thead>
@ -302,31 +404,48 @@
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.car }}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.car }}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.probability }}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.probability }}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.priority|capfirst }}</td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">{{ opportunity.priority|capfirst }}</td>
<td class="align-middle text-start fw-bold text-body-tertiary ps-1"><a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">View</a></td> <td class="align-middle text-start fw-bold text-body-tertiary ps-1">
<a class="btn btn-sm btn-phoenix-primary"
href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">View</a>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="tab-notes" role="tabpanel" aria-labelledby="notes-tab"> <div class="tab-pane fade"
id="tab-notes"
role="tabpanel"
aria-labelledby="notes-tab">
<div class="mb-1 d-flex align-items-center justify-content-between"> <div class="mb-1 d-flex align-items-center justify-content-between">
<h3 class="mb-4" id="scrollspyNotes">{{ _("Notes") }}</h3> <h3 class="mb-4" id="scrollspyNotes">{{ _("Notes") }}</h3>
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
<button class="btn btn-phoenix-primary btn-sm" type="button" onclick="reset_form()" data-bs-toggle="modal" data-bs-target="#noteModal"><span class="fas fa-plus me-1"></span>{{ _("Add Note") }}</button> <button class="btn btn-phoenix-primary btn-sm"
type="button"
onclick="reset_form()"
data-bs-toggle="modal"
data-bs-target="#noteModal">
<span class="fas fa-plus me-1"></span>{{ _("Add Note") }}
</button>
{% endif %} {% endif %}
</div> </div>
<div class="border-top border-bottom border-translucent"
<div class="border-top border-bottom border-translucent" id="leadDetailsTable"> id="leadDetailsTable">
<div class="table-responsive scrollbar mx-n1 px-1"> <div class="table-responsive scrollbar mx-n1 px-1">
<table class="table fs-9 mb-0"> <table class="table fs-9 mb-0">
<thead> <thead>
<tr> <tr>
<th class="align-middle pe-6 text-uppercase text-start" scope="col" style="width:40%;">{{ _("Note") }}</th> <th class="align-middle pe-6 text-uppercase text-start"
<th class="align-middle text-start text-uppercase white-space-nowrap" scope="col" style="width:40%;">{{ _("Created On")}}</th> scope="col"
<th class="align-middle text-start text-uppercase white-space-nowrap" scope="col" style="width:40%;">{{ _("Last Updated")}}</th> style="width:40%">{{ _("Note") }}</th>
<th class="align-middle text-start text-uppercase white-space-nowrap"
scope="col"
style="width:40%">{{ _("Created On") }}</th>
<th class="align-middle text-start text-uppercase white-space-nowrap"
scope="col"
style="width:40%">{{ _("Last Updated") }}</th>
<th class="align-middle pe-0 text-end" scope="col" style="width:10%;"></th> <th class="align-middle pe-0 text-end" scope="col" style="width:10%;"></th>
</tr> </tr>
</thead> </thead>
@ -347,13 +466,14 @@
data-url="{% url 'update_note' request.dealer.slug note.pk %}" data-url="{% url 'update_note' request.dealer.slug note.pk %}"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#noteModal" data-bs-target="#noteModal"
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>"> data-note-title="{{ _("Update") }}<i class='fas fa-pen-square text-primary ms-2'></i>">
{{ _("Update") }} {{ _("Update") }}
</a> </a>
<button class="btn btn-phoenix-danger btn-sm delete-btn" <button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'delete_note_to_lead' request.dealer.slug note.pk %}" data-url="{% url 'delete_note_to_lead' request.dealer.slug note.pk %}"
data-message="Are you sure you want to delete this note?" data-message="Are you sure you want to delete this note?"
data-bs-toggle="modal" data-bs-target="#deleteModal"> data-bs-toggle="modal"
data-bs-target="#deleteModal">
<i class="fas fa-trash"></i> <i class="fas fa-trash"></i>
</button> </button>
{% endif %} {% endif %}
@ -365,7 +485,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="tab-emails" role="tabpanel" aria-labelledby="emails-tab"> <div class="tab-pane fade"
id="tab-emails"
role="tabpanel"
aria-labelledby="emails-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-0" id="scrollspyEmails">{{ _("Emails") }}</h3> <h3 class="mb-0" id="scrollspyEmails">{{ _("Emails") }}</h3>
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
@ -379,28 +502,71 @@
</div> </div>
<div> <div>
<div class="scrollbar"> <div class="scrollbar">
<ul class="nav nav-underline fs-9 flex-nowrap mb-1" id="emailTab" role="tablist"> <ul class="nav nav-underline fs-9 flex-nowrap mb-1"
<li class="nav-item me-3"><a class="nav-link text-nowrap border-0 active" id="mail-tab" data-bs-toggle="tab" href="#tab-mail" aria-controls="mail-tab" role="tab" aria-selected="true">Mails ({{emails.sent.count}})<span class="text-body-tertiary fw-normal"></span></a></li> id="emailTab"
<li class="nav-item me-3"><a class="nav-link text-nowrap border-0" id="drafts-tab" data-bs-toggle="tab" href="#tab-drafts" aria-controls="drafts-tab" role="tab" aria-selected="true">Drafts ({{emails.draft.count}})<span class="text-body-tertiary fw-normal"></span></a></li> role="tablist">
<li class="nav-item me-3">
<a class="nav-link text-nowrap border-0 active"
id="mail-tab"
data-bs-toggle="tab"
href="#tab-mail"
aria-controls="mail-tab"
role="tab"
aria-selected="true">Mails ({{ emails.sent.count }})<span class="text-body-tertiary fw-normal"></span></a>
</li>
<li class="nav-item me-3">
<a class="nav-link text-nowrap border-0"
id="drafts-tab"
data-bs-toggle="tab"
href="#tab-drafts"
aria-controls="drafts-tab"
role="tab"
aria-selected="true">Drafts ({{ emails.draft.count }})<span class="text-body-tertiary fw-normal"></span></a>
</li>
</ul> </ul>
</div> </div>
<div class="tab-content" id="profileTabContent"> <div class="tab-content" id="profileTabContent">
<div class="tab-pane fade show active" id="tab-mail" role="tabpanel" aria-labelledby="mail-tab"> <div class="tab-pane fade show active"
<div class="border-top border-bottom border-translucent" id="allEmailsTable" data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'> id="tab-mail"
role="tabpanel"
aria-labelledby="mail-tab">
<div class="border-top border-bottom border-translucent"
id="allEmailsTable"
data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'>
<div class="table-responsive scrollbar mx-n1 px-1"> <div class="table-responsive scrollbar mx-n1 px-1">
<table class="table fs-9 mb-0"> <table class="table fs-9 mb-0">
<thead> <thead>
<tr> <tr>
<th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;"> <th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" type="checkbox" data-bulk-select='{"body":"all-email-table-body"}' /> <input class="form-check-input"
type="checkbox"
data-bulk-select='{"body":"all-email-table-body"}' />
</div> </div>
</th> </th>
<th class="sort white-space-nowrap align-middle pe-3 ps-0 text-uppercase" scope="col" data-sort="subject" style="width:31%; min-width:350px">Subject</th> <th class="sort white-space-nowrap align-middle pe-3 ps-0 text-uppercase"
<th class="sort align-middle pe-3 text-uppercase" scope="col" data-sort="sent" style="width:15%; min-width:130px">Sent by</th> scope="col"
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Date</th> data-sort="subject"
<th class="sort align-middle pe-0 text-uppercase" scope="col" style="width:15%; min-width:100px">Action</th> style="width:31%;
<th class="sort align-middle text-end text-uppercase" scope="col" data-sort="status" style="width:15%; min-width:100px">Status</th> min-width:350px">Subject</th>
<th class="sort align-middle pe-3 text-uppercase"
scope="col"
data-sort="sent"
style="width:15%;
min-width:130px">Sent by</th>
<th class="sort align-middle text-start text-uppercase"
scope="col"
data-sort="date"
style="min-width:165px">Date</th>
<th class="sort align-middle pe-0 text-uppercase"
scope="col"
style="width:15%;
min-width:100px">Action</th>
<th class="sort align-middle text-end text-uppercase"
scope="col"
data-sort="status"
style="width:15%;
min-width:100px">Status</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="all-email-table-body"> <tbody class="list" id="all-email-table-body">
@ -408,16 +574,23 @@
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="fs-9 align-middle px-0 py-3"> <td class="fs-9 align-middle px-0 py-3">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" type="checkbox" data-bulk-select-row='{"mail":{"subject":"Quary about purchased soccer socks","email":"jackson@mail.com"},"active":true,"sent":"Jackson Pollock","date":"Dec 29, 2021 10:23 am","source":"Call","type_status":{"label":"sent","type":"badge-phoenix-success"}}' /> <input class="form-check-input"
type="checkbox"
data-bulk-select-row='{"mail":{"subject":"Quary about purchased soccer socks","email":"jackson@mail.com"},"active":true,"sent":"Jackson Pollock","date":"Dec 29, 2021 10:23 am","source":"Call","type_status":{"label":"sent","type":"badge-phoenix-success"}}' />
</div> </div>
</td> </td>
<td class="subject order align-middle white-space-nowrap py-2 ps-0"><a class="fw-semibold text-primary" href="">{{email.subject}}</a> <td class="subject order align-middle white-space-nowrap py-2 ps-0">
<a class="fw-semibold text-primary" href="">{{ email.subject }}</a>
<div class="fs-10 d-block">{{ email.to_email }}</div> <div class="fs-10 d-block">{{ email.to_email }}</div>
</td> </td>
<td class="sent align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2">{{ email.from_email }}</td> <td class="sent align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2">{{ email.from_email }}</td>
<td class="date align-middle white-space-nowrap text-body py-2">{{ email.created|naturalday }}</td> <td class="date align-middle white-space-nowrap text-body py-2">{{ email.created|naturalday }}</td>
<td class="align-middle white-space-nowrap ps-3"><a class="text-body" href=""><span class="fa-solid fa-phone text-primary me-2"></span>Call</a></td> <td class="align-middle white-space-nowrap ps-3">
<td class="status align-middle fw-semibold text-end py-2"><span class="badge badge-phoenix fs-10 badge-phoenix-success">sent</span></td> <a class="text-body" href=""><span class="fa-solid fa-phone text-primary me-2"></span>Call</a>
</td>
<td class="status align-middle fw-semibold text-end py-2">
<span class="badge badge-phoenix fs-10 badge-phoenix-success">sent</span>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -425,32 +598,64 @@
</div> </div>
<div class="row align-items-center justify-content-between py-2 pe-0 fs-9"> <div class="row align-items-center justify-content-between py-2 pe-0 fs-9">
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<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-semibold" href="" data-list-view="*">View all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a><a class="fw-semibold d-none" href="" data-list-view="less">View Less<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a> <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-semibold" href="" data-list-view="*">View all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a><a class="fw-semibold d-none" href="" data-list-view="less">View Less<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
</div> </div>
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<button class="page-link" data-list-pagination="prev"><span class="fas fa-chevron-left"></span></button> <button class="page-link" data-list-pagination="prev">
<ul class="mb-0 pagination"></ul> <span class="fas fa-chevron-left"></span>
<button class="page-link pe-0" data-list-pagination="next"><span class="fas fa-chevron-right"></span></button> </button>
<ul class="mb-0 pagination">
</ul>
<button class="page-link pe-0" data-list-pagination="next">
<span class="fas fa-chevron-right"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane fade" id="tab-drafts" role="tabpanel" aria-labelledby="drafts-tab"> <div class="tab-pane fade"
<div class="border-top border-bottom border-translucent" id="draftsEmailsTable" data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'> id="tab-drafts"
role="tabpanel"
aria-labelledby="drafts-tab">
<div class="border-top border-bottom border-translucent"
id="draftsEmailsTable"
data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'>
<div class="table-responsive scrollbar mx-n1 px-1"> <div class="table-responsive scrollbar mx-n1 px-1">
<table class="table fs-9 mb-0"> <table class="table fs-9 mb-0">
<thead> <thead>
<tr> <tr>
<th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;"> <th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" type="checkbox" data-bulk-select='{"body":"drafts-email-table-body"}' /> <input class="form-check-input"
type="checkbox"
data-bulk-select='{"body":"drafts-email-table-body"}' />
</div> </div>
</th> </th>
<th class="sort white-space-nowrap align-middle pe-3 ps-0 text-uppercase" scope="col" data-sort="subject" style="width:31%; min-width:350px">Subject</th> <th class="sort white-space-nowrap align-middle pe-3 ps-0 text-uppercase"
<th class="sort align-middle pe-3 text-uppercase" scope="col" data-sort="sent" style="width:15%; min-width:130px">Sent by</th> scope="col"
<th class="sort align-middle text-start text-uppercase" scope="col" data-sort="date" style="min-width:165px">Date</th> data-sort="subject"
<th class="sort align-middle pe-0 text-uppercase" scope="col" style="width:15%; min-width:100px">Action</th> style="width:31%;
<th class="sort align-middle text-end text-uppercase" scope="col" data-sort="status" style="width:15%; min-width:100px">Status</th> min-width:350px">Subject</th>
<th class="sort align-middle pe-3 text-uppercase"
scope="col"
data-sort="sent"
style="width:15%;
min-width:130px">Sent by</th>
<th class="sort align-middle text-start text-uppercase"
scope="col"
data-sort="date"
style="min-width:165px">Date</th>
<th class="sort align-middle pe-0 text-uppercase"
scope="col"
style="width:15%;
min-width:100px">Action</th>
<th class="sort align-middle text-end text-uppercase"
scope="col"
data-sort="status"
style="width:15%;
min-width:100px">Status</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="drafts-email-table-body"> <tbody class="list" id="drafts-email-table-body">
@ -458,16 +663,24 @@
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="fs-9 align-middle px-0 py-3"> <td class="fs-9 align-middle px-0 py-3">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" type="checkbox" data-bulk-select-row='{"mail":{"subject":"Quary about purchased soccer socks","email":"jackson@mail.com"},"active":true,"sent":"Jackson Pollock","date":"Dec 29, 2021 10:23 am","source":"Call","type_status":{"label":"sent","type":"badge-phoenix-success"}}' /> <input class="form-check-input"
type="checkbox"
data-bulk-select-row='{"mail":{"subject":"Quary about purchased soccer socks","email":"jackson@mail.com"},"active":true,"sent":"Jackson Pollock","date":"Dec 29, 2021 10:23 am","source":"Call","type_status":{"label":"sent","type":"badge-phoenix-success"}}' />
</div> </div>
</td> </td>
<td class="subject order align-middle white-space-nowrap py-2 ps-0"><a class="fw-semibold text-primary" href="">{{email.subject}}</a> <td class="subject order align-middle white-space-nowrap py-2 ps-0">
<a class="fw-semibold text-primary" href="">{{ email.subject }}</a>
<div class="fs-10 d-block">{{ email.to_email }}</div> <div class="fs-10 d-block">{{ email.to_email }}</div>
</td> </td>
<td class="sent align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2">{{ email.from_email }}</td> <td class="sent align-middle white-space-nowrap text-start fw-bold text-body-tertiary py-2">{{ email.from_email }}</td>
<td class="date align-middle white-space-nowrap text-body py-2">{{ email.created }}</td> <td class="date align-middle white-space-nowrap text-body py-2">{{ email.created }}</td>
<td class="align-middle white-space-nowrap ps-3"><a class="text-body" href="{% url 'send_lead_email_with_template' request.dealer.slug lead.slug email.pk %}"><span class="fa-solid fa-email text-primary me-2"></span>Send</a></td> <td class="align-middle white-space-nowrap ps-3">
<td class="status align-middle fw-semibold text-end py-2"><span class="badge badge-phoenix fs-10 badge-phoenix-warning">draft</span></td> <a class="text-body"
href="{% url 'send_lead_email_with_template' request.dealer.slug lead.slug email.pk %}"><span class="fa-solid fa-email text-primary me-2"></span>Send</a>
</td>
<td class="status align-middle fw-semibold text-end py-2">
<span class="badge badge-phoenix fs-10 badge-phoenix-warning">draft</span>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -475,12 +688,19 @@
</div> </div>
<div class="row align-items-center justify-content-between py-2 pe-0 fs-9"> <div class="row align-items-center justify-content-between py-2 pe-0 fs-9">
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<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-semibold" href="" data-list-view="*">View all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a><a class="fw-semibold d-none" href="" data-list-view="less">View Less<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a> <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-semibold" href="" data-list-view="*">View all<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a><a class="fw-semibold d-none" href="" data-list-view="less">View Less<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
</div> </div>
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<button class="page-link" data-list-pagination="prev"><span class="fas fa-chevron-left"></span></button> <button class="page-link" data-list-pagination="prev">
<ul class="mb-0 pagination"></ul> <span class="fas fa-chevron-left"></span>
<button class="page-link pe-0" data-list-pagination="next"><span class="fas fa-chevron-right"></span></button> </button>
<ul class="mb-0 pagination">
</ul>
<button class="page-link pe-0" data-list-pagination="next">
<span class="fas fa-chevron-right"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -489,30 +709,55 @@
</div> </div>
</div> </div>
{% comment %} {% endcomment %} {% comment %} {% endcomment %}
<div class="tab-pane fade active show" id="tab-tasks" role="tabpanel" aria-labelledby="tasks-tab"> <div class="tab-pane fade active show"
id="tab-tasks"
role="tabpanel"
aria-labelledby="tasks-tab">
<div class="mb-1 d-flex justify-content-between align-items-center"> <div class="mb-1 d-flex justify-content-between align-items-center">
<h3 class="mb-0" id="scrollspyEmails">{{ _("Tasks") }}</h3> <h3 class="mb-0" id="scrollspyEmails">{{ _("Tasks") }}</h3>
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
{% comment %} <button class="btn btn-phoenix-primary btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#taskModal"><span class="fas fa-plus me-1"></span>{{ _("Add Task") }}</button> {% endcomment %} {% comment %} <button class="btn btn-phoenix-primary btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#taskModal"><span class="fas fa-plus me-1"></span>{{ _("Add Task") }}</button> {% endcomment %}
<button class="btn btn-phoenix-primary btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#scheduleModal"><span class="fas fa-plus me-1"></span>{{ _("Add Task") }}</button> <button class="btn btn-phoenix-primary btn-sm"
type="button"
data-bs-toggle="modal"
data-bs-target="#scheduleModal">
<span class="fas fa-plus me-1"></span>{{ _("Add Task") }}
</button>
{% endif %} {% endif %}
</div> </div>
<div> <div>
<div class="border-top border-bottom border-translucent"
<div class="border-top border-bottom border-translucent" id="allEmailsTable" data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'> id="allEmailsTable"
data-list='{"valueNames":["subject","sent","date","source","status"],"page":7,"pagination":true}'>
<div class="table-responsive scrollbar mx-n1 px-1"> <div class="table-responsive scrollbar mx-n1 px-1">
<table class="table fs-9 mb-0"> <table class="table fs-9 mb-0">
<thead> <thead>
<tr> <tr>
<th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;"> <th class="white-space-nowrap fs-9 align-middle ps-0" style="width:26px;">
<div class="form-check mb-0 fs-8"> <div class="form-check mb-0 fs-8">
<input class="form-check-input" type="checkbox" data-bulk-select='{"body":"all-email-table-body"}' /> <input class="form-check-input"
type="checkbox"
data-bulk-select='{"body":"all-email-table-body"}' />
</div> </div>
</th> </th>
<th class="sort white-space-nowrap align-middle pe-3 ps-0" scope="col" data-sort="subject" style="width:31%; min-width:100px">Name</th> <th class="sort white-space-nowrap align-middle pe-3 ps-0"
<th class="sort align-middle pe-3 text" scope="col" data-sort="sent" style="width:15%; min-width:400px">Note</th> scope="col"
<th class="sort align-middle text-start" scope="col" data-sort="date" style="min-width:100px">Due Date</th> data-sort="subject"
<th class="sort align-middle text-start" scope="col" data-sort="date" style="min-width:100px">Completed</th> style="width:31%;
min-width:100px">Name</th>
<th class="sort align-middle pe-3 text"
scope="col"
data-sort="sent"
style="width:15%;
min-width:400px">Note</th>
<th class="sort align-middle text-start"
scope="col"
data-sort="date"
style="min-width:100px">Due Date</th>
<th class="sort align-middle text-start"
scope="col"
data-sort="date"
style="min-width:100px">Completed</th>
</tr> </tr>
</thead> </thead>
<tbody class="list" id="all-tasks-table-body"> <tbody class="list" id="all-tasks-table-body">
@ -524,19 +769,25 @@
</div> </div>
<div class="row align-items-center justify-content-between py-2 pe-0 fs-9"> <div class="row align-items-center justify-content-between py-2 pe-0 fs-9">
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<p class="mb-0 d-none d-sm-block me-3 fw-semibold text-body" data-list-info="data-list-info"></p> <p class="mb-0 d-none d-sm-block me-3 fw-semibold text-body"
<a class="nav-link px-3 d-block" href="{% url 'appointment:get_user_appointments' %}"> <span class="me-2 text-body align-bottom" data-feather="calendar"></span>{{ _("View in Calendar") }} data-list-info="data-list-info"></p>
<a class="nav-link px-3 d-block"
href="{% url 'appointment:get_user_appointments' %}"> <span class="me-2 text-body align-bottom" data-feather="calendar"></span>{{ _("View in Calendar") }}
<span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a> <span class="fas fa-angle-right ms-1" data-fa-transform="down-1"></span></a>
</div> </div>
<div class="col-auto d-flex"> <div class="col-auto d-flex">
<button class="page-link" data-list-pagination="prev"><span class="fas fa-chevron-left"></span></button> <button class="page-link" data-list-pagination="prev">
<ul class="mb-0 pagination"></ul> <span class="fas fa-chevron-left"></span>
<button class="page-link pe-0" data-list-pagination="next"><span class="fas fa-chevron-right"></span></button> </button>
<ul class="mb-0 pagination">
</ul>
<button class="page-link pe-0" data-list-pagination="next">
<span class="fas fa-chevron-right"></span>
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% include 'modal/delete_modal.html' %} {% include 'modal/delete_modal.html' %}
<!-- add update Modal --> <!-- add update Modal -->
@ -555,7 +806,6 @@
</div> </div>
</div> </div>
</div> {% endcomment %} </div> {% endcomment %}
<!-- task Modal --> <!-- task Modal -->
{% include "components/task_modal.html" with content_type="lead" slug=lead.slug %} {% include "components/task_modal.html" with content_type="lead" slug=lead.slug %}
<!-- note Modal --> <!-- note Modal -->
@ -563,7 +813,6 @@
<!-- schedule Modal --> <!-- schedule Modal -->
{% include "components/schedule_modal.html" with content_type="lead" slug=lead.slug %} {% include "components/schedule_modal.html" with content_type="lead" slug=lead.slug %}
{% endblock content %} {% endblock content %}
{% block customJS %} {% block customJS %}
<script> <script>
function reset_form() { function reset_form() {

View File

@ -1,6 +1,5 @@
{% 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' %}
@ -8,7 +7,6 @@
{% trans 'Add New Lead' %} {% trans 'Add New Lead' %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block customcss %} {% block customcss %}
<style> <style>
.htmx-indicator{ .htmx-indicator{
@ -30,7 +28,6 @@
} }
</style> </style>
{% endblock customcss %} {% endblock customcss %}
{% block content %} {% block content %}
<div class="row justify-content-center mt-5 mb-3"> <div class="row justify-content-center mt-5 mb-3">
<div class="col-lg-8 col-md-10"> <div class="col-lg-8 col-md-10">
@ -44,17 +41,13 @@
{% endif %} {% endif %}
<li class="fas fa-bullhorn text-primary ms-2"></li> <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 bg-light-subtle">
<form class="form" method="post"> <form class="form" method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<hr class="my-2"> <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-phoenix-success btn-lg me-md-2" type="submit"> <button class="btn btn-phoenix-success 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") }} {{ _("Save") }}
@ -66,11 +59,9 @@
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const spinner = document.createElement('div'); const spinner = document.createElement('div');

View File

@ -1,27 +1,29 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static humanize %} {% load i18n static humanize %}
{% block title %}{{ _('Leads')|capfirst }}{% endblock title %} {% block title %}
{{ _("Leads") |capfirst }}
{% endblock title %}
{% block content %} {% block content %}
<div class="row g-3 mt-4 mb-4"> <div class="row g-3 mt-4 mb-4">
<h2 class="mb-2">{{ _("Leads")|capfirst }}<li class="fas fa-bullhorn text-primary ms-2"></li></h2> <h2 class="mb-2">
{{ _("Leads") |capfirst }}
<li class="fas fa-bullhorn text-primary ms-2"></li>
</h2>
<!-- Action Tracking Modal --> <!-- Action Tracking Modal -->
{% include "crm/leads/partials/update_action.html" %} {% include "crm/leads/partials/update_action.html" %}
<div class="row g-3 justify-content-between mb-4"> <div class="row g-3 justify-content-between mb-4">
<div class="col-auto"> <div class="col-auto">
<div class="d-md-flex justify-content-between"> <div class="d-md-flex justify-content-between">
{% if perms.inventory.add_lead %} {% if perms.inventory.add_lead %}
<div> <div>
<a href="{% url 'lead_create' request.dealer.slug %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{{ _("Add Lead") }}</a> <a href="{% url 'lead_create' request.dealer.slug %}"
class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{{ _("Add Lead") }}</a>
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<div class="d-flex"> <div class="d-flex">{% include 'partials/search_box.html' %}</div>
{% include 'partials/search_box.html' %}
</div>
</div> </div>
</div> </div>
<div class="row g-3"> <div class="row g-3">
@ -31,76 +33,111 @@
<table class="table align-items-center table-flush table-hover"> <table class="table align-items-center table-flush table-hover">
<thead> <thead>
<tr class="bg-body-highlight"> <tr class="bg-body-highlight">
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 20%;">{{ _("Lead Name")|capfirst }}</th> <th class="align-middle white-space-nowrap text-uppercase"
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 15%;"> scope="col"
style="width: 20%">{{ _("Lead Name") |capfirst }}</th>
<th class="align-middle white-space-nowrap text-uppercase"
scope="col"
style="width: 15%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center px-1 py-1 bg-success-subtle rounded me-2"><i class="text-success-dark fas fa-car"></i></div> <div class="d-flex align-items-center px-1 py-1 bg-success-subtle rounded me-2">
<i class="text-success-dark fas fa-car"></i>
</div>
<span>{{ _("Car") |capfirst }}</span> <span>{{ _("Car") |capfirst }}</span>
</div> </div>
</th> </th>
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 15%;"> <th class="align-middle white-space-nowrap text-uppercase"
scope="col"
style="width: 15%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center px-1 py-1 bg-success-subtle rounded me-2"><span class="text-success-dark" data-feather="mail"></span></div> <div class="d-flex align-items-center px-1 py-1 bg-success-subtle rounded me-2">
<span class="text-success-dark" data-feather="mail"></span>
</div>
<span>{{ _("email") |capfirst }}</span> <span>{{ _("email") |capfirst }}</span>
</div> </div>
</th> </th>
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 15%;"> <th class="align-middle white-space-nowrap text-uppercase"
scope="col"
style="width: 15%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center px-1 py-1 bg-primary-subtle rounded me-2"><span class="text-primary-dark" data-feather="phone"></span></div> <div class="d-flex align-items-center px-1 py-1 bg-primary-subtle rounded me-2">
<span class="text-primary-dark" data-feather="phone"></span>
</div>
<div class="" dir="ltr">{{ _("Phone Number") }}</div> <div class="" dir="ltr">{{ _("Phone Number") }}</div>
</div> </div>
</th> </th>
<th class="align-middle white-space-nowrap text-uppercase"
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 10%;"> scope="col"
style="width: 10%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center bg-warning-subtle rounded me-2"><span class="text-warning-dark" data-feather="zap"></span></div> <div class="d-flex align-items-center bg-warning-subtle rounded me-2">
<span class="text-warning-dark" data-feather="zap"></span>
</div>
<span>{{ _("Next Action") |capfirst }}</span> <span>{{ _("Next Action") |capfirst }}</span>
</div> </div>
</th> </th>
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 15%;"> <th class="align-middle white-space-nowrap text-uppercase"
scope="col"
style="width: 15%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center px-1 py-1 bg-primary-subtle rounded me-2"><span class="far fa-calendar-alt" ></span></div> <div class="d-flex align-items-center px-1 py-1 bg-primary-subtle rounded me-2">
<span class="far fa-calendar-alt"></span>
</div>
<span>{{ _("Scheduled at") }}</span> <span>{{ _("Scheduled at") }}</span>
</div> </div>
</th> </th>
<th class="align-middle white-space-nowrap text-uppercase"
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 10%;"> scope="col"
style="width: 10%">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center bg-success-subtle rounded me-2"><span class="text-success-dark" data-feather="user-check"></span></div> <div class="d-flex align-items-center bg-success-subtle rounded me-2">
<span class="text-success-dark" data-feather="user-check"></span>
</div>
<span>{{ _("Assigned To") |capfirst }}</span> <span>{{ _("Assigned To") |capfirst }}</span>
</div> </div>
</th> </th>
{% comment %} <th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 10%;"> {% comment %} <th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 10%;">
<div class="d-inline-flex flex-center"> <div class="d-inline-flex flex-center">
<div class="d-flex align-items-center bg-warning-subtle rounded me-2"><span class="text-warning-dark" data-feather="grid"></span></div> <div class="d-flex align-items-center bg-warning-subtle rounded me-2"><span class="text-warning-dark" data-feather="grid"></span></div>
<span>{{ _("Opportunity")|capfirst }}</span> <span>{{ _("Opportunity")|capfirst }}</span>
</div> </div>
</th> {% endcomment %} </th> {% endcomment %}
<th class="align-middle white-space-nowrap text-uppercase" scope="col" style="width: 15%;"> <th class="align-middle white-space-nowrap text-uppercase"
{{ _("Action") }} scope="col"
</th> style="width: 15%">{{ _("Action") }}</th>
<th class="text-end white-space-nowrap align-middle" scope="col"></th> <th class="text-end white-space-nowrap align-middle" scope="col"></th>
</tr> </tr>
{% for lead in leads %} {% for lead in leads %}
<!-- Delete Modal --> <!-- Delete Modal -->
<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true"> <div class="modal fade"
id="deleteModal"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabindex="-1"
aria-labelledby="deleteModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-sm"> <div class="modal-dialog modal-sm">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0"> <div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
<h4 class="mb-0 me-2 text-danger">{{ _("Delete")}}<i class="fas fa-exclamation-circle text-danger ms-2"></i></h4> <h4 class="mb-0 me-2 text-danger">
<button class="btn p-0 text-body-quaternary fs-6" data-bs-dismiss="modal" aria-label="Close"><span class="fas fa-times"></span></button> {{ _("Delete") }}<i class="fas fa-exclamation-circle text-danger ms-2"></i>
</h4>
<button class="btn p-0 text-body-quaternary fs-6"
data-bs-dismiss="modal"
aria-label="Close">
<span class="fas fa-times"></span>
</button>
</div> </div>
<div class="modal-body p-4"> <div class="modal-body p-4">
<p>{% trans "Are you sure you want to delete this lead?" %}</p> <p>{% trans "Are you sure you want to delete this lead?" %}</p>
</div> </div>
<div class="modal-footer flex justify-content-center border-top-0"> <div class="modal-footer flex justify-content-center border-top-0">
<a type="button" class="btn btn-sm btn-phoenix-danger w-100" href="{% url 'lead_delete' request.dealer.slug lead.slug %}"> <a type="button"
class="btn btn-sm btn-phoenix-danger w-100"
href="{% url 'lead_delete' request.dealer.slug lead.slug %}">
{% trans "Yes" %} {% trans "Yes" %}
</a> </a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -108,7 +145,9 @@
<tr class="hover-actions-trigger btn-reveal-trigger position-static"> <tr class="hover-actions-trigger btn-reveal-trigger position-static">
<td class="name align-middle white-space-nowrap ps-1"> <td class="name align-middle white-space-nowrap ps-1">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div><a class="fs-8 fw-bold" href="{% url 'lead_detail' request.dealer.slug lead.slug %}">{{lead.full_name|capfirst}}</a> <div>
<a class="fs-8 fw-bold"
href="{% url 'lead_detail' request.dealer.slug lead.slug %}">{{ lead.full_name|capfirst }}</a>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p> <p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p>
{% if lead.status == "new" %} {% if lead.status == "new" %}
@ -128,17 +167,27 @@
</div> </div>
</div> </div>
</td> </td>
<td class="align-middle white-space-nowrap fw-semibold">
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</a></td> <a class="text-body-highlight" href="">{{ lead.id_car_make.get_local_name }} - {{ lead.id_car_model.get_local_name }} {{ lead.year }}</a>
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="">{{ lead.email }}</a></td> </td>
<td class="align-middle white-space-nowrap fw-semibold"><a class="text-body-highlight" href="tel:{{ lead.phone_number }}">{{ lead.phone_number }}</a></td> <td class="align-middle white-space-nowrap fw-semibold">
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.next_action|upper }}</td> <a class="text-body-highlight" href="">{{ lead.email }}</a>
</td>
<td class="align-middle white-space-nowrap fw-semibold">
<a class="text-body-highlight" href="tel:{{ lead.phone_number }}">{{ lead.phone_number }}</a>
</td>
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">
{{ lead.next_action|upper }}
</td>
<td class="align-middle white-space-nowrap fw-semibold">{{ lead.next_action_date|upper }}</td> <td class="align-middle white-space-nowrap fw-semibold">{{ lead.next_action_date|upper }}</td>
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight"> <td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="avatar avatar-tiny me-2"> <div class="avatar avatar-tiny me-2">
{% if lead.staff.logo %} {% if lead.staff.logo %}
<img class="avatar-img rounded-circle" src="{{ lead.staff.thumbnail.url }}" onerror="this.src='/static/img/brand/brand-logo.png'" alt="Logo"> <img class="avatar-img rounded-circle"
src="{{ lead.staff.thumbnail.url }}"
onerror="this.src='/static/img/brand/brand-logo.png'"
alt="Logo">
{% endif %} {% endif %}
</div> </div>
<small> <small>
@ -175,8 +224,7 @@
<td class="align-middle white-space-nowrap text-end"> <td class="align-middle white-space-nowrap text-end">
{% if user == lead.staff.user or request.is_dealer %} {% if user == lead.staff.user or request.is_dealer %}
<div class="btn-reveal-trigger position-static"> <div class="btn-reveal-trigger position-static">
<button <button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
data-boundary="window" data-boundary="window"
@ -187,22 +235,28 @@
</button> </button>
<div class="dropdown-menu dropdown-menu-end py-2"> <div class="dropdown-menu dropdown-menu-end py-2">
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
<a href="{% url 'lead_update' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Edit" %}</a> <a href="{% url 'lead_update' request.dealer.slug lead.slug %}"
class="dropdown-item text-success-dark">{% trans "Edit" %}</a>
{% endif %} {% endif %}
{% if perms.inventory.change_lead %} {% if perms.inventory.change_lead %}
<button class="dropdown-item text-primary" onclick="openActionModal('{{ lead.pk }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')"> <button class="dropdown-item text-primary"
onclick="openActionModal('{{ lead.pk }}', '{{ lead.action }}', '{{ lead.next_action }}', '{{ lead.next_action_date|date:"Y-m-d\TH:i" }}')">
{% trans "Update Actions" %} {% trans "Update Actions" %}
</button> </button>
{% endif %} {% endif %}
{% if not lead.opportunity %} {% if not lead.opportunity %}
{% if perms.inventory.add_opportunity %} {% if perms.inventory.add_opportunity %}
<a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}" class="dropdown-item text-success-dark">{% trans "Convert to Opportunity" %}</a> <a href="{% url 'lead_opportunity_create' request.dealer.slug lead.slug %}"
class="dropdown-item text-success-dark">{% trans "Convert to Opportunity" %}</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if perms.inventory.delete_lead %} {% if perms.inventory.delete_lead %}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button> <button class="dropdown-item text-danger"
data-bs-toggle="modal"
data-bs-target="#deleteModal">
{% trans "Delete" %}
</button>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -211,17 +265,11 @@
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</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="d-flex justify-content-end mt-3">
<div class="d-flex">{% include 'partials/pagination.html' %}</div>
<div class="d-flex">
{% include 'partials/pagination.html'%}
</div>
</div> </div>
{% endif %} {% endif %}
{% else %} {% else %}
@ -233,7 +281,6 @@
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block customJS %} {% block customJS %}
<script> <script>
// Initialize SweetAlert Toast for general messages // Initialize SweetAlert Toast for general messages
@ -359,5 +406,4 @@
}); });
} }
</script> </script>
{% endblock customJS %} {% endblock customJS %}

View File

@ -1,9 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load crispy_forms_filters %} {% load crispy_forms_filters %}
{% load i18n static %} {% load i18n static %}
{% block title %}
{% block title %}{{ _("Leads") }}{% endblock title %} {{ _("Leads") }}
{% endblock title %}
{% block content %} {% block content %}
<div class="card email-content"> <div class="card email-content">
<h5 class="card-header">Send Mail</h5> <h5 class="card-header">Send Mail</h5>

View File

@ -1,7 +1,8 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static %} {% load i18n static %}
{% block title %}{{ _('Leads Tracking')|capfirst }}{% endblock title %} {% block title %}
{{ _("Leads Tracking") |capfirst }}
{% endblock title %}
{% block customCSS %} {% block customCSS %}
<style> <style>
.kanban-column { .kanban-column {
@ -68,74 +69,88 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col"> <div class="col">
<div class="d-flex justify-content-between mb-3"> <div class="d-flex justify-content-between mb-3">
<h3>{{ _("Lead Tracking")}}<li class="fas fa-bullhorn text-primary ms-2"></li></h3> <h3>
{{ _("Lead Tracking") }}
<li class="fas fa-bullhorn text-primary ms-2"></li>
</h3>
</div> </div>
<div class="row g-3"> <div class="row g-3">
<!-- New Lead --> <!-- New Lead -->
<div class="col-md"> <div class="col-md">
<div class="kanban-column bg-body"> <div class="kanban-column bg-body">
<div class="kanban-header opacity-75"><span class="text-body">{{ _("New Leads")}} ({{new|length}})</span></div> <div class="kanban-header opacity-75">
<span class="text-body">{{ _("New Leads") }} ({{ new|length }})</span>
</div>
{% for lead in new %} {% for lead in new %}
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}"> <a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card"> <div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br> <strong>{{ lead.full_name|capfirst }}</strong>
<small>{{lead.email}}</small><br> <br>
<small>{{ lead.email }}</small>
<br>
<small>{{ lead.phone_number }}</small> <small>{{ lead.phone_number }}</small>
</div> </div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<!-- Follow Ups --> <!-- Follow Ups -->
<div class="col-md"> <div class="col-md">
<div class="kanban-column bg-body"> <div class="kanban-column bg-body">
<div class="kanban-header opacity-75"><span class="text-body">{{ _("Follow Ups")}} ({{follow_up|length}})</span></div> <div class="kanban-header opacity-75">
<span class="text-body">{{ _("Follow Ups") }} ({{ follow_up|length }})</span>
</div>
{% for lead in follow_up %} {% for lead in follow_up %}
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}"> <a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card"> <div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br> <strong>{{ lead.full_name|capfirst }}</strong>
<small>{{lead.email}}</small><br> <br>
<small>{{ lead.email }}</small>
<br>
<small>{{ lead.phone_number }}</small> <small>{{ lead.phone_number }}</small>
</div> </div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<!-- Negotiation --> <!-- Negotiation -->
<div class="col-md"> <div class="col-md">
<div class="kanban-column bg-body"> <div class="kanban-column bg-body">
<div class="kanban-header opacity-75"><span class="text-body">{{ _("Negotiation Ups")}} ({{follow_up|length}})</span></div> <div class="kanban-header opacity-75">
<span class="text-body">{{ _("Negotiation Ups") }} ({{ follow_up|length }})</span>
</div>
{% for lead in negotiation %} {% for lead in negotiation %}
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}"> <a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card"> <div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br> <strong>{{ lead.full_name|capfirst }}</strong>
<small>{{lead.email}}</small><br> <br>
<small>{{ lead.email }}</small>
<br>
<small>{{ lead.phone_number }}</small> <small>{{ lead.phone_number }}</small>
</div> </div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<!-- Won --> <!-- Won -->
<div class="col-md"> <div class="col-md">
<div class="kanban-column bg-body"> <div class="kanban-column bg-body">
<div class="kanban-header bg-success-light opacity-75"><span class="text-body">{{ _("Won") }} ({{won|length}}) ({{follow_up|length}})</span></div> <div class="kanban-header bg-success-light opacity-75">
<span class="text-body">{{ _("Won") }} ({{ won|length }}) ({{ follow_up|length }})</span>
</div>
{% for lead in won %} {% for lead in won %}
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}"> <a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card"> <div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br> <strong>{{ lead.full_name|capfirst }}</strong>
<small>{{lead.email}}</small><br> <br>
<small>{{ lead.email }}</small>
<br>
<small>{{ lead.phone_number }}</small> <small>{{ lead.phone_number }}</small>
</div> </div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<!-- Lose --> <!-- Lose -->
<div class="col-md"> <div class="col-md">
<div class="kanban-column bg-body"> <div class="kanban-column bg-body">
@ -143,8 +158,10 @@
{% for lead in lose %} {% for lead in lose %}
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}"> <a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card"> <div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br> <strong>{{ lead.full_name|capfirst }}</strong>
<small>{{lead.email}}</small><br> <br>
<small>{{ lead.email }}</small>
<br>
<small>{{ lead.phone_number }}</small> <small>{{ lead.phone_number }}</small>
</div> </div>
</a> </a>

View File

@ -1,6 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static i18n humanize %} {% load static i18n humanize %}
{% block customCSS %} {% block customCSS %}
<style> <style>
.card { .card {
@ -21,17 +20,16 @@
} }
</style> </style>
{% endblock customCSS %} {% endblock customCSS %}
{% block content %} {% block content %}
<div class="container-fluid"> <div class="container-fluid">
<!-- Welcome Row --> <!-- Welcome Row -->
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0">مرحبًا ismail mosa</h5> <h5 class="mb-0">مرحبًا</h5>
<div> <div>
<button class="btn btn-phoenix-secondary dropdown-toggle" data-bs-toggle="dropdown">الصفحة الرئيسية لـ ismail mosa</button> <button class="btn btn-phoenix-secondary dropdown-toggle"
data-bs-toggle="dropdown">الصفحة الرئيسية لـ </button>
</div> </div>
</div> </div>
<!-- Main Row --> <!-- Main Row -->
<div class="row"> <div class="row">
<!-- Tasks --> <!-- Tasks -->
@ -52,7 +50,9 @@
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><a href="#">Register for upcoming CRM Webinars</a></td> <td>
<a href="#">Register for upcoming CRM Webinars</a>
</td>
<td>16/02/2025</td> <td>16/02/2025</td>
<td>Not Started</td> <td>Not Started</td>
<td>Low</td> <td>Low</td>
@ -60,7 +60,9 @@
<td>Kris Marrier (Sample)</td> <td>Kris Marrier (Sample)</td>
</tr> </tr>
<tr> <tr>
<td><a href="#">Refer CRM Videos</a></td> <td>
<a href="#">Refer CRM Videos</a>
</td>
<td>18/02/2025</td> <td>18/02/2025</td>
<td>In Progress</td> <td>In Progress</td>
<td>Normal</td> <td>Normal</td>
@ -73,13 +75,14 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Meetings --> <!-- Meetings -->
<div class="col-md-6 mb-4"> <div class="col-md-6 mb-4">
<div class="card h-100"> <div class="card h-100">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center">
<span>الاجتماعات الخاصة بي</span> <span>الاجتماعات الخاصة بي</span>
<span class="spinner-border spinner-border-sm text-muted" role="status" aria-hidden="true"></span> <span class="spinner-border spinner-border-sm text-muted"
role="status"
aria-hidden="true"></span>
</div> </div>
<div class="card-body p-0"> <div class="card-body p-0">
<table class="table table-hover align-middle mb-0"> <table class="table table-hover align-middle mb-0">
@ -114,7 +117,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Bottom Row --> <!-- Bottom Row -->
<div class="row"> <div class="row">
<!-- Today's Leads --> <!-- Today's Leads -->
@ -122,18 +124,21 @@
<div class="card h-100"> <div class="card h-100">
<div class="card-header">العملاء المحتملون لليوم</div> <div class="card-header">العملاء المحتملون لليوم</div>
<div class="card-body empty-state"> <div class="card-body empty-state">
<img src="https://cdn-icons-png.flaticon.com/512/1828/1828945.png" width="64" alt="No Data"> <img src="https://cdn-icons-png.flaticon.com/512/1828/1828945.png"
width="64"
alt="No Data">
<p class="mt-3">لم يتم العثور على أي العملاء المحتملون.</p> <p class="mt-3">لم يتم العثور على أي العملاء المحتملون.</p>
</div> </div>
</div> </div>
</div> </div>
<!-- Deals Closed This Month --> <!-- Deals Closed This Month -->
<div class="col-md-6 mb-4"> <div class="col-md-6 mb-4">
<div class="card h-100"> <div class="card h-100">
<div class="card-header">تم إقفال صفقات هذا الشهر</div> <div class="card-header">تم إقفال صفقات هذا الشهر</div>
<div class="card-body empty-state"> <div class="card-body empty-state">
<img src="https://cdn-icons-png.flaticon.com/512/1828/1828945.png" width="64" alt="No Data"> <img src="https://cdn-icons-png.flaticon.com/512/1828/1828945.png"
width="64"
alt="No Data">
<p class="mt-3">لم يتم العثور على أي صفقات.</p> <p class="mt-3">لم يتم العثور على أي صفقات.</p>
</div> </div>
</div> </div>

View File

@ -1,15 +1,21 @@
<div class="modal fade" id="actionTrackingModal" tabindex="-1" aria-labelledby="actionTrackingModalLabel" aria-hidden="true"> <div class="modal fade"
id="actionTrackingModal"
tabindex="-1"
aria-labelledby="actionTrackingModalLabel"
aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title" id="actionTrackingModalLabel">{{ _("Update Lead Actions") }}</h5> <h5 class="modal-title" id="actionTrackingModalLabel">{{ _("Update Lead Actions") }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"></button>
</div> </div>
<form id="actionTrackingForm" method="post"> <form id="actionTrackingForm" method="post">
<div class="modal-body"> <div class="modal-body">
{% csrf_token %} {% csrf_token %}
<input type="hidden" id="leadId" name="lead_id"> <input type="hidden" id="leadId" name="lead_id">
<div class="mb-3"> <div class="mb-3">
<label for="currentAction" class="form-label">{{ _("Current Stage") }}</label> <label for="currentAction" class="form-label">{{ _("Current Stage") }}</label>
<select class="form-select" id="currentAction" name="current_action" required> <select class="form-select" id="currentAction" name="current_action" required>
@ -21,7 +27,6 @@
<option value="converted">{{ _("Converted") }}</option> <option value="converted">{{ _("Converted") }}</option>
</select> </select>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="nextAction" class="form-label">{{ _("Next Action") }}</label> <label for="nextAction" class="form-label">{{ _("Next Action") }}</label>
<select class="form-select" id="nextAction" name="next_action" required> <select class="form-select" id="nextAction" name="next_action" required>
@ -32,19 +37,22 @@
<option value="email">{{ _("Email") }}</option> <option value="email">{{ _("Email") }}</option>
</select> </select>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="nextActionDate" class="form-label">{{ _("Next Action Date") }}</label> <label for="nextActionDate" class="form-label">{{ _("Next Action Date") }}</label>
<input type="datetime-local" class="form-control" id="nextActionDate" name="next_action_date"> <input type="datetime-local"
class="form-control"
id="nextActionDate"
name="next_action_date">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="actionNotes" class="form-label">{{ _("Notes") }}</label> <label for="actionNotes" class="form-label">{{ _("Notes") }}</label>
<textarea class="form-control" id="actionNotes" name="action_notes" rows="3"></textarea> <textarea class="form-control" id="actionNotes" name="action_notes" rows="3"></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-phoenix-secondary" data-bs-dismiss="modal">{{ _("Close") }}</button> <button type="button"
class="btn btn-phoenix-secondary"
data-bs-dismiss="modal">{{ _("Close") }}</button>
<button type="submit" class="btn btn-phoenix-primary">{{ _("Save Changes") }}</button> <button type="submit" class="btn btn-phoenix-primary">{{ _("Save Changes") }}</button>
</div> </div>
</form> </form>

View File

@ -1,21 +1,21 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n static crispy_forms_filters %} {% load i18n static crispy_forms_filters %}
{% block content %} {% block content %}
<h3>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h3> <h3>
{% if object %}
{{ _("Update") }}
{% else %}
{{ _("Create") }}
{% endif %}
</h3>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button <button type="submit"
type="submit"
name="schedule_lead" name="schedule_lead"
id="lead-save" id="lead-save"
class="btn btn-phoenix-primary" class="btn btn-phoenix-primary">{{ _("Save") }}</button>
> <a href="{% url 'lead_list' request.dealer.slug %}"
{{ _("Save") }} class="btn btn-phoenix-secondary">{{ _("Cancel") }}</a>
</button>
<a href="{% url 'lead_list' request.dealer.slug %}" class="btn btn-phoenix-secondary">
{{ _("Cancel") }}
</a>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -1,14 +1,15 @@
{% load i18n static crispy_forms_filters %} {% load i18n static crispy_forms_filters %}
{% if form.instance.pk %} {% if form.instance.pk %}
<form method="post" action="{% url 'update_note_to_lead' note.pk %}" enctype="multipart/form-data"> <form method="post"
action="{% url 'update_note_to_lead' note.pk %}"
enctype="multipart/form-data">
{% else %} {% else %}
<form method="post" action="{% url 'add_note_to_lead' lead.slug %}" enctype="multipart/form-data"> <form method="post"
action="{% url 'add_note_to_lead' lead.slug %}"
enctype="multipart/form-data">
{% endif %} {% endif %}
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
{% if form.instance.pk %} {% if form.instance.pk %}
<button type="submit" class="btn btn-sm btn-phoenix-primary w-100">{{ _("Update") }}</button> <button type="submit" class="btn btn-sm btn-phoenix-primary w-100">{{ _("Update") }}</button>
{% else %} {% else %}

View File

@ -1,6 +1,7 @@
{% load i18n static %} {% load i18n static %}
<div class="dropdown-menu dropdown-menu-end notification-dropdown-menu py-0 shadow border navbar-dropdown-caret"
<div class="dropdown-menu dropdown-menu-end notification-dropdown-menu py-0 shadow border navbar-dropdown-caret" id="navbarDropdownNotfication" aria-labelledby="navbarDropdownNotfication"> id="navbarDropdownNotfication"
aria-labelledby="navbarDropdownNotfication">
<div class="card position-relative border-0"> <div class="card position-relative border-0">
<div class="card-header p-2"> <div class="card-header p-2">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
@ -15,20 +16,31 @@
<div class="flex-1 me-sm-3"> <div class="flex-1 me-sm-3">
<h4 class="fs-9 text-body-emphasis">{{ _("System") }}</h4> <h4 class="fs-9 text-body-emphasis">{{ _("System") }}</h4>
<ul id="notification-list"> <ul id="notification-list">
</ul> </ul>
</div> </div>
</div> </div>
<div class="dropdown notification-dropdown"> <div class="dropdown notification-dropdown">
<button class="btn fs-10 btn-sm dropdown-toggle dropdown-caret-none transition-none" 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 text-body"></span></button> <button class="btn fs-10 btn-sm dropdown-toggle dropdown-caret-none transition-none"
<div class="dropdown-menu py-2"><a class="dropdown-item">Mark as Read</a></div> 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 text-body"></span>
</button>
<div class="dropdown-menu py-2">
<a class="dropdown-item">Mark as Read</a>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="card-footer p-0 border-top border-translucent border-0"> <div class="card-footer p-0 border-top border-translucent border-0">
<div class="my-2 text-center fw-bold fs-10 text-body-tertiary text-opactity-85"><a class="fw-bolder" href="{% url 'notifications_history' %}">Notification history</a></div> <div class="my-2 text-center fw-bold fs-10 text-body-tertiary text-opactity-85">
<a class="fw-bolder" href="{% url 'notifications_history' %}">Notification history</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,5 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<div class="content"> <div class="content">
<h2 class="mb-5">{{ _("Notifications") }}</h2> <h2 class="mb-5">{{ _("Notifications") }}</h2>
<div class="d-flex justify-content-end mb-3"> <div class="d-flex justify-content-end mb-3">
@ -15,14 +13,19 @@
<div class="me-3 flex-1 mt-2"> <div class="me-3 flex-1 mt-2">
<h4 class="fs-9 text-body-emphasis">{{ _("System") }}:</h4> <h4 class="fs-9 text-body-emphasis">{{ _("System") }}:</h4>
{% if notification.is_read %} {% if notification.is_read %}
<p class="fs-9 text-body-highlight"><span class="far fa-envelope text-success-dark fs-8 me-1"></span><span class="me-1">{{ notification.message|safe }}</span> <span class="ms-2 text-body-tertiary text-opacity-85 fw-bold fs-10 text-end">{{ notification.created|timesince }}</span></p> <p class="fs-9 text-body-highlight">
<span class="far fa-envelope text-success-dark fs-8 me-1"></span><span class="me-1">{{ notification.message|safe }}</span> <span class="ms-2 text-body-tertiary text-opacity-85 fw-bold fs-10 text-end">{{ notification.created|timesince }}</span>
</p>
{% else %} {% else %}
<p class="fs-9 text-body-highlight"><span class="far fa-envelope-open text-danger-dark fs-8 me-1"></span><span>{{ notification.message|safe }}</span> <span class="ms-2 text-body-tertiary text-opacity-85 fw-bold fs-10 text-end">{{ notification.created|timesince }}</span></p> <p class="fs-9 text-body-highlight">
<span class="far fa-envelope-open text-danger-dark fs-8 me-1"></span><span>{{ notification.message|safe }}</span> <span class="ms-2 text-body-tertiary text-opacity-85 fw-bold fs-10 text-end">{{ notification.created|timesince }}</span>
</p>
{% endif %} {% endif %}
<p class="text-body-secondary fs-9 mb-0"><span class="me-1 far fa-clock"></span>{{ notification.created }}</p> <p class="text-body-secondary fs-9 mb-0">
<span class="me-1 far fa-clock"></span>{{ notification.created }}
</p>
</div> </div>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -33,11 +36,7 @@
<a href="?page=1">&laquo; first</a> <a href="?page=1">&laquo; first</a>
<a href="?page={{ notifications.previous_page_number }}">previous</a> <a href="?page={{ notifications.previous_page_number }}">previous</a>
{% endif %} {% endif %}
<span class="current">Page {{ notifications.number }} of {{ notifications.paginator.num_pages }}.</span>
<span class="current">
Page {{ notifications.number }} of {{ notifications.paginator.num_pages }}.
</span>
{% if notifications.has_next %} {% if notifications.has_next %}
<a href="?page={{ notifications.next_page_number }}">next</a> <a href="?page={{ notifications.next_page_number }}">next</a>
<a href="?page={{ notifications.paginator.num_pages }}">last &raquo;</a> <a href="?page={{ notifications.paginator.num_pages }}">last &raquo;</a>
@ -47,6 +46,4 @@
{% else %} {% else %}
<p>No notifications found.</p> <p>No notifications found.</p>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

Some files were not shown because too many files have changed in this diff Show More