adding some features
This commit is contained in:
parent
856be645ab
commit
e1e791abf6
BIN
assets/pasted-20260201-075032-c186b500.png
Normal file
BIN
assets/pasted-20260201-075032-c186b500.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/pasted-20260201-081838-f3ed2987.png
Normal file
BIN
assets/pasted-20260201-081838-f3ed2987.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -24,19 +24,26 @@ class ProfileInline(admin.StackedInline):
|
||||
verbose_name_plural = _('Profiles')
|
||||
fieldsets = (
|
||||
(None, {'fields': ('role', 'is_approved', 'phone_number', 'profile_picture', 'address')}),
|
||||
(_('Driver Assessment'), {'fields': ('driver_grade', 'is_recommended')}),
|
||||
(_('Driver Info'), {'fields': ('license_front_image', 'license_back_image', 'car_plate_number', 'bank_account_number'), 'classes': ('collapse',)}),
|
||||
(_('Location'), {'fields': ('country', 'governate', 'city'), 'classes': ('collapse',)}),
|
||||
)
|
||||
|
||||
class CustomUserAdmin(UserAdmin):
|
||||
inlines = (ProfileInline,)
|
||||
list_display = ('username', 'email', 'get_role', 'get_approval_status', 'is_active', 'is_staff', 'send_whatsapp_link')
|
||||
list_filter = ('is_active', 'is_staff', 'profile__role', 'profile__is_approved')
|
||||
list_display = ('username', 'email', 'get_role', 'get_driver_grade', 'get_approval_status', 'is_active', 'is_staff', 'send_whatsapp_link')
|
||||
list_filter = ('is_active', 'is_staff', 'profile__role', 'profile__is_approved', 'profile__driver_grade')
|
||||
|
||||
def get_role(self, obj):
|
||||
return obj.profile.get_role_display()
|
||||
get_role.short_description = _('Role')
|
||||
|
||||
def get_driver_grade(self, obj):
|
||||
if obj.profile.role == 'car_owner':
|
||||
return obj.profile.get_driver_grade_display()
|
||||
return "-"
|
||||
get_driver_grade.short_description = _('Grade')
|
||||
|
||||
def get_approval_status(self, obj):
|
||||
return obj.profile.is_approved
|
||||
get_approval_status.short_description = _('Approved')
|
||||
@ -192,6 +199,10 @@ class PlatformProfileAdmin(admin.ModelAdmin):
|
||||
(_('Financial Configuration'), {
|
||||
'fields': ('platform_fee_percentage', 'enable_payment')
|
||||
}),
|
||||
(_('Maintenance / Availability'), {
|
||||
'fields': ('accepting_shipments', 'maintenance_message_en', 'maintenance_message_ar'),
|
||||
'description': _('Toggle to allow or stop receiving new parcel shipments. If stopped, buttons will turn red and an alert will be shown.')
|
||||
}),
|
||||
(_('Testing / Development'), {
|
||||
'fields': ('auto_mark_paid',),
|
||||
'description': _('Enable this to automatically mark NEW parcels as "Paid" (useful for testing so drivers can see them immediately).')
|
||||
|
||||
@ -47,6 +47,10 @@ class ParcelListCreateView(generics.ListCreateAPIView):
|
||||
return Parcel.objects.none()
|
||||
|
||||
def perform_create(self, serializer):
|
||||
from .models import PlatformProfile
|
||||
platform_profile = PlatformProfile.objects.first()
|
||||
if platform_profile and not platform_profile.accepting_shipments:
|
||||
raise permissions.PermissionDenied(platform_profile.maintenance_message or "The platform is currently not accepting new shipments.")
|
||||
# Only shippers can create
|
||||
if self.request.user.profile.role != 'shipper':
|
||||
raise permissions.PermissionDenied("Only shippers can create parcels.")
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.7 on 2026-02-01 12:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0026_profile_bank_account_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='driver_grade',
|
||||
field=models.CharField(choices=[('none', 'No Grade'), ('bronze_3', 'Bronze III'), ('bronze_2', 'Bronze II'), ('bronze_1', 'Bronze I'), ('silver', 'Silver'), ('gold', 'Gold')], default='none', max_length=20, verbose_name='Driver Grade'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='is_recommended',
|
||||
field=models.BooleanField(default=False, verbose_name='Recommended by Shippers'),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.2.7 on 2026-02-01 13:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0027_profile_driver_grade_profile_is_recommended'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='platformprofile',
|
||||
name='accepting_shipments',
|
||||
field=models.BooleanField(default=True, help_text='Toggle to allow or stop receiving new parcel shipments.', verbose_name='Accepting Shipments'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformprofile',
|
||||
name='maintenance_message_ar',
|
||||
field=models.TextField(blank=True, help_text='Message to show when shipments are stopped.', verbose_name='Maintenance Message (Arabic)'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='platformprofile',
|
||||
name='maintenance_message_en',
|
||||
field=models.TextField(blank=True, help_text='Message to show when shipments are stopped.', verbose_name='Maintenance Message (English)'),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
@ -65,8 +65,16 @@ class City(models.Model):
|
||||
|
||||
class Profile(models.Model):
|
||||
ROLE_CHOICES = (
|
||||
('shipper', _('Shipper')),
|
||||
('car_owner', _('Car Owner')),
|
||||
("shipper", _("Shipper")),
|
||||
("car_owner", _("Car Owner")),
|
||||
)
|
||||
DRIVER_GRADE_CHOICES = (
|
||||
("none", _("No Grade")),
|
||||
("bronze_3", _("Bronze III")),
|
||||
("bronze_2", _("Bronze II")),
|
||||
("bronze_1", _("Bronze I")),
|
||||
("silver", _("Silver")),
|
||||
("gold", _("Gold")),
|
||||
)
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name=_('User'))
|
||||
role = models.CharField(_('Role'), max_length=20, choices=ROLE_CHOICES, default='shipper')
|
||||
@ -85,6 +93,10 @@ class Profile(models.Model):
|
||||
city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('City'))
|
||||
|
||||
# Approval Status
|
||||
# Driver Assessment
|
||||
driver_grade = models.CharField(_("Driver Grade"), max_length=20, choices=DRIVER_GRADE_CHOICES, default="none")
|
||||
is_recommended = models.BooleanField(_("Recommended by Shippers"), default=False)
|
||||
|
||||
is_approved = models.BooleanField(_('Approved'), default=False, help_text=_("Designates whether this user is approved to use the platform (mainly for drivers)."))
|
||||
|
||||
def __str__(self):
|
||||
@ -166,6 +178,17 @@ class PlatformProfile(models.Model):
|
||||
# Testing / Development
|
||||
auto_mark_paid = models.BooleanField(_('Test Mode: Auto-Paid'), default=False, help_text=_("If enabled, newly created parcels will automatically be marked as 'Paid' for testing."))
|
||||
|
||||
# Maintenance / Availability
|
||||
accepting_shipments = models.BooleanField(_("Accepting Shipments"), default=True, help_text=_("Toggle to allow or stop receiving new parcel shipments."))
|
||||
maintenance_message_en = models.TextField(_("Maintenance Message (English)"), blank=True, help_text=_("Message to show when shipments are stopped."))
|
||||
maintenance_message_ar = models.TextField(_("Maintenance Message (Arabic)"), blank=True, help_text=_("Message to show when shipments are stopped."))
|
||||
|
||||
@property
|
||||
def maintenance_message(self):
|
||||
if get_language() == "ar":
|
||||
return self.maintenance_message_ar or _("Service is temporarily suspended. Please try again later.")
|
||||
return self.maintenance_message_en or _("Service is temporarily suspended. Please try again later.")
|
||||
|
||||
@property
|
||||
def privacy_policy(self):
|
||||
if get_language() == 'ar':
|
||||
|
||||
@ -170,7 +170,7 @@
|
||||
|
||||
{% if not user.is_authenticated %}
|
||||
<li class="nav-item ms-lg-3 d-none d-lg-block">
|
||||
<a href="{% url 'shipment_request' %}" class="btn btn-masarx-primary btn-sm rounded-pill px-4">{% trans "Start Shipping" %}</a>
|
||||
{% if platform_profile.accepting_shipments %}<a href="{% url 'shipment_request' %}" class="btn btn-masarx-active btn-sm rounded-pill px-4">{% trans "Start Shipping" %}</a>{% else %}<button class="btn btn-masarx-stopped btn-sm rounded-pill px-4" disabled title="{{ platform_profile.maintenance_message }}">{% trans "Stopped" %}</button>{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
@ -2,6 +2,14 @@
|
||||
{% load static i18n %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<style>
|
||||
.bg-bronze { background-color: #cd7f32; }
|
||||
.bg-silver { background-color: #c0c0c0; }
|
||||
.bg-gold { background-color: #ffd700; }
|
||||
.text-bronze { color: #cd7f32; }
|
||||
</style>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section">
|
||||
<div class="container">
|
||||
@ -9,8 +17,13 @@
|
||||
<div class="col-lg-6 mb-5 mb-lg-0">
|
||||
<h1 class="display-3 mb-4">{% trans "Small Shipments," %}<br><span style="color: var(--accent-orange)">{% trans "Smart Delivery." %}</span></h1>
|
||||
<p class="lead mb-5 opacity-75">{% trans "masarX connects shippers with local car owners for fast, reliable, and trackable deliveries. Your cargo, our priority." %}</p>
|
||||
{% if not platform_profile.accepting_shipments and platform_profile.maintenance_message %}
|
||||
<div class="alert alert-danger mb-4 py-2 px-3 small border-0 shadow-sm" style="border-radius: 12px; max-width: 500px;">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i> {{ platform_profile.maintenance_message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-flex gap-3">
|
||||
<a href="{% url 'shipment_request' %}" class="btn btn-masarx-primary">{% trans "Start Shipping" %}</a>
|
||||
{% if platform_profile.accepting_shipments %}<a href="{% url 'shipment_request' %}" class="btn btn-masarx-active">{% trans "Start Shipping" %}</a>{% else %}<button class="btn btn-masarx-stopped" disabled style="cursor: not-allowed;">{% trans "Service Stopped" %}</button>{% endif %}
|
||||
<a href="#how-it-works" class="btn btn-outline-light border-2 px-4 py-2" style="border-radius: 12px;">{% trans "Learn More" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -94,7 +107,21 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-0">{{ driver.user.first_name }} {{ driver.user.last_name|first }}.</h6>
|
||||
<h6 class="mb-0">
|
||||
{{ driver.user.first_name }} {{ driver.user.last_name|first }}.
|
||||
{% if driver.driver_grade != "none" %}
|
||||
{% if "bronze" in driver.driver_grade %}
|
||||
<span class="badge bg-bronze text-white small" title="{{ driver.get_driver_grade_display }}"><i class="bi bi-award"></i> {{ driver.get_driver_grade_display }}</span>
|
||||
{% elif driver.driver_grade == "silver" %}
|
||||
<span class="badge bg-silver text-dark small" title="Silver"><i class="bi bi-award-fill"></i> Silver</span>
|
||||
{% elif driver.driver_grade == "gold" %}
|
||||
<span class="badge bg-gold text-dark small" title="Gold"><i class="bi bi-award-fill"></i> Gold</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if driver.is_recommended %}
|
||||
<span class="badge bg-success small" title="{% trans "Recommended by Shippers" %}"><i class="bi bi-hand-thumbs-up"></i></span>
|
||||
{% endif %}
|
||||
</h6>
|
||||
<small class="text-muted">{% trans "Driver" %}</small>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
|
||||
@ -4,6 +4,13 @@
|
||||
{% block title %}{% trans "My Profile" %} | masarX{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<style>
|
||||
.bg-bronze { background-color: #cd7f32; }
|
||||
.bg-silver { background-color: #c0c0c0; }
|
||||
.bg-gold { background-color: #ffd700; }
|
||||
</style>
|
||||
|
||||
<section class="py-5 bg-light" style="min-height: 80vh;">
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
@ -32,7 +39,21 @@
|
||||
<span class="text-white fs-1">{{ profile.user.first_name|first|upper }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<h3 class="mt-3">{{ profile.user.get_full_name }}</h3>
|
||||
<h3 class="mt-3">
|
||||
{{ profile.user.get_full_name }}
|
||||
{% if profile.driver_grade != "none" %}
|
||||
{% if "bronze" in profile.driver_grade %}
|
||||
<span class="badge bg-bronze text-white fs-6 ms-2" title="{{ profile.get_driver_grade_display }}"><i class="bi bi-award"></i> {{ profile.get_driver_grade_display }}</span>
|
||||
{% elif profile.driver_grade == "silver" %}
|
||||
<span class="badge bg-silver text-dark fs-6 ms-2" title="Silver"><i class="bi bi-award-fill"></i> Silver</span>
|
||||
{% elif profile.driver_grade == "gold" %}
|
||||
<span class="badge bg-gold text-dark fs-6 ms-2" title="Gold"><i class="bi bi-award-fill"></i> Gold</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if profile.is_recommended %}
|
||||
<span class="badge bg-success fs-6 ms-2" title="{% trans "Recommended by Shippers" %}"><i class="bi bi-hand-thumbs-up"></i></span>
|
||||
{% endif %}
|
||||
</h3>
|
||||
<p class="text-muted">{{ profile.get_role_display }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
@ -2,10 +2,26 @@
|
||||
{% load i18n core_tags %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<style>
|
||||
.bg-bronze { background-color: #cd7f32; }
|
||||
.bg-silver { background-color: #c0c0c0; }
|
||||
.bg-gold { background-color: #ffd700; }
|
||||
</style>
|
||||
|
||||
<div class="container py-5">
|
||||
{% if not platform_profile.accepting_shipments and platform_profile.maintenance_message %}
|
||||
<div class="alert alert-danger mb-4 py-3 px-4 shadow-sm border-0 d-flex align-items-center" style="border-radius: 15px;">
|
||||
<i class="bi bi-exclamation-triangle-fill fs-4 me-3"></i>
|
||||
<div>
|
||||
<h5 class="alert-heading mb-1">{% trans "Service Notice" %}</h5>
|
||||
<p class="mb-0 opacity-75">{{ platform_profile.maintenance_message }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1>{% trans "My Shipments" %}</h1>
|
||||
<a href="{% url 'shipment_request' %}" class="btn btn-masarx-primary">{% trans "New Shipment" %}</a>
|
||||
{% if platform_profile.accepting_shipments %}<a href="{% url 'shipment_request' %}" class="btn btn-masarx-active">{% trans "New Shipment" %}</a>{% else %}<button class="btn btn-masarx-stopped" disabled style="cursor: not-allowed;">{% trans "Service Stopped" %}</button>{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Tabs -->
|
||||
@ -97,7 +113,24 @@
|
||||
|
||||
<hr>
|
||||
<p class="card-text small mb-0"><strong>{% trans "Receiver" %}:</strong> {{ parcel.receiver_name }}</p>
|
||||
<p class="card-text small"><strong>{% trans "Carrier" %}:</strong> {% if parcel.carrier %}{{ parcel.carrier.get_full_name|default:parcel.carrier.username }}{% else %}{% trans "Waiting for pickup" %}{% endif %}</p>
|
||||
<p class="card-text small"><strong>{% trans "Carrier" %}:</strong>
|
||||
{% if parcel.carrier %}
|
||||
{{ parcel.carrier.get_full_name|default:parcel.carrier.username }}
|
||||
{% if parcel.carrier.profile.driver_grade != "none" %}
|
||||
{% if "bronze" in parcel.carrier.profile.driver_grade %}
|
||||
<span class="badge bg-bronze text-white small ms-1" title="{{ parcel.carrier.profile.get_driver_grade_display }}}"><i class="bi bi-award"></i></span>
|
||||
{% elif parcel.carrier.profile.driver_grade == "silver" %}
|
||||
<span class="badge bg-silver text-dark small ms-1" title="Silver"><i class="bi bi-award-fill"></i></span>
|
||||
{% elif parcel.carrier.profile.driver_grade == "gold" %}
|
||||
<span class="badge bg-gold text-dark small ms-1" title="Gold"><i class="bi bi-award-fill"></i></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if parcel.carrier.profile.is_recommended %}
|
||||
<span class="badge bg-success small ms-1" title="{% trans "Recommended by Shippers" %}"><i class="bi bi-hand-thumbs-up"></i></span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% trans "Waiting for pickup" %}
|
||||
{% endif %}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -130,7 +163,23 @@
|
||||
</span>
|
||||
<span class="d-flex align-items-center gap-1">
|
||||
<i class="bi bi-truck"></i>
|
||||
{% if parcel.carrier %}{{ parcel.carrier.get_full_name|default:parcel.carrier.username }}{% else %}{% trans "Waiting" %}{% endif %}
|
||||
{% if parcel.carrier %}
|
||||
{{ parcel.carrier.get_full_name|default:parcel.carrier.username }}
|
||||
{% if parcel.carrier.profile.driver_grade != "none" %}
|
||||
{% if "bronze" in parcel.carrier.profile.driver_grade %}
|
||||
<span class="badge bg-bronze text-white small ms-1" title="{{ parcel.carrier.profile.get_driver_grade_display }}}"><i class="bi bi-award"></i></span>
|
||||
{% elif parcel.carrier.profile.driver_grade == "silver" %}
|
||||
<span class="badge bg-silver text-dark small ms-1" title="Silver"><i class="bi bi-award-fill"></i></span>
|
||||
{% elif parcel.carrier.profile.driver_grade == "gold" %}
|
||||
<span class="badge bg-gold text-dark small ms-1" title="Gold"><i class="bi bi-award-fill"></i></span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if parcel.carrier.profile.is_recommended %}
|
||||
<span class="badge bg-success small ms-1" title="{% trans "Recommended by Shippers" %}"><i class="bi bi-hand-thumbs-up"></i></span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% trans "Waiting" %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -223,7 +272,7 @@
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<p class="lead">{% trans "You have no active shipments." %}</p>
|
||||
<a href="{% url 'shipment_request' %}" class="btn btn-masarx-primary">{% trans "Send your first shipment" %}</a>
|
||||
{% if platform_profile.accepting_shipments %}<a href="{% url 'shipment_request' %}" class="btn btn-masarx-active">{% trans "Send your first shipment" %}</a>{% else %}<button class="btn btn-masarx-stopped" disabled style="cursor: not-allowed;">{% trans "Service Stopped" %}</button>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@ -286,6 +286,11 @@ def dashboard(request):
|
||||
|
||||
@login_required
|
||||
def shipment_request(request):
|
||||
from .models import PlatformProfile
|
||||
platform_profile = PlatformProfile.objects.first()
|
||||
if platform_profile and not platform_profile.accepting_shipments:
|
||||
messages.warning(request, platform_profile.maintenance_message or _("The platform is currently not accepting new shipments."))
|
||||
return redirect("dashboard")
|
||||
profile, created = Profile.objects.get_or_create(user=request.user)
|
||||
if profile.role != 'shipper':
|
||||
messages.error(request, _("Only shippers can request shipments."))
|
||||
|
||||
@ -239,3 +239,30 @@ h1, h2, h3, h4, h5, h6 {
|
||||
[dir="rtl"] .text-left {
|
||||
text-align: right !important;
|
||||
}
|
||||
/* Shipment Status Buttons */
|
||||
.btn-masarx-active {
|
||||
background-color: #2fb344 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 12px 30px !important;
|
||||
border-radius: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.btn-masarx-active:hover {
|
||||
background-color: #248a35 !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(47, 179, 68, 0.2);
|
||||
}
|
||||
.btn-masarx-stopped {
|
||||
background-color: #d63939 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 12px 30px !important;
|
||||
border-radius: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.btn-masarx-stopped:hover {
|
||||
background-color: #b02a2a !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(214, 57, 57, 0.2);
|
||||
}
|
||||
|
||||
@ -26,11 +26,12 @@ h1, h2, h3, h4, h5, h6 {
|
||||
flex-direction: row !important;
|
||||
align-items: center !important;
|
||||
justify-content: space-between !important;
|
||||
flex-wrap: nowrap !important; /* Ensure they stay on one line */
|
||||
flex-wrap: nowrap !important;
|
||||
gap: 2px !important;
|
||||
width: 100% !important;
|
||||
box-sizing: border-box !important;
|
||||
/* overflow: hidden; Removed to allow dropdown list to show */
|
||||
position: relative !important;
|
||||
z-index: 100 !important;
|
||||
}
|
||||
|
||||
/* Hide any stray shortcuts that might have survived JS cleanup */
|
||||
@ -39,14 +40,21 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
|
||||
.masar-date-filter-row select {
|
||||
appearance: auto !important; /* Force native dropdown appearance */
|
||||
-webkit-appearance: auto !important;
|
||||
-moz-appearance: auto !important;
|
||||
|
||||
width: 32% !important;
|
||||
min-width: 0 !important;
|
||||
font-size: 11px !important;
|
||||
padding: 0 2px !important;
|
||||
padding: 2px !important; /* Relaxed padding */
|
||||
height: 28px !important;
|
||||
line-height: 1 !important;
|
||||
box-sizing: border-box !important;
|
||||
margin: 0 !important;
|
||||
background-color: white !important;
|
||||
border: 1px solid #ced4da !important;
|
||||
border-radius: 4px !important;
|
||||
color: #495057 !important;
|
||||
}
|
||||
|
||||
.masar-date-filter-row input {
|
||||
@ -57,22 +65,23 @@ h1, h2, h3, h4, h5, h6 {
|
||||
height: 28px !important;
|
||||
margin: 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
background-color: white !important;
|
||||
border: 1px solid #ced4da !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
|
||||
/* Specific fix for date inputs to ensure they look clean */
|
||||
.masar-date-filter-row input[type="date"] {
|
||||
-webkit-appearance: none; /* Remove some browser defaults */
|
||||
appearance: none;
|
||||
line-height: 28px;
|
||||
}
|
||||
.masar-date-filter-row input[type="date"]::-webkit-inner-spin-button,
|
||||
.masar-date-filter-row input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
/* Make the calendar icon smaller and fit */
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@ -230,3 +239,30 @@ h1, h2, h3, h4, h5, h6 {
|
||||
[dir="rtl"] .text-left {
|
||||
text-align: right !important;
|
||||
}
|
||||
/* Shipment Status Buttons */
|
||||
.btn-masarx-active {
|
||||
background-color: #2fb344 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 12px 30px !important;
|
||||
border-radius: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.btn-masarx-active:hover {
|
||||
background-color: #248a35 !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(47, 179, 68, 0.2);
|
||||
}
|
||||
.btn-masarx-stopped {
|
||||
background-color: #d63939 !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 12px 30px !important;
|
||||
border-radius: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.btn-masarx-stopped:hover {
|
||||
background-color: #b02a2a !important;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(214, 57, 57, 0.2);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
(function($) {
|
||||
// Masar Date Range Filter Layout Fix v4
|
||||
// Masar Date Range Filter Layout Fix v5
|
||||
// Forces a horizontal layout for the Date Range Filter in Django Admin Sidebar
|
||||
// v4: Switches to type="date", removes Django's calendar shortcuts to prevent layout breakage.
|
||||
// v5: Removes Bootstrap classes from Select to ensure native popup works reliably.
|
||||
|
||||
function initDateRangeDropdown() {
|
||||
|
||||
@ -30,7 +30,8 @@
|
||||
var $wrapper = $('<div class="masar-date-filter-row"></div>');
|
||||
|
||||
// Create the Quick Select Dropdown
|
||||
var $select = $('<select class="form-control custom-select admin-date-dropdown">' +
|
||||
// REMOVED 'form-control' and 'custom-select' to prevent Bootstrap/AdminLTE from interfering with click/rendering
|
||||
var $select = $('<select class="admin-date-dropdown">' +
|
||||
'<option value="any">Any</option>' +
|
||||
'<option value="today">Today</option>' +
|
||||
'<option value="7days">7 Days</option>' +
|
||||
@ -39,7 +40,6 @@
|
||||
'</select>');
|
||||
|
||||
// CONVERT INPUTS TO HTML5 DATE
|
||||
// This gives us a native picker and removes the need for Django's clunky JS shortcuts
|
||||
$gte.attr('type', 'date').removeClass('vDateField');
|
||||
$lte.attr('type', 'date').removeClass('vDateField');
|
||||
|
||||
@ -53,8 +53,6 @@
|
||||
$wrapper.append($lte);
|
||||
|
||||
// 3. AGGRESSIVE CLEANUP
|
||||
// Remove text nodes, BRs, AND Django's calendar shortcuts (.datetimeshortcuts)
|
||||
// We search the *original parent* for these leftovers.
|
||||
$parent.contents().filter(function() {
|
||||
return (
|
||||
(this.nodeType === 3 && $.trim($(this).text()) !== '') || // Text
|
||||
@ -63,9 +61,6 @@
|
||||
);
|
||||
}).remove();
|
||||
|
||||
// Also hide any shortcuts that might be dynamically appended later (via CSS rule or observer)
|
||||
// But removing the 'vDateField' class above usually prevents Django from initializing them.
|
||||
|
||||
// Logic for Dropdown Changes
|
||||
function formatDate(d) {
|
||||
var year = d.getFullYear();
|
||||
@ -87,7 +82,7 @@
|
||||
var today = new Date();
|
||||
|
||||
if (val === 'custom') {
|
||||
// Do nothing, let user edit
|
||||
// Do nothing
|
||||
} else {
|
||||
if (val === 'any') {
|
||||
$gte.val('');
|
||||
|
||||
BIN
staticfiles/pasted-20260201-075032-c186b500.png
Normal file
BIN
staticfiles/pasted-20260201-075032-c186b500.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
staticfiles/pasted-20260201-081838-f3ed2987.png
Normal file
BIN
staticfiles/pasted-20260201-081838-f3ed2987.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Loading…
x
Reference in New Issue
Block a user