Autosave: 20260126-125014
This commit is contained in:
parent
6943d83b2c
commit
59561573fc
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -254,9 +254,9 @@ class ParcelForm(forms.ModelForm):
|
||||
self.fields['receiver_phone_code'].queryset = Country.objects.exclude(phone_code='').order_by(name_field)
|
||||
self.fields['receiver_phone_code'].label_from_instance = lambda obj: f"{obj.phone_code} ({obj.name})"
|
||||
|
||||
# Default Country logic
|
||||
# Default Country logic (Oman) - Only if not editing
|
||||
oman = Country.objects.filter(name_en='Oman').first()
|
||||
if oman:
|
||||
if not self.instance.pk and oman:
|
||||
self.fields['receiver_phone_code'].initial = oman
|
||||
self.fields['pickup_country'].initial = oman
|
||||
self.fields['delivery_country'].initial = oman
|
||||
@ -283,6 +283,8 @@ class ParcelForm(forms.ModelForm):
|
||||
self.fields['pickup_governate'].queryset = Governate.objects.filter(country_id=country_id).order_by(name_field)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
elif self.instance.pk and self.instance.pickup_country:
|
||||
self.fields['pickup_governate'].queryset = Governate.objects.filter(country=self.instance.pickup_country).order_by(name_field)
|
||||
elif oman:
|
||||
self.fields['pickup_governate'].queryset = Governate.objects.filter(country=oman).order_by(name_field)
|
||||
|
||||
@ -292,6 +294,8 @@ class ParcelForm(forms.ModelForm):
|
||||
self.fields['pickup_city'].queryset = City.objects.filter(governate_id=gov_id).order_by(name_field)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
elif self.instance.pk and self.instance.pickup_governate:
|
||||
self.fields['pickup_city'].queryset = City.objects.filter(governate_id=self.instance.pickup_governate.id).order_by(name_field)
|
||||
|
||||
# Delivery
|
||||
self.fields['delivery_governate'].queryset = Governate.objects.none()
|
||||
@ -303,6 +307,8 @@ class ParcelForm(forms.ModelForm):
|
||||
self.fields['delivery_governate'].queryset = Governate.objects.filter(country_id=country_id).order_by(name_field)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
elif self.instance.pk and self.instance.delivery_country:
|
||||
self.fields['delivery_governate'].queryset = Governate.objects.filter(country=self.instance.delivery_country).order_by(name_field)
|
||||
elif oman:
|
||||
self.fields['delivery_governate'].queryset = Governate.objects.filter(country=oman).order_by(name_field)
|
||||
|
||||
@ -312,6 +318,8 @@ class ParcelForm(forms.ModelForm):
|
||||
self.fields['delivery_city'].queryset = City.objects.filter(governate_id=gov_id).order_by(name_field)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
elif self.instance.pk and self.instance.delivery_governate:
|
||||
self.fields['delivery_city'].queryset = City.objects.filter(governate_id=self.instance.delivery_governate.id).order_by(name_field)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<div class="container mt-5">
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Home" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
<h1>{{ article.title }}</h1>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Home -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Home" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
205
core/templates/core/edit_parcel.html
Normal file
205
core/templates/core/edit_parcel.html
Normal file
@ -0,0 +1,205 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<!-- Back to Dashboard -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm p-4" style="border-radius: 20px;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="mb-0">{% trans "Edit Shipment" %}</h2>
|
||||
<span class="badge bg-warning text-dark">{{ parcel.tracking_number }}</span>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="row g-3">
|
||||
<!-- General Info -->
|
||||
<div class="col-12">
|
||||
<label class="form-label" for="{{ form.description.id_for_label }}">{{ form.description.label }}</label>
|
||||
{{ form.description }}
|
||||
{% if form.description.errors %}
|
||||
<div class="text-danger small">{{ form.description.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.weight.id_for_label }}">{{ form.weight.label }}</label>
|
||||
{{ form.weight }}
|
||||
{% if form.weight.errors %}
|
||||
<div class="text-danger small">{{ form.weight.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.price.id_for_label }}">{{ form.price.label }}</label>
|
||||
{{ form.price }}
|
||||
{% if form.price.errors %}
|
||||
<div class="text-danger small">{{ form.price.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Pickup Details -->
|
||||
<div class="col-12 mt-4">
|
||||
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Pickup Details" %}</h4>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.pickup_country.id_for_label }}">{{ form.pickup_country.label }}</label>
|
||||
{{ form.pickup_country }}
|
||||
{% if form.pickup_country.errors %}
|
||||
<div class="text-danger small">{{ form.pickup_country.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.pickup_governate.id_for_label }}">{{ form.pickup_governate.label }}</label>
|
||||
{{ form.pickup_governate }}
|
||||
{% if form.pickup_governate.errors %}
|
||||
<div class="text-danger small">{{ form.pickup_governate.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.pickup_city.id_for_label }}">{{ form.pickup_city.label }}</label>
|
||||
{{ form.pickup_city }}
|
||||
{% if form.pickup_city.errors %}
|
||||
<div class="text-danger small">{{ form.pickup_city.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.pickup_address.id_for_label }}">{{ form.pickup_address.label }}</label>
|
||||
{{ form.pickup_address }}
|
||||
{% if form.pickup_address.errors %}
|
||||
<div class="text-danger small">{{ form.pickup_address.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Delivery Details -->
|
||||
<div class="col-12 mt-4">
|
||||
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Delivery Details" %}</h4>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.delivery_country.id_for_label }}">{{ form.delivery_country.label }}</label>
|
||||
{{ form.delivery_country }}
|
||||
{% if form.delivery_country.errors %}
|
||||
<div class="text-danger small">{{ form.delivery_country.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.delivery_governate.id_for_label }}">{{ form.delivery_governate.label }}</label>
|
||||
{{ form.delivery_governate }}
|
||||
{% if form.delivery_governate.errors %}
|
||||
<div class="text-danger small">{{ form.delivery_governate.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.delivery_city.id_for_label }}">{{ form.delivery_city.label }}</label>
|
||||
{{ form.delivery_city }}
|
||||
{% if form.delivery_city.errors %}
|
||||
<div class="text-danger small">{{ form.delivery_city.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.delivery_address.id_for_label }}">{{ form.delivery_address.label }}</label>
|
||||
{{ form.delivery_address }}
|
||||
{% if form.delivery_address.errors %}
|
||||
<div class="text-danger small">{{ form.delivery_address.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Receiver Details -->
|
||||
<div class="col-12 mt-4">
|
||||
<h4 class="mb-3 text-secondary border-bottom pb-2">{% trans "Receiver Details" %}</h4>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.receiver_name.id_for_label }}">{{ form.receiver_name.label }}</label>
|
||||
{{ form.receiver_name }}
|
||||
{% if form.receiver_name.errors %}
|
||||
<div class="text-danger small">{{ form.receiver_name.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label" for="{{ form.receiver_phone.id_for_label }}">{{ form.receiver_phone.label }}</label>
|
||||
<div class="d-flex gap-2">
|
||||
<div class="flex-shrink-0" style="width: 140px;">
|
||||
{{ form.receiver_phone_code }}
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
{{ form.receiver_phone }}
|
||||
</div>
|
||||
</div>
|
||||
{% if form.receiver_phone_code.errors %}
|
||||
<div class="text-danger small">{{ form.receiver_phone_code.errors }}</div>
|
||||
{% endif %}
|
||||
{% if form.receiver_phone.errors %}
|
||||
<div class="text-danger small">{{ form.receiver_phone.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4 d-flex gap-2">
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-outline-secondary w-50 py-3">{% trans "Cancel" %}</a>
|
||||
<button type="submit" class="btn btn-masarx-primary w-50 py-3">{% trans "Update Shipment" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
function setupDependentDropdowns(countryId, governateId, cityId) {
|
||||
const countrySelect = document.getElementById(countryId);
|
||||
const governateSelect = document.getElementById(governateId);
|
||||
const citySelect = document.getElementById(cityId);
|
||||
|
||||
if (!countrySelect || !governateSelect || !citySelect) return;
|
||||
|
||||
countrySelect.addEventListener('change', function() {
|
||||
const val = this.value;
|
||||
governateSelect.innerHTML = '<option value="">{% trans "Select Governate" %}</option>';
|
||||
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
|
||||
|
||||
if (val) {
|
||||
fetch(`{% url 'get_governates' %}?country_id=${val}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
data.forEach(item => {
|
||||
const option = document.createElement('option');
|
||||
option.value = item.id;
|
||||
option.textContent = item.name;
|
||||
governateSelect.appendChild(option);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
governateSelect.addEventListener('change', function() {
|
||||
const val = this.value;
|
||||
citySelect.innerHTML = '<option value="">{% trans "Select City" %}</option>';
|
||||
|
||||
if (val) {
|
||||
fetch(`{% url 'get_cities' %}?governate_id=${val}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
data.forEach(item => {
|
||||
const option = document.createElement('option');
|
||||
option.value = item.id;
|
||||
option.textContent = item.name;
|
||||
citySelect.appendChild(option);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setupDependentDropdowns('id_pickup_country', 'id_pickup_governate', 'id_pickup_city');
|
||||
setupDependentDropdowns('id_delivery_country', 'id_delivery_governate', 'id_delivery_city');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Profile -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'profile' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Profile" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Profile" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -4,14 +4,15 @@
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Invoice {{ parcel.tracking_number }}</title>
|
||||
<title>{% trans "Invoice" %} {{ parcel.tracking_number }}</title>
|
||||
<style>
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 2cm;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
/* Prioritize Noto Sans for Arabic support */
|
||||
font-family: 'Noto Sans', 'Noto Sans Arabic', 'DejaVu Sans', sans-serif;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
@ -113,7 +114,11 @@
|
||||
}
|
||||
.paid { color: #0f9d58; border: 1px solid #0f9d58; }
|
||||
.pending { color: #f4b400; border: 1px solid #f4b400; }
|
||||
.ar-text { direction: rtl; unicode-bidi: embed; }
|
||||
.ar-text {
|
||||
font-family: 'Noto Sans', 'Noto Sans Arabic', 'DejaVu Sans', sans-serif;
|
||||
direction: rtl;
|
||||
unicode-bidi: embed;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -225,4 +230,4 @@
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -3,109 +3,147 @@
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Label {{ parcel.tracking_number }}</title>
|
||||
<title>{% trans "Label" %} {{ parcel.tracking_number }}</title>
|
||||
<style>
|
||||
@page {
|
||||
size: 100mm 150mm;
|
||||
margin: 0;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif; /* WeasyPrint uses system fonts. Ensure Arabic font is available. */
|
||||
/* Prioritize Noto Sans for Arabic support */
|
||||
font-family: 'Noto Sans', 'Noto Sans Arabic', 'DejaVu Sans', sans-serif;
|
||||
margin: 0;
|
||||
padding: 5mm;
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
width: 100mm;
|
||||
height: 150mm;
|
||||
color: #000;
|
||||
font-size: 10px; /* Reduced base font size */
|
||||
overflow: hidden; /* Prevent spillover */
|
||||
}
|
||||
.container {
|
||||
width: 94mm;
|
||||
height: 144mm; /* Reduced height to be safely inside 150mm */
|
||||
margin: 3mm auto; /* 3mm top/bottom margin */
|
||||
border: 2px solid #000;
|
||||
height: 138mm;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
page-break-inside: avoid;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.header {
|
||||
border-bottom: 2px solid #000;
|
||||
padding: 5px;
|
||||
padding: 3px;
|
||||
text-align: center;
|
||||
height: 20mm;
|
||||
height: 18mm; /* Reduced */
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.header img {
|
||||
max-height: 15mm;
|
||||
max-width: 80mm;
|
||||
max-height: 100%;
|
||||
max-width: 90%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 16px; /* Reduced */
|
||||
}
|
||||
.big-code {
|
||||
font-size: 20px;
|
||||
font-size: 16px; /* Reduced */
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
padding: 4px;
|
||||
border-bottom: 2px solid #000;
|
||||
background-color: #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
height: 10mm;
|
||||
}
|
||||
.address-box {
|
||||
border-bottom: 1px solid #000;
|
||||
padding: 8px;
|
||||
padding: 5px;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
font-size: 10px; /* Reduced */
|
||||
}
|
||||
.main-info {
|
||||
display: flex;
|
||||
border-bottom: 2px solid #000;
|
||||
flex-shrink: 0;
|
||||
height: 14mm; /* Reduced */
|
||||
}
|
||||
.section {
|
||||
padding: 8px;
|
||||
padding: 2px;
|
||||
flex: 1;
|
||||
border-right: 1px solid #000;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.section:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
.qr-code {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
padding: 3px;
|
||||
border-bottom: 2px solid #000;
|
||||
flex-shrink: 0;
|
||||
height: 30mm; /* Reduced */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.qr-code img {
|
||||
width: 30mm;
|
||||
height: 30mm;
|
||||
width: 22mm; /* Reduced */
|
||||
height: 22mm;
|
||||
}
|
||||
.tracking-number {
|
||||
font-size: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-top: 2px;
|
||||
font-family: monospace;
|
||||
}
|
||||
.footer {
|
||||
padding: 5px;
|
||||
padding: 3px;
|
||||
text-align: center;
|
||||
font-size: 9px;
|
||||
font-size: 8px; /* Reduced */
|
||||
flex-shrink: 0;
|
||||
height: 8mm;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
h3 {
|
||||
margin: 0 0 5px 0;
|
||||
font-size: 10px;
|
||||
margin: 0 0 2px 0;
|
||||
font-size: 9px;
|
||||
text-transform: uppercase;
|
||||
color: #333;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
padding-bottom: 2px;
|
||||
padding-bottom: 1px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h3 span.ar { font-weight: normal; }
|
||||
p { margin: 0 0 2px 0; line-height: 1.2; }
|
||||
.bold { font-weight: bold; font-size: 13px; }
|
||||
p { margin: 0 0 1px 0; line-height: 1.1; }
|
||||
.bold { font-weight: bold; font-size: 11px; }
|
||||
.dual-text {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px;
|
||||
}
|
||||
.ar-text {
|
||||
font-family: sans-serif;
|
||||
font-family: 'Noto Sans', 'Noto Sans Arabic', 'DejaVu Sans', sans-serif;
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
<div class="text-center mt-4">
|
||||
<a href="{% url 'login' %}" class="text-decoration-none text-muted">
|
||||
<i class="bi bi-arrow-left me-1"></i> {% trans "Back to Login" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-1"></i> {% trans "Back to Login" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<div class="container py-5">
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Home" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
<h1>{% trans "Privacy Policy" %}</h1>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Dashboard -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Dashboard" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -5,6 +5,13 @@
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<!-- Back to Dashboard -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 rounded-4">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Home -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Home" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0">{% trans "Scan Parcel QR" %}</h1>
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-left"></i> {% trans "Back to Dashboard" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %}"></i> {% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<!-- Back to Dashboard -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Dashboard" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -61,6 +61,17 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{% if parcel.status == 'pending' %}
|
||||
<div class="d-flex gap-2 mb-2">
|
||||
<a href="{% url 'edit_parcel' parcel.id %}" class="btn btn-sm btn-outline-info w-100" title="{% trans 'Edit Shipment' %}">
|
||||
<i class="fas fa-edit me-1"></i> {% trans "Edit" %}
|
||||
</a>
|
||||
<a href="{% url 'cancel_parcel' parcel.id %}" class="btn btn-sm btn-outline-danger w-100" title="{% trans 'Cancel Shipment' %}" onclick="return confirm('{% trans "Are you sure you want to cancel this shipment?" %}');">
|
||||
<i class="fas fa-times me-1"></i> {% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if parcel.payment_status == 'pending' %}
|
||||
{% if payments_enabled %}
|
||||
<a href="{% url 'initiate_payment' parcel.id %}" class="btn btn-sm btn-outline-primary w-100 mb-2">
|
||||
@ -126,6 +137,15 @@
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 w-100 justify-content-md-end">
|
||||
{% if parcel.status == 'pending' %}
|
||||
<a href="{% url 'edit_parcel' parcel.id %}" class="btn btn-sm btn-outline-info" title="{% trans 'Edit' %}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a href="{% url 'cancel_parcel' parcel.id %}" class="btn btn-sm btn-outline-danger" title="{% trans 'Cancel' %}" onclick="return confirm('{% trans "Are you sure you want to cancel this shipment?" %}');">
|
||||
<i class="fas fa-times"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<a href="{% url 'generate_parcel_label' parcel.id %}" class="btn btn-sm btn-outline-dark" target="_blank" title="{% trans 'Print Label' %}">
|
||||
<i class="fas fa-print"></i>
|
||||
</a>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<div class="container py-5">
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Home" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
<h1>{% trans "Terms and Conditions" %}</h1>
|
||||
|
||||
@ -7,6 +7,13 @@
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<!-- Back to Home -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'index' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Home" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 rounded-4">
|
||||
<div class="card-body p-4 p-md-5">
|
||||
<h2 class="text-center mb-4">{% trans "Track Your Shipment" %}</h2>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Edit Profile -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'edit_profile' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Edit Profile" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Edit Profile" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<!-- Back to Register -->
|
||||
<div class="mb-4">
|
||||
<a href="{% url 'register' %}" class="btn btn-link text-decoration-none text-muted ps-0">
|
||||
<i class="bi bi-arrow-left me-2"></i>{% trans "Back to Register" %}
|
||||
<i class="bi {% if LANGUAGE_BIDI %}bi-arrow-right{% else %}bi-arrow-left{% endif %} me-2"></i>{% trans "Back to Register" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -34,6 +34,8 @@ urlpatterns = [
|
||||
path('dashboard/', views.dashboard, name='dashboard'),
|
||||
path('scan-qr/', views.scan_qr_view, name='scan_qr'),
|
||||
path('shipment-request/', views.shipment_request, name='shipment_request'),
|
||||
path('parcel/<int:parcel_id>/edit/', views.edit_parcel, name='edit_parcel'),
|
||||
path('parcel/<int:parcel_id>/cancel/', views.cancel_parcel, name='cancel_parcel'),
|
||||
path('track/', views.track_parcel, name='track'),
|
||||
path('accept-parcel/<int:parcel_id>/', views.accept_parcel, name='accept_parcel'),
|
||||
path('update-status/<int:parcel_id>/', views.update_status, name='update_status'),
|
||||
|
||||
@ -848,4 +848,36 @@ def update_parcel_status_ajax(request):
|
||||
return JsonResponse({'success': True})
|
||||
|
||||
except Exception as e:
|
||||
return JsonResponse({'success': False, 'error': str(e)})
|
||||
return JsonResponse({'success': False, 'error': str(e)})
|
||||
|
||||
@login_required
|
||||
def edit_parcel(request, parcel_id):
|
||||
parcel = get_object_or_404(Parcel, id=parcel_id, shipper=request.user)
|
||||
|
||||
if parcel.status != 'pending':
|
||||
messages.error(request, _("You can only edit pending shipments."))
|
||||
return redirect('dashboard')
|
||||
|
||||
if request.method == 'POST':
|
||||
form = ParcelForm(request.POST, instance=parcel)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, _("Shipment updated successfully."))
|
||||
return redirect('dashboard')
|
||||
else:
|
||||
form = ParcelForm(instance=parcel)
|
||||
|
||||
return render(request, 'core/edit_parcel.html', {'form': form, 'parcel': parcel})
|
||||
|
||||
@login_required
|
||||
def cancel_parcel(request, parcel_id):
|
||||
parcel = get_object_or_404(Parcel, id=parcel_id, shipper=request.user)
|
||||
|
||||
if parcel.status != 'pending':
|
||||
messages.error(request, _("You can only cancel pending shipments."))
|
||||
else:
|
||||
parcel.status = 'cancelled'
|
||||
parcel.save()
|
||||
messages.success(request, _("Shipment cancelled successfully."))
|
||||
|
||||
return redirect('dashboard')
|
||||
|
||||
Binary file not shown.
@ -772,7 +772,8 @@ msgstr "مرحباً،"
|
||||
msgid ""
|
||||
"You are receiving this email because you requested a password reset for your "
|
||||
"account at"
|
||||
msgstr "تتلقى هذه الرسالة لأنك طلبت إعادة تعيين كلمة المرور لحسابك في"
|
||||
msgstr ""
|
||||
"تتلقى هذه الرسالة لأنك طلبت إعادة تعيين كلمة المرور لحسابك في"
|
||||
|
||||
#: core/templates/core/emails/password_reset_email.html:11
|
||||
msgid "Please click the button below to choose a new password:"
|
||||
@ -879,7 +880,8 @@ msgstr "أدرج طردك"
|
||||
#: core/templates/core/index.html:64
|
||||
msgid ""
|
||||
"Enter shipment details, weight, and delivery addresses. It's quick and easy."
|
||||
msgstr "أدخل تفاصيل الشحنة والوزن وعناوين التوصيل. إنه سريع وسهل."
|
||||
msgstr ""
|
||||
"أدخل تفاصيل الشحنة والوزن وعناوين التوصيل. إنه سريع وسهل."
|
||||
|
||||
#: core/templates/core/index.html:72
|
||||
msgid "Connect with Driver"
|
||||
@ -888,7 +890,8 @@ msgstr "تواصل مع السائق"
|
||||
#: core/templates/core/index.html:73
|
||||
msgid ""
|
||||
"A verified car owner near you picks up the parcel and starts the journey."
|
||||
msgstr "يقوم صاحب سيارة تم التحقق منه بالقرب منك باستلام الطرد وبدء الرحلة."
|
||||
msgstr ""
|
||||
"يقوم صاحب سيارة تم التحقق منه بالقرب منك باستلام الطرد وبدء الرحلة."
|
||||
|
||||
#: core/templates/core/index.html:81
|
||||
msgid "Secure Delivery"
|
||||
@ -1330,3 +1333,60 @@ msgstr "لا توجد شحنات بعد. ابدأ الشحن الآن!"
|
||||
|
||||
msgid "Shipments"
|
||||
msgstr "شحنات"
|
||||
|
||||
msgid "Track Shipment"
|
||||
msgstr "تتبع الشحنة"
|
||||
|
||||
msgid "Track Your Shipment"
|
||||
msgstr "تتبع شحنتك"
|
||||
|
||||
msgid "Enter Tracking ID (e.g. TRK123456789)"
|
||||
msgstr "أدخل رقم التتبع (مثال: TRK123456789)"
|
||||
|
||||
msgid "Shipment Status"
|
||||
msgstr "حالة الشحنة"
|
||||
|
||||
msgid "Order Placed"
|
||||
msgstr "تم الطلب"
|
||||
|
||||
msgid "On the Way"
|
||||
msgstr "في الطريق"
|
||||
|
||||
msgid "Current Status"
|
||||
msgstr "الحالة الحالية"
|
||||
|
||||
msgid "Last Updated"
|
||||
msgstr "آخر تحديث"
|
||||
|
||||
msgid "Enter your tracking number above to see shipment details."
|
||||
msgstr "أدخل رقم التتبع أعلاه لرؤية تفاصيل الشحنة."
|
||||
|
||||
msgid "Label"
|
||||
msgstr "الملصق"
|
||||
|
||||
msgid "Invoice"
|
||||
msgstr "الفاتورة"
|
||||
|
||||
msgid "Edit"
|
||||
msgstr "تعديل"
|
||||
|
||||
msgid "Edit Shipment"
|
||||
msgstr "تعديل الشحنة"
|
||||
|
||||
msgid "Cancel Shipment"
|
||||
msgstr "إلغاء الشحنة"
|
||||
|
||||
msgid "Print Label"
|
||||
msgstr "طباعة الملصق"
|
||||
|
||||
msgid "Are you sure you want to cancel this shipment?"
|
||||
msgstr "هل أنت متأكد أنك تريد إلغاء هذه الشحنة؟"
|
||||
|
||||
msgid "Point your camera at the Parcel Label QR Code"
|
||||
msgstr "وجه الكاميرا نحو رمز الاستجابة السريعة (QR) الخاص بالملصق"
|
||||
|
||||
msgid "Scan QR Code"
|
||||
msgstr "مسح رمز الاستجابة السريعة"
|
||||
|
||||
msgid "Tracking No"
|
||||
msgstr "رقم التتبع"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user