diff --git a/config/__pycache__/__init__.cpython-311.pyc b/config/__pycache__/__init__.cpython-311.pyc
index 423a636..89a21c8 100644
Binary files a/config/__pycache__/__init__.cpython-311.pyc and b/config/__pycache__/__init__.cpython-311.pyc differ
diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc
index 96bce55..e97298a 100644
Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ
diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc
index 0b85e94..cc6f4b1 100644
Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ
diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc
index 9c49e09..a54dacc 100644
Binary files a/config/__pycache__/wsgi.cpython-311.pyc and b/config/__pycache__/wsgi.cpython-311.pyc differ
diff --git a/config/settings.py b/config/settings.py
index 291d043..066e1f2 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -42,6 +42,7 @@ SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = "None"
CSRF_COOKIE_SAMESITE = "None"
+SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
@@ -61,6 +62,7 @@ INSTALLED_APPS = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -133,7 +135,7 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
-LANGUAGE_CODE = 'en-us'
+LANGUAGE_CODE = 'en'
TIME_ZONE = 'UTC'
@@ -180,3 +182,17 @@ if EMAIL_USE_SSL:
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
+from django.utils.translation import gettext_lazy as _
+
+LANGUAGES = [
+ ('en', _('English')),
+ ('ar', _('Arabic')),
+]
+
+LOCALE_PATHS = [
+ BASE_DIR / 'locale',
+]
+
+MEDIA_URL = 'media/'
+MEDIA_ROOT = BASE_DIR / 'media'
diff --git a/config/urls.py b/config/urls.py
index bcfc074..cfd9fd4 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -1,25 +1,10 @@
-"""
-URL configuration for config project.
-
-The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/5.2/topics/http/urls/
-Examples:
-Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: path('', views.home, name='home')
-Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
-Including another URLconf
- 1. Import the include() function: from django.urls import include, path
- 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
-"""
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
+ path('i18n/', include('django.conf.urls.i18n')),
path("admin/", admin.site.urls),
path("", include("core.urls")),
]
@@ -27,3 +12,4 @@ urlpatterns = [
if settings.DEBUG:
urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets")
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
diff --git a/core/__pycache__/__init__.cpython-311.pyc b/core/__pycache__/__init__.cpython-311.pyc
index 74b1112..d90f7be 100644
Binary files a/core/__pycache__/__init__.cpython-311.pyc and b/core/__pycache__/__init__.cpython-311.pyc differ
diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc
index a5ed392..214e066 100644
Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ
diff --git a/core/__pycache__/apps.cpython-311.pyc b/core/__pycache__/apps.cpython-311.pyc
index 6f131d4..f24c7b7 100644
Binary files a/core/__pycache__/apps.cpython-311.pyc and b/core/__pycache__/apps.cpython-311.pyc differ
diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc
index 75bf223..e9a897c 100644
Binary files a/core/__pycache__/context_processors.cpython-311.pyc and b/core/__pycache__/context_processors.cpython-311.pyc differ
diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc
index e061640..6eff269 100644
Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ
diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc
index 5a69659..244821d 100644
Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ
diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc
index 2a36fd6..e5c3557 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 8c38f3f..3e1ca68 100644
--- a/core/admin.py
+++ b/core/admin.py
@@ -1,3 +1,30 @@
from django.contrib import admin
+from .models import Profile, Truck, Shipment, Bid, Message
-# Register your models here.
+@admin.register(Profile)
+class ProfileAdmin(admin.ModelAdmin):
+ list_display = ('user', 'role', 'phone_number')
+ list_filter = ('role',)
+ search_fields = ('user__username', 'phone_number')
+
+@admin.register(Truck)
+class TruckAdmin(admin.ModelAdmin):
+ list_display = ('truck_type', 'model', 'plate_no', 'owner', 'load_capacity')
+ search_fields = ('plate_no', 'owner__username', 'truck_type')
+
+@admin.register(Shipment)
+class ShipmentAdmin(admin.ModelAdmin):
+ list_display = ('origin', 'destination', 'shipper', 'status', 'delivery_date')
+ list_filter = ('status', 'delivery_date')
+ search_fields = ('origin', 'destination', 'shipper__username')
+
+@admin.register(Bid)
+class BidAdmin(admin.ModelAdmin):
+ list_display = ('shipment', 'truck_owner', 'amount', 'status')
+ list_filter = ('status',)
+ search_fields = ('shipment__origin', 'shipment__destination', 'truck_owner__username')
+
+@admin.register(Message)
+class MessageAdmin(admin.ModelAdmin):
+ list_display = ('shipment', 'sender', 'timestamp')
+ search_fields = ('content', 'sender__username')
diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py
new file mode 100644
index 0000000..b83d0bc
--- /dev/null
+++ b/core/migrations/0001_initial.py
@@ -0,0 +1,26 @@
+# Generated by Django 5.2.7 on 2026-01-23 07:18
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Profile',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('role', models.CharField(choices=[('SHIPPER', 'Shipper (Need Goods Moved)'), ('TRUCK_OWNER', 'Truck Owner (Service Provider)'), ('ADMIN', 'Administrator')], default='SHIPPER', max_length=20)),
+ ('phone_number', models.CharField(blank=True, max_length=20)),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/core/migrations/0002_shipment_message_truck_shipment_assigned_truck_bid.py b/core/migrations/0002_shipment_message_truck_shipment_assigned_truck_bid.py
new file mode 100644
index 0000000..a8a2cef
--- /dev/null
+++ b/core/migrations/0002_shipment_message_truck_shipment_assigned_truck_bid.py
@@ -0,0 +1,76 @@
+# Generated by Django 5.2.7 on 2026-01-23 09:01
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Shipment',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('description', models.TextField(verbose_name='Goods Description')),
+ ('weight', models.CharField(max_length=100, verbose_name='Weight/Volume')),
+ ('origin', models.CharField(max_length=255, verbose_name='Origin')),
+ ('destination', models.CharField(max_length=255, verbose_name='Destination')),
+ ('delivery_date', models.DateField(verbose_name='Requested Delivery Date')),
+ ('status', models.CharField(choices=[('OPEN', 'Open for Bids'), ('IN_PROGRESS', 'In Progress'), ('COMPLETED', 'Completed'), ('CANCELLED', 'Cancelled')], default='OPEN', max_length=20)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('shipper', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shipments', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Message',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('content', models.TextField()),
+ ('timestamp', models.DateTimeField(auto_now_add=True)),
+ ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_messages', to=settings.AUTH_USER_MODEL)),
+ ('shipment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='core.shipment')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Truck',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('truck_type', models.CharField(max_length=100, verbose_name='Truck Type')),
+ ('model', models.CharField(max_length=100, verbose_name='Model')),
+ ('year', models.PositiveIntegerField(verbose_name='Year')),
+ ('plate_no', models.CharField(max_length=50, verbose_name='Plate No')),
+ ('load_capacity', models.CharField(max_length=100, verbose_name='Load Capacity')),
+ ('color', models.CharField(max_length=50, verbose_name='Color')),
+ ('truck_picture', models.ImageField(blank=True, null=True, upload_to='trucks/', verbose_name='Truck Picture')),
+ ('registration_front', models.ImageField(blank=True, null=True, upload_to='docs/', verbose_name='Registration Front')),
+ ('registration_back', models.ImageField(blank=True, null=True, upload_to='docs/', verbose_name='Registration Back')),
+ ('driver_license', models.ImageField(blank=True, null=True, upload_to='docs/', verbose_name='Driver License')),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trucks', to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.AddField(
+ model_name='shipment',
+ name='assigned_truck',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_shipments', to='core.truck'),
+ ),
+ migrations.CreateModel(
+ name='Bid',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('amount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Offer Amount')),
+ ('comments', models.TextField(blank=True, verbose_name='Comments')),
+ ('status', models.CharField(choices=[('PENDING', 'Pending'), ('ACCEPTED', 'Accepted'), ('REJECTED', 'Rejected')], default='PENDING', max_length=20)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('truck_owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bids', to=settings.AUTH_USER_MODEL)),
+ ('shipment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bids', to='core.shipment')),
+ ('truck', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.truck')),
+ ],
+ ),
+ ]
diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc
new file mode 100644
index 0000000..ea4016a
Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ
diff --git a/core/migrations/__pycache__/0002_shipment_message_truck_shipment_assigned_truck_bid.cpython-311.pyc b/core/migrations/__pycache__/0002_shipment_message_truck_shipment_assigned_truck_bid.cpython-311.pyc
new file mode 100644
index 0000000..ef3f7ed
Binary files /dev/null and b/core/migrations/__pycache__/0002_shipment_message_truck_shipment_assigned_truck_bid.cpython-311.pyc differ
diff --git a/core/migrations/__pycache__/__init__.cpython-311.pyc b/core/migrations/__pycache__/__init__.cpython-311.pyc
index 9c833c8..88b26f9 100644
Binary files a/core/migrations/__pycache__/__init__.cpython-311.pyc and b/core/migrations/__pycache__/__init__.cpython-311.pyc differ
diff --git a/core/models.py b/core/models.py
index 71a8362..de81f2d 100644
--- a/core/models.py
+++ b/core/models.py
@@ -1,3 +1,99 @@
from django.db import models
+from django.contrib.auth.models import User
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from django.utils.translation import gettext_lazy as _
-# Create your models here.
+class Profile(models.Model):
+ ROLE_CHOICES = (
+ ('SHIPPER', _('Shipper (Need Goods Moved)')),
+ ('TRUCK_OWNER', _('Truck Owner (Service Provider)')),
+ ('ADMIN', _('Administrator')),
+ )
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
+ role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='SHIPPER')
+ phone_number = models.CharField(max_length=20, blank=True)
+
+ def __str__(self):
+ return f"{self.user.username} - {self.role}"
+
+class Truck(models.Model):
+ owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='trucks')
+ truck_type = models.CharField(_('Truck Type'), max_length=100)
+ model = models.CharField(_('Model'), max_length=100)
+ year = models.PositiveIntegerField(_('Year'))
+ plate_no = models.CharField(_('Plate No'), max_length=50)
+ load_capacity = models.CharField(_('Load Capacity'), max_length=100)
+ color = models.CharField(_('Color'), max_length=50)
+
+ # Pictures
+ truck_picture = models.ImageField(_('Truck Picture'), upload_to='trucks/', blank=True, null=True)
+ registration_front = models.ImageField(_('Registration Front'), upload_to='docs/', blank=True, null=True)
+ registration_back = models.ImageField(_('Registration Back'), upload_to='docs/', blank=True, null=True)
+ driver_license = models.ImageField(_('Driver License'), upload_to='docs/', blank=True, null=True)
+
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return f"{self.truck_type} - {self.plate_no}"
+
+class Shipment(models.Model):
+ STATUS_CHOICES = (
+ ('OPEN', _('Open for Bids')),
+ ('IN_PROGRESS', _('In Progress')),
+ ('COMPLETED', _('Completed')),
+ ('CANCELLED', _('Cancelled')),
+ )
+ shipper = models.ForeignKey(User, on_delete=models.CASCADE, related_name='shipments')
+ description = models.TextField(_('Goods Description'))
+ weight = models.CharField(_('Weight/Volume'), max_length=100)
+ origin = models.CharField(_('Origin'), max_length=255)
+ destination = models.CharField(_('Destination'), max_length=255)
+ delivery_date = models.DateField(_('Requested Delivery Date'))
+ status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='OPEN')
+
+ assigned_truck = models.ForeignKey(Truck, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_shipments')
+
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return f"{self.origin} to {self.destination} - {self.status}"
+
+class Bid(models.Model):
+ STATUS_CHOICES = (
+ ('PENDING', _('Pending')),
+ ('ACCEPTED', _('Accepted')),
+ ('REJECTED', _('Rejected')),
+ )
+ shipment = models.ForeignKey(Shipment, on_delete=models.CASCADE, related_name='bids')
+ truck_owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bids')
+ truck = models.ForeignKey(Truck, on_delete=models.CASCADE)
+ amount = models.DecimalField(_('Offer Amount'), max_digits=10, decimal_places=2)
+ comments = models.TextField(_('Comments'), blank=True)
+ status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='PENDING')
+
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return f"Bid by {self.truck_owner.username} for {self.shipment}"
+
+class Message(models.Model):
+ shipment = models.ForeignKey(Shipment, on_delete=models.CASCADE, related_name='messages')
+ sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
+ content = models.TextField()
+ timestamp = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return f"From {self.sender.username} at {self.timestamp}"
+
+@receiver(post_save, sender=User)
+def create_user_profile(sender, instance, created, **kwargs):
+ if created:
+ Profile.objects.create(user=instance)
+
+@receiver(post_save, sender=User)
+def save_user_profile(sender, instance, **kwargs):
+ if hasattr(instance, 'profile'):
+ instance.profile.save()
+ else:
+ Profile.objects.create(user=instance)
diff --git a/core/templates/base.html b/core/templates/base.html
index 1e7e5fb..7ea38ab 100644
--- a/core/templates/base.html
+++ b/core/templates/base.html
@@ -1,25 +1,156 @@
+{% load static i18n %}
-
+
- {% block title %}Knowledge Base{% endblock %}
+
+ {% block title %}MASAR CARGO{% endblock %}
{% if project_description %}
-
-
{% endif %}
- {% if project_image_url %}
-
-
+
+
+
+ {% if request.LANGUAGE_CODE == 'ar' %}
+
{% endif %}
- {% load static %}
+
+
+
+
{% block head %}{% endblock %}
+
- {% block content %}{% endblock %}
+
+
+ {% if messages %}
+
+ {% for message in messages %}
+
+ {{ message }}
+
+
+ {% endfor %}
+
+ {% endif %}
+
+
+ {% block content %}{% endblock %}
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/core/templates/core/index.html b/core/templates/core/index.html
index faec813..23febdf 100644
--- a/core/templates/core/index.html
+++ b/core/templates/core/index.html
@@ -1,145 +1,142 @@
-{% extends "base.html" %}
-
-{% block title %}{{ project_name }}{% endblock %}
-
-{% block head %}
-
-
-
-
-{% endblock %}
+{% extends 'base.html' %}
+{% load i18n static %}
{% block content %}
-
-
-
Analyzing your requirements and generating your app…
-
-
Loading…
+
+
+
+
+
+
+ {% trans "Smart Cargo Solutions" %}
+ {% trans "Locally & Abroad" %}
+
+
+ {% trans "The most reliable platform connecting shippers with truck owners across the region. Transparent, fast, and secure." %}
+
+
+
+
+

+
+
- AppWizzy AI is collecting your requirements and applying the first changes.
- This page will refresh automatically as the plan is implemented.
-
- Runtime: Django {{ django_version }} · Python {{ python_version }}
- — UTC {{ current_time|date:"Y-m-d H:i:s" }}
-
-
-
-
+
+
+
+
+
+
+
{% trans "How would you like to use MASAR?" %}
+
{% trans "Choose your path to get started with our platform." %}
+
+
+
+
+
+
+
+
+
{% trans "I am a Shipper" %}
+
+ {% trans "I need to move goods locally or abroad. Post your shipment, receive offers from verified drivers, and track your cargo in real-time." %}
+
+
+ - {% trans "Post shipments easily" %}
+ - {% trans "Compare competitive bids" %}
+ - {% trans "Real-time tracking" %}
+
+
{% trans "Find a Truck" %}
+
+
+
+
+
+
+
+
+
{% trans "I am a Truck Owner" %}
+
+ {% trans "I have trucks and want to find cargo to transport. Register your fleet, bid on available jobs, and grow your business." %}
+
+
+ - {% trans "Access daily cargo leads" %}
+ - {% trans "Flexible bidding system" %}
+ - {% trans "Direct chat with shippers" %}
+
+
{% trans "Register Your Truck" %}
+
+
+
+
+
+
+
+
+
+
+
+
{% trans "Everything you need for seamless logistics" %}
+
+
+
+
{% trans "WhatsApp Integration" %}
+
{% trans "Receive instant updates and communicate easily via WhatsApp API." %}
+
+
+
+
+
+
{% trans "Multilingual Support" %}
+
{% trans "Fully accessible in both Arabic and English for all users." %}
+
+
+
+
+
+
{% trans "Secure Documentation" %}
+
{% trans "Digital verification of truck registration and driver licenses." %}
+
+
+
+
+
+
+

+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
{% trans "Ready to move your cargo?" %}
+
{% trans "Join thousands of shippers and drivers on MASAR today." %}
+
{% trans "Join Now" %}
+
+
+
+
{% endblock %}
\ No newline at end of file
diff --git a/core/templates/core/marketplace.html b/core/templates/core/marketplace.html
new file mode 100644
index 0000000..d3c8358
--- /dev/null
+++ b/core/templates/core/marketplace.html
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
{% trans "Shipment Marketplace" %}
+
+ {% for shipment in shipments %}
+
+
+
+
+ {% trans "Open for Bids" %}
+ {{ shipment.created_at|timesince }} {% trans "ago" %}
+
+
{{ shipment.origin }} {{ shipment.destination }}
+
{{ shipment.description|truncatechars:100 }}
+
+
+ {% trans "Weight" %}
+ {{ shipment.weight }}
+
+
+ {% trans "Delivery Date" %}
+ {{ shipment.delivery_date }}
+
+
+
{% trans "Place an Offer" %}
+
+
+
+ {% empty %}
+
+
{% trans "No shipments available at the moment." %}
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/core/templates/core/place_bid.html b/core/templates/core/place_bid.html
new file mode 100644
index 0000000..8a4e79e
--- /dev/null
+++ b/core/templates/core/place_bid.html
@@ -0,0 +1,51 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
{% trans "Place an Offer" %}
+
+ {% trans "Shipment:" %} {{ shipment.origin }} to {{ shipment.destination }}
+ {% trans "Goods:" %} {{ shipment.description }}
+
+
+ {% if trucks %}
+
+ {% else %}
+
+
{% trans "You must register a truck before placing a bid." %}
+
{% trans "Register Truck Now" %}
+
+ {% endif %}
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/post_shipment.html b/core/templates/core/post_shipment.html
new file mode 100644
index 0000000..4a3303e
--- /dev/null
+++ b/core/templates/core/post_shipment.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
{% trans "Post a New Shipment" %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/shipment_detail.html b/core/templates/core/shipment_detail.html
new file mode 100644
index 0000000..e87b32e
--- /dev/null
+++ b/core/templates/core/shipment_detail.html
@@ -0,0 +1,101 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
+
{{ shipment.origin }} {{ shipment.destination }}
+
+ {{ shipment.get_status_display }}
+
+
+
+
{% trans "Details" %}
+
{{ shipment.description }}
+
+
+ {% trans "Weight" %}
+ {{ shipment.weight }}
+
+
+ {% trans "Delivery Date" %}
+ {{ shipment.delivery_date }}
+
+
+
+
+
+ {% if user == shipment.shipper and shipment.status == 'OPEN' %}
+
+
+
+
+
+
+
+ | {% trans "Truck Owner" %} |
+ {% trans "Truck" %} |
+ {% trans "Amount" %} |
+ {% trans "Action" %} |
+
+
+
+ {% for bid in bids %}
+
+ | {{ bid.truck_owner.username }} |
+ {{ bid.truck.truck_type }} |
+ ${{ bid.amount }} |
+
+ {% trans "Accept" %}
+ |
+
+ {% empty %}
+
+ | {% trans "No bids received yet." %} |
+
+ {% endfor %}
+
+
+
+
+
+ {% endif %}
+
+ {% if shipment.status == 'IN_PROGRESS' %}
+
+
+
+ {% trans "Shipment in progress!" %}
+ {% trans "Assigned Truck:" %} {{ shipment.assigned_truck.truck_type }} ({{ shipment.assigned_truck.plate_no }})
+
+
+
+ {% endif %}
+
+
+
+
+
+
{% trans "Contact Information" %}
+
+ {% trans "Shipper:" %} {{ shipment.shipper.username }}
+ {% if shipment.status == 'IN_PROGRESS' %}
+ {% trans "Phone:" %} {{ shipment.shipper.profile.phone_number }}
+ {% endif %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/shipper_dashboard.html b/core/templates/core/shipper_dashboard.html
new file mode 100644
index 0000000..9672079
--- /dev/null
+++ b/core/templates/core/shipper_dashboard.html
@@ -0,0 +1,61 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
{% trans "Shipper Dashboard" %}
+
+ {% trans "Post New Shipment" %}
+
+
+
+
+
+
+
+
+
+
+
+
+ | {% trans "Description" %} |
+ {% trans "Route" %} |
+ {% trans "Delivery Date" %} |
+ {% trans "Status" %} |
+ {% trans "Bids" %} |
+ {% trans "Action" %} |
+
+
+
+ {% for shipment in shipments %}
+
+ | {{ shipment.description|truncatechars:30 }} |
+ {{ shipment.origin }} {{ shipment.destination }} |
+ {{ shipment.delivery_date }} |
+
+
+ {{ shipment.get_status_display }}
+
+ |
+ {{ shipment.bids.count }} |
+
+ {% trans "View Details" %}
+ |
+
+ {% empty %}
+
+ | {% trans "No shipments posted yet." %} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/truck_owner_dashboard.html b/core/templates/core/truck_owner_dashboard.html
new file mode 100644
index 0000000..919e63a
--- /dev/null
+++ b/core/templates/core/truck_owner_dashboard.html
@@ -0,0 +1,79 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
{% trans "Truck Owner Dashboard" %}
+
+
+
+
+
+
+
+
+ {% if trucks %}
+
+ {% for truck in trucks %}
+ -
+ {{ truck.truck_type }} - {{ truck.plate_no }}
+ {{ truck.load_capacity }}
+
+ {% endfor %}
+
+ {% else %}
+
{% trans "No trucks registered." %}
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+ | {% trans "Shipment" %} |
+ {% trans "Amount" %} |
+ {% trans "Status" %} |
+
+
+
+ {% for bid in bids %}
+
+ | {{ bid.shipment.origin }} - {{ bid.shipment.destination }} |
+ {{ bid.amount }} |
+
+
+ {{ bid.get_status_display }}
+
+ |
+
+ {% empty %}
+
+ | {% trans "No bids placed." %} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/truck_register.html b/core/templates/core/truck_register.html
new file mode 100644
index 0000000..c3ac686
--- /dev/null
+++ b/core/templates/core/truck_register.html
@@ -0,0 +1,73 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
{% trans "Register a Truck" %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/registration/login.html b/core/templates/registration/login.html
new file mode 100644
index 0000000..0f5dc9d
--- /dev/null
+++ b/core/templates/registration/login.html
@@ -0,0 +1,33 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
+
{% trans "Login" %}
+
+
+
{% trans "Don't have an account?" %} {% trans "Register" %}
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/registration/register.html b/core/templates/registration/register.html
new file mode 100644
index 0000000..b5eab21
--- /dev/null
+++ b/core/templates/registration/register.html
@@ -0,0 +1,40 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+
+
+
+
{% trans "Create your account" %}
+
+
+
{% trans "Already have an account?" %} {% trans "Login" %}
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/core/urls.py b/core/urls.py
index 6299e3d..ba2a209 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -1,7 +1,17 @@
from django.urls import path
-
-from .views import home
+from django.contrib.auth import views as auth_views
+from . import views
urlpatterns = [
- path("", home, name="home"),
-]
+ path("", views.home, name="home"),
+ path("register/", views.register, name="register"),
+ path("login/", auth_views.LoginView.as_view(), name="login"),
+ path("logout/", auth_views.LogoutView.as_view(), name="logout"),
+ path("dashboard/", views.dashboard, name="dashboard"),
+ path("truck/register/", views.truck_register, name="truck_register"),
+ path("shipment/post/", views.post_shipment, name="post_shipment"),
+ path("marketplace/", views.marketplace, name="marketplace"),
+ path("shipment/
/", views.shipment_detail, name="shipment_detail"),
+ path("shipment//bid/", views.place_bid, name="place_bid"),
+ path("bid//accept/", views.accept_bid, name="accept_bid"),
+]
\ No newline at end of file
diff --git a/core/views.py b/core/views.py
index c9aed12..e03d3f5 100644
--- a/core/views.py
+++ b/core/views.py
@@ -1,25 +1,172 @@
-import os
-import platform
-
-from django import get_version as django_version
-from django.shortcuts import render
+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
+from django.contrib.auth.forms import UserCreationForm
from django.utils import timezone
-
+from .models import Profile, Truck, Shipment, Bid, Message
+from django.contrib import messages
+from django.utils.translation import gettext as _
+from django.db.models import Q
def home(request):
- """Render the landing screen with loader and environment details."""
- host_name = request.get_host().lower()
- agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
- now = timezone.now()
-
+ """Render the landing screen for MASAR CARGO."""
+ if request.user.is_authenticated:
+ return redirect('dashboard')
context = {
- "project_name": "New Style",
- "agent_brand": agent_brand,
- "django_version": django_version(),
- "python_version": platform.python_version(),
- "current_time": now,
- "host_name": host_name,
- "project_description": os.getenv("PROJECT_DESCRIPTION", ""),
- "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
+ "deployment_timestamp": timezone.now().timestamp(),
}
return render(request, "core/index.html", context)
+
+def register(request):
+ if request.method == 'POST':
+ form = UserCreationForm(request.POST)
+ role = request.POST.get('role')
+ phone = request.POST.get('phone_number')
+ if form.is_valid():
+ user = form.save()
+ profile = user.profile
+ profile.role = role
+ profile.phone_number = phone
+ profile.save()
+ login(request, user)
+ return redirect('dashboard')
+ else:
+ form = UserCreationForm()
+ return render(request, 'registration/register.html', {'form': form})
+
+@login_required
+def dashboard(request):
+ profile = request.user.profile
+ if profile.role == 'SHIPPER':
+ my_shipments = Shipment.objects.filter(shipper=request.user).order_by('-created_at')
+ return render(request, 'core/shipper_dashboard.html', {'shipments': my_shipments})
+ elif profile.role == 'TRUCK_OWNER':
+ my_trucks = Truck.objects.filter(owner=request.user)
+ my_bids = Bid.objects.filter(truck_owner=request.user).order_by('-created_at')
+ return render(request, 'core/truck_owner_dashboard.html', {
+ 'trucks': my_trucks,
+ 'bids': my_bids
+ })
+ else:
+ return redirect('/admin/')
+
+@login_required
+def truck_register(request):
+ if request.user.profile.role != 'TRUCK_OWNER':
+ return redirect('dashboard')
+
+ if request.method == 'POST':
+ truck_type = request.POST.get('truck_type')
+ model = request.POST.get('model')
+ year = request.POST.get('year')
+ plate_no = request.POST.get('plate_no')
+ load_capacity = request.POST.get('load_capacity')
+ color = request.POST.get('color')
+
+ truck = Truck.objects.create(
+ owner=request.user,
+ truck_type=truck_type,
+ model=model,
+ year=year,
+ plate_no=plate_no,
+ load_capacity=load_capacity,
+ color=color,
+ truck_picture=request.FILES.get('truck_picture'),
+ registration_front=request.FILES.get('registration_front'),
+ registration_back=request.FILES.get('registration_back'),
+ driver_license=request.FILES.get('driver_license')
+ )
+ messages.success(request, _("Truck registered successfully!"))
+ return redirect('dashboard')
+
+ return render(request, 'core/truck_register.html')
+
+@login_required
+def post_shipment(request):
+ if request.user.profile.role != 'SHIPPER':
+ return redirect('dashboard')
+
+ if request.method == 'POST':
+ description = request.POST.get('description')
+ weight = request.POST.get('weight')
+ origin = request.POST.get('origin')
+ destination = request.POST.get('destination')
+ delivery_date = request.POST.get('delivery_date')
+
+ Shipment.objects.create(
+ shipper=request.user,
+ description=description,
+ weight=weight,
+ origin=origin,
+ destination=destination,
+ delivery_date=delivery_date
+ )
+ messages.success(request, _("Shipment posted successfully!"))
+ return redirect('dashboard')
+
+ return render(request, 'core/post_shipment.html')
+
+@login_required
+def marketplace(request):
+ if request.user.profile.role != 'TRUCK_OWNER':
+ return redirect('dashboard')
+
+ shipments = Shipment.objects.filter(status='OPEN').order_by('-created_at')
+ return render(request, 'core/marketplace.html', {'shipments': shipments})
+
+@login_required
+def place_bid(request, shipment_id):
+ shipment = get_object_or_404(Shipment, id=shipment_id)
+ if request.user.profile.role != 'TRUCK_OWNER':
+ return redirect('dashboard')
+
+ my_trucks = Truck.objects.filter(owner=request.user)
+ if request.method == 'POST':
+ truck_id = request.POST.get('truck')
+ amount = request.POST.get('amount')
+ comments = request.POST.get('comments')
+
+ truck = get_object_or_404(Truck, id=truck_id, owner=request.user)
+ Bid.objects.create(
+ shipment=shipment,
+ truck_owner=request.user,
+ truck=truck,
+ amount=amount,
+ comments=comments
+ )
+ messages.success(request, _("Bid placed successfully!"))
+ return redirect('marketplace')
+
+ return render(request, 'core/place_bid.html', {'shipment': shipment, 'trucks': my_trucks})
+
+@login_required
+def shipment_detail(request, shipment_id):
+ shipment = get_object_or_404(Shipment, id=shipment_id)
+ # Security: check if user is shipper or a truck owner who bid
+ if shipment.shipper != request.user and not Bid.objects.filter(shipment=shipment, truck_owner=request.user).exists():
+ if request.user.profile.role != 'ADMIN':
+ return redirect('dashboard')
+
+ bids = shipment.bids.all()
+ return render(request, 'core/shipment_detail.html', {'shipment': shipment, 'bids': bids})
+
+@login_required
+def accept_bid(request, bid_id):
+ bid = get_object_or_404(Bid, id=bid_id)
+ if bid.shipment.shipper != request.user:
+ return redirect('dashboard')
+
+ # Accept this bid
+ bid.status = 'ACCEPTED'
+ bid.save()
+
+ # Reject others
+ bid.shipment.bids.exclude(id=bid_id).update(status='REJECTED')
+
+ # Update shipment
+ bid.shipment.status = 'IN_PROGRESS'
+ bid.shipment.assigned_truck = bid.truck
+ bid.shipment.save()
+
+ messages.success(request, _("Bid accepted! Shipment is now in progress."))
+ return redirect('shipment_detail', shipment_id=bid.shipment.id)
diff --git a/locale/ar/LC_MESSAGES/django.mo b/locale/ar/LC_MESSAGES/django.mo
new file mode 100644
index 0000000..993798e
Binary files /dev/null and b/locale/ar/LC_MESSAGES/django.mo differ
diff --git a/locale/ar/LC_MESSAGES/django.po b/locale/ar/LC_MESSAGES/django.po
new file mode 100644
index 0000000..38e53f8
--- /dev/null
+++ b/locale/ar/LC_MESSAGES/django.po
@@ -0,0 +1,619 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2026-01-23 09:04+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#: config/settings.py:188
+msgid "English"
+msgstr "الإنجليزية"
+
+#: config/settings.py:189
+msgid "Arabic"
+msgstr "العربية"
+
+#: core/models.py:9 core/templates/registration/register.html:19
+msgid "Shipper (Need Goods Moved)"
+msgstr "شاحن (بحاجة لنقل بضائع)"
+
+#: core/models.py:10 core/templates/registration/register.html:20
+msgid "Truck Owner (Service Provider)"
+msgstr "صاحب شاحنة (مزود خدمة)"
+
+#: core/models.py:11
+msgid "Administrator"
+msgstr "مدير النظام"
+
+#: core/models.py:22 core/templates/core/truck_register.html:15
+msgid "Truck Type"
+msgstr "نوع الشاحنة"
+
+#: core/models.py:23 core/templates/core/truck_register.html:19
+msgid "Model"
+msgstr "الموديل"
+
+#: core/models.py:24 core/templates/core/truck_register.html:25
+msgid "Year"
+msgstr "السنة"
+
+#: core/models.py:25 core/templates/core/truck_register.html:29
+msgid "Plate No"
+msgstr "رقم اللوحة"
+
+#: core/models.py:26
+msgid "Load Capacity"
+msgstr "حمولة الشاحنة"
+
+#: core/models.py:27 core/templates/core/truck_register.html:33
+msgid "Color"
+msgstr "اللون"
+
+#: core/models.py:30 core/templates/core/truck_register.html:47
+msgid "Truck Picture"
+msgstr "صورة الشاحنة"
+
+#: core/models.py:31
+msgid "Registration Front"
+msgstr "التسجيل (الوجه الأمامي)"
+
+#: core/models.py:32
+#, fuzzy
+#| msgid "Register Your Truck"
+msgid "Registration Back"
+msgstr "سجل شاحنتك"
+
+#: core/models.py:33 core/templates/core/truck_register.html:51
+msgid "Driver License"
+msgstr "رخصة القيادة"
+
+#: core/models.py:42 core/templates/core/marketplace.html:13
+msgid "Open for Bids"
+msgstr "مفتوح للعروض"
+
+#: core/models.py:43
+msgid "In Progress"
+msgstr "قيد التنفيذ"
+
+#: core/models.py:44
+msgid "Completed"
+msgstr "مكتمل"
+
+#: core/models.py:45
+msgid "Cancelled"
+msgstr "ملغي"
+
+#: core/models.py:48 core/templates/core/post_shipment.html:14
+msgid "Goods Description"
+msgstr "وصف البضائع"
+
+#: core/models.py:49 core/templates/core/post_shipment.html:18
+msgid "Weight/Volume"
+msgstr "الوزن/الحجم"
+
+#: core/models.py:50 core/templates/core/post_shipment.html:23
+msgid "Origin"
+msgstr "المصدر"
+
+#: core/models.py:51 core/templates/core/post_shipment.html:27
+msgid "Destination"
+msgstr "الوجهة"
+
+#: core/models.py:52 core/templates/core/post_shipment.html:32
+msgid "Requested Delivery Date"
+msgstr "تاريخ التسليم المطلوب"
+
+#: core/models.py:64
+msgid "Pending"
+msgstr "قيد الانتظار"
+
+#: core/models.py:65
+msgid "Accepted"
+msgstr "مقبول"
+
+#: core/models.py:66
+msgid "Rejected"
+msgstr "مرفوض"
+
+#: core/models.py:71
+msgid "Offer Amount"
+msgstr "قيمة العرض"
+
+#: core/models.py:72
+msgid "Comments"
+msgstr "تعليقات"
+
+#: core/templates/base.html:49
+msgid "Dashboard"
+msgstr "لوحة التحكم"
+
+#: core/templates/base.html:53
+msgid "Marketplace"
+msgstr "السوق"
+
+#: core/templates/base.html:91
+msgid "Logout"
+msgstr "تسجيل الخروج"
+
+#: core/templates/base.html:98 core/templates/registration/login.html:11
+#: core/templates/registration/login.html:22
+#: core/templates/registration/register.html:32
+msgid "Login"
+msgstr "تسجيل الدخول"
+
+#: core/templates/base.html:101
+msgid "Get Started"
+msgstr "ابدأ الآن"
+
+#: core/templates/base.html:129
+msgid "Empowering logistics with smart technology. Locally and abroad."
+msgstr "تمكين الخدمات اللوجستية بتقنيات ذكية. محلياً ودولياً."
+
+#: core/templates/base.html:132
+msgid "Quick Links"
+msgstr "روابط سريعة"
+
+#: core/templates/base.html:134
+msgid "Privacy Policy"
+msgstr "سياسة الخصوصية"
+
+#: core/templates/base.html:135
+msgid "Terms of Service"
+msgstr "شروط الخدمة"
+
+#: core/templates/base.html:136
+msgid "Contact Us"
+msgstr "اتصل بنا"
+
+#: core/templates/base.html:140
+msgid "Contact"
+msgstr "اتصال"
+
+#: core/templates/core/index.html:11
+msgid "Smart Cargo Solutions"
+msgstr "حلول شحن ذكية"
+
+#: core/templates/core/index.html:12
+msgid "Locally & Abroad"
+msgstr "محلياً ودولياً"
+
+#: core/templates/core/index.html:15
+msgid ""
+"The most reliable platform connecting shippers with truck owners across the "
+"region. Transparent, fast, and secure."
+msgstr ""
+"المنصة الأكثر موثوقية لربط الشاحنين مع أصحاب الشاحنات في جميع أنحاء المنطقة. "
+"شفافة، سريعة، وآمنة."
+
+#: core/templates/core/index.html:18
+msgid "Start Shipping"
+msgstr "ابدأ الشحن"
+
+#: core/templates/core/index.html:19
+msgid "Learn More"
+msgstr "تعلم المزيد"
+
+#: core/templates/core/index.html:33
+msgid "How would you like to use MASAR?"
+msgstr "كيف تود استخدام مسار؟"
+
+#: core/templates/core/index.html:34
+msgid "Choose your path to get started with our platform."
+msgstr "اختر مسارك للبدء مع منصتنا."
+
+#: core/templates/core/index.html:43
+msgid "I am a Shipper"
+msgstr "أنا شاحن"
+
+#: core/templates/core/index.html:45
+msgid ""
+"I need to move goods locally or abroad. Post your shipment, receive offers "
+"from verified drivers, and track your cargo in real-time."
+msgstr ""
+"أريد نقل بضائع محلياً أو دولياً. انشر شحنتك، واستقبل عروضاً من سائقين موثقين، "
+"وتتبع شحنتك في الوقت الفعلي."
+
+#: core/templates/core/index.html:48
+msgid "Post shipments easily"
+msgstr "انشر الشحنات بسهولة"
+
+#: core/templates/core/index.html:49
+msgid "Compare competitive bids"
+msgstr "قارن العروض التنافسية"
+
+#: core/templates/core/index.html:50
+msgid "Real-time tracking"
+msgstr "تتبع في الوقت الفعلي"
+
+#: core/templates/core/index.html:52
+msgid "Find a Truck"
+msgstr "ابحث عن شاحنة"
+
+#: core/templates/core/index.html:61
+msgid "I am a Truck Owner"
+msgstr "أنا صاحب شاحنة"
+
+#: core/templates/core/index.html:63
+msgid ""
+"I have trucks and want to find cargo to transport. Register your fleet, bid "
+"on available jobs, and grow your business."
+msgstr ""
+"لدي شاحنات وأريد العثور على بضائع لنقلها. سجل أسطولك، وقدم عروضك على الوظائف "
+"المتاحة، ونمِ عملك."
+
+#: core/templates/core/index.html:66
+msgid "Access daily cargo leads"
+msgstr "الوصول إلى فرص شحن يومية"
+
+#: core/templates/core/index.html:67
+msgid "Flexible bidding system"
+msgstr "نظام عروض مرن"
+
+#: core/templates/core/index.html:68
+msgid "Direct chat with shippers"
+msgstr "دردشة مباشرة مع الشاحنين"
+
+#: core/templates/core/index.html:70
+msgid "Register Your Truck"
+msgstr "سجل شاحنتك"
+
+#: core/templates/core/index.html:82
+msgid "Everything you need for seamless logistics"
+msgstr "كل ما تحتاجه للوجستيات سلسة"
+
+#: core/templates/core/index.html:90
+msgid "WhatsApp Integration"
+msgstr "تكامل واتساب"
+
+#: core/templates/core/index.html:91
+msgid "Receive instant updates and communicate easily via WhatsApp API."
+msgstr "استقبل تحديثات فورية وتواصل بسهولة عبر واجهة برمجة تطبيقات واتساب."
+
+#: core/templates/core/index.html:101
+msgid "Multilingual Support"
+msgstr "دعم متعدد اللغات"
+
+#: core/templates/core/index.html:102
+msgid "Fully accessible in both Arabic and English for all users."
+msgstr "متاح بالكامل باللغتين العربية والإنجليزية لجميع المستخدمين."
+
+#: core/templates/core/index.html:112
+msgid "Secure Documentation"
+msgstr "توثيق آمن"
+
+#: core/templates/core/index.html:113
+msgid "Digital verification of truck registration and driver licenses."
+msgstr "التحقق الرقمي من تسجيل الشاحنات ورخص القيادة."
+
+#: core/templates/core/index.html:135
+msgid "Ready to move your cargo?"
+msgstr "هل أنت مستعد لنقل شحنتك؟"
+
+#: core/templates/core/index.html:136
+msgid "Join thousands of shippers and drivers on MASAR today."
+msgstr "انضم إلى آلاف الشاحنين والسائقين على مسار اليوم."
+
+#: core/templates/core/index.html:137
+msgid "Join Now"
+msgstr "انضم الآن"
+
+#: core/templates/core/marketplace.html:6
+msgid "Shipment Marketplace"
+msgstr "سوق الشحنات"
+
+#: core/templates/core/marketplace.html:14
+msgid "ago"
+msgstr "منذ"
+
+#: core/templates/core/marketplace.html:20
+#: core/templates/core/shipment_detail.html:21
+msgid "Weight"
+msgstr "الوزن"
+
+#: core/templates/core/marketplace.html:24
+#: core/templates/core/shipment_detail.html:25
+#: core/templates/core/shipper_dashboard.html:26
+msgid "Delivery Date"
+msgstr "تاريخ التسليم"
+
+#: core/templates/core/marketplace.html:28
+#: core/templates/core/place_bid.html:10
+msgid "Place an Offer"
+msgstr "قدم عرضاً"
+
+#: core/templates/core/marketplace.html:34
+msgid "No shipments available at the moment."
+msgstr "لا توجد شحنات متاحة حالياً."
+
+#: core/templates/core/place_bid.html:12
+msgid "Shipment:"
+msgstr "الشحنة:"
+
+#: core/templates/core/place_bid.html:13
+msgid "Goods:"
+msgstr "البضائع:"
+
+#: core/templates/core/place_bid.html:20
+msgid "Select Truck"
+msgstr "اختر الشاحنة"
+
+#: core/templates/core/place_bid.html:28
+msgid "Your Offer Amount"
+msgstr "مبلغ عرضك"
+
+#: core/templates/core/place_bid.html:35
+msgid "Comments/Conditions"
+msgstr "التعليقات/الشروط"
+
+#: core/templates/core/place_bid.html:38
+msgid "Submit Offer"
+msgstr "تقديم العرض"
+
+#: core/templates/core/place_bid.html:42
+msgid "You must register a truck before placing a bid."
+msgstr "يجب عليك تسجيل شاحنة قبل تقديم عرض."
+
+#: core/templates/core/place_bid.html:43
+#, fuzzy
+#| msgid "Register Your Truck"
+msgid "Register Truck Now"
+msgstr "سجل شاحنتك"
+
+#: core/templates/core/post_shipment.html:10
+#, fuzzy
+#| msgid "Post shipments easily"
+msgid "Post a New Shipment"
+msgstr "انشر الشحنات بسهولة"
+
+#: core/templates/core/post_shipment.html:15
+msgid "What are you moving? (e.g. 500 boxes of food)"
+msgstr "ماذا ستنقل؟ (مثال: 500 صندوق مواد غذائية)"
+
+#: core/templates/core/post_shipment.html:24
+#: core/templates/core/post_shipment.html:28
+msgid "City, Country"
+msgstr "المدينة، الدولة"
+
+#: core/templates/core/post_shipment.html:35
+#, fuzzy
+#| msgid "Post shipments easily"
+msgid "Post Shipment"
+msgstr "انشر الشحنات بسهولة"
+
+#: core/templates/core/shipment_detail.html:17
+msgid "Details"
+msgstr "التفاصيل"
+
+#: core/templates/core/shipment_detail.html:35
+msgid "Received Bids"
+msgstr "العروض المستلمة"
+
+#: core/templates/core/shipment_detail.html:42
+#, fuzzy
+#| msgid "I am a Truck Owner"
+msgid "Truck Owner"
+msgstr "أنا صاحب شاحنة"
+
+#: core/templates/core/shipment_detail.html:43
+msgid "Truck"
+msgstr "الشاحنة"
+
+#: core/templates/core/shipment_detail.html:44
+#: core/templates/core/truck_owner_dashboard.html:51
+msgid "Amount"
+msgstr "المبلغ"
+
+#: core/templates/core/shipment_detail.html:45
+#: core/templates/core/shipper_dashboard.html:29
+msgid "Action"
+msgstr "الإجراء"
+
+#: core/templates/core/shipment_detail.html:55
+msgid "Accept"
+msgstr "قبول"
+
+#: core/templates/core/shipment_detail.html:60
+msgid "No bids received yet."
+msgstr "لم يتم استلام عروض بعد."
+
+#: core/templates/core/shipment_detail.html:74
+msgid "Shipment in progress!"
+msgstr "الشحنة قيد التنفيذ!"
+
+#: core/templates/core/shipment_detail.html:75
+#, fuzzy
+#| msgid "Find a Truck"
+msgid "Assigned Truck:"
+msgstr "ابحث عن شاحنة"
+
+#: core/templates/core/shipment_detail.html:80
+msgid "Contact Driver on WhatsApp"
+msgstr "تواصل مع السائق عبر واتساب"
+
+#: core/templates/core/shipment_detail.html:89
+msgid "Contact Information"
+msgstr "معلومات الاتصال"
+
+#: core/templates/core/shipment_detail.html:91
+#, fuzzy
+#| msgid "I am a Shipper"
+msgid "Shipper:"
+msgstr "أنا شاحن"
+
+#: core/templates/core/shipment_detail.html:93
+msgid "Phone:"
+msgstr "الهاتف:"
+
+#: core/templates/core/shipper_dashboard.html:7
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Shipper Dashboard"
+msgstr "لوحة التحكم"
+
+#: core/templates/core/shipper_dashboard.html:9
+#, fuzzy
+#| msgid "Post shipments easily"
+msgid "Post New Shipment"
+msgstr "انشر الشحنات بسهولة"
+
+#: core/templates/core/shipper_dashboard.html:17
+msgid "My Shipments"
+msgstr "شحناتي"
+
+#: core/templates/core/shipper_dashboard.html:24
+msgid "Description"
+msgstr "الوصف"
+
+#: core/templates/core/shipper_dashboard.html:25
+msgid "Route"
+msgstr "المسار"
+
+#: core/templates/core/shipper_dashboard.html:27
+#: core/templates/core/truck_owner_dashboard.html:52
+msgid "Status"
+msgstr "الحالة"
+
+#: core/templates/core/shipper_dashboard.html:28
+msgid "Bids"
+msgstr "العروض"
+
+#: core/templates/core/shipper_dashboard.html:45
+msgid "View Details"
+msgstr "عرض التفاصيل"
+
+#: core/templates/core/shipper_dashboard.html:50
+#, fuzzy
+#| msgid "Post shipments easily"
+msgid "No shipments posted yet."
+msgstr "انشر الشحنات بسهولة"
+
+#: core/templates/core/truck_owner_dashboard.html:7
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Truck Owner Dashboard"
+msgstr "لوحة التحكم"
+
+#: core/templates/core/truck_owner_dashboard.html:10
+msgid "Find Shipments"
+msgstr "ابحث عن شحنات"
+
+#: core/templates/core/truck_owner_dashboard.html:13
+#, fuzzy
+#| msgid "Register Your Truck"
+msgid "Register Truck"
+msgstr "سجل شاحنتك"
+
+#: core/templates/core/truck_owner_dashboard.html:22
+msgid "My Trucks"
+msgstr "شاحناتي"
+
+#: core/templates/core/truck_owner_dashboard.html:35
+msgid "No trucks registered."
+msgstr "لا توجد شاحنات مسجلة."
+
+#: core/templates/core/truck_owner_dashboard.html:43
+msgid "My Active Bids"
+msgstr "عروضي النشطة"
+
+#: core/templates/core/truck_owner_dashboard.html:50
+msgid "Shipment"
+msgstr "الشحنة"
+
+#: core/templates/core/truck_owner_dashboard.html:68
+msgid "No bids placed."
+msgstr "لا توجد عروض مقدمة."
+
+#: core/templates/core/truck_register.html:10
+#, fuzzy
+#| msgid "Register Your Truck"
+msgid "Register a Truck"
+msgstr "سجل شاحنتك"
+
+#: core/templates/core/truck_register.html:38
+msgid "Load Capacity (e.g. 20 Tons)"
+msgstr "الحمولة (مثال: 20 طن)"
+
+#: core/templates/core/truck_register.html:43
+msgid "Documents & Photos"
+msgstr "المستندات والصور"
+
+#: core/templates/core/truck_register.html:57
+msgid "Registration (Front Face)"
+msgstr "التسجيل (الوجه الأمامي)"
+
+#: core/templates/core/truck_register.html:61
+msgid "Registration (Back Face)"
+msgstr "التسجيل (الوجه الخلفي)"
+
+#: core/templates/core/truck_register.html:66
+msgid "Submit Registration"
+msgstr "إرسال التسجيل"
+
+#: core/templates/registration/login.html:15
+msgid "Username"
+msgstr "اسم المستخدم"
+
+#: core/templates/registration/login.html:19
+msgid "Password"
+msgstr "كلمة المرور"
+
+#: core/templates/registration/login.html:25
+msgid "Don't have an account?"
+msgstr "ليس لديك حساب؟"
+
+#: core/templates/registration/login.html:25
+#: core/templates/registration/register.html:29
+msgid "Register"
+msgstr "تسجيل"
+
+#: core/templates/registration/register.html:11
+msgid "Create your account"
+msgstr "أنشئ حسابك"
+
+#: core/templates/registration/register.html:17
+msgid "I am a:"
+msgstr "أنا:"
+
+#: core/templates/registration/register.html:25
+msgid "Phone Number"
+msgstr "رقم الهاتف"
+
+#: core/templates/registration/register.html:32
+msgid "Already have an account?"
+msgstr "لديك حساب بالفعل؟"
+
+#: core/views.py:79
+msgid "Truck registered successfully!"
+msgstr "تم تسجيل الشاحنة بنجاح!"
+
+#: core/views.py:104
+msgid "Shipment posted successfully!"
+msgstr "تم نشر الشحنة بنجاح!"
+
+#: core/views.py:137
+msgid "Bid placed successfully!"
+msgstr "تم تقديم العرض بنجاح!"
+
+#: core/views.py:171
+msgid "Bid accepted! Shipment is now in progress."
+msgstr "تم قبول العرض! الشحنة قيد التنفيذ الآن."
+
+#~ msgid "Features"
+#~ msgstr "المميزات"
+
+#~ msgid "How it Works"
+#~ msgstr "كيف يعمل"
diff --git a/media/trucks/red_truk.jfif b/media/trucks/red_truk.jfif
new file mode 100644
index 0000000..af339ca
Binary files /dev/null and b/media/trucks/red_truk.jfif differ
diff --git a/static/css/custom.css b/static/css/custom.css
index 925f6ed..48834d9 100644
--- a/static/css/custom.css
+++ b/static/css/custom.css
@@ -1,4 +1,131 @@
-/* Custom styles for the application */
-body {
- font-family: system-ui, -apple-system, sans-serif;
+@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&family=Outfit:wght@400;600;700&display=swap');
+
+:root {
+ --primary-color: #0A1D37;
+ --secondary-color: #2196F3;
+ --accent-color: #00BCD4;
+ --bg-light: #F4F7F6;
+ --white: #FFFFFF;
+ --text-dark: #333333;
+ --text-muted: #666666;
}
+
+body {
+ font-family: 'Outfit', 'Cairo', sans-serif;
+ background-color: var(--bg-light);
+ color: var(--text-dark);
+ margin: 0;
+ overflow-x: hidden;
+}
+
+[lang="ar"] body {
+ direction: rtl;
+ text-align: right;
+}
+
+.navbar {
+ background-color: var(--white);
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ padding: 1rem 2rem;
+}
+
+.navbar-brand {
+ font-weight: 700;
+ font-size: 1.5rem;
+ color: var(--primary-color) !important;
+}
+
+.nav-link {
+ color: var(--primary-color) !important;
+ font-weight: 600;
+ margin: 0 10px;
+}
+
+.btn-primary {
+ background-color: var(--secondary-color);
+ border: none;
+ padding: 10px 25px;
+ border-radius: 50px;
+ font-weight: 600;
+ transition: all 0.3s ease;
+}
+
+.btn-primary:hover {
+ background-color: var(--primary-color);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3);
+}
+
+.btn-outline-primary {
+ border: 2px solid var(--secondary-color);
+ color: var(--secondary-color);
+ padding: 10px 25px;
+ border-radius: 50px;
+ font-weight: 600;
+}
+
+.hero-section {
+ padding: 100px 0;
+ background: linear-gradient(135deg, var(--white) 0%, #E3F2FD 100%);
+ position: relative;
+ overflow: hidden;
+}
+
+.hero-title {
+ font-size: 3.5rem;
+ font-weight: 700;
+ color: var(--primary-color);
+ margin-bottom: 20px;
+ line-height: 1.2;
+}
+
+.hero-subtitle {
+ font-size: 1.25rem;
+ color: var(--text-muted);
+ margin-bottom: 40px;
+}
+
+.role-card {
+ background: var(--white);
+ padding: 40px;
+ border-radius: 20px;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.05);
+ transition: all 0.3s ease;
+ border: 1px solid transparent;
+ height: 100%;
+ cursor: pointer;
+}
+
+.role-card:hover {
+ border-color: var(--secondary-color);
+ transform: translateY(-10px);
+}
+
+.role-icon {
+ font-size: 3rem;
+ color: var(--secondary-color);
+ margin-bottom: 20px;
+}
+
+.role-title {
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: var(--primary-color);
+}
+
+.role-desc {
+ color: var(--text-muted);
+ margin-bottom: 25px;
+}
+
+footer {
+ background-color: var(--primary-color);
+ color: var(--white);
+ padding: 50px 0;
+}
+
+/* RTL Adjustments */
+[lang="ar"] .ms-auto {
+ margin-right: auto !important;
+ margin-left: 0 !important;
+}
\ No newline at end of file
diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css
index 108056f..48834d9 100644
--- a/staticfiles/css/custom.css
+++ b/staticfiles/css/custom.css
@@ -1,21 +1,131 @@
+@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&family=Outfit:wght@400;600;700&display=swap');
:root {
- --bg-color-start: #6a11cb;
- --bg-color-end: #2575fc;
- --text-color: #ffffff;
- --card-bg-color: rgba(255, 255, 255, 0.01);
- --card-border-color: rgba(255, 255, 255, 0.1);
+ --primary-color: #0A1D37;
+ --secondary-color: #2196F3;
+ --accent-color: #00BCD4;
+ --bg-light: #F4F7F6;
+ --white: #FFFFFF;
+ --text-dark: #333333;
+ --text-muted: #666666;
}
+
body {
+ font-family: 'Outfit', 'Cairo', sans-serif;
+ background-color: var(--bg-light);
+ color: var(--text-dark);
margin: 0;
- font-family: 'Inter', sans-serif;
- background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
- color: var(--text-color);
- display: flex;
- justify-content: center;
- align-items: center;
- min-height: 100vh;
- text-align: center;
- overflow: hidden;
- position: relative;
+ overflow-x: hidden;
}
+
+[lang="ar"] body {
+ direction: rtl;
+ text-align: right;
+}
+
+.navbar {
+ background-color: var(--white);
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ padding: 1rem 2rem;
+}
+
+.navbar-brand {
+ font-weight: 700;
+ font-size: 1.5rem;
+ color: var(--primary-color) !important;
+}
+
+.nav-link {
+ color: var(--primary-color) !important;
+ font-weight: 600;
+ margin: 0 10px;
+}
+
+.btn-primary {
+ background-color: var(--secondary-color);
+ border: none;
+ padding: 10px 25px;
+ border-radius: 50px;
+ font-weight: 600;
+ transition: all 0.3s ease;
+}
+
+.btn-primary:hover {
+ background-color: var(--primary-color);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 15px rgba(33, 150, 243, 0.3);
+}
+
+.btn-outline-primary {
+ border: 2px solid var(--secondary-color);
+ color: var(--secondary-color);
+ padding: 10px 25px;
+ border-radius: 50px;
+ font-weight: 600;
+}
+
+.hero-section {
+ padding: 100px 0;
+ background: linear-gradient(135deg, var(--white) 0%, #E3F2FD 100%);
+ position: relative;
+ overflow: hidden;
+}
+
+.hero-title {
+ font-size: 3.5rem;
+ font-weight: 700;
+ color: var(--primary-color);
+ margin-bottom: 20px;
+ line-height: 1.2;
+}
+
+.hero-subtitle {
+ font-size: 1.25rem;
+ color: var(--text-muted);
+ margin-bottom: 40px;
+}
+
+.role-card {
+ background: var(--white);
+ padding: 40px;
+ border-radius: 20px;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.05);
+ transition: all 0.3s ease;
+ border: 1px solid transparent;
+ height: 100%;
+ cursor: pointer;
+}
+
+.role-card:hover {
+ border-color: var(--secondary-color);
+ transform: translateY(-10px);
+}
+
+.role-icon {
+ font-size: 3rem;
+ color: var(--secondary-color);
+ margin-bottom: 20px;
+}
+
+.role-title {
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: var(--primary-color);
+}
+
+.role-desc {
+ color: var(--text-muted);
+ margin-bottom: 25px;
+}
+
+footer {
+ background-color: var(--primary-color);
+ color: var(--white);
+ padding: 50px 0;
+}
+
+/* RTL Adjustments */
+[lang="ar"] .ms-auto {
+ margin-right: auto !important;
+ margin-left: 0 !important;
+}
\ No newline at end of file