diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc
index e97298a..c5d4013 100644
Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ
diff --git a/config/settings.py b/config/settings.py
index 066e1f2..1c26d7f 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -196,3 +196,13 @@ LOCALE_PATHS = [
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
+
+from django.contrib.messages import constants as messages
+MESSAGE_TAGS = {
+ messages.DEBUG: 'secondary',
+ messages.INFO: 'info',
+ messages.SUCCESS: 'success',
+ messages.WARNING: 'warning',
+ messages.ERROR: 'danger',
+}
+
diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc
new file mode 100644
index 0000000..ba213a6
Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ
diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc
index e5c3557..00c55ae 100644
Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ
diff --git a/core/forms.py b/core/forms.py
new file mode 100644
index 0000000..a294740
--- /dev/null
+++ b/core/forms.py
@@ -0,0 +1,52 @@
+from django import forms
+from .models import Truck, Shipment, Bid
+from django.utils.translation import gettext_lazy as _
+
+class TruckForm(forms.ModelForm):
+ class Meta:
+ model = Truck
+ fields = [
+ 'truck_type', 'model', 'year', 'plate_no',
+ 'load_capacity', 'color', 'truck_picture',
+ 'registration_front', 'registration_back', 'driver_license'
+ ]
+ widgets = {
+ 'truck_type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('e.g. Flatbed, Trailer')}),
+ 'model': 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'}),
+ 'color': 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'}),
+ 'driver_license': forms.FileInput(attrs={'class': 'form-control'}),
+ }
+
+class ShipmentForm(forms.ModelForm):
+ class Meta:
+ model = Shipment
+ fields = ['description', 'weight', 'origin', 'destination', 'delivery_date']
+ widgets = {
+ 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
+ 'weight': forms.TextInput(attrs={'class': 'form-control'}),
+ 'origin': forms.TextInput(attrs={'class': 'form-control'}),
+ 'destination': forms.TextInput(attrs={'class': 'form-control'}),
+ 'delivery_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
+ }
+
+class BidForm(forms.ModelForm):
+ class Meta:
+ model = Bid
+ fields = ['truck', 'amount', 'comments']
+ widgets = {
+ 'truck': forms.Select(attrs={'class': 'form-select'}),
+ 'amount': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
+ 'comments': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
+ }
+
+ def __init__(self, *args, **kwargs):
+ user = kwargs.pop('user', None)
+ super().__init__(*args, **kwargs)
+ if user:
+ self.fields['truck'].queryset = Truck.objects.filter(owner=user)
\ No newline at end of file
diff --git a/core/templates/core/admin_dashboard.html b/core/templates/core/admin_dashboard.html
new file mode 100644
index 0000000..dd8715d
--- /dev/null
+++ b/core/templates/core/admin_dashboard.html
@@ -0,0 +1,104 @@
+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Admin Dashboard" %} - MASAR CARGO{% endblock %}
+
+{% block content %}
+
+
+
+
{% trans "Administrator Dashboard" %}
+
{% trans "System overview and management" %}
+
+
+
+
+
+
+
+
+
{{ total_users }}
+
{% trans "Total Users" %}
+
+
+
+
+
+
{{ total_trucks }}
+
{% trans "Registered Trucks" %}
+
+
+
+
+
+
{{ total_shipments }}
+
{% trans "Total Shipments" %}
+
+
+
+
+
+
{{ total_bids }}
+
{% trans "Active Bids" %}
+
+
+
+
+
+
{% trans "Quick Actions" %}
+
+
+
+
+
+{% endblock %}
diff --git a/core/templates/core/place_bid.html b/core/templates/core/place_bid.html
index 8a4e79e..ea68a77 100644
--- a/core/templates/core/place_bid.html
+++ b/core/templates/core/place_bid.html
@@ -13,27 +13,33 @@
{% trans "Goods:" %} {{ shipment.description }}
- {% if trucks %}
+ {% if form.errors %}
+
+ {% trans "Please correct the errors below." %}
+ {{ form.non_field_errors }}
+
+ {% endif %}
+
+ {% if form.fields.truck.queryset.exists %}
@@ -48,4 +54,4 @@
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/core/templates/core/post_shipment.html b/core/templates/core/post_shipment.html
index 4a3303e..4e89f1e 100644
--- a/core/templates/core/post_shipment.html
+++ b/core/templates/core/post_shipment.html
@@ -8,29 +8,42 @@
{% trans "Post a New Shipment" %}
+
+ {% if form.errors %}
+
+ {% trans "Please correct the errors below." %}
+ {{ form.non_field_errors }}
+
+ {% endif %}
+
@@ -39,4 +52,4 @@
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/core/templates/core/truck_register.html b/core/templates/core/truck_register.html
index c3ac686..832064c 100644
--- a/core/templates/core/truck_register.html
+++ b/core/templates/core/truck_register.html
@@ -8,35 +8,49 @@
{% trans "Register a Truck" %}
+
+ {% if form.errors %}
+
+ {% trans "Please correct the errors below." %}
+ {{ form.non_field_errors }}
+
+ {% endif %}
+
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/core/views.py b/core/views.py
index e03d3f5..32e746d 100644
--- a/core/views.py
+++ b/core/views.py
@@ -4,14 +4,14 @@ from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.utils import timezone
from .models import Profile, Truck, Shipment, Bid, Message
+from .forms import TruckForm, ShipmentForm, BidForm
from django.contrib import messages
from django.utils.translation import gettext as _
from django.db.models import Q
+from django.contrib.auth.models import User
def home(request):
"""Render the landing screen for MASAR CARGO."""
- if request.user.is_authenticated:
- return redirect('dashboard')
context = {
"deployment_timestamp": timezone.now().timestamp(),
}
@@ -47,8 +47,17 @@ def dashboard(request):
'trucks': my_trucks,
'bids': my_bids
})
+ elif profile.role == 'ADMIN' or request.user.is_superuser:
+ context = {
+ 'total_users': User.objects.count(),
+ 'total_trucks': Truck.objects.count(),
+ 'total_shipments': Shipment.objects.count(),
+ 'total_bids': Bid.objects.count(),
+ }
+ return render(request, 'core/admin_dashboard.html', context)
else:
- return redirect('/admin/')
+ # Fallback for undefined roles
+ return redirect('/')
@login_required
def truck_register(request):
@@ -56,30 +65,19 @@ def truck_register(request):
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')
+ form = TruckForm(request.POST, request.FILES)
+ if form.is_valid():
+ truck = form.save(commit=False)
+ truck.owner = request.user
+ truck.save()
+ messages.success(request, _("Truck registered successfully!"))
+ return redirect('dashboard')
+ else:
+ messages.error(request, _("There was an error in your registration. Please check the form."))
+ else:
+ form = TruckForm()
- return render(request, 'core/truck_register.html')
+ return render(request, 'core/truck_register.html', {'form': form})
@login_required
def post_shipment(request):
@@ -120,31 +118,28 @@ def place_bid(request, 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')
+ form = BidForm(request.POST, user=request.user)
+ if form.is_valid():
+ bid = form.save(commit=False)
+ bid.truck_owner = request.user
+ bid.shipment = shipment
+ bid.save()
+ messages.success(request, _("Bid placed successfully!"))
+ return redirect('marketplace')
+ else:
+ messages.error(request, _("Error placing bid. Please check the form."))
+ else:
+ form = BidForm(user=request.user)
- return render(request, 'core/place_bid.html', {'shipment': shipment, 'trucks': my_trucks})
+ return render(request, 'core/place_bid.html', {'form': form, 'shipment': shipment})
@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':
+ if request.user.profile.role != 'ADMIN' and not request.user.is_superuser:
return redirect('dashboard')
bids = shipment.bids.all()