diff --git a/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc b/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc index fa3eb0f8..1928ca12 100644 Binary files a/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc and b/osinaweb/billing/add/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/billing/add/__pycache__/views.cpython-312.pyc b/osinaweb/billing/add/__pycache__/views.cpython-312.pyc index e3344495..11a293a8 100644 Binary files a/osinaweb/billing/add/__pycache__/views.cpython-312.pyc and b/osinaweb/billing/add/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/billing/add/urls.py b/osinaweb/billing/add/urls.py index 860eb6fe..97dc4702 100644 --- a/osinaweb/billing/add/urls.py +++ b/osinaweb/billing/add/urls.py @@ -7,8 +7,7 @@ urlpatterns = [ path('service', views.add_service, name='addservice'), path('order//', views.add_order, name='addorder'), - path('invoice-pdf//', views.add_invoice_pdf, name='addinvoice'), - path('payment-pdf//', views.add_payment_pdf, name='addpayment'), + path('service///', views.add_service_in_order, name='addserviceinorder'), @@ -16,5 +15,4 @@ urlpatterns = [ path('payment//', views.add_payment_modal, name='add_payment_modal'), path('payment_comment/', views.add_payment_comment_modal, name='add_payment_comment_modal'), - ] diff --git a/osinaweb/billing/add/views.py b/osinaweb/billing/add/views.py index c1b41a70..1c79925c 100644 --- a/osinaweb/billing/add/views.py +++ b/osinaweb/billing/add/views.py @@ -8,7 +8,7 @@ import os from osinacore.decorators import * from django.core.files.base import ContentFile from django.db.models import Q -from weasyprint import HTML, CSS + @staff_login_required @@ -211,116 +211,7 @@ def add_payment_comment_modal(request): -def add_invoice_pdf(request, order_id): - order = get_object_or_404(Order, id=order_id) - - current_year = str(timezone.now().year)[-2:] - last_invoice = Invoice.objects.all().last() - if last_invoice: - last_invoice_number = int(last_invoice.invoice_number.split('-')[1].split('+')[0]) - new_invoice_number = f"$0{current_year}-{last_invoice_number + 1}" - else: - new_invoice_number = f"$0{current_year}-1425" - - - - invoice = Invoice.objects.create( - invoice_number = new_invoice_number, - order=order, - date_created=datetime.now(), - ) - - template = get_template('details_templates/invoice-details.html') - context = {'order': order} - html_string = template.render(context) - - # Define the CSS string with Poppins font - css_string = ''' - @font-face { - font-family: 'Poppins'; - src: url('path_to_poppins_font_file.ttf') format('truetype'); /* Update the path to the font file */ - } - - body { - font-family: 'Poppins', sans-serif; /* Use Poppins font for the entire document */ - } - - /* Your existing CSS styles */ - /* Add or modify styles as needed */ - ''' - - # Generate PDF - pdf = HTML(string=html_string).write_pdf( - stylesheets=[ - CSS(string=css_string), - CSS(string='@page { margin: 30px; }') - ], - presentational_hints=True - ) - - filename = f'invoice_{invoice.invoice_number}.pdf' - pdf_content = ContentFile(pdf) - invoice.pdf.save(filename, pdf_content, save=True) - - - # Return PDF - response = HttpResponse(pdf, content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' - return response - - - - - - - -def add_payment_pdf(request, order_id): - order = get_object_or_404(Order, id=order_id) - payments = OrderPayment.objects.filter(order = order) - paid_amount = OrderPayment.objects.filter(order=order, date_paid__isnull=False).aggregate(total_paid=Sum('amount'))['total_paid'] or 0 - cart_total = order.get_cart_total - remaining_amount = cart_total - paid_amount - - - invoice = order.invoice - - # Render both invoice and payment details templates to HTML - invoice_template = get_template('details_templates/invoice-details.html') - payment_template = get_template('details_templates/payment-details.html') - invoice_html = invoice_template.render({'order': order}) - payment_html = payment_template.render({'order': order, 'payments':payments, 'remaining_amount':remaining_amount,}) - - # Combine the HTML content of both templates - combined_html = f"{invoice_html}
{payment_html}" - - # Define CSS - css_string = ''' - @font-face { - font-family: 'Poppins'; - src: url('path_to_poppins_font_file.ttf') format('truetype'); /* Update the path to the font file */ - } - - body { - font-family: 'Poppins', sans-serif; /* Use Poppins font for the entire document */ - } - - /* Your existing CSS styles */ - /* Add or modify styles as needed */ - ''' - - # Generate PDF - pdf = HTML(string=combined_html).write_pdf( - stylesheets=[ - CSS(string=css_string), - CSS(string='@page { margin: 30px; }') - ], - presentational_hints=True - ) - # Return PDF - response = HttpResponse(pdf, content_type='application/pdf') - response['Content-Disposition'] = 'attachment; filename="my_pdf.pdf"' - return response diff --git a/osinaweb/customercore/__pycache__/urls.cpython-312.pyc b/osinaweb/customercore/__pycache__/urls.cpython-312.pyc index 4199a252..bd22ffbe 100644 Binary files a/osinaweb/customercore/__pycache__/urls.cpython-312.pyc and b/osinaweb/customercore/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/customercore/__pycache__/views.cpython-312.pyc b/osinaweb/customercore/__pycache__/views.cpython-312.pyc index cf81886a..3499ee7c 100644 Binary files a/osinaweb/customercore/__pycache__/views.cpython-312.pyc and b/osinaweb/customercore/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/customercore/payment/__pycache__/views.cpython-312.pyc b/osinaweb/customercore/payment/__pycache__/views.cpython-312.pyc index 88f4b939..7fe5263e 100644 Binary files a/osinaweb/customercore/payment/__pycache__/views.cpython-312.pyc and b/osinaweb/customercore/payment/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/customercore/templates/listing_pages/customer-invoices.html b/osinaweb/customercore/templates/listing_pages/customer-invoices.html index b7702622..7ea4ce9c 100644 --- a/osinaweb/customercore/templates/listing_pages/customer-invoices.html +++ b/osinaweb/customercore/templates/listing_pages/customer-invoices.html @@ -51,7 +51,8 @@ {{invoice.order.orderpayment_set.all.last.date_due}} {% else %} - - {% endif %}

+ {% endif %} +

diff --git a/osinaweb/customercore/templates/user_profile_pages/user-profile.html b/osinaweb/customercore/templates/user_profile_pages/user-profile.html new file mode 100644 index 00000000..fe40a080 --- /dev/null +++ b/osinaweb/customercore/templates/user_profile_pages/user-profile.html @@ -0,0 +1,91 @@ +{% extends "customer_main.html" %} +{%load static%} +{% block content %} + +
+
+
+
+ +
+ +
+

{{request.user.first_name}} {{request.user.last_name}}

+

{{request.user.email}}

+
+
+ + +
+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/osinaweb/customercore/templates/user_profile_pages/user-settings.html b/osinaweb/customercore/templates/user_profile_pages/user-settings.html new file mode 100644 index 00000000..5bb372f7 --- /dev/null +++ b/osinaweb/customercore/templates/user_profile_pages/user-settings.html @@ -0,0 +1,90 @@ +{% extends "customer_main.html" %} +{%load static%} +{% block content %} + +
+
+
+
+ +
+ +
+

{{request.user.first_name}} {{request.user.last_name}}

+

{{request.user.email}}

+
+
+ + +
+ +
+

Change Password

+ +
+ {% csrf_token %} + + + +

+ + + + + +

+ + +
+
+
+ + + + + + + +{% endblock %} \ No newline at end of file diff --git a/osinaweb/customercore/urls.py b/osinaweb/customercore/urls.py index 290267c5..fef96de9 100644 --- a/osinaweb/customercore/urls.py +++ b/osinaweb/customercore/urls.py @@ -29,4 +29,12 @@ urlpatterns = [ path('shared-hosting-plans/', views.shared_hosting_plans, name='sharedhostingplans'), path('cloud-vps-hosting-plans/', views.cloud_vps_hosting_plans, name='cloudvpshostingplans'), path('dedicated-servers-plans/', views.dedicated_servers_plans, name='dedicatedserversplans'), + + + # USER PROFILE + path('user-profile/', views.user_profile, name='userprofile'), + path('user-settings/', views.user_settings, name='usersettings'), + + path('changepassword/', views.change_password, name="changepassword"), + path('check_current_password/', views.check_current_password, name='check_current_password'), ] diff --git a/osinaweb/customercore/views.py b/osinaweb/customercore/views.py index 90978f35..1fcf363e 100644 --- a/osinaweb/customercore/views.py +++ b/osinaweb/customercore/views.py @@ -7,6 +7,9 @@ from django.db.models import Q from django.http import Http404 from django.db.models import OuterRef, Subquery from customercore.views import * +from django.contrib.auth.hashers import check_password +from django.contrib.auth import update_session_auth_hash, logout +import json @@ -264,3 +267,61 @@ def dedicated_servers_plans(request, *args, **kwargs): +# USER PROFILE +@customer_login_required +def user_profile(request, *args, **kwargs): + + context = { + + } + + return render(request, 'user_profile_pages/user-profile.html', context) + + + +@customer_login_required +def user_settings(request, *args, **kwargs): + + context = { + + } + + return render(request, 'user_profile_pages/user-settings.html', context) + + + + +def change_password(request): + if request.method == 'POST': + current_password = request.POST['current_password'] + new_password = request.POST['new_password'] + confirm_password = request.POST['confirm_password'] + + if check_password(current_password, request.user.password): + if new_password == confirm_password: + request.user.set_password(new_password) + request.user.save() + update_session_auth_hash(request, request.user) + logout(request) + return redirect('home') + + return render(request, 'accounts/change_password.html') + + + +def check_current_password(request): + if request.method == 'POST': + try: + data = json.loads(request.body.decode('utf-8')) + current_password = data.get('current_password') + except json.JSONDecodeError: + return JsonResponse({'is_current_password_correct': False}) + + user = request.user + + if check_password(current_password, request.user.password): + return JsonResponse({'is_current_password_correct': True}) + else: + return JsonResponse({'is_current_password_correct': False}) + + return JsonResponse({'error': 'Invalid request method'}, status=400) \ No newline at end of file diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index 9e91a117..bb6f86a7 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/__pycache__/admin.cpython-312.pyc b/osinaweb/osinacore/__pycache__/admin.cpython-312.pyc index 29a208db..c446b54e 100644 Binary files a/osinaweb/osinacore/__pycache__/admin.cpython-312.pyc and b/osinaweb/osinacore/__pycache__/admin.cpython-312.pyc differ diff --git a/osinaweb/osinacore/__pycache__/models.cpython-312.pyc b/osinaweb/osinacore/__pycache__/models.cpython-312.pyc index a959616e..9f2d29f6 100644 Binary files a/osinaweb/osinacore/__pycache__/models.cpython-312.pyc and b/osinaweb/osinacore/__pycache__/models.cpython-312.pyc differ diff --git a/osinaweb/osinacore/__pycache__/views.cpython-312.pyc b/osinaweb/osinacore/__pycache__/views.cpython-312.pyc index 2e27dc4a..fd84b944 100644 Binary files a/osinaweb/osinacore/__pycache__/views.cpython-312.pyc and b/osinaweb/osinacore/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/osinacore/edit/__pycache__/urls.cpython-312.pyc b/osinaweb/osinacore/edit/__pycache__/urls.cpython-312.pyc index 618e110f..09f93300 100644 Binary files a/osinaweb/osinacore/edit/__pycache__/urls.cpython-312.pyc and b/osinaweb/osinacore/edit/__pycache__/urls.cpython-312.pyc differ diff --git a/osinaweb/osinacore/edit/__pycache__/views.cpython-312.pyc b/osinaweb/osinacore/edit/__pycache__/views.cpython-312.pyc index f8de4577..5bc1f328 100644 Binary files a/osinaweb/osinacore/edit/__pycache__/views.cpython-312.pyc and b/osinaweb/osinacore/edit/__pycache__/views.cpython-312.pyc differ diff --git a/osinaweb/osinacore/migrations/__pycache__/0082_pinnedproject.cpython-312.pyc b/osinaweb/osinacore/migrations/__pycache__/0082_pinnedproject.cpython-312.pyc new file mode 100644 index 00000000..23d9c4fe Binary files /dev/null and b/osinaweb/osinacore/migrations/__pycache__/0082_pinnedproject.cpython-312.pyc differ diff --git a/osinaweb/osinacore/templates/customer_main.html b/osinaweb/osinacore/templates/customer_main.html index d5fc138a..533fde89 100644 --- a/osinaweb/osinacore/templates/customer_main.html +++ b/osinaweb/osinacore/templates/customer_main.html @@ -189,13 +189,23 @@ @@ -384,13 +394,23 @@ style="display: none;" id="userProfileDropdown">
+ class="w-full py-3 flex items-center gap-2 text-white hover:text-osiblue duration-300 cursor-pointer border-b border-white border-opacity-10">

Logout

+ +
+ + + + +

User Profile

+
+
diff --git a/osinaweb/osinacore/templates/details_templates/customer-details.html b/osinaweb/osinacore/templates/details_templates/customer-details.html index 1f5cad7b..8d442925 100644 --- a/osinaweb/osinacore/templates/details_templates/customer-details.html +++ b/osinaweb/osinacore/templates/details_templates/customer-details.html @@ -71,6 +71,13 @@

Email: {{customer.user.email}}

+ +
+

Mobile Number: {{customer.mobile_number}}

+
+ + {% if customer.personal_website %}

Personal Website: {% if user_offline %} -

+

You are Currently Offline

diff --git a/osinaweb/osinacore/templates/projects-by-status.html b/osinaweb/osinacore/templates/projects-by-status.html index 45154c65..36e2f7a9 100644 --- a/osinaweb/osinacore/templates/projects-by-status.html +++ b/osinaweb/osinacore/templates/projects-by-status.html @@ -74,6 +74,14 @@ {% if project.open_user_tasks_count == 1 %} Task {% else %} Tasks {% endif %}

+
+ + + + +

{{project.ticket_set.all.count}} Open {% if project.ticket_set.all.count == 1 %} Ticket {% else %} Tickets {% endif %}

+

+
- - -
- View - - Edit - - -
@@ -109,7 +106,7 @@ {% if project.note_set.exists %} {% with last_note=project.note_set.last %}
-

{{ last_note.text }}

+

{{ last_note.text }}

:not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(-1px * var(--tw-space-x-reverse)); @@ -1897,6 +1905,11 @@ video { border-bottom-left-radius: 0.375rem; } +.rounded-e-lg { + border-start-end-radius: 0.5rem; + border-end-end-radius: 0.5rem; +} + .rounded-e-md { border-start-end-radius: 0.375rem; border-end-end-radius: 0.375rem; @@ -1917,6 +1930,11 @@ video { border-bottom-right-radius: 0.375rem; } +.rounded-s-lg { + border-start-start-radius: 0.5rem; + border-end-start-radius: 0.5rem; +} + .rounded-t-md { border-top-left-radius: 0.375rem; border-top-right-radius: 0.375rem; @@ -1927,16 +1945,6 @@ video { border-top-right-radius: 0px; } -.rounded-e-lg { - border-start-end-radius: 0.5rem; - border-end-end-radius: 0.5rem; -} - -.rounded-s-lg { - border-start-start-radius: 0.5rem; - border-end-start-radius: 0.5rem; -} - .rounded-bl-lg { border-bottom-left-radius: 0.5rem; } @@ -2011,6 +2019,10 @@ video { border-bottom-width: 2px; } +.border-e-0 { + border-inline-end-width: 0px; +} + .border-l { border-left-width: 1px; } @@ -2027,10 +2039,6 @@ video { border-top-width: 1px; } -.border-e-0 { - border-inline-end-width: 0px; -} - .border-none { border-style: none; } @@ -2040,6 +2048,11 @@ video { border-color: rgb(0 0 0 / var(--tw-border-opacity)); } +.border-blue-300 { + --tw-border-opacity: 1; + border-color: rgb(147 197 253 / var(--tw-border-opacity)); +} + .border-blue-400 { --tw-border-opacity: 1; border-color: rgb(96 165 250 / var(--tw-border-opacity)); @@ -2090,6 +2103,11 @@ video { border-color: rgb(107 114 128 / var(--tw-border-opacity)); } +.border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); +} + .border-green-700 { --tw-border-opacity: 1; border-color: rgb(21 128 61 / var(--tw-border-opacity)); @@ -2175,16 +2193,6 @@ video { border-color: rgb(202 138 4 / var(--tw-border-opacity)); } -.border-blue-300 { - --tw-border-opacity: 1; - border-color: rgb(147 197 253 / var(--tw-border-opacity)); -} - -.border-gray-700 { - --tw-border-opacity: 1; - border-color: rgb(55 65 81 / var(--tw-border-opacity)); -} - .border-r-transparent { border-right-color: transparent; } @@ -2217,6 +2225,11 @@ video { background-color: rgb(96 165 250 / var(--tw-bg-opacity)); } +.bg-blue-50 { + --tw-bg-opacity: 1; + background-color: rgb(239 246 255 / var(--tw-bg-opacity)); +} + .bg-blue-500 { --tw-bg-opacity: 1; background-color: rgb(59 130 246 / var(--tw-bg-opacity)); @@ -2446,11 +2459,6 @@ video { background-color: rgb(202 138 4 / var(--tw-bg-opacity)); } -.bg-blue-50 { - --tw-bg-opacity: 1; - background-color: rgb(239 246 255 / var(--tw-bg-opacity)); -} - .bg-opacity-10 { --tw-bg-opacity: 0.1; } @@ -3621,11 +3629,6 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.hover\:bg-blue-100:hover { - --tw-bg-opacity: 1; - background-color: rgb(219 234 254 / var(--tw-bg-opacity)); -} - .hover\:bg-opacity-100:hover { --tw-bg-opacity: 1; } @@ -3638,10 +3641,6 @@ video { --tw-bg-opacity: 0.6; } -.hover\:bg-opacity-40:hover { - --tw-bg-opacity: 0.4; -} - .hover\:p-2:hover { padding: 0.5rem; } @@ -3701,16 +3700,6 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity)); } -.hover\:text-blue-700:hover { - --tw-text-opacity: 1; - color: rgb(29 78 216 / var(--tw-text-opacity)); -} - -.hover\:text-gray-700:hover { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); -} - .focus\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; @@ -3726,51 +3715,11 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity)); } -:is([dir="rtl"] .rtl\:rotate-180) { - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - @media (prefers-color-scheme: dark) { - .dark\:border-gray-700 { - --tw-border-opacity: 1; - border-color: rgb(55 65 81 / var(--tw-border-opacity)); - } - - .dark\:bg-gray-700 { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81 / var(--tw-bg-opacity)); - } - - .dark\:bg-gray-800 { - --tw-bg-opacity: 1; - background-color: rgb(31 41 55 / var(--tw-bg-opacity)); - } - .dark\:text-gray-600 { --tw-text-opacity: 1; color: rgb(75 85 99 / var(--tw-text-opacity)); } - - .dark\:text-gray-400 { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); - } - - .dark\:text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } - - .dark\:hover\:bg-gray-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81 / var(--tw-bg-opacity)); - } - - .dark\:hover\:text-white:hover { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); - } } @media (min-width: 650px) { @@ -3879,10 +3828,6 @@ video { grid-template-columns: repeat(2, minmax(0, 1fr)); } - .s\:grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - .s\:flex-row { flex-direction: row; } @@ -3895,14 +3840,6 @@ video { gap: 0px; } - .s\:border-b-0 { - border-bottom-width: 0px; - } - - .s\:border-r { - border-right-width: 1px; - } - .s\:p-9 { padding: 2.25rem; } @@ -4065,10 +4002,6 @@ video { border-top-right-radius: 0px; } - .l\:border-b-0 { - border-bottom-width: 0px; - } - .l\:border-l { border-left-width: 1px; } @@ -4121,6 +4054,10 @@ video { width: 300px; } + .xlg1\:w-\[70\%\] { + width: 70%; + } + .xlg1\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } @@ -4159,6 +4096,10 @@ video { } @media (min-width: 1350px) { + .xxlg1\:col-span-2 { + grid-column: span 2 / span 2; + } + .xxlg1\:block { display: block; } diff --git a/osinaweb/static/images/ositcom_logos/full-logo-blue-bg.png b/osinaweb/static/images/ositcom_logos/full-logo-blue-bg.png new file mode 100644 index 00000000..d04229e4 Binary files /dev/null and b/osinaweb/static/images/ositcom_logos/full-logo-blue-bg.png differ diff --git a/osinaweb/static/js/customer_dashboard/change-password.js b/osinaweb/static/js/customer_dashboard/change-password.js new file mode 100644 index 00000000..f55f8b38 --- /dev/null +++ b/osinaweb/static/js/customer_dashboard/change-password.js @@ -0,0 +1,93 @@ +document.addEventListener("DOMContentLoaded", function () { + const currentPasswordInput = document.getElementById("currentPasswordInput"); + const oldPasswordMatchError = document.getElementById("oldPasswordMatchError"); + const passwordForm = document.getElementById("settingsContainer"); + const passwordInput1 = document.querySelector('input[name="new_password"]'); + const passwordInput2 = document.querySelector('input[name="confirm_password"]'); + const passwordMatchError = document.getElementById('passwordMatchError'); + + + passwordForm.addEventListener("submit", function (e) { + e.preventDefault(); // Prevent the default form submission. + + // Clear error messages. + oldPasswordMatchError.textContent = ''; + passwordMatchError.textContent = ''; + + // Get the entered passwords. + const currentPassword = currentPasswordInput.value; + const newPassword1 = passwordInput1.value; + const newPassword2 = passwordInput2.value; + + // Function to get the CSRF token from cookies. + function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie !== '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i].trim(); + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } + + // Function to check passwords and perform validation + function validatePasswords() { + // Password strength requirements + const isLengthValid = newPassword1.length >= 8; + + if (newPassword1 && newPassword2) { + if (newPassword1 === newPassword2) { + let errorMessage = ''; + + if (!isLengthValid) { + errorMessage += '- At least 8 characters\n'; + } + + if (errorMessage) { + passwordMatchError.textContent = errorMessage; + passwordMatchError.style.whiteSpace = 'pre-line'; + } + } else { + passwordMatchError.textContent = 'Passwords do not match'; + } + } + } + + // Check if the passwords match and perform validation + if (currentPassword && newPassword1 && newPassword2) { + // Send an AJAX request to check the current password. + fetch('/check_current_password/', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': getCookie('csrftoken') + }, + body: JSON.stringify({ current_password: currentPassword }), + }) + .then(response => response.json()) + .then(data => { + if (data.is_current_password_correct) { + // Current password is correct, now validate the new passwords. + validatePasswords(); + + // Check if there are any error messages. + if (!oldPasswordMatchError.textContent && !passwordMatchError.textContent) { + // Password checks passed, submit the form. + passwordForm.submit(); + } + } else { + // Password is incorrect. Display an error message. + oldPasswordMatchError.textContent = 'Incorrect password'; + } + }) + .catch(error => { + console.error('Error:', error); + }); + } + }); +});