dem1
This commit is contained in:
parent
d457a5b75d
commit
de92a4ccc0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -42,6 +42,7 @@ SESSION_COOKIE_SECURE = True
|
|||||||
CSRF_COOKIE_SECURE = True
|
CSRF_COOKIE_SECURE = True
|
||||||
SESSION_COOKIE_SAMESITE = "None"
|
SESSION_COOKIE_SAMESITE = "None"
|
||||||
CSRF_COOKIE_SAMESITE = "None"
|
CSRF_COOKIE_SAMESITE = "None"
|
||||||
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||||
@ -61,6 +62,7 @@ INSTALLED_APPS = [
|
|||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
@ -133,7 +135,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
# https://docs.djangoproject.com/en/5.2/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en'
|
||||||
|
|
||||||
TIME_ZONE = 'UTC'
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
@ -180,3 +182,17 @@ if EMAIL_USE_SSL:
|
|||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
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'
|
||||||
|
|||||||
@ -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.contrib import admin
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path('i18n/', include('django.conf.urls.i18n')),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("", include("core.urls")),
|
path("", include("core.urls")),
|
||||||
]
|
]
|
||||||
@ -27,3 +12,4 @@ urlpatterns = [
|
|||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets")
|
urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets")
|
||||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,30 @@
|
|||||||
from django.contrib import admin
|
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')
|
||||||
|
|||||||
26
core/migrations/0001_initial.py
Normal file
26
core/migrations/0001_initial.py
Normal file
@ -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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
BIN
core/migrations/__pycache__/0001_initial.cpython-311.pyc
Normal file
BIN
core/migrations/__pycache__/0001_initial.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,99 @@
|
|||||||
from django.db import models
|
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)
|
||||||
|
|||||||
@ -1,25 +1,156 @@
|
|||||||
|
{% load static i18n %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="{{ request.LANGUAGE_CODE }}" {% if request.LANGUAGE_CODE == 'ar' %}dir="rtl"{% endif %}>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{% block title %}Knowledge Base{% endblock %}</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{% block title %}MASAR CARGO{% endblock %}</title>
|
||||||
{% if project_description %}
|
{% if project_description %}
|
||||||
<meta name="description" content="{{ project_description }}">
|
<meta name="description" content="{{ project_description }}">
|
||||||
<meta property="og:description" content="{{ project_description }}">
|
|
||||||
<meta property="twitter:description" content="{{ project_description }}">
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if project_image_url %}
|
|
||||||
<meta property="og:image" content="{{ project_image_url }}">
|
<!-- Bootstrap 5 CSS -->
|
||||||
<meta property="twitter:image" content="{{ project_image_url }}">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
{% if request.LANGUAGE_CODE == 'ar' %}
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.rtl.min.css">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% load static %}
|
|
||||||
|
<!-- Font Awesome -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
|
<style>
|
||||||
|
body { font-family: 'Outfit', sans-serif; background-color: #f8f9fa; }
|
||||||
|
{% if request.LANGUAGE_CODE == 'ar' %}
|
||||||
|
body { font-family: 'Cairo', sans-serif; }
|
||||||
|
{% endif %}
|
||||||
|
.navbar { background-color: #0A1D37; }
|
||||||
|
.navbar-brand, .nav-link { color: #fff !important; }
|
||||||
|
.btn-primary { background-color: #2196F3; border-color: #2196F3; }
|
||||||
|
footer { background-color: #0A1D37; color: #fff; padding: 3rem 0; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% block content %}{% endblock %}
|
<nav class="navbar navbar-expand-lg sticky-top">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<i class="fa-solid fa-truck-fast me-2 text-info"></i> MASAR CARGO
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto align-items-center">
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'dashboard' %}">{% trans "Dashboard" %}</a>
|
||||||
|
</li>
|
||||||
|
{% if user.profile.role == 'TRUCK_OWNER' %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'marketplace' %}">{% trans "Marketplace" %}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<li class="nav-item dropdown ms-lg-3">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="langDropdown" role="button" data-bs-toggle="dropdown">
|
||||||
|
<i class="fa-solid fa-globe me-1"></i> {{ request.LANGUAGE_CODE|upper }}
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<form action="{% url 'set_language' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input name="next" type="hidden" value="{{ request.path }}">
|
||||||
|
<input name="language" type="hidden" value="en">
|
||||||
|
<button type="submit" class="dropdown-item">English</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<form action="{% url 'set_language' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input name="next" type="hidden" value="{{ request.path }}">
|
||||||
|
<input name="language" type="hidden" value="ar">
|
||||||
|
<button type="submit" class="dropdown-item">العربية</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<li class="nav-item dropdown ms-lg-3">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">
|
||||||
|
<i class="fa-solid fa-user-circle me-1"></i> {{ user.username }}
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<form action="{% url 'logout' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" class="dropdown-item">{% trans "Logout" %}</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="nav-item ms-lg-3">
|
||||||
|
<a class="nav-link" href="{% url 'login' %}">{% trans "Login" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="btn btn-primary" href="{% url 'register' %}">{% trans "Get Started" %}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% if messages %}
|
||||||
|
<div class="container mt-3">
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||||
|
{{ message }}
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<h4 class="fw-bold">MASAR CARGO</h4>
|
||||||
|
<p class="text-white-50">{% trans "Empowering logistics with smart technology. Locally and abroad." %}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<h5 class="fw-bold">{% trans "Quick Links" %}</h5>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><a href="#" class="text-white-50 text-decoration-none">{% trans "Privacy Policy" %}</a></li>
|
||||||
|
<li><a href="#" class="text-white-50 text-decoration-none">{% trans "Terms of Service" %}</a></li>
|
||||||
|
<li><a href="#" class="text-white-50 text-decoration-none">{% trans "Contact Us" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<h5 class="fw-bold">{% trans "Contact" %}</h5>
|
||||||
|
<p class="text-white-50">
|
||||||
|
<i class="fa-brands fa-whatsapp me-2"></i> +123 456 7890<br>
|
||||||
|
<i class="fa-solid fa-envelope me-2"></i> info@masarcargo.com
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="bg-white-50">
|
||||||
|
<p class="text-center text-white-50 mb-0">© 2026 MASAR CARGO. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- Bootstrap 5 JS Bundle -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -1,145 +1,142 @@
|
|||||||
{% extends "base.html" %}
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n static %}
|
||||||
{% block title %}{{ project_name }}{% endblock %}
|
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
body::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
|
|
||||||
animation: bg-pan 20s linear infinite;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bg-pan {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
background-position: 100% 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background: var(--card-bg-color);
|
|
||||||
border: 1px solid var(--card-border-color);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2.5rem 2rem;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0 0 1.2rem;
|
|
||||||
letter-spacing: -0.02em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
opacity: 0.92;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
margin: 1.5rem auto;
|
|
||||||
width: 56px;
|
|
||||||
height: 56px;
|
|
||||||
border: 4px solid rgba(255, 255, 255, 0.25);
|
|
||||||
border-top-color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.runtime code {
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
padding: 0.15rem 0.45rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1rem;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
opacity: 0.75;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<main>
|
<!-- Hero Section -->
|
||||||
<div class="card">
|
<section class="hero-section py-5">
|
||||||
<h1>Analyzing your requirements and generating your app…</h1>
|
<div class="container">
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
<div class="row align-items-center">
|
||||||
<span class="sr-only">Loading…</span>
|
<div class="col-lg-6 mb-5 mb-lg-0">
|
||||||
|
<h1 class="hero-title display-4 fw-bold mb-4">
|
||||||
|
{% trans "Smart Cargo Solutions" %}<br>
|
||||||
|
<span class="text-primary">{% trans "Locally & Abroad" %}</span>
|
||||||
|
</h1>
|
||||||
|
<p class="hero-subtitle lead text-muted mb-4">
|
||||||
|
{% trans "The most reliable platform connecting shippers with truck owners across the region. Transparent, fast, and secure." %}
|
||||||
|
</p>
|
||||||
|
<div class="d-flex gap-3">
|
||||||
|
<a href="{% url 'register' %}" class="btn btn-primary btn-lg px-4">{% trans "Start Shipping" %}</a>
|
||||||
|
<a href="#how-it-works" class="btn btn-outline-primary btn-lg px-4">{% trans "Learn More" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<img src="https://img.freepik.com/free-vector/delivery-truck-with-packages-concept_23-2148464601.jpg" alt="Logistics" class="img-fluid rounded-4 shadow-lg">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p>
|
</section>
|
||||||
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
|
|
||||||
<p class="runtime">
|
<!-- Role Selection Section -->
|
||||||
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
|
<section class="py-5 bg-light" id="how-it-works">
|
||||||
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
|
<div class="container py-5">
|
||||||
</p>
|
<div class="text-center mb-5">
|
||||||
</div>
|
<h2 class="fw-bold text-primary">{% trans "How would you like to use MASAR?" %}</h2>
|
||||||
</main>
|
<p class="text-muted">{% trans "Choose your path to get started with our platform." %}</p>
|
||||||
<footer>
|
</div>
|
||||||
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
|
<div class="row g-4">
|
||||||
</footer>
|
<!-- Shipper Role -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card h-100 border-0 shadow-sm p-4 text-center">
|
||||||
|
<div class="mb-4">
|
||||||
|
<i class="fa-solid fa-box-open fa-3x text-primary"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="fw-bold">{% trans "I am a Shipper" %}</h3>
|
||||||
|
<p class="text-muted">
|
||||||
|
{% trans "I need to move goods locally or abroad. Post your shipment, receive offers from verified drivers, and track your cargo in real-time." %}
|
||||||
|
</p>
|
||||||
|
<ul class="list-unstyled text-start mb-4 mx-auto" style="max-width: 300px;">
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Post shipments easily" %}</li>
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Compare competitive bids" %}</li>
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Real-time tracking" %}</li>
|
||||||
|
</ul>
|
||||||
|
<a href="{% url 'register' %}" class="btn btn-primary w-100 py-3">{% trans "Find a Truck" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Truck Owner Role -->
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card h-100 border-0 shadow-sm p-4 text-center">
|
||||||
|
<div class="mb-4">
|
||||||
|
<i class="fa-solid fa-truck fa-3x text-primary"></i>
|
||||||
|
</div>
|
||||||
|
<h3 class="fw-bold">{% trans "I am a Truck Owner" %}</h3>
|
||||||
|
<p class="text-muted">
|
||||||
|
{% trans "I have trucks and want to find cargo to transport. Register your fleet, bid on available jobs, and grow your business." %}
|
||||||
|
</p>
|
||||||
|
<ul class="list-unstyled text-start mb-4 mx-auto" style="max-width: 300px;">
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Access daily cargo leads" %}</li>
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Flexible bidding system" %}</li>
|
||||||
|
<li><i class="fa-solid fa-check text-success me-2"></i> {% trans "Direct chat with shippers" %}</li>
|
||||||
|
</ul>
|
||||||
|
<a href="{% url 'register' %}" class="btn btn-primary w-100 py-3">{% trans "Register Your Truck" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Features Section -->
|
||||||
|
<section class="bg-white py-5" id="features">
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row g-5 align-items-center">
|
||||||
|
<div class="col-lg-5">
|
||||||
|
<h2 class="fw-bold mb-4">{% trans "Everything you need for seamless logistics" %}</h2>
|
||||||
|
<div class="d-flex mb-4">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<div class="bg-light p-3 rounded-3 text-primary">
|
||||||
|
<i class="fa-brands fa-whatsapp fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-4">
|
||||||
|
<h5 class="fw-bold">{% trans "WhatsApp Integration" %}</h5>
|
||||||
|
<p class="text-muted">{% trans "Receive instant updates and communicate easily via WhatsApp API." %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex mb-4">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<div class="bg-light p-3 rounded-3 text-primary">
|
||||||
|
<i class="fa-solid fa-language fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-4">
|
||||||
|
<h5 class="fw-bold">{% trans "Multilingual Support" %}</h5>
|
||||||
|
<p class="text-muted">{% trans "Fully accessible in both Arabic and English for all users." %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<div class="bg-light p-3 rounded-3 text-primary">
|
||||||
|
<i class="fa-solid fa-shield-halved fa-2x"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ms-4">
|
||||||
|
<h5 class="fw-bold">{% trans "Secure Documentation" %}</h5>
|
||||||
|
<p class="text-muted">{% trans "Digital verification of truck registration and driver licenses." %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-7">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-6">
|
||||||
|
<img src="https://img.freepik.com/free-photo/view-truck-with-cargo_23-2150821510.jpg" class="img-fluid rounded-4 shadow" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="col-6 mt-5">
|
||||||
|
<img src="https://img.freepik.com/free-photo/industrial-port-container-yard-with-cranes-logistic-import-export-business-logistics-background_35641-2693.jpg" class="img-fluid rounded-4 shadow" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Call to Action -->
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="bg-primary text-white p-5 rounded-5 text-center shadow-lg">
|
||||||
|
<h2 class="fw-bold mb-3">{% trans "Ready to move your cargo?" %}</h2>
|
||||||
|
<p class="mb-4 opacity-75">{% trans "Join thousands of shippers and drivers on MASAR today." %}</p>
|
||||||
|
<a href="{% url 'register' %}" class="btn btn-light btn-lg px-5 rounded-pill fw-bold text-primary">{% trans "Join Now" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
39
core/templates/core/marketplace.html
Normal file
39
core/templates/core/marketplace.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<h2 class="mb-4">{% trans "Shipment Marketplace" %}</h2>
|
||||||
|
<div class="row">
|
||||||
|
{% for shipment in shipments %}
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card shadow-sm h-100 border-0">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<span class="badge bg-primary">{% trans "Open for Bids" %}</span>
|
||||||
|
<small class="text-muted">{{ shipment.created_at|timesince }} {% trans "ago" %}</small>
|
||||||
|
</div>
|
||||||
|
<h5 class="card-title">{{ shipment.origin }} <i class="fa-solid fa-arrow-right mx-2"></i> {{ shipment.destination }}</h5>
|
||||||
|
<p class="card-text text-muted">{{ shipment.description|truncatechars:100 }}</p>
|
||||||
|
<div class="d-flex gap-4 mb-3">
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">{% trans "Weight" %}</small>
|
||||||
|
<strong>{{ shipment.weight }}</strong>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<small class="text-muted d-block">{% trans "Delivery Date" %}</small>
|
||||||
|
<strong>{{ shipment.delivery_date }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="{% url 'place_bid' shipment.id %}" class="btn btn-outline-primary w-100">{% trans "Place an Offer" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% empty %}
|
||||||
|
<div class="col-12 text-center py-5">
|
||||||
|
<p class="lead text-muted">{% trans "No shipments available at the moment." %}</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
51
core/templates/core/place_bid.html
Normal file
51
core/templates/core/place_bid.html
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h2 class="mb-4">{% trans "Place an Offer" %}</h2>
|
||||||
|
<div class="alert alert-info mb-4">
|
||||||
|
<strong>{% trans "Shipment:" %}</strong> {{ shipment.origin }} to {{ shipment.destination }}<br>
|
||||||
|
<strong>{% trans "Goods:" %}</strong> {{ shipment.description }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if trucks %}
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Select Truck" %}</label>
|
||||||
|
<select name="truck" class="form-select" required>
|
||||||
|
{% for truck in trucks %}
|
||||||
|
<option value="{{ truck.id }}">{{ truck.truck_type }} - {{ truck.plate_no }} ({{ truck.load_capacity }})</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Your Offer Amount" %}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text">$</span>
|
||||||
|
<input type="number" name="amount" class="form-control" step="0.01" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Comments/Conditions" %}</label>
|
||||||
|
<textarea name="comments" class="form-control" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-3">{% trans "Submit Offer" %}</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<div class="text-center py-4">
|
||||||
|
<p class="text-danger">{% trans "You must register a truck before placing a bid." %}</p>
|
||||||
|
<a href="{% url 'truck_register' %}" class="btn btn-success">{% trans "Register Truck Now" %}</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
42
core/templates/core/post_shipment.html
Normal file
42
core/templates/core/post_shipment.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h2 class="mb-4">{% trans "Post a New Shipment" %}</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Goods Description" %}</label>
|
||||||
|
<textarea name="description" class="form-control" rows="4" placeholder="{% trans 'What are you moving? (e.g. 500 boxes of food)' %}" required></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Weight/Volume" %}</label>
|
||||||
|
<input type="text" name="weight" class="form-control" placeholder="e.g. 5 Tons" required>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Origin" %}</label>
|
||||||
|
<input type="text" name="origin" class="form-control" placeholder="{% trans 'City, Country' %}" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Destination" %}</label>
|
||||||
|
<input type="text" name="destination" class="form-control" placeholder="{% trans 'City, Country' %}" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Requested Delivery Date" %}</label>
|
||||||
|
<input type="date" name="delivery_date" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-3 mt-4">{% trans "Post Shipment" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
101
core/templates/core/shipment_detail.html
Normal file
101
core/templates/core/shipment_detail.html
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card shadow-sm mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h2 class="mb-0">{{ shipment.origin }} <i class="fa-solid fa-arrow-right mx-2"></i> {{ shipment.destination }}</h2>
|
||||||
|
<span class="badge {% if shipment.status == 'OPEN' %}bg-primary{% elif shipment.status == 'IN_PROGRESS' %}bg-warning{% else %}bg-success{% endif %} fs-6">
|
||||||
|
{{ shipment.get_status_display }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<h5>{% trans "Details" %}</h5>
|
||||||
|
<p>{{ shipment.description }}</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6 mb-3">
|
||||||
|
<small class="text-muted d-block">{% trans "Weight" %}</small>
|
||||||
|
<strong>{{ shipment.weight }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 mb-3">
|
||||||
|
<small class="text-muted d-block">{% trans "Delivery Date" %}</small>
|
||||||
|
<strong>{{ shipment.delivery_date }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if user == shipment.shipper and shipment.status == 'OPEN' %}
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-white">
|
||||||
|
<h5 class="mb-0">{% trans "Received Bids" %}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Truck Owner" %}</th>
|
||||||
|
<th>{% trans "Truck" %}</th>
|
||||||
|
<th>{% trans "Amount" %}</th>
|
||||||
|
<th>{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for bid in bids %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ bid.truck_owner.username }}</td>
|
||||||
|
<td>{{ bid.truck.truck_type }}</td>
|
||||||
|
<td>${{ bid.amount }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'accept_bid' bid.id %}" class="btn btn-sm btn-success">{% trans "Accept" %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="4" class="text-center py-4 text-muted">{% trans "No bids received yet." %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if shipment.status == 'IN_PROGRESS' %}
|
||||||
|
<div class="alert alert-success d-flex align-items-center">
|
||||||
|
<i class="fa-solid fa-truck-moving fa-2x me-3"></i>
|
||||||
|
<div>
|
||||||
|
<strong>{% trans "Shipment in progress!" %}</strong><br>
|
||||||
|
{% trans "Assigned Truck:" %} {{ shipment.assigned_truck.truck_type }} ({{ shipment.assigned_truck.plate_no }})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<a href="https://wa.me/{{ shipment.assigned_truck.owner.profile.phone_number }}" class="btn btn-success btn-lg">
|
||||||
|
<i class="fa-brands fa-whatsapp me-2"></i> {% trans "Contact Driver on WhatsApp" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5>{% trans "Contact Information" %}</h5>
|
||||||
|
<p>
|
||||||
|
<strong>{% trans "Shipper:" %}</strong> {{ shipment.shipper.username }}<br>
|
||||||
|
{% if shipment.status == 'IN_PROGRESS' %}
|
||||||
|
<strong>{% trans "Phone:" %}</strong> {{ shipment.shipper.profile.phone_number }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
61
core/templates/core/shipper_dashboard.html
Normal file
61
core/templates/core/shipper_dashboard.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h2>{% trans "Shipper Dashboard" %}</h2>
|
||||||
|
<a href="{% url 'post_shipment' %}" class="btn btn-success">
|
||||||
|
<i class="fa-solid fa-plus me-2"></i> {% trans "Post New Shipment" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-white">
|
||||||
|
<h5 class="mb-0">{% trans "My Shipments" %}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover mb-0">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Description" %}</th>
|
||||||
|
<th>{% trans "Route" %}</th>
|
||||||
|
<th>{% trans "Delivery Date" %}</th>
|
||||||
|
<th>{% trans "Status" %}</th>
|
||||||
|
<th>{% trans "Bids" %}</th>
|
||||||
|
<th>{% trans "Action" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for shipment in shipments %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ shipment.description|truncatechars:30 }}</td>
|
||||||
|
<td>{{ shipment.origin }} <i class="fa-solid fa-arrow-right mx-1"></i> {{ shipment.destination }}</td>
|
||||||
|
<td>{{ shipment.delivery_date }}</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge {% if shipment.status == 'OPEN' %}bg-primary{% elif shipment.status == 'IN_PROGRESS' %}bg-warning{% else %}bg-success{% endif %}">
|
||||||
|
{{ shipment.get_status_display }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ shipment.bids.count }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'shipment_detail' shipment.id %}" class="btn btn-sm btn-outline-primary">{% trans "View Details" %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center py-4">{% trans "No shipments posted yet." %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
79
core/templates/core/truck_owner_dashboard.html
Normal file
79
core/templates/core/truck_owner_dashboard.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h2>{% trans "Truck Owner Dashboard" %}</h2>
|
||||||
|
<div>
|
||||||
|
<a href="{% url 'marketplace' %}" class="btn btn-primary me-2">
|
||||||
|
<i class="fa-solid fa-search me-2"></i> {% trans "Find Shipments" %}
|
||||||
|
</a>
|
||||||
|
<a href="{% url 'truck_register' %}" class="btn btn-success">
|
||||||
|
<i class="fa-solid fa-plus me-2"></i> {% trans "Register Truck" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card shadow-sm h-100">
|
||||||
|
<div class="card-header bg-white">
|
||||||
|
<h5 class="mb-0">{% trans "My Trucks" %}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
{% if trucks %}
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% for truck in trucks %}
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
{{ truck.truck_type }} - {{ truck.plate_no }}
|
||||||
|
<span class="badge bg-secondary">{{ truck.load_capacity }}</span>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-center py-3">{% trans "No trucks registered." %}</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-4">
|
||||||
|
<div class="card shadow-sm h-100">
|
||||||
|
<div class="card-header bg-white">
|
||||||
|
<h5 class="mb-0">{% trans "My Active Bids" %}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Shipment" %}</th>
|
||||||
|
<th>{% trans "Amount" %}</th>
|
||||||
|
<th>{% trans "Status" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for bid in bids %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ bid.shipment.origin }} - {{ bid.shipment.destination }}</td>
|
||||||
|
<td>{{ bid.amount }}</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge {% if bid.status == 'PENDING' %}bg-warning{% elif bid.status == 'ACCEPTED' %}bg-success{% else %}bg-danger{% endif %}">
|
||||||
|
{{ bid.get_status_display }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center py-3">{% trans "No bids placed." %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
73
core/templates/core/truck_register.html
Normal file
73
core/templates/core/truck_register.html
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h2 class="mb-4">{% trans "Register a Truck" %}</h2>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Truck Type" %}</label>
|
||||||
|
<input type="text" name="truck_type" class="form-control" placeholder="e.g. Flatbed, Trailer" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Model" %}</label>
|
||||||
|
<input type="text" name="model" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<label class="form-label">{% trans "Year" %}</label>
|
||||||
|
<input type="number" name="year" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<label class="form-label">{% trans "Plate No" %}</label>
|
||||||
|
<input type="text" name="plate_no" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<label class="form-label">{% trans "Color" %}</label>
|
||||||
|
<input type="text" name="color" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Load Capacity (e.g. 20 Tons)" %}</label>
|
||||||
|
<input type="text" name="load_capacity" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr class="my-4">
|
||||||
|
<h5>{% trans "Documents & Photos" %}</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Truck Picture" %}</label>
|
||||||
|
<input type="file" name="truck_picture" class="form-control" accept="image/*">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Driver License" %}</label>
|
||||||
|
<input type="file" name="driver_license" class="form-control" accept="image/*">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Registration (Front Face)" %}</label>
|
||||||
|
<input type="file" name="registration_front" class="form-control" accept="image/*">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">{% trans "Registration (Back Face)" %}</label>
|
||||||
|
<input type="file" name="registration_back" class="form-control" accept="image/*">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-3 mt-4">{% trans "Submit Registration" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
33
core/templates/registration/login.html
Normal file
33
core/templates/registration/login.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h2 class="text-center mb-4">{% trans "Login" %}</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Username" %}</label>
|
||||||
|
<input type="text" name="username" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Password" %}</label>
|
||||||
|
<input type="password" name="password" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-2">{% trans "Login" %}</button>
|
||||||
|
</form>
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<p>{% trans "Don't have an account?" %} <a href="{% url 'register' %}">{% trans "Register" %}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
40
core/templates/registration/register.html
Normal file
40
core/templates/registration/register.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-body p-5">
|
||||||
|
<h2 class="text-center mb-4">{% trans "Create your account" %}</h2>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "I am a:" %}</label>
|
||||||
|
<select name="role" class="form-select" required>
|
||||||
|
<option value="SHIPPER">{% trans "Shipper (Need Goods Moved)" %}</option>
|
||||||
|
<option value="TRUCK_OWNER">{% trans "Truck Owner (Service Provider)" %}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">{% trans "Phone Number" %}</label>
|
||||||
|
<input type="text" name="phone_number" class="form-control" placeholder="+1234567890">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-100 py-2">{% trans "Register" %}</button>
|
||||||
|
</form>
|
||||||
|
<div class="text-center mt-3">
|
||||||
|
<p>{% trans "Already have an account?" %} <a href="{% url 'login' %}">{% trans "Login" %}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
16
core/urls.py
16
core/urls.py
@ -1,7 +1,17 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.contrib.auth import views as auth_views
|
||||||
from .views import home
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
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/<int:shipment_id>/", views.shipment_detail, name="shipment_detail"),
|
||||||
|
path("shipment/<int:shipment_id>/bid/", views.place_bid, name="place_bid"),
|
||||||
|
path("bid/<int:bid_id>/accept/", views.accept_bid, name="accept_bid"),
|
||||||
]
|
]
|
||||||
185
core/views.py
185
core/views.py
@ -1,25 +1,172 @@
|
|||||||
import os
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
import platform
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib.auth import login, authenticate
|
||||||
from django import get_version as django_version
|
from django.contrib.auth.forms import UserCreationForm
|
||||||
from django.shortcuts import render
|
|
||||||
from django.utils import timezone
|
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):
|
def home(request):
|
||||||
"""Render the landing screen with loader and environment details."""
|
"""Render the landing screen for MASAR CARGO."""
|
||||||
host_name = request.get_host().lower()
|
if request.user.is_authenticated:
|
||||||
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
|
return redirect('dashboard')
|
||||||
now = timezone.now()
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"project_name": "New Style",
|
"deployment_timestamp": timezone.now().timestamp(),
|
||||||
"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", ""),
|
|
||||||
}
|
}
|
||||||
return render(request, "core/index.html", context)
|
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)
|
||||||
|
|||||||
BIN
locale/ar/LC_MESSAGES/django.mo
Normal file
BIN
locale/ar/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
619
locale/ar/LC_MESSAGES/django.po
Normal file
619
locale/ar/LC_MESSAGES/django.po
Normal file
@ -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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\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 "كيف يعمل"
|
||||||
BIN
media/trucks/red_truk.jfif
Normal file
BIN
media/trucks/red_truk.jfif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@ -1,4 +1,131 @@
|
|||||||
/* Custom styles for the application */
|
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&family=Outfit:wght@400;600;700&display=swap');
|
||||||
body {
|
|
||||||
font-family: system-ui, -apple-system, sans-serif;
|
: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;
|
||||||
}
|
}
|
||||||
@ -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 {
|
:root {
|
||||||
--bg-color-start: #6a11cb;
|
--primary-color: #0A1D37;
|
||||||
--bg-color-end: #2575fc;
|
--secondary-color: #2196F3;
|
||||||
--text-color: #ffffff;
|
--accent-color: #00BCD4;
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
--bg-light: #F4F7F6;
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
--white: #FFFFFF;
|
||||||
|
--text-dark: #333333;
|
||||||
|
--text-muted: #666666;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-family: 'Outfit', 'Cairo', sans-serif;
|
||||||
|
background-color: var(--bg-light);
|
||||||
|
color: var(--text-dark);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'Inter', sans-serif;
|
overflow-x: hidden;
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
}
|
||||||
color: var(--text-color);
|
|
||||||
display: flex;
|
[lang="ar"] body {
|
||||||
justify-content: center;
|
direction: rtl;
|
||||||
align-items: center;
|
text-align: right;
|
||||||
min-height: 100vh;
|
}
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
.navbar {
|
||||||
position: relative;
|
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;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user