diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 36d2b33..c9f108d 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 640695f..c0eda85 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 82e52a2..5941460 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 1fb517a..502dd53 100644 --- a/core/admin.py +++ b/core/admin.py @@ -4,7 +4,7 @@ from django.shortcuts import render from django.http import HttpResponseRedirect from django.contrib import messages from django.utils.translation import gettext_lazy as _ -from .models import Profile, Truck, Shipment, Bid, Message, WhatsAppConfig, Country, City, TruckType, AppSetting, Banner +from .models import Profile, Truck, Shipment, Bid, Message, WhatsAppConfig, Country, City, TruckType, AppSetting, Banner, HomeSection from .whatsapp import send_whatsapp_message @admin.register(Country) @@ -102,4 +102,11 @@ class AppSettingAdmin(admin.ModelAdmin): class BannerAdmin(admin.ModelAdmin): list_display = ('title', 'order', 'is_active', 'created_at') list_editable = ('order', 'is_active') - search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar') \ No newline at end of file + search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar') + +@admin.register(HomeSection) +class HomeSectionAdmin(admin.ModelAdmin): + list_display = ('title', 'section_type', 'order', 'is_active') + list_editable = ('order', 'is_active') + list_filter = ('section_type', 'is_active', 'background_color') + search_fields = ('title', 'title_ar', 'subtitle', 'subtitle_ar', 'content', 'content_ar') diff --git a/core/migrations/0016_homesection.py b/core/migrations/0016_homesection.py new file mode 100644 index 0000000..8d1aa2c --- /dev/null +++ b/core/migrations/0016_homesection.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2.7 on 2026-01-24 03:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0015_banner'), + ] + + operations = [ + migrations.CreateModel( + name='HomeSection', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200, verbose_name='Title (EN)')), + ('title_ar', models.CharField(blank=True, max_length=200, verbose_name='Title (AR)')), + ('subtitle', models.CharField(blank=True, max_length=255, verbose_name='Subtitle (EN)')), + ('subtitle_ar', models.CharField(blank=True, max_length=255, verbose_name='Subtitle (AR)')), + ('content', models.TextField(blank=True, verbose_name='Content (EN)')), + ('content_ar', models.TextField(blank=True, verbose_name='Content (AR)')), + ('image', models.ImageField(blank=True, null=True, upload_to='home_sections/', verbose_name='Image')), + ('order', models.PositiveIntegerField(default=0, verbose_name='Order')), + ('is_active', models.BooleanField(default=True, verbose_name='Is Active')), + ('section_type', models.CharField(choices=[('SIMPLE', 'Simple Text & Image'), ('FEATURES', 'Features List'), ('CTA', 'Call to Action')], default='SIMPLE', max_length=20)), + ('background_color', models.CharField(default='white', help_text='e.g. white, light, primary', max_length=50)), + ], + options={ + 'verbose_name': 'Home Section', + 'verbose_name_plural': 'Home Sections', + 'ordering': ['order'], + }, + ), + ] diff --git a/core/migrations/__pycache__/0016_homesection.cpython-311.pyc b/core/migrations/__pycache__/0016_homesection.cpython-311.pyc new file mode 100644 index 0000000..a42075d Binary files /dev/null and b/core/migrations/__pycache__/0016_homesection.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 36e9cda..ec465ab 100644 --- a/core/models.py +++ b/core/models.py @@ -279,6 +279,50 @@ class Banner(models.Model): return self.subtitle_ar return self.subtitle +class HomeSection(models.Model): + SECTION_TYPES = ( + ('SIMPLE', _('Simple Text & Image')), + ('FEATURES', _('Features List')), + ('CTA', _('Call to Action')), + ) + title = models.CharField(_('Title (EN)'), max_length=200) + title_ar = models.CharField(_('Title (AR)'), max_length=200, blank=True) + subtitle = models.CharField(_('Subtitle (EN)'), max_length=255, blank=True) + subtitle_ar = models.CharField(_('Subtitle (AR)'), max_length=255, blank=True) + content = models.TextField(_('Content (EN)'), blank=True) + content_ar = models.TextField(_('Content (AR)'), blank=True) + image = models.ImageField(_('Image'), upload_to='home_sections/', blank=True, null=True) + order = models.PositiveIntegerField(_('Order'), default=0) + is_active = models.BooleanField(_('Is Active'), default=True) + section_type = models.CharField(max_length=20, choices=SECTION_TYPES, default='SIMPLE') + background_color = models.CharField(max_length=50, default='white', help_text="e.g. white, light, primary") + + class Meta: + verbose_name = _('Home Section') + verbose_name_plural = _('Home Sections') + ordering = ['order'] + + def __str__(self): + return self.title + + @property + def display_title(self): + if get_language() == 'ar' and self.title_ar: + return self.title_ar + return self.title + + @property + def display_subtitle(self): + if get_language() == 'ar' and self.subtitle_ar: + return self.subtitle_ar + return self.subtitle + + @property + def display_content(self): + if get_language() == 'ar' and self.content_ar: + return self.content_ar + return self.content + @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: @@ -307,4 +351,4 @@ def sync_user_groups(sender, instance, **kwargs): instance.user.groups.remove(*other_groups) # Add user to the correct group - instance.user.groups.add(group) + instance.user.groups.add(group) \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index b8a78a4..7c7ada1 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -50,7 +50,7 @@ {% endif %} - + {% if not banners %}
@@ -76,6 +76,51 @@
{% endif %} + +{% for section in home_sections %} +
+
+ {% if section.section_type == 'SIMPLE' %} +
+
+

{{ section.display_title }}

+ {% if section.display_subtitle %} +
{{ section.display_subtitle }}
+ {% endif %} +
+ {{ section.display_content|linebreaks }} +
+
+ {% if section.image %} +
+ {{ section.display_title }} +
+ {% endif %} +
+ {% elif section.section_type == 'CTA' %} +
+

{{ section.display_title }}

+ {% if section.display_subtitle %} +

{{ section.display_subtitle }}

+ {% endif %} +
+ {{ section.display_content|linebreaks }} +
+ {% trans "Get Started" %} +
+ {% elif section.section_type == 'FEATURES' %} +
+

{{ section.display_title }}

+

{{ section.display_subtitle }}

+
+
+ {{ section.display_content|safe }} +
+ {% endif %} +
+
+{% endfor %} +
@@ -189,4 +234,4 @@
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/core/views.py b/core/views.py index 700236e..9a89dbc 100644 --- a/core/views.py +++ b/core/views.py @@ -2,7 +2,7 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib.auth import login, authenticate, logout from django.utils import timezone -from .models import Profile, Truck, Shipment, Bid, Message, OTPCode, Country, City, AppSetting, Banner +from .models import Profile, Truck, Shipment, Bid, Message, OTPCode, Country, City, AppSetting, Banner, HomeSection from .forms import TruckForm, ShipmentForm, BidForm, UserRegistrationForm, OTPVerifyForm, ShipperOfferForm from django.contrib import messages from django.utils.translation import gettext as _ @@ -14,9 +14,11 @@ from django.contrib.auth.forms import AuthenticationForm def home(request): """Render the landing screen for MASAR CARGO.""" banners = Banner.objects.filter(is_active=True) + home_sections = HomeSection.objects.filter(is_active=True).order_by('order') context = { "deployment_timestamp": timezone.now().timestamp(), "banners": banners, + "home_sections": home_sections, } return render(request, "core/index.html", context) @@ -399,4 +401,4 @@ def terms_of_service(request): 'content': app_settings.terms_of_service if app_settings else _("Terms of service are coming soon.") } } - return render(request, 'core/article_detail.html', context) \ No newline at end of file + return render(request, 'core/article_detail.html', context) diff --git a/media/app/ahlalalkhair_logo.jpg b/media/app/ahlalalkhair_logo.jpg new file mode 100644 index 0000000..7d677ac Binary files /dev/null and b/media/app/ahlalalkhair_logo.jpg differ diff --git a/media/app/masarlogo.jpg b/media/app/masarlogo.jpg new file mode 100644 index 0000000..f1a0ae3 Binary files /dev/null and b/media/app/masarlogo.jpg differ