update29
This commit is contained in:
parent
9561e00531
commit
3b66669105
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -166,3 +166,25 @@ class RenewSubscriptionForm(forms.Form):
|
||||
widget=forms.Select(attrs={'class': 'form-select'}),
|
||||
label=_('Subscription Plan')
|
||||
)
|
||||
|
||||
class AppSettingForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AppSetting
|
||||
fields = '__all__'
|
||||
widgets = {
|
||||
'app_name': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'logo': forms.FileInput(attrs={'class': 'form-control'}),
|
||||
'slogan': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'registration_number': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'tax_number': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'contact_phone': forms.TextInput(attrs={'class': 'form-control'}),
|
||||
'contact_email': forms.EmailInput(attrs={'class': 'form-control'}),
|
||||
'contact_address': forms.Textarea(attrs={'class': 'form-control', 'rows': 2}),
|
||||
'terms_of_service': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
|
||||
'privacy_policy': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
|
||||
'subscription_enabled': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
||||
'shipper_monthly_fee': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
|
||||
'shipper_annual_fee': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
|
||||
'truck_owner_monthly_fee': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
|
||||
'truck_owner_annual_fee': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
|
||||
}
|
||||
@ -355,6 +355,19 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a href="{% url 'admin_app_settings' %}" class="card border-0 shadow-sm p-3 text-decoration-none text-dark h-100 hover-card">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="rounded-circle bg-light p-3 me-3 text-danger">
|
||||
<i class="fa-solid fa-sliders"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="mb-0 fw-bold">{% trans 'Application Settings' %}</h6>
|
||||
<small class="text-muted">{% trans 'Control fees, logo, and legal text' %}</small>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
145
core/templates/core/app_settings.html
Normal file
145
core/templates/core/app_settings.html
Normal file
@ -0,0 +1,145 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="mb-0">{% trans "Application Settings" %}</h2>
|
||||
<a href="{% url 'dashboard' %}" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-arrow-left"></i> {% trans "Back to Dashboard" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="post" enctype="multipart/form-data" class="card shadow-sm border-0">
|
||||
{% csrf_token %}
|
||||
<div class="card-body p-4">
|
||||
<h5 class="card-title mb-4 border-bottom pb-2">{% trans "General Information" %}</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.app_name.label }}</label>
|
||||
{{ form.app_name }}
|
||||
{% if form.app_name.errors %}<div class="text-danger small">{{ form.app_name.errors }}</div>{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.slogan.label }}</label>
|
||||
{{ form.slogan }}
|
||||
{% if form.slogan.errors %}<div class="text-danger small">{{ form.slogan.errors }}</div>{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.logo.label }}</label>
|
||||
{{ form.logo }}
|
||||
{% if form.logo.errors %}<div class="text-danger small">{{ form.logo.errors }}</div>{% endif %}
|
||||
{% if form.instance.logo %}
|
||||
<div class="mt-2">
|
||||
<img src="{{ form.instance.logo.url }}" alt="Logo" class="img-thumbnail" style="height: 50px;">
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title mt-5 mb-4 border-bottom pb-2">{% trans "Contact & Legal" %}</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.registration_number.label }}</label>
|
||||
{{ form.registration_number }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.tax_number.label }}</label>
|
||||
{{ form.tax_number }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.contact_phone.label }}</label>
|
||||
{{ form.contact_phone }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">{{ form.contact_email.label }}</label>
|
||||
{{ form.contact_email }}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">{{ form.contact_address.label }}</label>
|
||||
{{ form.contact_address }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title mt-5 mb-4 border-bottom pb-2">{% trans "Subscription Fees" %}</h5>
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch">
|
||||
{{ form.subscription_enabled }}
|
||||
<label class="form-check-label" for="{{ form.subscription_enabled.id_for_label }}">
|
||||
{{ form.subscription_enabled.label }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="fees-section" {% if not form.instance.subscription_enabled %}style="display:none;"{% endif %}>
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6">
|
||||
<div class="p-3 bg-light rounded">
|
||||
<h6 class="fw-bold mb-3">{% trans "Shipper Fees" %}</h6>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small">{{ form.shipper_monthly_fee.label }}</label>
|
||||
{{ form.shipper_monthly_fee }}
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label class="form-label small">{{ form.shipper_annual_fee.label }}</label>
|
||||
{{ form.shipper_annual_fee }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="p-3 bg-light rounded">
|
||||
<h6 class="fw-bold mb-3">{% trans "Truck Owner Fees" %}</h6>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small">{{ form.truck_owner_monthly_fee.label }}</label>
|
||||
{{ form.truck_owner_monthly_fee }}
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label class="form-label small">{{ form.truck_owner_annual_fee.label }}</label>
|
||||
{{ form.truck_owner_annual_fee }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title mt-5 mb-4 border-bottom pb-2">{% trans "Policies" %}</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label class="form-label">{{ form.terms_of_service.label }}</label>
|
||||
{{ form.terms_of_service }}
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">{{ form.privacy_policy.label }}</label>
|
||||
{{ form.privacy_policy }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer p-4 bg-white border-top-0">
|
||||
<button type="submit" class="btn btn-primary px-5 py-2">
|
||||
{% trans "Save All Changes" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const subEnabled = document.getElementById('{{ form.subscription_enabled.id_for_label }}');
|
||||
const feesSection = document.getElementById('fees-section');
|
||||
|
||||
if (subEnabled) {
|
||||
subEnabled.addEventListener('change', function() {
|
||||
if (this.checked) {
|
||||
feesSection.style.display = 'block';
|
||||
} else {
|
||||
feesSection.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -28,4 +28,5 @@ urlpatterns = [
|
||||
path("receipt/<str:receipt_number>/", views.transaction_receipt, name="transaction_receipt"),
|
||||
path("admin/financials/", views.admin_financials, name="admin_financials"),
|
||||
path("admin/refund/<str:receipt_number>/", views.issue_refund, name="issue_refund"),
|
||||
path("admin/settings/", views.admin_app_settings, name="admin_app_settings"),
|
||||
]
|
||||
@ -4,7 +4,10 @@ from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth import login, authenticate, logout
|
||||
from django.utils import timezone
|
||||
from .models import Profile, Truck, Shipment, Bid, Message, OTPCode, Country, City, AppSetting, Banner, HomeSection, Transaction
|
||||
from .forms import TruckForm, ShipmentForm, BidForm, UserRegistrationForm, OTPVerifyForm, ShipperOfferForm, RenewSubscriptionForm
|
||||
from .forms import (
|
||||
TruckForm, ShipmentForm, BidForm, UserRegistrationForm,
|
||||
OTPVerifyForm, ShipperOfferForm, RenewSubscriptionForm, AppSettingForm
|
||||
)
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import gettext as _
|
||||
from django.db.models import Q
|
||||
@ -583,3 +586,20 @@ def issue_refund(request, receipt_number):
|
||||
|
||||
messages.success(request, _("Refund issued successfully! Receipt: %(receipt)s") % {'receipt': refund.receipt_number})
|
||||
return redirect('admin_financials')
|
||||
|
||||
@login_required
|
||||
def admin_app_settings(request):
|
||||
if not (request.user.profile.role == 'ADMIN' or request.user.is_superuser):
|
||||
return redirect('dashboard')
|
||||
|
||||
settings_obj = AppSetting.objects.first()
|
||||
if request.method == 'POST':
|
||||
form = AppSettingForm(request.POST, request.FILES, instance=settings_obj)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, _("Application settings updated successfully."))
|
||||
return redirect('admin_app_settings')
|
||||
else:
|
||||
form = AppSettingForm(instance=settings_obj)
|
||||
|
||||
return render(request, 'core/app_settings.html', {'form': form})
|
||||
Loading…
x
Reference in New Issue
Block a user