Autosave: 20260204-171755
This commit is contained in:
parent
f4cb2d0af8
commit
0da3beb95c
Binary file not shown.
Binary file not shown.
@ -43,6 +43,8 @@ SESSION_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_SECURE = True
|
||||
SESSION_COOKIE_SAMESITE = "None"
|
||||
CSRF_COOKIE_SAMESITE = "None"
|
||||
LANGUAGE_COOKIE_SAMESITE = "None"
|
||||
LANGUAGE_COOKIE_SECURE = True
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||
|
||||
@ -5,9 +5,10 @@ from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('i18n/', include('django.conf.urls.i18n')),
|
||||
path('', include('core.urls')),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
||||
Binary file not shown.
@ -101,3 +101,12 @@ class PackageAdmin(ActionsModelAdmin):
|
||||
list_editable = ('is_active',)
|
||||
filter_horizontal = ('subjects',)
|
||||
search_fields = ('name_en', 'name_ar')
|
||||
|
||||
class Media:
|
||||
js = ('js/admin_package.js',)
|
||||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
form = super().get_form(request, obj, **kwargs)
|
||||
if obj and obj.classroom:
|
||||
form.base_fields['subjects'].queryset = Subject.objects.filter(classroom=obj.classroom)
|
||||
return form
|
||||
@ -1,14 +1,18 @@
|
||||
{% load i18n static %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="ar" dir="rtl">
|
||||
<html lang="{{ LANGUAGE_CODE }}" dir="{% if LANGUAGE_CODE == 'ar' %}rtl{% else %}ltr{% endif %}">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}منصة التعليم الإلكتروني{% endblock %}</title>
|
||||
<title>{% block title %}{% if LANGUAGE_CODE == 'ar' %}منصة التعليم الإلكتروني{% else %}EduPlatform{% endif %}{% endblock %}</title>
|
||||
|
||||
<!-- Bootstrap 5 CDN (RTL) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
<!-- Bootstrap 5 CDN -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap{% if LANGUAGE_CODE == 'ar' %}.rtl{% endif %}.min.css" rel="stylesheet">
|
||||
|
||||
<!-- FontAwesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
@ -91,6 +95,11 @@
|
||||
background: radial-gradient(circle, rgba(45, 49, 250, 0.1) 0%, transparent 70%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
html[dir="ltr"] .hero-section::before {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 3rem 0;
|
||||
@ -122,35 +131,62 @@
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">الدورات</a>
|
||||
<a class="nav-link" href="#">{% if LANGUAGE_CODE == 'ar' %}الدورات{% else %}Courses{% endif %}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">المعلمون</a>
|
||||
<a class="nav-link" href="#">{% if LANGUAGE_CODE == 'ar' %}المعلمون{% else %}Teachers{% endif %}</a>
|
||||
</li>
|
||||
{% if user.is_staff %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/">المسؤول</a>
|
||||
<a class="nav-link" href="/admin/">{% if LANGUAGE_CODE == 'ar' %}المسؤول{% else %}Admin{% endif %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="d-flex align-items-center">
|
||||
<!-- Language Switcher -->
|
||||
<div class="dropdown mx-3">
|
||||
<button class="btn btn-link nav-link p-0 text-dark d-flex align-items-center gap-2 dropdown-toggle text-decoration-none" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fas fa-globe fa-lg text-primary"></i>
|
||||
<span class="small fw-bold">{{ LANGUAGE_CODE|upper }}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0" aria-labelledby="languageDropdown" style="border-radius: 12px;">
|
||||
{% get_available_languages as LANGUAGES %}
|
||||
{% get_language_info_list for LANGUAGES as languages %}
|
||||
{% for language in languages %}
|
||||
<li>
|
||||
<form action="{% url 'set_language' %}" method="post" class="d-block">
|
||||
{% csrf_token %}
|
||||
<input name="next" type="hidden" value="{{ request.get_full_path }}">
|
||||
<input name="language" type="hidden" value="{{ language.code }}">
|
||||
<button type="submit" class="dropdown-item py-2 d-flex justify-content-between align-items-center {% if language.code == LANGUAGE_CODE %}bg-light text-primary fw-bold{% endif %}">
|
||||
<span>{{ language.name_local }}</span>
|
||||
{% if language.code == LANGUAGE_CODE %}
|
||||
<i class="fas fa-check small"></i>
|
||||
{% endif %}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<div class="dropdown ms-2">
|
||||
<button class="btn btn-link text-decoration-none dropdown-toggle text-dark d-flex align-items-center" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="fw-semibold">{{ user.username }}</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0" aria-labelledby="userDropdown" style="border-radius: 12px;">
|
||||
<li><a class="dropdown-item py-2" href="{% url 'profile' %}">الملف الشخصي</a></li>
|
||||
<li><a class="dropdown-item py-2" href="{% url 'profile' %}">{% if LANGUAGE_CODE == 'ar' %}الملف الشخصي{% else %}Profile{% endif %}</a></li>
|
||||
{% if user.is_staff %}
|
||||
<li><a class="dropdown-item py-2" href="/admin/">لوحة تحكم المسؤول</a></li>
|
||||
<li><a class="dropdown-item py-2" href="/admin/">{% if LANGUAGE_CODE == 'ar' %}لوحة تحكم المسؤول{% else %}Dashboard{% endif %}</a></li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item py-2 text-danger" href="{% url 'logout' %}">تسجيل الخروج</a></li>
|
||||
<li><a class="dropdown-item py-2 text-danger" href="{% url 'logout' %}">{% if LANGUAGE_CODE == 'ar' %}تسجيل الخروج{% else %}Logout{% endif %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'register_student' %}" class="btn btn-outline-primary me-2">تسجيل</a>
|
||||
<a href="{% url 'login' %}" class="btn btn-primary">دخول</a>
|
||||
<a href="{% url 'register_student' %}" class="btn btn-outline-primary me-2">{% if LANGUAGE_CODE == 'ar' %}تسجيل{% else %}Register{% endif %}</a>
|
||||
<a href="{% url 'login' %}" class="btn btn-primary">{% if LANGUAGE_CODE == 'ar' %}دخول{% else %}Login{% endif %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@ -161,7 +197,7 @@
|
||||
|
||||
<footer class="footer mt-5">
|
||||
<div class="container text-center">
|
||||
<p>© 2026 EduPlatform. جميع الحقوق محفوظة.</p>
|
||||
<p>© 2026 EduPlatform. {% if LANGUAGE_CODE == 'ar' %}جميع الحقوق محفوظة.{% else %}All rights reserved.{% endif %}</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}الرئيسية | EduPlatform{% endblock %}
|
||||
{% block title %}
|
||||
{% if LANGUAGE_CODE == 'ar' %}الرئيسية | منصة التعليم الإلكتروني{% else %}Home | EduPlatform{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="hero-section">
|
||||
@ -9,14 +11,26 @@
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-6">
|
||||
<h1 class="display-4 fw-bold mb-4">
|
||||
تعلم من أفضل المعلمين في أي وقت وأي مكان
|
||||
{% if LANGUAGE_CODE == 'ar' %}
|
||||
تعلم من أفضل المعلمين في أي وقت وأي مكان
|
||||
{% else %}
|
||||
Learn from the best teachers anytime, anywhere
|
||||
{% endif %}
|
||||
</h1>
|
||||
<p class="lead mb-5 text-muted">
|
||||
منصة تعليمية متكاملة تدعم الطلاب والمعلمين مع دروس حية ومصادر تعليمية متميزة.
|
||||
{% if LANGUAGE_CODE == 'ar' %}
|
||||
منصة تعليمية متكاملة تدعم الطلاب والمعلمين مع دروس حية ومصادر تعليمية متميزة.
|
||||
{% else %}
|
||||
A comprehensive educational platform supporting students and teachers with live lessons and premium resources.
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="d-flex gap-3">
|
||||
<a href="#levels-section" class="btn btn-primary btn-lg px-5">ابدأ الآن</a>
|
||||
<a href="#" class="btn btn-outline-secondary btn-lg px-5">اعرف المزيد</a>
|
||||
<a href="#levels-section" class="btn btn-primary btn-lg px-5">
|
||||
{% if LANGUAGE_CODE == 'ar' %}ابدأ الآن{% else %}Start Now{% endif %}
|
||||
</a>
|
||||
<a href="#" class="btn btn-outline-secondary btn-lg px-5">
|
||||
{% if LANGUAGE_CODE == 'ar' %}اعرف المزيد{% else %}Learn More{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 d-none d-lg-block">
|
||||
@ -24,8 +38,12 @@
|
||||
<div style="width: 400px; height: 400px; background: var(--primary-color); border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; opacity: 0.1; position: absolute; top: -50px; left: 50px;"></div>
|
||||
<div style="width: 300px; height: 300px; background: var(--secondary-color); border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; opacity: 0.1; position: absolute; bottom: -50px; right: 50px;"></div>
|
||||
<div class="glass-card text-center position-relative z-1">
|
||||
<h3 class="fw-bold mb-3">مستعد للبدء؟</h3>
|
||||
<p>انضم لآلاف الطلاب اليوم.</p>
|
||||
<h3 class="fw-bold mb-3">
|
||||
{% if LANGUAGE_CODE == 'ar' %}مستعد للبدء؟{% else %}Ready to Start?{% endif %}
|
||||
</h3>
|
||||
<p>
|
||||
{% if LANGUAGE_CODE == 'ar' %}انضم لآلاف الطلاب اليوم.{% else %}Join thousands of students today.{% endif %}
|
||||
</p>
|
||||
<div class="avatar-group d-flex justify-content-center mt-4">
|
||||
<div style="width: 40px; height: 40px; border-radius: 50%; background: #ccc; border: 2px solid #fff; margin-left: -10px;"></div>
|
||||
<div style="width: 40px; height: 40px; border-radius: 50%; background: #ddd; border: 2px solid #fff; margin-left: -10px;"></div>
|
||||
@ -41,8 +59,12 @@
|
||||
<section id="levels-section" class="subjects-section py-5">
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h2 class="fw-bold">برامجنا التعليمية</h2>
|
||||
<p class="text-muted">استكشف المواد المخصصة لكل مرحلة دراسية.</p>
|
||||
<h2 class="fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}برامجنا التعليمية{% else %}Our Educational Programs{% endif %}
|
||||
</h2>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}استكشف المواد المخصصة لكل مرحلة دراسية.{% else %}Explore subjects tailored for each educational level.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% for level in levels %}
|
||||
@ -52,7 +74,7 @@
|
||||
{{ forloop.counter }}
|
||||
</div>
|
||||
<h3 class="fw-bold mb-0">
|
||||
{{ level.name_ar }}
|
||||
{% if LANGUAGE_CODE == 'ar' %}{{ level.name_ar }}{% else %}{{ level.name_en|default:level.name_ar }}{% endif %}
|
||||
</h3>
|
||||
<hr class="flex-grow-1 ms-4 d-none d-md-block opacity-10">
|
||||
</div>
|
||||
@ -63,21 +85,27 @@
|
||||
<div class="glass-card h-100 p-0 overflow-hidden shadow-sm">
|
||||
<div style="height: 180px; background: {% cycle '#E3F2FD' '#F3E5F5' '#E8F5E9' %}; display: flex; align-items: center; justify-content: center;">
|
||||
{% if subject.image %}
|
||||
<img src="{{ subject.image.url }}" class="img-fluid" alt="{{ subject.name_en }}">
|
||||
<img src="{{ subject.image.url }}" class="img-fluid" alt="{% if LANGUAGE_CODE == 'ar' %}{{ subject.name_ar }}{% else %}{{ subject.name_en }}{% endif %}">
|
||||
{% else %}
|
||||
<span class="display-2" style="opacity: 0.2;">📚</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="p-4">
|
||||
<h4 class="fw-bold mb-3">
|
||||
{{ subject.name_ar }}
|
||||
{% if LANGUAGE_CODE == 'ar' %}{{ subject.name_ar }}{% else %}{{ subject.name_en|default:subject.name_ar }}{% endif %}
|
||||
</h4>
|
||||
<p class="text-muted small mb-4">
|
||||
{{ subject.description_ar|truncatewords:15 }}
|
||||
{% if LANGUAGE_CODE == 'ar' %}
|
||||
{{ subject.description_ar|truncatewords:15 }}
|
||||
{% else %}
|
||||
{{ subject.description_en|default:subject.description_ar|truncatewords:15 }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="h5 fw-bold mb-0 text-primary">${{ subject.price }}</span>
|
||||
<a href="{% url 'subject_detail' subject.pk %}" class="btn btn-primary btn-sm">اشتراك</a>
|
||||
<a href="{% url 'subject_detail' subject.pk %}" class="btn btn-primary btn-sm">
|
||||
{% if LANGUAGE_CODE == 'ar' %}اشتراك{% else %}Subscribe{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -85,7 +113,7 @@
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="alert alert-light border-0 text-center py-4">
|
||||
لا توجد مواد متاحة لهذا المستوى بعد.
|
||||
{% if LANGUAGE_CODE == 'ar' %}لا توجد مواد متاحة لهذا المستوى بعد.{% else %}No subjects available for this level yet.{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@ -99,8 +127,12 @@
|
||||
<section id="teachers-section" class="py-5 bg-light">
|
||||
<div class="container">
|
||||
<div class="text-center mb-5">
|
||||
<h2 class="fw-bold">تعرف على معلمينا</h2>
|
||||
<p class="text-muted">تعلم من نخبة من المعلمين.</p>
|
||||
<h2 class="fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}تعرف على معلمينا{% else %}Meet Our Teachers{% endif %}
|
||||
</h2>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}تعلم من نخبة من المعلمين.{% else %}Learn from elite educators.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 justify-content-center">
|
||||
@ -122,13 +154,15 @@
|
||||
<p class="text-primary small fw-bold mb-3">{{ teacher.specialization|default:"معلم" }}</p>
|
||||
|
||||
<p class="text-muted small mb-4">
|
||||
{{ teacher.bio|default:"لا توجد نبذة."|truncatewords:20 }}
|
||||
{{ teacher.bio|default:"No bio available."|truncatewords:20 }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12 text-center">
|
||||
<p class="text-muted">لا يوجد معلمين حالياً.</p>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}لا يوجد معلمين حالياً.{% else %}No teachers available at the moment.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -141,22 +175,34 @@
|
||||
<div class="col-md-4">
|
||||
<div class="p-4">
|
||||
<div class="mb-3 text-primary h1">🎥</div>
|
||||
<h5 class="fw-bold">دروس مباشرة</h5>
|
||||
<p class="text-muted">انضم لجلسات تفاعلية عبر Google Meet.</p>
|
||||
<h5 class="fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}دروس مباشرة{% else %}Live Lessons{% endif %}
|
||||
</h5>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}انضم لجلسات تفاعلية عبر Google Meet.{% else %}Join interactive sessions via Google Meet.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="p-4">
|
||||
<div class="mb-3 text-primary h1">📁</div>
|
||||
<h5 class="fw-bold">المصادر</h5>
|
||||
<p class="text-muted">الوصول لمواد الدورة عبر Google Drive.</p>
|
||||
<h5 class="fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}المصادر{% else %}Resources{% endif %}
|
||||
</h5>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}الوصول لمواد الدورة عبر Google Drive.{% else %}Access course materials via Google Drive.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="p-4">
|
||||
<div class="mb-3 text-primary h1">💳</div>
|
||||
<h5 class="fw-bold">دفع سهل</h5>
|
||||
<p class="text-muted">دفع آمن عبر بوابة ثواني.</p>
|
||||
<h5 class="fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}دفع سهل{% else %}Easy Payment{% endif %}
|
||||
</h5>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}دفع آمن عبر بوابة ثواني.{% else %}Secure payment via Thawani Gateway.{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block title %}تسجيل الدخول{% endblock %}
|
||||
{% block title %}
|
||||
{% if LANGUAGE_CODE == 'ar' %}تسجيل الدخول{% else %}Login{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container hero-section">
|
||||
@ -9,8 +11,12 @@
|
||||
<div class="col-md-6 col-lg-5">
|
||||
<div class="glass-card p-5">
|
||||
<div class="text-center mb-4">
|
||||
<h2 class="text-primary fw-bold">مرحباً بعودتك</h2>
|
||||
<p class="text-muted">سجل الدخول لمتابعة رحلتك التعليمية</p>
|
||||
<h2 class="text-primary fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}مرحباً بعودتك{% else %}Welcome Back{% endif %}
|
||||
</h2>
|
||||
<p class="text-muted">
|
||||
{% if LANGUAGE_CODE == 'ar' %}سجل الدخول لمتابعة رحلتك التعليمية{% else %}Login to continue your educational journey{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form method="post">
|
||||
@ -18,29 +24,32 @@
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
اسم المستخدم أو كلمة المرور غير صحيحة.
|
||||
{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم أو كلمة المرور غير صحيحة.{% else %}Invalid username or password.{% endif %}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<input type="text" name="username" autofocus autocapitalize="none" autocomplete="username" maxlength="150" required id="id_username" class="form-control" placeholder="اسم المستخدم">
|
||||
<label for="id_username"><i class="fas fa-user me-2"></i>اسم المستخدم</label>
|
||||
<input type="text" name="username" autofocus autocapitalize="none" autocomplete="username" maxlength="150" required id="id_username" class="form-control" placeholder="{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم{% else %}Username{% endif %}">
|
||||
<label for="id_username"><i class="fas fa-user me-2"></i>{% if LANGUAGE_CODE == 'ar' %}اسم المستخدم{% else %}Username{% endif %}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-4">
|
||||
<input type="password" name="password" autocomplete="current-password" required id="id_password" class="form-control" placeholder="كلمة المرور">
|
||||
<label for="id_password"><i class="fas fa-lock me-2"></i>كلمة المرور</label>
|
||||
<input type="password" name="password" autocomplete="current-password" required id="id_password" class="form-control" placeholder="{% if LANGUAGE_CODE == 'ar' %}كلمة المرور{% else %}Password{% endif %}">
|
||||
<label for="id_password"><i class="fas fa-lock me-2"></i>{% if LANGUAGE_CODE == 'ar' %}كلمة المرور{% else %}Password{% endif %}</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100 py-3 fs-5 fw-bold shadow-sm">
|
||||
دخول <i class="fas fa-arrow-left ms-2"></i>
|
||||
{% if LANGUAGE_CODE == 'ar' %}دخول{% else %}Login{% endif %}
|
||||
<i class="fas fa-arrow-left ms-2"></i>
|
||||
</button>
|
||||
|
||||
<div class="text-center mt-4">
|
||||
<p class="text-muted mb-0">
|
||||
ليس لديك حساب؟
|
||||
<a href="{% url 'register_student' %}" class="text-primary text-decoration-none fw-bold">سجل هنا</a>
|
||||
{% if LANGUAGE_CODE == 'ar' %}ليس لديك حساب؟{% else %}Don't have an account?{% endif %}
|
||||
<a href="{% url 'register_student' %}" class="text-primary text-decoration-none fw-bold">
|
||||
{% if LANGUAGE_CODE == 'ar' %}سجل هنا{% else %}Register here{% endif %}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
95
static/js/admin_package.js
Normal file
95
static/js/admin_package.js
Normal file
@ -0,0 +1,95 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
$(function() {
|
||||
console.log("Admin Package JS loaded");
|
||||
|
||||
var $levelSelect = $('#id_classroom');
|
||||
var $subjectSelect = $('#id_subjects');
|
||||
|
||||
// Debug selector finding
|
||||
if (!$levelSelect.length) console.error("Classroom select #id_classroom not found!");
|
||||
if (!$subjectSelect.length) console.error("Subjects select #id_subjects not found!");
|
||||
|
||||
// Check if we are in the admin change form
|
||||
if (!$levelSelect.length || !$subjectSelect.length) return;
|
||||
|
||||
var isArabic = $('html').attr('lang') === 'ar' || $('body').hasClass('rtl');
|
||||
|
||||
function updateSubjects(levelId, selectedValues) {
|
||||
console.log("Updating subjects for level:", levelId);
|
||||
|
||||
if (!levelId) {
|
||||
$subjectSelect.html('');
|
||||
refreshSelectFilter();
|
||||
return;
|
||||
}
|
||||
|
||||
$.getJSON('/ajax/get-subjects-by-level/', {level_id: levelId}, function(data) {
|
||||
console.log("Received subjects:", data);
|
||||
var options = '';
|
||||
$.each(data, function(index, subject) {
|
||||
var selected = '';
|
||||
if (selectedValues && selectedValues.indexOf(subject.id.toString()) !== -1) {
|
||||
selected = ' selected';
|
||||
}
|
||||
var name = isArabic ? subject.name_ar : subject.name_en;
|
||||
options += '<option value="' + subject.id + '"' + selected + '>' + name + '</option>';
|
||||
});
|
||||
$subjectSelect.html(options);
|
||||
refreshSelectFilter();
|
||||
})
|
||||
.fail(function(jqxhr, textStatus, error) {
|
||||
console.error("AJAX Error:", textStatus, error);
|
||||
});
|
||||
}
|
||||
|
||||
function refreshSelectFilter() {
|
||||
var fieldName = 'subjects';
|
||||
// Django's filter_horizontal uses SelectFilter2
|
||||
if (typeof SelectFilter2 !== 'undefined') {
|
||||
console.log("Refreshing SelectFilter2");
|
||||
// Remove the existing widget elements
|
||||
$('.selector').has('#id_' + fieldName + '_from').remove();
|
||||
|
||||
// Re-initialize it
|
||||
SelectFilter2.init('id_' + fieldName, fieldName, false);
|
||||
} else if (typeof SelectFilter !== 'undefined') {
|
||||
console.log("Refreshing SelectFilter (Legacy)");
|
||||
$('.selector').has('#id_' + fieldName + '_from').remove();
|
||||
SelectFilter.init('id_' + fieldName, fieldName, false);
|
||||
} else {
|
||||
console.warn("SelectFilter not found!");
|
||||
}
|
||||
}
|
||||
|
||||
$levelSelect.on('change', function() {
|
||||
console.log("Classroom changed to:", $(this).val());
|
||||
var selectedValues = [];
|
||||
// Reset subjects when classroom changes
|
||||
updateSubjects($(this).val(), []);
|
||||
});
|
||||
|
||||
// If we are editing an existing package
|
||||
if ($levelSelect.val()) {
|
||||
console.log("Initial load with classroom:", $levelSelect.val());
|
||||
// Get currently selected values
|
||||
var selectedValues = [];
|
||||
|
||||
// Try to get from the "chosen" side of filter_horizontal if it exists
|
||||
// Since this runs on page load, standard Django might have already rendered the widget
|
||||
$('#id_subjects_to option').each(function() {
|
||||
selectedValues.push($(this).val());
|
||||
});
|
||||
|
||||
// Fallback if widget not yet initialized or for simple select
|
||||
if (selectedValues.length === 0) {
|
||||
$subjectSelect.find('option:selected').each(function() {
|
||||
selectedValues.push($(this).val());
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Initial selected values:", selectedValues);
|
||||
updateSubjects($levelSelect.val(), selectedValues);
|
||||
}
|
||||
});
|
||||
})(django.jQuery);
|
||||
95
staticfiles/js/admin_package.js
Normal file
95
staticfiles/js/admin_package.js
Normal file
@ -0,0 +1,95 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
$(function() {
|
||||
console.log("Admin Package JS loaded");
|
||||
|
||||
var $levelSelect = $('#id_classroom');
|
||||
var $subjectSelect = $('#id_subjects');
|
||||
|
||||
// Debug selector finding
|
||||
if (!$levelSelect.length) console.error("Classroom select #id_classroom not found!");
|
||||
if (!$subjectSelect.length) console.error("Subjects select #id_subjects not found!");
|
||||
|
||||
// Check if we are in the admin change form
|
||||
if (!$levelSelect.length || !$subjectSelect.length) return;
|
||||
|
||||
var isArabic = $('html').attr('lang') === 'ar' || $('body').hasClass('rtl');
|
||||
|
||||
function updateSubjects(levelId, selectedValues) {
|
||||
console.log("Updating subjects for level:", levelId);
|
||||
|
||||
if (!levelId) {
|
||||
$subjectSelect.html('');
|
||||
refreshSelectFilter();
|
||||
return;
|
||||
}
|
||||
|
||||
$.getJSON('/ajax/get-subjects-by-level/', {level_id: levelId}, function(data) {
|
||||
console.log("Received subjects:", data);
|
||||
var options = '';
|
||||
$.each(data, function(index, subject) {
|
||||
var selected = '';
|
||||
if (selectedValues && selectedValues.indexOf(subject.id.toString()) !== -1) {
|
||||
selected = ' selected';
|
||||
}
|
||||
var name = isArabic ? subject.name_ar : subject.name_en;
|
||||
options += '<option value="' + subject.id + '"' + selected + '>' + name + '</option>';
|
||||
});
|
||||
$subjectSelect.html(options);
|
||||
refreshSelectFilter();
|
||||
})
|
||||
.fail(function(jqxhr, textStatus, error) {
|
||||
console.error("AJAX Error:", textStatus, error);
|
||||
});
|
||||
}
|
||||
|
||||
function refreshSelectFilter() {
|
||||
var fieldName = 'subjects';
|
||||
// Django's filter_horizontal uses SelectFilter2
|
||||
if (typeof SelectFilter2 !== 'undefined') {
|
||||
console.log("Refreshing SelectFilter2");
|
||||
// Remove the existing widget elements
|
||||
$('.selector').has('#id_' + fieldName + '_from').remove();
|
||||
|
||||
// Re-initialize it
|
||||
SelectFilter2.init('id_' + fieldName, fieldName, false);
|
||||
} else if (typeof SelectFilter !== 'undefined') {
|
||||
console.log("Refreshing SelectFilter (Legacy)");
|
||||
$('.selector').has('#id_' + fieldName + '_from').remove();
|
||||
SelectFilter.init('id_' + fieldName, fieldName, false);
|
||||
} else {
|
||||
console.warn("SelectFilter not found!");
|
||||
}
|
||||
}
|
||||
|
||||
$levelSelect.on('change', function() {
|
||||
console.log("Classroom changed to:", $(this).val());
|
||||
var selectedValues = [];
|
||||
// Reset subjects when classroom changes
|
||||
updateSubjects($(this).val(), []);
|
||||
});
|
||||
|
||||
// If we are editing an existing package
|
||||
if ($levelSelect.val()) {
|
||||
console.log("Initial load with classroom:", $levelSelect.val());
|
||||
// Get currently selected values
|
||||
var selectedValues = [];
|
||||
|
||||
// Try to get from the "chosen" side of filter_horizontal if it exists
|
||||
// Since this runs on page load, standard Django might have already rendered the widget
|
||||
$('#id_subjects_to option').each(function() {
|
||||
selectedValues.push($(this).val());
|
||||
});
|
||||
|
||||
// Fallback if widget not yet initialized or for simple select
|
||||
if (selectedValues.length === 0) {
|
||||
$subjectSelect.find('option:selected').each(function() {
|
||||
selectedValues.push($(this).val());
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Initial selected values:", selectedValues);
|
||||
updateSubjects($levelSelect.val(), selectedValues);
|
||||
}
|
||||
});
|
||||
})(django.jQuery);
|
||||
BIN
staticfiles/pasted-20260204-135454-c72e44de.png
Normal file
BIN
staticfiles/pasted-20260204-135454-c72e44de.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 202 KiB |
Loading…
x
Reference in New Issue
Block a user