This commit is contained in:
Flatlogic Bot 2026-01-23 10:53:11 +00:00
parent 9a495913c0
commit e6e1b4b0ec
12 changed files with 509 additions and 198 deletions

View File

@ -34,17 +34,21 @@ class TruckForm(forms.ModelForm):
class Meta:
model = Truck
fields = [
'truck_type', 'model', 'year', 'plate_no',
'load_capacity', 'color', 'truck_picture',
'truck_type', 'truck_type_ar', 'model', 'model_ar', 'year', 'plate_no',
'load_capacity', 'load_capacity_ar', 'color', 'color_ar', 'truck_picture',
'registration_front', 'registration_back', 'driver_license'
]
widgets = {
'truck_type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('e.g. Flatbed, Trailer')}),
'truck_type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('e.g. Flatbed')}),
'truck_type_ar': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('مثلا سطحة')}),
'model': forms.TextInput(attrs={'class': 'form-control'}),
'model_ar': forms.TextInput(attrs={'class': 'form-control'}),
'year': forms.NumberInput(attrs={'class': 'form-control'}),
'plate_no': forms.TextInput(attrs={'class': 'form-control'}),
'load_capacity': forms.TextInput(attrs={'class': 'form-control'}),
'load_capacity_ar': forms.TextInput(attrs={'class': 'form-control'}),
'color': forms.TextInput(attrs={'class': 'form-control'}),
'color_ar': forms.TextInput(attrs={'class': 'form-control'}),
'truck_picture': forms.FileInput(attrs={'class': 'form-control'}),
'registration_front': forms.FileInput(attrs={'class': 'form-control'}),
'registration_back': forms.FileInput(attrs={'class': 'form-control'}),
@ -80,4 +84,4 @@ class BidForm(forms.ModelForm):
# Only allow bidding with approved trucks
self.fields['truck'].queryset = Truck.objects.filter(owner=user, is_approved=True)
if not self.fields['truck'].queryset.exists():
self.fields['truck'].help_text = _("You must have an approved truck to place a bid.")
self.fields['truck'].help_text = _("You must have an approved truck to place a bid.")

View File

@ -0,0 +1,53 @@
# Generated by Django 5.2.7 on 2026-01-23 10:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0003_truck_is_approved'),
]
operations = [
migrations.AddField(
model_name='truck',
name='color_ar',
field=models.CharField(blank=True, max_length=50, verbose_name='Color (AR)'),
),
migrations.AddField(
model_name='truck',
name='load_capacity_ar',
field=models.CharField(blank=True, max_length=100, verbose_name='Load Capacity (AR)'),
),
migrations.AddField(
model_name='truck',
name='model_ar',
field=models.CharField(blank=True, max_length=100, verbose_name='Model (AR)'),
),
migrations.AddField(
model_name='truck',
name='truck_type_ar',
field=models.CharField(blank=True, max_length=100, verbose_name='Truck Type (AR)'),
),
migrations.AlterField(
model_name='truck',
name='color',
field=models.CharField(max_length=50, verbose_name='Color (EN)'),
),
migrations.AlterField(
model_name='truck',
name='load_capacity',
field=models.CharField(max_length=100, verbose_name='Load Capacity (EN)'),
),
migrations.AlterField(
model_name='truck',
name='model',
field=models.CharField(max_length=100, verbose_name='Model (EN)'),
),
migrations.AlterField(
model_name='truck',
name='truck_type',
field=models.CharField(max_length=100, verbose_name='Truck Type (EN)'),
),
]

View File

@ -3,6 +3,7 @@ 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 _
from django.utils.translation import get_language
class Profile(models.Model):
ROLE_CHOICES = (
@ -19,12 +20,21 @@ class Profile(models.Model):
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)
# English fields
truck_type = models.CharField(_('Truck Type (EN)'), max_length=100)
model = models.CharField(_('Model (EN)'), max_length=100)
load_capacity = models.CharField(_('Load Capacity (EN)'), max_length=100)
color = models.CharField(_('Color (EN)'), max_length=50)
# Arabic fields
truck_type_ar = models.CharField(_('Truck Type (AR)'), max_length=100, blank=True)
model_ar = models.CharField(_('Model (AR)'), max_length=100, blank=True)
load_capacity_ar = models.CharField(_('Load Capacity (AR)'), max_length=100, blank=True)
color_ar = models.CharField(_('Color (AR)'), max_length=50, blank=True)
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)
@ -36,7 +46,31 @@ class Truck(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.truck_type} - {self.plate_no}"
return f"{self.display_truck_type} - {self.plate_no}"
@property
def display_truck_type(self):
if get_language() == 'ar' and self.truck_type_ar:
return self.truck_type_ar
return self.truck_type
@property
def display_model(self):
if get_language() == 'ar' and self.model_ar:
return self.model_ar
return self.model
@property
def display_load_capacity(self):
if get_language() == 'ar' and self.load_capacity_ar:
return self.load_capacity_ar
return self.load_capacity
@property
def display_color(self):
if get_language() == 'ar' and self.color_ar:
return self.color_ar
return self.color
class Shipment(models.Model):
STATUS_CHOICES = (
@ -97,4 +131,4 @@ def save_user_profile(sender, instance, **kwargs):
if hasattr(instance, 'profile'):
instance.profile.save()
else:
Profile.objects.create(user=instance)
Profile.objects.create(user=instance)

View File

@ -69,19 +69,19 @@
<tr>
<td>{{ truck.owner.username }}<br><small class="text-muted">{{ truck.owner.email }}</small></td>
<td>
<strong>{{ truck.truck_type }}</strong><br>
<small>{{ truck.model }} ({{ truck.year }}) - {{ truck.color }}</small>
<strong>{{ truck.display_truck_type }}</strong><br>
<small>{{ truck.display_model }} ({{ truck.year }}) - {{ truck.display_color }}</small>
</td>
<td>{{ truck.plate_no }}</td>
<td class="text-end">
<button type="button" class="btn btn-outline-info btn-sm me-2 view-truck-btn"
data-bs-toggle="modal" data-bs-target="#truckDetailsModal"
data-truck-type="{{ truck.truck_type }}"
data-truck-model="{{ truck.model }}"
data-truck-type="{{ truck.display_truck_type }}"
data-truck-model="{{ truck.display_model }}"
data-truck-year="{{ truck.year }}"
data-truck-plate="{{ truck.plate_no }}"
data-truck-capacity="{{ truck.load_capacity }}"
data-truck-color="{{ truck.color }}"
data-truck-capacity="{{ truck.display_load_capacity }}"
data-truck-color="{{ truck.display_color }}"
data-truck-owner="{{ truck.owner.username }}"
data-truck-picture="{% if truck.truck_picture %}{{ truck.truck_picture.url }}{% endif %}"
data-reg-front="{% if truck.registration_front %}{{ truck.registration_front.url }}{% endif %}"
@ -126,19 +126,19 @@
<tr>
<td>{{ truck.owner.username }}</td>
<td>
<strong>{{ truck.truck_type }}</strong><br>
<small>{{ truck.model }} ({{ truck.year }})</small>
<strong>{{ truck.display_truck_type }}</strong><br>
<small>{{ truck.display_model }} ({{ truck.year }})</small>
</td>
<td>{{ truck.plate_no }}</td>
<td class="text-end">
<button type="button" class="btn btn-outline-info btn-sm me-2 view-truck-btn"
data-bs-toggle="modal" data-bs-target="#truckDetailsModal"
data-truck-type="{{ truck.truck_type }}"
data-truck-model="{{ truck.model }}"
data-truck-type="{{ truck.display_truck_type }}"
data-truck-model="{{ truck.display_model }}"
data-truck-year="{{ truck.year }}"
data-truck-plate="{{ truck.plate_no }}"
data-truck-capacity="{{ truck.load_capacity }}"
data-truck-color="{{ truck.color }}"
data-truck-capacity="{{ truck.display_load_capacity }}"
data-truck-color="{{ truck.display_color }}"
data-truck-owner="{{ truck.owner.username }}"
data-truck-picture="{% if truck.truck_picture %}{{ truck.truck_picture.url }}{% endif %}"
data-reg-front="{% if truck.registration_front %}{{ truck.registration_front.url }}{% endif %}"

View File

@ -49,7 +49,7 @@
{% for bid in bids %}
<tr>
<td>{{ bid.truck_owner.username }}</td>
<td>{{ bid.truck.truck_type }}</td>
<td>{{ bid.truck.display_truck_type }}</td>
<td>${{ bid.amount }}</td>
<td>
<a href="{% url 'accept_bid' bid.id %}" class="btn btn-sm btn-success">{% trans "Accept" %}</a>
@ -72,7 +72,7 @@
<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 }})
{% trans "Assigned Truck:" %} {{ shipment.assigned_truck.display_truck_type }} ({{ shipment.assigned_truck.plate_no }})
</div>
</div>
<div class="mt-4">
@ -98,4 +98,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -27,17 +27,17 @@
<div class="col-md-4 mb-4">
<div class="card h-100 shadow-sm border-0">
{% if truck.truck_picture %}
<img src="{{ truck.truck_picture.url }}" class="card-img-top" alt="{{ truck.truck_type }}" style="height: 200px; object-fit: cover;">
<img src="{{ truck.truck_picture.url }}" class="card-img-top" alt="{{ truck.display_truck_type }}" style="height: 200px; object-fit: cover;">
{% else %}
<div class="bg-light d-flex align-items-center justify-content-center" style="height: 200px;">
<i class="fa-solid fa-truck fa-4x text-secondary"></i>
</div>
{% endif %}
<div class="card-body">
<h5 class="card-title">{{ truck.truck_type }}</h5>
<h5 class="card-title">{{ truck.display_truck_type }}</h5>
<p class="card-text mb-1"><strong>{% trans "Plate No:" %}</strong> {{ truck.plate_no }}</p>
<p class="card-text mb-1"><strong>{% trans "Model:" %}</strong> {{ truck.model }} ({{ truck.year }})</p>
<p class="card-text mb-1"><strong>{% trans "Capacity:" %}</strong> {{ truck.load_capacity }}</p>
<p class="card-text mb-1"><strong>{% trans "Model:" %}</strong> {{ truck.display_model }} ({{ truck.year }})</p>
<p class="card-text mb-1"><strong>{% trans "Capacity:" %}</strong> {{ truck.display_load_capacity }}</p>
</div>
<div class="card-footer bg-white border-0">
<span class="badge bg-success w-100 py-2">{% trans "Approved" %}</span>
@ -60,7 +60,7 @@
<div class="col-md-4 mb-4">
<div class="card h-100 shadow-sm border-0 opacity-75">
<div class="card-body">
<h5 class="card-title text-muted">{{ truck.truck_type }}</h5>
<h5 class="card-title text-muted">{{ truck.display_truck_type }}</h5>
<p class="card-text mb-1"><strong>{% trans "Plate No:" %}</strong> {{ truck.plate_no }}</p>
<p class="card-text">{% trans "Submitted on:" %} {{ truck.created_at|date }}</p>
</div>

View File

@ -4,7 +4,7 @@
{% block content %}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="col-md-10">
<div class="card shadow">
<div class="card-body p-5">
<h2 class="mb-4">{% trans "Register a Truck" %}</h2>
@ -18,39 +18,70 @@
<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>
{{ form.truck_type }}
{{ form.truck_type.errors }}
<div class="col-md-6 border-end">
<h5 class="mb-3 text-primary">{% trans "English Details" %}</h5>
<div class="mb-3">
<label class="form-label">{{ form.truck_type.label }}</label>
{{ form.truck_type }}
{{ form.truck_type.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.model.label }}</label>
{{ form.model }}
{{ form.model.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.load_capacity.label }}</label>
{{ form.load_capacity }}
{{ form.load_capacity.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.color.label }}</label>
{{ form.color }}
{{ form.color.errors }}
</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">{% trans "Model" %}</label>
{{ form.model }}
{{ form.model.errors }}
<div class="col-md-6">
<h5 class="mb-3 text-success">{% trans "Arabic Details" %}</h5>
<div class="mb-3">
<label class="form-label">{{ form.truck_type_ar.label }}</label>
{{ form.truck_type_ar }}
{{ form.truck_type_ar.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.model_ar.label }}</label>
{{ form.model_ar }}
{{ form.model_ar.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.load_capacity_ar.label }}</label>
{{ form.load_capacity_ar }}
{{ form.load_capacity_ar.errors }}
</div>
<div class="mb-3">
<label class="form-label">{{ form.color_ar.label }}</label>
{{ form.color_ar }}
{{ form.color_ar.errors }}
</div>
</div>
</div>
<hr class="my-4">
<h5 class="mb-3">{% trans "General Information" %}</h5>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label">{% trans "Year" %}</label>
<div class="col-md-6 mb-3">
<label class="form-label">{{ form.year.label }}</label>
{{ form.year }}
{{ form.year.errors }}
</div>
<div class="col-md-4 mb-3">
<label class="form-label">{% trans "Plate No" %}</label>
<div class="col-md-6 mb-3">
<label class="form-label">{{ form.plate_no.label }}</label>
{{ form.plate_no }}
{{ form.plate_no.errors }}
</div>
<div class="col-md-4 mb-3">
<label class="form-label">{% trans "Color" %}</label>
{{ form.color }}
{{ form.color.errors }}
</div>
</div>
<div class="mb-3">
<label class="form-label">{% trans "Load Capacity (e.g. 20 Tons)" %}</label>
{{ form.load_capacity }}
{{ form.load_capacity.errors }}
</div>
<hr class="my-4">

Binary file not shown.

File diff suppressed because it is too large Load Diff