Merge branch 'main' of http://10.10.1.136:3000/ismail/haikal into frontend

This commit is contained in:
KhanFaheed 2025-05-21 19:34:13 +03:00
commit 6b56156921
67 changed files with 1321 additions and 768 deletions

View File

@ -1,5 +1,3 @@
import hashlib
import json
import requests

View File

@ -1,3 +1,2 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,17 +1,15 @@
from django.core.paginator import Paginator
from django.http import JsonResponse
from rest_framework import permissions, status, viewsets, generics
from rest_framework import permissions, status, viewsets
from inventory.utils import get_user_type
from . import models, serializers
from .services import get_car_data
from inventory import models as inventory_models
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.utils.translation import gettext as _
from inventory import models as inventory_models
from inventory.services import get_make, get_model, decodevin
from inventory.services import decodevin
import logging
logger = logging.getLogger(__name__)

View File

@ -1,3 +1,2 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,3 +1,2 @@
from django.test import TestCase
# Create your tests here.

View File

@ -7,7 +7,6 @@ from django_ledger import models as ledger_models
from import_export.admin import ExportMixin
from import_export.resources import ModelResource
from .models import Car
# # Define resource class
# class CarSerieResource(ModelResource):

View File

@ -5,7 +5,7 @@ class InventoryConfig(AppConfig):
name = 'inventory'
def ready(self):
import inventory.signals
pass
#from decimal import Decimal
#from inventory.models import VatRate
#VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)

View File

@ -1,11 +1,8 @@
import re
from django.core.cache import cache
from datetime import datetime
from luhnchecker.luhn import Luhn
from django.core.validators import RegexValidator
from django.contrib.auth.models import Permission
from appointment.models import Service
from phonenumber_field.formfields import PhoneNumberField
from django.core.validators import MinLengthValidator
from django import forms
from plans.models import PlanPricing
@ -17,9 +14,6 @@ from .mixins import AddClassMixin
from django_ledger.forms.invoice import (
InvoiceModelCreateForm as InvoiceModelCreateFormBase,
)
from django_ledger.forms.estimate import (
EstimateModelCreateForm as EstimateModelCreateFormBase,
)
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase
@ -1062,6 +1056,7 @@ class LeadForm(forms.ModelForm):
"crn",
"vrn",
"year",
"salary",
"source",
"channel",
"staff",

View File

@ -1,7 +1,4 @@
import re
from itertools import cycle
from datetime import datetime
from typing import List
def vin_year(vin_char: str) -> int:
@ -1830,7 +1827,7 @@ def decode_vin_haikalna(vin):
pattern = r"^[A-HJ-NPR-Z0-9]{17}$"
if not re.match(pattern, vin):
raise Exception(f"VIN number must only contain alphanumeric symbols except 'I', 'O', and 'Q' ")
raise Exception("VIN number must only contain alphanumeric symbols except 'I', 'O', and 'Q' ")
vin = vin.upper()

View File

@ -1,11 +1,9 @@
import os
import json
import pymysql
import pandas as pd
from django.core.management.base import BaseCommand
from sqlalchemy import create_engine
from tqdm import tqdm # Progress bar support
from django.conf import settings
# Database connection details
db_config = {

View File

@ -11,19 +11,19 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs):
vin,description = self.generate_vin()
result = decodevin(vin)
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
self.stdout.write(self.style.SUCCESS(f'Generated VIN: {vin}'))
self.stdout.write(self.style.SUCCESS(f'Description: {description}'))
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
self.stdout.write(self.style.SUCCESS(f'Decoded VIN: {result}'))
make,model,year_model = result.values()
self.stdout.write(self.style.SUCCESS(f'VIN: {vin} - Make {make} - Model {model} - Model Year {year_model}'))
m = get_model(model)
self.stdout.write(self.style.SUCCESS(f'Make: {m.id_car_make} - Model: {m}'))
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))
self.stdout.write(self.style.SUCCESS('####################################################################################################'))

View File

@ -1,6 +1,6 @@
# management/commands/create_plans.py
from django.core.management.base import BaseCommand
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing
from plans.models import Plan, Quota, Pricing, PlanPricing
from decimal import Decimal
from django.db.models import Q

View File

@ -1,12 +1,7 @@
# management/commands/create_plans.py
from decimal import Decimal
from datetime import timedelta
from django.db.models import Q
from django.utils import timezone
from plans.quota import get_user_quota
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing,UserPlan,Order,BillingInfo,AbstractOrder
from plans.models import Plan, Quota, PlanQuota, Pricing, PlanPricing
class Command(BaseCommand):
help = 'Create basic subscription plans structure'

View File

@ -1,9 +1,5 @@
from django.core.management.base import BaseCommand
from django.core.mail import send_mail
from allauth.account.models import EmailConfirmation
from inventory.tasks import send_email
from django.contrib.auth import get_user_model
import re
from inventory.tasks import create_coa_accounts
from inventory.models import Dealer

View File

@ -1,12 +1,6 @@
import logging
from django.conf import settings
from inventory import models
from django.utils import timezone
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
from fpdf import FPDF
import os
from inventory.utils import get_user_type
@ -67,7 +61,7 @@ class InjectParamsMiddleware:
try:
# request.entity = request.user.dealer.entity
request.dealer = get_user_type(request)
except Exception as e:
except Exception:
pass
response = self.get_response(request)
return response
@ -98,7 +92,7 @@ class InjectDealerMiddleware:
request.is_dealer = True
if hasattr(request.user, "staffmember"):
request.is_staff = True
except Exception as e:
except Exception:
pass
response = self.get_response(request)
return response

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-05-21 10:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0005_notes_dealer'),
]
operations = [
migrations.AddField(
model_name='organization',
name='slug',
field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.7 on 2025-05-21 13:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_organization_slug'),
]
operations = [
migrations.AddField(
model_name='staff',
name='active',
field=models.BooleanField(default=True, verbose_name='Active'),
),
migrations.AddField(
model_name='staff',
name='slug',
field=models.SlugField(blank=True, editable=False, max_length=255, null=True, unique=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-05-21 15:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0007_staff_active_staff_slug'),
]
operations = [
migrations.AddField(
model_name='lead',
name='salary',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Salary'),
),
]

View File

@ -1,6 +1,4 @@
from django import forms
from django.utils.translation import get_language
from django.urls import reverse, reverse_lazy
class AddClassMixin:
"""

View File

@ -3,7 +3,7 @@ from django.contrib.auth.models import Permission
from decimal import Decimal
from django.utils.text import slugify
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.validators import MinValueValidator
import hashlib
from django.db import models
from datetime import timedelta
@ -23,12 +23,12 @@ from django.contrib.auth.models import Group
from inventory.utils import get_user_type, to_dict
from .mixins import LocalizedNameMixin
from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel,AccountModel,EntityManagementModel
from django_ledger.models import EstimateModel,InvoiceModel,AccountModel,EntityManagementModel
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from appointment.models import StaffMember
from plans.quota import get_user_quota
from plans.models import UserPlan,Quota,PlanQuota
from plans.models import UserPlan
# from plans.models import AbstractPlan
# from simple_history.models import HistoricalRecords
@ -548,7 +548,7 @@ class Car(Base):
def ready(self):
try:
return all([self.colors ,self.finances,])
except Exception as e:
except Exception:
return False
def get_transfer(self):
return self.transfer_logs.filter(active=True).first()
@ -1000,11 +1000,37 @@ class Staff(models.Model, LocalizedNameMixin):
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number"))
staff_type = models.CharField(choices=StaffTypes.choices, max_length=255, verbose_name=_("Staff Type"))
active = models.BooleanField(default=True, verbose_name=_("Active"))
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
slug = models.SlugField(max_length=255, unique=True, editable=False, null=True, blank=True)
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(f"{self.name}")
self.slug = base_slug
counter = 1
while self.__class__.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
self.slug = f"{base_slug}-{counter}"
counter += 1
super().save(*args, **kwargs)
objects = StaffUserManager()
def deactivate_account(self):
self.active = False
self.user.is_active = False
self.user.save()
self.save()
def activate_account(self):
self.active = True
self.user.is_active = True
self.user.save()
self.save()
def permenant_delete(self):
# self.user.delete()
self.staff_member.delete()
self.delete()
@property
def email(self):
return self.staff_member.user.email
@ -1256,7 +1282,17 @@ class Customer(models.Model):
self.customer_model.save()
self.user.save()
self.save()
def activate_account(self):
self.active = True
self.customer_model.active = True
self.user.is_active = True
self.customer_model.save()
self.user.save()
self.save()
def permenant_delete(self):
self.customer_model.delete()
self.user.delete()
self.delete()
class Organization(models.Model, LocalizedNameMixin):
dealer = models.ForeignKey(
Dealer, on_delete=models.CASCADE, related_name="organizations"
@ -1282,6 +1318,18 @@ class Organization(models.Model, LocalizedNameMixin):
active = models.BooleanField(default=True, verbose_name=_("Active"))
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
slug = models.SlugField(max_length=255, unique=True, editable=False, null=True, blank=True)
def save(self, *args, **kwargs):
if not self.slug:
base_slug = slugify(f"{self.name}")
self.slug = base_slug
counter = 1
while self.__class__.objects.filter(slug=self.slug).exclude(pk=self.pk).exists():
self.slug = f"{base_slug}-{counter}"
counter += 1
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Organization")
@ -1348,6 +1396,17 @@ class Organization(models.Model, LocalizedNameMixin):
self.user.save()
self.customer_model.save()
self.save()
def activate_account(self):
self.active = True
self.customer_model.active = True
self.user.is_active = True
self.customer_model.save()
self.user.save()
self.save()
def permenant_delete(self):
self.user.delete()
self.customer_model.delete()
self.delete()
class Representative(models.Model, LocalizedNameMixin):
dealer = models.ForeignKey(
@ -1447,7 +1506,6 @@ class Lead(models.Model):
blank=True,
null=True
)
next_action_date = models.DateTimeField(
verbose_name=_("Next Action Date"),
blank=True,
@ -1455,6 +1513,7 @@ class Lead(models.Model):
)
is_converted = models.BooleanField(default=False)
converted_at = models.DateTimeField(null=True, blank=True)
salary = models.PositiveIntegerField(verbose_name=_("Salary"), blank=True, null=True)
created = models.DateTimeField(
auto_now_add=True, verbose_name=_("Created"), db_index=True
)
@ -1548,7 +1607,6 @@ class Lead(models.Model):
return Activity.objects.filter(dealer=self.dealer,content_type__model="lead", object_id=self.pk).order_by('-updated').first()
def save(self, *args, **kwargs):
self.status = self.get_status()
if not self.slug:
base_slug = slugify(f"{self.last_name} {self.first_name}")
self.slug = base_slug
@ -1882,7 +1940,13 @@ class Vendor(models.Model, LocalizedNameMixin):
balance_type="credit",
active=True
)
def activate_account(self):
self.active = True
self.vendor_model.active = True
self.save()
def permenant_delete(self):
self.vendor_model.delete()
self.delete()
class Payment(models.Model):
METHOD_CHOICES = [
("cash", _("cash")),
@ -2034,7 +2098,7 @@ class CustomGroup(models.Model):
try:
for perm in Permission.objects.filter(content_type__app_label="inventory"):
self.add_permission(perm)
except Exception as e:
except Exception:
pass
def set_default_permissions(self):

View File

@ -5,14 +5,10 @@ Services module
import requests
import json
from django_ledger.models import EntityModel
from inventory.utils import get_jwt_token, get_user_type
from pyvin import VIN
from django.conf import settings
from openai import OpenAI
from .models import Car,CarMake,CarModel
from inventory.haikalna import decode_vin_haikalna
from .models import CarMake
def get_make(item):

View File

@ -1,33 +1,20 @@
from inventory.tasks import create_coa_accounts,create_accounts_for_make,create_settings
from inventory.tasks import create_coa_accounts
from django.contrib.auth.models import Group
from decimal import Decimal
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save
from inventory.models import VatRate
from plans.quota import get_user_quota
from .utils import to_dict
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import get_user_model
from django_ledger.io import roles
from django_ledger.models import (
EntityModel,
AccountModel,
ItemModel,
ItemModelAbstract,
UnitOfMeasureModel,
VendorModel,
EstimateModel,
CustomerModel,
JournalEntryModel,
TransactionModel,
LedgerModel,
BillModel,
ItemTransactionModel
LedgerModel
)
from . import models
from django.utils.timezone import now
from django.db import transaction
from django.core.exceptions import ValidationError
User = get_user_model()

View File

@ -2,7 +2,7 @@ from django.conf import settings
from django.utils.timesince import timesince
import django_tables2 as tables
from django.utils.translation import gettext_lazy as _
from .models import Car, CarFinance, ExteriorColors, InteriorColors, CarColors
from .models import Car
from .utils import get_local_name
from django.utils.html import format_html

View File

@ -1,11 +1,10 @@
from time import sleep
from datetime import datetime
from django.db import transaction
from django_ledger.io import roles
from django.core.mail import send_mail
from background_task import background
from django.utils.translation import gettext_lazy as _
from inventory.models import DealerSettings,CarMake,Dealer
from inventory.models import DealerSettings,Dealer

View File

@ -5,7 +5,6 @@ from django.urls import reverse
from django.utils.formats import number_format
from django_ledger.io.io_core import get_localdate,validate_activity
from django.conf import settings
from django.utils.translation import get_language
register = template.Library()

View File

@ -7,19 +7,16 @@
# """
from calendar import month_abbr
from random import randint
from django import template
from django.db.models import Sum
from django.urls import reverse
from django.utils.formats import number_format
from decimal import Decimal
# from django_ledger import __version__
# from django_ledger.forms.app_filters import EntityFilterForm, ActivityFilterForm
# from django_ledger.forms.feedback import BugReportForm, RequestNewFeatureForm
# from django_ledger.io import CREDIT, DEBIT, ROLES_ORDER_ALL
from django_ledger.io.io_core import validate_activity, get_localdate
from django_ledger.io.io_core import get_localdate
# from django_ledger.models import TransactionModel, BillModel, InvoiceModel, EntityUnitModel
# from django_ledger.settings import (
# DJANGO_LEDGER_FINANCIAL_ANALYSIS, DJANGO_LEDGER_CURRENCY_SYMBOL,

View File

@ -1,8 +1,6 @@
import json
from . import models as m
from datetime import datetime
from django.urls import reverse
from django_ledger import models as lm
from django.test import Client, TestCase
from django.contrib.auth import get_user_model
from django_ledger.io.io_core import get_localdate

View File

@ -3,7 +3,6 @@ from django.urls import path
from django_tables2.export.export import TableExport
from . import views
from allauth.account import views as allauth_views
urlpatterns = [
@ -395,12 +394,12 @@ path(
# ),
# Users URLs
path("user/create/", views.UserCreateView.as_view(), name="user_create"),
path("user/<int:pk>/update/", views.UserUpdateView.as_view(), name="user_update"),
path("user/<int:pk>/", views.UserDetailView.as_view(), name="user_detail"),
path("user/", views.UserListView.as_view(), name="user_list"),
path("user/<int:pk>/confirm/", views.UserDeleteview, name="user_delete"),
path("user/<int:pk>/groups/", views.UserGroupView, name="user_groups"),
path("user/create/", views.UserCreateView.as_view(), name="user_create"),
path("user/<slug:slug>/", views.UserDetailView.as_view(), name="user_detail"),
path("user/<slug:slug>/groups/", views.UserGroupView, name="user_groups"),
path("user/<slug:slug>/update/", views.UserUpdateView.as_view(), name="user_update"),
path("user/<slug:slug>/confirm/", views.UserDeleteview, name="user_delete"),
# Group URLs
path("group/create/", views.GroupCreateView.as_view(), name="group_create"),
path("group/<int:pk>/update/", views.GroupUpdateView.as_view(), name="group_update"),
@ -409,26 +408,26 @@ path(
path("group/<int:pk>/confirm/", views.GroupDeleteview, name="group_delete"),
path("group/<int:pk>/permission/", views.GroupPermissionView, name="group_permission"),
# Organization URLs
path(
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
),
path(
"organizations/<int:pk>/",
views.OrganizationDetailView.as_view(),
name="organization_detail",
),
path(
"organizations/create/",
views.OrganizationCreateView.as_view(),
name="organization_create",
),
path(
"organizations/<int:pk>/update/",
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
),
path(
"organizations/<slug:slug>/",
views.OrganizationDetailView.as_view(),
name="organization_detail",
),
path(
"organizations/<slug:slug>/update/",
views.OrganizationUpdateView.as_view(),
name="organization_update",
),
path(
"organizations/<int:pk>/delete/",
"organizations/<slug:slug>/delete/",
views.OrganizationDeleteView,
name="organization_delete",
),
@ -802,6 +801,11 @@ path(
path('entity/<slug:entity_slug>/data/pnl/',
views.PnLAPIView.as_view(),
name='entity-json-pnl'),
# Admin Management...
path('management/', views.management_view, name='management'),
path('management/user_management/', views.user_management, name='user_management'),
path('management/<str:content_type>/<slug:slug>/activate_account/', views.activate_account, name='activate_account'),
path('management/<str:content_type>/<slug:slug>/permenant_delete_account/', views.permenant_delete_account, name='permenant_delete_account'),
]

View File

@ -1,7 +1,6 @@
from decimal import Decimal
from django.conf import settings
from inventory import models
from django_ledger.models.items import ItemModel
def calculate_vat(value):
"""Helper to calculate VAT dynamically for a given value."""

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
import pymysql
from sqlalchemy import create_engine
import pandas as pd

View File

@ -1,6 +1,5 @@
from vininfo.utils import merge_wmi
from vininfo.dicts import WMI
wmi_manufacturer_mapping = {

View File

@ -1,10 +1,5 @@
import json
import requests
from django.urls import reverse
from django.conf import settings
from django.contrib.auth.models import User
from inventory.models import PaymentHistory,Notification
from plans.models import Order, PlanPricing,AbstractOrder
from inventory.models import Notification
def run():
user = User.objects.first()

View File

@ -1,41 +1,13 @@
from django_ledger.forms.account import AccountModelUpdateForm, AccountModelCreateForm
import requests
import os
from dotenv import load_dotenv
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from django_ledger.models.invoice import InvoiceModel
from django_ledger.utils import accruable_net_summary
from decimal import Decimal
from django_ledger.models import (
EstimateModel,
EntityModel,
ItemModel,
ItemTransactionModel,
AccountModel,
CustomerModel,
EntityManagementModel,
)
# from rich import print
from datetime import date
from inventory.models import (
Car,
Dealer,
VatRate,
Lead,
CarMake,
CarModel,
Schedule,
CustomGroup,
)
from inventory.utils import CarFinanceCalculator
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
from django.contrib.auth import get_user_model
from django_ledger.io.io_core import get_localdate
from datetime import datetime, timedelta
from django.utils import timezone
import hashlib
from django_ledger.io import roles
User = get_user_model()

View File

@ -1,23 +1,8 @@
from django_ledger.forms.account import AccountModelUpdateForm,AccountModelCreateForm
import requests
import os
from dotenv import load_dotenv
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from django_ledger.models.invoice import InvoiceModel
from django_ledger.utils import accruable_net_summary
from decimal import Decimal
from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel
from django_ledger.models import EntityModel
# from rich import print
from datetime import date
from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup
from inventory.utils import CarFinanceCalculator
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
from inventory.models import CarMake
from django.contrib.auth import get_user_model
from django_ledger.io.io_core import get_localdate
from datetime import datetime, timedelta
from django.utils import timezone
import hashlib
from django_ledger.io import roles
User = get_user_model()

View File

@ -1,24 +1,9 @@
from django_ledger.forms.account import AccountModelUpdateForm,AccountModelCreateForm
import requests
import os
from dotenv import load_dotenv
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group
from django_ledger.models.invoice import InvoiceModel
from django_ledger.utils import accruable_net_summary
from decimal import Decimal
from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel
from rich import print
from datetime import date
from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup
from inventory.models import Car
from inventory.utils import CarFinanceCalculator
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
from django.contrib.auth import get_user_model
from django_ledger.io.io_core import get_localdate
from datetime import datetime, timedelta
from django.utils import timezone
import hashlib
from django_ledger.io import roles
User = get_user_model()

View File

@ -0,0 +1,17 @@
{% extends 'base.html' %}
{% block content %}
<div class="d-flex justify-content-center align-items-center mt-10">
<div class="text-center">
<h1>Activate Account</h1>
<p>Are you sure you want to activate this account "{{ obj.email }}"?</p>
<form method="post">
{% csrf_token %}
<div class="d-flex justify-content-center">
<button class="btn btn-primary mx-2" type="submit">Activate</button>
<a class="btn btn-secondary mx-2" href="{% url 'user_management' %}">Cancel</a>
</div>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block content %}
<h1><i class="fas fa-tools me-2"></i>Admin Management</h1>
<div class="row row-cols-1 row-cols-md-4 g-4 mt-10">
<div class="col">
<a href="{% url 'user_management' %}">
<div class="card h-100">
<div class="card-header text-center">
<h5 class="card-title">User Management</h5>
<span style="font-size: 2rem; font-weight: 500;" class="me-2"><i class="fas fa-user"></i></span>
</div>
</div>
</a>
</div>
</div>
{% endblock content %}

View File

@ -0,0 +1,18 @@
{% extends 'base.html' %}
{% block content %}
<div class="d-flex justify-content-center align-items-center mt-10">
<div class="text-center">
<h1 class="display-4">Delete Account</h1>
<p class="lead">Are you sure you want to delete this account "{{ obj.email }}"? This will delete all associated information for this user.</p>
<form method="post">
{% csrf_token %}
<div class="d-flex justify-content-center">
<button class="btn btn-danger mx-2" type="submit"><i class="fas fa-trash me-2"></i> Delete Permenantly</button>
<a class="btn btn-secondary mx-2" href="{% url 'user_management' %}"><i class="fas fa-ban me-2"></i>Cancel</a>
</div>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,243 @@
{% extends 'base.html' %}
{% load i18n static humanize %}
{% block title %}
{% trans 'User Management' %}
{% endblock title %}
{% block content %}
<section class="pt-5 pb-9">
<div class="row">
<h2 class="mb-4">{% trans 'User Management' %}</h2>
<div class="row g-3 justify-content-between mb-4">
<div class="col-12">
<h3 class="mb-3">{% trans 'Customers' %}</h3>
<div class="table-responsive scrollbar mx-n1 px-1">
<table class="table table-hover fs-9 mb-0">
<thead>
<tr>
<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" scope="col" 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 border-end border-translucent" 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>
</thead>
<tbody class="list" id="leal-tables-body">
{% for customer in customers %}
<tr>
<td class="ps-0">{{ customer.first_name }}</td>
<td class="ps-0">{{ customer.last_name }}</td>
<td class="ps-0">{{ customer.email }}</td>
<td class="ps-0">
{% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
{% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
{% endif %}
</td>
<td class="ps-0">{{ customer.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static">
<button
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h fs-10"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' 'customer' customer.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
<div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' 'customer' customer.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
</div>
</div>
</td>
</tr>
{% empty %}
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<h3 class="mb-3">{% trans 'Organizations' %}</h3>
<div class="table-responsive scrollbar mx-n1 px-1">
<table class="table table-hover fs-9 mb-0">
<thead>
<tr>
<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" scope="col" 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 border-end border-translucent" 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>
</thead>
<tbody class="list" id="leal-tables-body">
{% for organization in organizations %}
<tr>
<td class="ps-0">{{ organization.name }}</td>
<td class="ps-0">{{ organization.arabic_name }}</td>
<td class="ps-0">{{ organization.email }}</td>
<td class="ps-0">
{% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
{% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
{% endif %}
</td>
<td class="ps-0">{{ organization.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static">
<button
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h fs-10"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' 'organization' organization.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
<div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' 'organization' organization.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
</div>
</div>
</td>
</tr>
{% empty %}
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<h3 class="mb-3">{% trans 'Vendors' %}</h3>
<div class="table-responsive scrollbar mx-n1 px-1">
<table class="table table-hover fs-9 mb-0">
<thead>
<tr>
<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" scope="col" 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>
</thead>
<tbody class="list" id="leal-tables-body">
{% for vendor in vendors %}
<tr>
<td class="ps-0">{{ vendor.name }}</td>
<td class="ps-0">{{ vendor.arabic_name }}</td>
<td class="ps-0">{{ vendor.email }}</td>
<td class="ps-0">
{% if customer.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
{% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
{% endif %}
</td>
<td class="ps-0">{{ vendor.created_at|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static">
<button
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h fs-10"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' 'vendor' vendor.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
<div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' 'vendor' vendor.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
</div>
</div>
</td>
</tr>
{% empty %}
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<h3 class="mb-3">{% trans 'Staff' %}</h3>
<div class="table-responsive scrollbar mx-n1 px-1">
<table class="table table-hover fs-9 mb-0">
<thead>
<tr>
<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" scope="col" 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>
</thead>
<tbody class="list" id="leal-tables-body">
{% for obj in staff %}
<tr>
<td class="ps-0">{{ obj.name }}</td>
<td class="ps-0">{{ obj.arabic_name }}</td>
<td class="ps-0">{{ obj.email }}</td>
<td class="ps-0">
{% if obj.active %}
<span class="fas fa-check-circle text-success"></span> {{ _('Active') }}
{% else %}
<span class="fas fa-times-circle text-danger"></span> {{ _('Inactive') }}
{% endif %}
</td>
<td class="ps-0">{{ obj.created|naturalday|capfirst }}</td>
<td class="align-middle white-space-nowrap text-end">
<div class="btn-reveal-trigger position-static">
<button
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button"
data-bs-toggle="dropdown"
data-boundary="window"
aria-haspopup="true"
aria-expanded="false"
data-bs-reference="parent">
<span class="fas fa-ellipsis-h fs-10"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'activate_account' 'staff' obj.slug %}"><button class="dropdown-item">{% trans "Activate" %}</button></a>
<div class="dropdown-divider"></div>
<a href="{% url 'permenant_delete_account' 'staff' obj.slug %}"><button class="dropdown-item text-danger">{% trans "Permenantly Delete" %}</button></a>
</div>
</div>
</td>
</tr>
{% empty %}
<td colspan="6" class="text-center">{% trans 'No data available in table' %}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
{% endblock %}

View File

@ -130,14 +130,16 @@
<h5 class="text-body-highlight mb-0 text-end">{{ _("Status")}}
{% 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>
{% elif lead.status == "pending" %}
<span class="badge badge-phoenix badge-phoenix-warning"><span class="badge-label">{{_("Pending")}}</span><span class="fa fa-clock-o ms-1"></span></span>
{% elif lead.status == "in_progress" %}
<span class="badge badge-phoenix badge-phoenix-info"><span class="badge-label">{{_("In Progress")}}</span><span class="fa fa-wrench ms-1"></span></span>
{% elif lead.status == "qualified" %}
<span class="badge badge-phoenix badge-phoenix-success"><span class="badge-label">{{_("Qualified")}}</span><span class="fa fa-check ms-1"></span></span>
{% elif lead.status == "canceled" %}
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Canceled")}}</span><span class="fa fa-times ms-1"></span></span>
{% elif lead.status == "follow_up" %}
<span class="badge badge-phoenix badge-phoenix-warning"><span class="badge-label">{{_("Follow Up")}}</span><span class="fa fa-clock-o ms-1"></span></span>
{% elif lead.status == "negotiation" %}
<span class="badge badge-phoenix badge-phoenix-info"><span class="badge-label">{{_("Negotiation")}}</span><span class="fa fa-wrench ms-1"></span></span>
{% elif lead.status == "won" %}
<span class="badge badge-phoenix badge-phoenix-success"><span class="badge-label">{{_("Won")}}</span><span class="fa fa-check ms-1"></span></span>
{% elif lead.status == "lost" %}
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Lost")}}</span><span class="fa fa-times ms-1"></span></span>
{% elif lead.status == "closed" %}
<span class="badge badge-phoenix badge-phoenix-danger"><span class="badge-label">{{_("Closed")}}</span><span class="fa fa-times ms-1"></span></span>
{% endif %}
</h5>
</div>
@ -158,51 +160,51 @@
<div class="card-body">
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-envelope-alt"> </span>
<h5 class="text-body-highlight mb-0">{{ _("Email") }}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Email") }}</h5>
</div>
<a href="{{ lead.email}}">{{ lead.email }}</a>
<span class="text-body-secondary">{{ lead.email }}</span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-phone"> </span>
<h5 class="text-body-highlight mb-0">{{ _("Phone") }}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Phone") }}</h5>
</div>
<a href="{{ lead.phone_number}}">{{ lead.phone_number}} </a>
<span class="text-body-secondary">{{ lead.phone_number}} </span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-dollar-alt"></span>
<h5 class="text-body-highlight mb-0">{{ _("Salary")}}</h5>
<div class="d-flex align-items-center mb-1"><span class="currency">{{CURRENCY}}</span>&nbsp;
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Salary")}}</h5>
</div>
<p class="mb-0 text-body-secondary">{{lead.salary}} </p>
<p class="mb-0 text-body-secondary"><small><span class="currency">{{CURRENCY}}</span></small>&nbsp;{{lead.salary}} </p>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-clock"></span>
<h5 class="text-body-highlight mb-0">{{ _("Created")}}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Created")}}</h5>
</div>
<p class="mb-0 text-body-secondary">{{ lead.created|naturalday|capfirst }}</p>
<span class="text-body-secondary">{{ lead.created|naturalday|capfirst }}</span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
<h5 class="text-body-highlight mb-0">{{ _("Lead Source")}}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Source")}}</h5>
</div>
<p class="mb-0 text-body-secondary">{{ lead.source|upper }}</p>
<span class="text-body-secondary">{{ lead.source|upper }}</span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-file-check-alt"></span>
<h5 class="text-body-highlight mb-0">{{ _("Lead Channel")}}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Lead Channel")}}</h5>
</div>
<p class="mb-0 text-body-secondary">{{ lead.channel|upper }}</p>
<span class="text-body-secondary">{{ lead.channel|upper }}</span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-estate"></span>
<h5 class="mb-0">{{ _("Address") }}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("Address") }}</h5>
</div>
<p class="mb-0 text-body-secondary">{{ lead.address}}</p>
<span class="text-body-secondary">{{ lead.address}}</span>
</div>
<div class="mb-3">
<div class="d-flex align-items-center mb-1"><span class="me-2 uil uil-map"></span>
<h5 class="mb-0 text-body-highlight">{{ _("City") }}</h5>
<h5 class="text-body-highlight fw-bold mb-0">{{ _("City") }}</h5>
</div>
<p class="mb-0 text-body-secondary">{{ lead.city }}</p>
<span class="text-body-secondary">{{ lead.city }}</span>
</div>
</div>
</div>
@ -213,7 +215,7 @@
<div class="col-md-7 col-lg-7 col-xl-8">
<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-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></div>
<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>
</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="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>
@ -329,17 +331,17 @@
<td class="align-middle text-end white-space-nowrap pe-0 action py-2">
{% if note.created_by == request.user %}
<a id="updateBtn"
href="#"
onclick="updateNote(this)"
class="btn btn-sm btn-phoenix-primary me-2"
data-pk="{{ note.pk }}"
data-note="{{ note.note|escapejs }}"
data-url="{% url 'update_note' note.pk %}"
data-bs-toggle="modal"
data-bs-target="#noteModal"
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>">
{{ _("Update") }}
</a>
href="#"
onclick="updateNote(this)"
class="btn btn-sm btn-phoenix-primary me-2"
data-pk="{{ note.pk }}"
data-note="{{ note.note|escapejs }}"
data-url="{% url 'update_note' note.pk %}"
data-bs-toggle="modal"
data-bs-target="#noteModal"
data-note-title="{{ _('Update') }}<i class='fas fa-pen-square text-primary ms-2'></i>">
{{ _("Update") }}
</a>
<button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'delete_note_to_lead' note.pk %}"
data-message="Are you sure you want to delete this note?"
@ -582,7 +584,6 @@
</div>
<!-- note Modal -->
<div class="modal fade" id="noteModal" tabindex="-1" aria-labelledby="noteModalLabel" aria-hidden="true">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header justify-content-between align-items-start gap-5 px-4 pt-4 pb-3 border-0">
@ -606,103 +607,120 @@
{% block customJS %}
<script>
function updateNote(e) {
let url = e.getAttribute('data-url')
let note = e.getAttribute('data-note')
document.querySelector('#id_note').value = note
let form = document.querySelector('.add_note_form')
form.action = url
let url = e.getAttribute('data-url')
let note = e.getAttribute('data-note')
document.querySelector('#id_note').value = note
let form = document.querySelector('.add_note_form')
form.action = url
}
function reset_form() {
document.querySelector('#id_note').value = ""
let form = document.querySelector('.add_note_form')
form.action = "{% url 'add_note' 'lead' lead.slug %}"
document.querySelector('#id_note').value = ""
let form = document.querySelector('.add_note_form')
form.action = "{% url 'add_note' 'lead' lead.slug %}"
}
document.addEventListener("DOMContentLoaded", function () {
let Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
// Display Django messages
{% if messages %}
{% for message in messages %}
Toast.fire({
icon: "{{ message.tags }}",
titleText: "{{ message|safe }}"
});
{% endfor %}
{% endif %}
function openActionModal(leadId, currentAction, nextAction, nextActionDate) {
const modal = new bootstrap.Modal(document.getElementById('actionTrackingModal'));
document.getElementById('leadId').value = leadId;
document.getElementById('currentAction').value = currentAction;
document.getElementById('nextAction').value = nextAction;
document.getElementById('nextActionDate').value = nextActionDate;
modal.show();
}
document.getElementById('actionTrackingForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
// Show loading indicator
Swal.fire({
let Toast = Swal.mixin({
toast: true,
icon: 'info',
text: 'Please wait...',
allowOutsideClick: false,
position: "top-end",
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
fetch("{% url 'update_lead_actions' %}", {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': '{{ csrf_token }}'
}
})
.then(response => response.json())
.then(data => {
Swal.close();
if (data.success) {
// Display Django messages
{% if messages %}
{% for message in messages %}
Toast.fire({
icon: "{{ message.tags }}",
titleText: "{{ message|safe }}"
});
{% endfor %}
{% endif %}
function openActionModal(leadId, currentAction, nextAction, nextActionDate) {
const modal = new bootstrap.Modal(document.getElementById('actionTrackingModal'));
document.getElementById('leadId').value = leadId;
document.getElementById('currentAction').value = currentAction;
document.getElementById('nextAction').value = nextAction;
document.getElementById('nextActionDate').value = nextActionDate;
modal.show();
}
document.getElementById('actionTrackingForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
// Show loading indicator
Swal.fire({
toast: true,
icon: 'info',
text: 'Please wait...',
allowOutsideClick: false,
position: "top-end",
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
fetch("{% url 'update_lead_actions' %}", {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': '{{ csrf_token }}'
}
})
.then(response => response.json())
.then(data => {
Swal.close();
if (data.success) {
// Success notification
Swal.fire({
toast: true,
icon: 'success',
position: "top-end",
text: data.message || 'Actions updated successfully',
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
}).then(() => {
location.reload(); // Refresh after user clicks OK
});
} else {
Swal.fire({
toast: true,
icon: 'success',
position: "top-end",
text: data.message || 'Actions updated successfully',
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
}).then(() => {
location.reload(); // Refresh after user clicks OK
});
} else {
// Error notification
Swal.fire({
toast: true,
icon: 'error',
position: "top-end",
text: data.message || 'Failed to update actions',
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
}
})
.catch(error => {
Swal.close();
console.error('Error:', error);
Swal.fire({
toast: true,
icon: 'error',
position: "top-end",
text: data.message || 'Failed to update actions',
text: 'An unexpected error occurred',
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
@ -711,34 +729,16 @@
toast.onmouseleave = Swal.resumeTimer;
}
});
}
})
.catch(error => {
Swal.close();
console.error('Error:', error);
Swal.fire({
toast: true,
icon: 'error',
position: "top-end",
text: 'An unexpected error occurred',
showConfirmButton: false,
timer: 2000,
timerProgressBar: false,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
});
});
});
// Helper function for notifications
function notify(tag, msg) {
Toast.fire({
icon: tag,
titleText: msg
});
}
});
function notify(tag, msg) {
Toast.fire({
icon: tag,
titleText: msg
});
}
</script>
{% endblock customJS %}

View File

@ -1,25 +1,25 @@
{% extends 'base.html' %}
{% load i18n static crispy_forms_filters %}
{% block customcss %}
<style>
.htmx-indicator{
opacity:0;
transition: opacity 500ms ease-in;
}
.htmx-request .htmx-indicator{
opacity:1;
}
.htmx-request.htmx-indicator{
opacity:1;
}
</style>
<style>
.htmx-indicator{
opacity:0;
transition: opacity 500ms ease-in;
}
.htmx-request .htmx-indicator{
opacity:1;
}
.htmx-request.htmx-indicator{
opacity:1;
}
</style>
{% endblock customcss %}
{% block content %}
<div class="container-fluid">
<h1>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h1>
<div class="row mb-3">
<div class="col-sm-6 col-md-8">
<div class="col-sm-6 col-md-8">
<form class="form" method="post">
{% csrf_token %}
@ -36,7 +36,7 @@
</div>
</div>
<script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// First, create the spinner div (or use the existing one)
const spinner = document.createElement('div');

View File

@ -182,6 +182,7 @@
<td class="align-middle white-space-nowrap fw-semibold"><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 fw-semibold">
{% if request.user.staffmember.staff %}
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
@ -221,7 +222,8 @@
</div>
</div>
</div>
</div>
</div>
{% endif %}
</td>
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.get_status|upper }}</td>
<td class="align-middle white-space-nowrap text-body-tertiary text-opacity-85 fw-semibold text-body-highlight">{{ lead.staff|upper }}</td>

View File

@ -1,23 +1,23 @@
{% load i18n static humanize %}
{% load custom_filters %}
{% block customCSS %}
<style>
.bg-success-soft {
background-color: rgba(25, 135, 84, 0.1) !important;
opacity: .8;
}
.bg-danger-soft {
background-color: rgba(220, 53, 69, 0.1) !important;
opacity: .8;
}
</style>
<style>
.bg-success-soft {
background-color: rgba(25, 135, 84, 0.1) !important;
opacity: .8;
}
.bg-danger-soft {
background-color: rgba(220, 53, 69, 0.1) !important;
opacity: .8;
}
</style>
{% endblock customCSS %}
{% for opportunity in opportunities %}
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
<div class="card h-100
{% if opportunity.get_stage_display == 'Closed Won' %}bg-success-soft
{% elif opportunity.get_stage_display == 'Closed Lost' %}bg-danger-soft{% endif %}">
{% if opportunity.get_stage_display == 'Closed Won' %}bg-success-soft
{% elif opportunity.get_stage_display == 'Closed Lost' %}bg-danger-soft{% endif %}">
<div class="card-body">
<h5 class="mb-4">Opportunity for {{ opportunity.customer.customer_name }}</h5>
@ -35,8 +35,8 @@
<span class="badge badge-phoenix fs-10 badge-phoenix-danger">{{ opportunity.get_stage_display }}</span>
{% endif %}
<span class="badge badge-phoenix fs-10
{% if opportunity.get_stage_display == 'Won' %}badge-phoenix-success
{% elif opportunity.get_stage_display == 'Lost' %}badge-phoenix-danger{% endif %}">
{% if opportunity.get_stage_display == 'Won' %}badge-phoenix-success
{% elif opportunity.get_stage_display == 'Lost' %}badge-phoenix-danger{% endif %}">
{{ opportunity.get_status_display }}
</span>
</div>
@ -61,7 +61,7 @@
</div>
</td>
<td class="text-end">
<p class="fw-semibold fs-9 mb-0 text-body-emphasis"><span class="currency">{{ CURRENCY }}</span>{{ opportunity.expected_revenue }}</p>
<p class="fw-semibold fs-9 mb-0 text-body-emphasis"><span class="currency">{{ CURRENCY }}</span>{{ opportunity.expected_revenue }}</p>
</td>
</tr>

View File

@ -26,7 +26,7 @@
{% csrf_token %}
{{ form|crispy }}
<div class="col-12">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>

View File

@ -6,6 +6,12 @@
</div>
<div class="col-auto">
<div class="row g-2 g-sm-3">
<div class="col-auto">
<a href="{% url 'order_list' %}" class="btn btn-phoenix-success"><span class="fas fa-list me-2"></span>{{ _("Orders") }}</a>
</div>
<div class="col-auto">
<a href="{% url 'billing_info' %}" class="btn btn-phoenix-info"><span class="fas fa-credit-card me-2"></span>{{ _("Billing Information") }}</a>
</div>
<div class="col-auto">
<a href="{% url 'account_change_password' %}" class="btn btn-phoenix-danger"><span class="fas fa-key me-2"></span>{{ _("Change Password") }}</a>
</div>
@ -108,7 +114,7 @@
<a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Renew") }}</a>
{% endif %}
{% if dealer.user.userplan.plan.name != "Enterprise" %}
<a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Upgrade") }}</a>
<a href="{% url 'pricing_page' %}" class="btn btn-sm btn-phoenix-primary ms-2"><span class="fas fa-rocket me-2"></span>{{ _("Upgrade") }}</a>
{% endif %}
{% else %}
<span class="text-body-tertiary fw-semibold">You have no active plan.</span> <a href="{% url 'pricing_page' %}" class="btn btn-phoenix-secondary ms-2"><span class="fas fa-arrow-right me-2"></span>{{ _("Subscribe") }}</a>

View File

@ -435,6 +435,11 @@
<a class="nav-link px-3 d-block" href="{% url 'dealer_settings' request.user.dealer.slug %}"> <span class="me-2 text-body align-bottom" data-feather="settings"></span>{{ _("Settings") }}</a>
{% endif %}
</li>
<li class="nav-item">
{% if request.is_dealer %}
<a class="nav-link px-3 d-block" href="{% url 'management' %}"> <span class="me-2 text-body align-bottom" data-feather="shield"></span>{{ _("Admin Managemnet") }}</a>
{% endif %}
</li>
<li class="nav-item">
<a class="nav-link px-3 d-block" href=""> <span class="me-2 text-body align-bottom" data-feather="help-circle"></span>Help Center</a>
</li>

View File

@ -58,7 +58,7 @@
</div>
</div> {% endcomment %}
{% comment %} <div class="row justify-content-center g-1 mt-4">
<div class="col-auto">
@ -73,7 +73,7 @@
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>

View File

@ -44,15 +44,15 @@
</div> {% endcomment %}
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>

View File

@ -106,7 +106,7 @@
<button type="submit" class="btn btn-sm btn-success me-1">{% trans "Save" %}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger me-1">{% trans "Cancel" %}</a>
</div>
</main>
</div>
</div>

View File

@ -20,7 +20,7 @@
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>
</div>

View File

@ -23,7 +23,7 @@
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i> {{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>
</div>

View File

@ -4,39 +4,39 @@
{% block title %}{% trans "bank account" %}{% endblock title %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<div class="card shadow rounded bg-body">
<div class="card-header">
<p class="mb-0">
{% if customer.created %}
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<div class="card shadow rounded bg-body">
<div class="card-header">
<p class="mb-0">
{% if customer.created %}
<!--<i class="bi bi-pencil-square"></i>-->
{{ _("Edit Bank Account") }}
{% else %}
{{ _("Edit Bank Account") }}
{% else %}
<!--<i class="bi bi-person-plus"></i> -->
{{ _("Add Bank Account") }}
{% endif %}
</p>
</div>
<div class="card-body">
<form method="post" class="form" novalidate>
{% csrf_token %}
{{ form|crispy }}
{% for error in form.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
<div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
{{ _("Add Bank Account") }}
{% endif %}
</p>
</div>
</form>
<div class="card-body">
<form method="post" class="form" novalidate>
{% csrf_token %}
{{ form|crispy }}
{% for error in form.errors %}
<div class="text-danger">{{ error }}</div>
{% endfor %}
<div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -89,5 +89,5 @@
</div>
{% endblock %}

View File

@ -42,7 +42,7 @@
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>
{% endblock content %}

View File

@ -26,7 +26,7 @@
<div class="text-danger">{{ error }}</div>
{% endfor %}
<div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
@ -34,7 +34,7 @@
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>
</div>
</div>

View File

@ -17,11 +17,11 @@
<a href="{% url 'ledger_list' %}" class="btn btn-danger"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a>
</div> {% endcomment %}
<div class="d-flex justify-content-center">
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</div>
</form>
</div>

View File

@ -13,7 +13,7 @@
<div class="d-flex">
<a href="{% url 'organization_update' organization.pk %}" class="btn btn-sm btn-warning me-2">{% trans "Edit" %}</a>
<button class="btn btn-phoenix-danger btn-sm delete-btn"
data-url="{% url 'organization_delete' organization.pk %}"
data-url="{% url 'organization_delete' organization.slug %}"
data-message="Are you sure you want to delete this organization?"
data-bs-toggle="modal" data-bs-target="#deleteModal">
{% trans 'Delete' %}<i class="fas fa-trash ms-1"></i>

View File

@ -93,7 +93,7 @@
{% trans 'Are you sure you want to delete this Organization?' %}
</p>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">{% trans 'No' %}</button>
<a type="button" class="btn btn-danger btn-sm" href="{% url 'organization_delete' org.pk %}">{% trans 'Yes' %}</a>
<a type="button" class="btn btn-danger btn-sm" href="{% url 'organization_delete' org.slug %}">{% trans 'Yes' %}</a>
</div>
</div>
</div>
@ -102,7 +102,7 @@
<td class="name align-middle white-space-nowrap ps-0">
<div class="d-flex align-items-center">
<div>
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.pk %}">{{ org.name }}</a>
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.slug %}">{{ org.name }}</a>
<div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p><span class="badge badge-phoenix badge-phoenix-primary">{{ org.name }}</span>
</div>
@ -121,7 +121,7 @@
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'organization_update' org.pk %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
<a href="{% url 'organization_update' org.slug %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
{% if perms.django_ledger.delete_customermodel %}
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button>
{% endif %}

View File

@ -22,7 +22,7 @@
<div class="container text-center" data-aos="fade-up">
<div class="py-5">
<i class="bi bi-x-circle-fill text-danger" style="font-size: 5rem;"></i>
<h2 class="mt-4">{% trans "Payment Failed"%}</h2>
<h2 class="mt-4">{% trans "Payment Failed"%}</h2>
{% if message %}
<p class="lead">{{message}}.</p>
{% else %}

View File

@ -207,26 +207,26 @@
{% block customJS %}
<script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById('wizardForm');
const form = document.getElementById('wizardForm');
form.addEventListener('submit', function(e) {
e.preventDefault(); // Prevent default form submission
form.addEventListener('submit', function(e) {
e.preventDefault(); // Prevent default form submission
// Show loading alert
Swal.fire({
title: 'Processing...',
html: 'Please wait while we submit your form',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
Swal.fire({
title: 'Processing...',
html: 'Please wait while we submit your form',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
// Submit the form after a slight delay to ensure Swal is shown
setTimeout(() => {
form.submit();
}, 100);
});
setTimeout(() => {
form.submit();
}, 100);
});
const radios = document.querySelectorAll('.btn-check');
radios.forEach(radio => {

View File

@ -68,13 +68,13 @@
</div> {% endcomment %}
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>

View File

@ -55,7 +55,7 @@
</td>
<td class="align-middle product white-space-nowrap">{{ invoice.created }}</td>
<td class="align-middle product white-space-nowrap">
<a href="{% url 'invoice_detail' invoice.pk %}"
<a href="{% url 'invoice_detail' invoice.pk %}"
class="btn btn-sm btn-phoenix-success">
<i class="fa-regular fa-eye me-1"></i>
{% trans "View" %}

View File

@ -27,7 +27,7 @@
</div>
<h4 class="my-4">Groups</h4>
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'user_groups' user_.pk %}"><i class="fa-solid fa-users"></i> Manage Groups</a>
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'user_groups' user_.slug %}"><i class="fa-solid fa-users"></i> Manage Groups</a>
<table class="table table-hover table-responsive-sm fs-9 mb-0">
<thead>
<tr>
@ -48,13 +48,13 @@
</table>
</div>
<div class="card-footer d-flex ">
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'user_update' user_.id %}">
<a class="btn btn-sm btn-phoenix-primary me-1" href="{% url 'user_update' user_.slug %}">
{{ _("Edit") }}
<i class="fa-solid fa-pen-to-square"></i>
</a>
<button class="btn btn-phoenix-danger btn-sm delete-btn me-1"
data-url="{% url 'user_delete' user_.id %}"
data-url="{% url 'user_delete' user_.slug %}"
data-message="{{ _("Are you sure you want to delete this user?")}}"
data-bs-toggle="modal" data-bs-target="#deleteModal">
{{ _("Delete") }}

View File

@ -2,10 +2,7 @@
{% load i18n %}
{% load crispy_forms_filters %}
{% block title %}{% trans "Group" %}{% endblock title %}
{% block content %}
<div class="row">
<div class="row">
<div class="col-sm-9">
@ -16,7 +13,6 @@
</div>
<div class="row">
<div class="col-sm-9">
<form class="row g-3 mb-9" method="post" class="form" novalidate>
{% csrf_token %}
{{ redirect_field }}

View File

@ -11,8 +11,16 @@
<div class="col-auto">
<div class="d-md-flex justify-content-between">
<div>
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-user-tie"></i> {% trans "Add New Staff" %}</a>
<a href="{% url 'group_list' %}" class="btn btn-sm btn-phoenix-success"><i class="fa-solid fa-user-group"></i> {% trans "Manage Groups & Permissions" %}</a>
{% if request.user.userplan %}
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-user-tie"></i> {% trans "Add New Staff" %}</a>
<a href="{% url 'group_list' %}" class="btn btn-sm btn-phoenix-success"><i class="fa-solid fa-user-group"></i> {% trans "Manage Groups & Permissions" %}</a>
{% else %}
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
<i class="fa-solid fa-circle-info fs-6"></i>
<p class="mb-0 flex-1">{{ _("No Active Subscription,please activate your subscription.") }}<a href="{% url 'pricing_page' %}" class="ms-3 text-body-primary fs-9">Manage Subscription</a></p>
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endif %}
</div>
</div>
</div>
@ -33,7 +41,7 @@
<tr>
<td class="align-middle white-space-nowrap ps-0">
<div>
<a class="fs-8 fw-bold" href="{% url 'user_detail' user.pk%}">{{ user.arabic_name }}</a>
<a class="fs-8 fw-bold" href="{% url 'user_detail' user.slug%}">{{ user.arabic_name }}</a>
<div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2">{{ user.name }}</p>
</div>
@ -47,7 +55,7 @@
<td class="align-middle white-space-nowrap">
<a class="btn btn-phoenix-success"
href="{% url 'user_detail' user.id %}">
href="{% url 'user_detail' user.slug %}">
<i class="fa-solid fa-eye"></i>
{% trans 'view'|capfirst %}
</a>

View File

@ -35,11 +35,11 @@
<div class="text-danger">{{ error }}</div>
{% endfor %}
<div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form>