Add IntelliJ IDEA project configuration files

This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.
master
kikimor 8 months ago
parent 0eefaad424
commit 78d570ad4f

@ -5,26 +5,39 @@
</component>
<component name="ChangeListManager">
<list default="true" id="7410a44d-51b9-408b-85ad-4fa46776b372" name="Changes" comment="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<change afterPath="$PROJECT_DIR$/common/urls.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/static/styles/styles.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/client-dashboard-original.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/landing-page.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/users/forms.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/users/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DepoT/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/settings.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/DepoT/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/DepoT/urls.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/static/styles/forms.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/employee-base.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/employee-dashboard-content.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/employee-sidebar.html" afterDir="false" />
<change afterPath="$PROJECT_DIR$/templates/recent.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/admin.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/forms.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/models.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/accounts/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/accounts/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/urls.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/views.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client-base.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-base.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client-booking-content.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-booking-content.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/client-sidebar.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/client-sidebar.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/registration/login.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/registration/login.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/templates/registration/register.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/registration/register.html" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ChangesViewManager" show_ignored="true" />
<component name="DjangoConsoleOptions" custom-start-script="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)">
<option name="myCustomStartScript" value="import sys; print('Python %s on %s' % (sys.version, sys.platform))&#10;import django; print('Django %s' % django.get_version())&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;if 'setup' in dir(django): django.setup()&#10;import django_manage_shell; django_manage_shell.run(PROJECT_ROOT)" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="HTML File" />
<option value="Python Script" />
<option value="CSS File" />
<option value="HTML File" />
</list>
</option>
</component>
@ -48,17 +61,24 @@
"RunOnceActivity.ShowReadmeOnStart": "true",
"django.template.preview.state": "SHOW_EDITOR_AND_PREVIEW",
"git-widget-placeholder": "master",
"last_opened_file_path": "C:/dev_projects/python/Django/DepoT/templates",
"last_opened_file_path": "C:/dev_projects/python/Django/DepoT/templates/registration",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"vue.rearranger.settings.migration": "true"
},
"keyToStringList": {
"DatabaseDriversLRU": [
"postgresql"
]
}
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\dev_projects\python\Django\DepoT\templates\registration" />
<recent name="C:\dev_projects\python\Django\DepoT\templates" />
<recent name="C:\dev_projects\python\Django\DepoT\static\styles" />
</key>
@ -106,7 +126,7 @@
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1750784740296</updated>
<workItem from="1750784741367" duration="29605000" />
<workItem from="1750784741367" duration="164972000" />
</task>
<task id="LOCAL-00001" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
@ -124,7 +144,55 @@
<option name="project" value="LOCAL" />
<updated>1750855273832</updated>
</task>
<option name="localTasksCounter" value="3" />
<task id="LOCAL-00003" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1750942491703</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1750942491703</updated>
</task>
<task id="LOCAL-00004" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1750942543055</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1750942543055</updated>
</task>
<task id="LOCAL-00005" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1750942560128</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1750942560128</updated>
</task>
<task id="LOCAL-00006" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1751295996186</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1751295996186</updated>
</task>
<task id="LOCAL-00007" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1751359397230</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1751359397230</updated>
</task>
<task id="LOCAL-00008" summary="Add IntelliJ IDEA project configuration files&#10;&#10;This commit adds IntelliJ IDEA-specific configuration files for the project, including module setup, version control integration, inspection profiles, and workspace settings. These files facilitate development environment configuration for contributors using IntelliJ IDEA.">
<option name="closed" value="true" />
<created>1751443902965</created>
<option name="number" value="00008" />
<option name="presentableId" value="LOCAL-00008" />
<option name="project" value="LOCAL" />
<updated>1751443902965</updated>
</task>
<option name="localTasksCounter" value="9" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -138,11 +206,18 @@
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/common/views.py</url>
<line>22</line>
<option name="timeStamp" value="1" />
<url>file://$PROJECT_DIR$/containers/views.py</url>
<line>35</line>
<option name="timeStamp" value="13" />
</line-breakpoint>
</breakpoints>
<default-breakpoints>
<breakpoint type="python-exception">
<properties notifyOnTerminate="true" exception="BaseException">
<option name="notifyOnTerminate" value="true" />
</properties>
</breakpoint>
</default-breakpoints>
</breakpoint-manager>
</component>
</project>

@ -12,13 +12,14 @@ class DepotUserAdmin(UserAdmin):
'company',
'line',
'company_permissions',
'new_field1',
'is_company_admin',
'user_type',
)}),
)
# Add fields to display in list view
list_display = UserAdmin.list_display + ('phone_number', 'company', 'line', 'is_company_admin')
list_display = ('username', 'email', 'user_type', 'company', 'line', 'is_active', 'is_staff', 'is_superuser')
search_fields = ('username', 'email')
list_filter = ('user_type', 'is_active', 'is_staff', 'is_superuser')
# Add fields to the add form
add_fieldsets = UserAdmin.add_fieldsets + (
@ -28,7 +29,6 @@ class DepotUserAdmin(UserAdmin):
'company',
'line',
'company_permissions',
'new_field1',
'is_company_admin',
'user_type',
)}),
)

@ -16,18 +16,25 @@ class RegisterForm(ModelForm):
password1 = CharField(label='Password', widget=PasswordInput)
password2 = CharField(label='Confirm Password', widget=PasswordInput)
field_order = ['username', 'email', 'password1', 'password2', 'phone_number', 'line', 'company_permissions']
field_order = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
class Meta:
model = get_user_model()
fields = ['username', 'email', 'password1', 'password2', 'phone_number', 'line', 'company_permissions']
fields = ['username', 'email', 'password1', 'password2', 'phone_number', 'company', 'line', 'user_type', 'company_permissions', 'employee_permissions', 'is_active']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password1'].widget.attrs.update({'autocomplete': 'new-password'})
self.fields['password2'].widget.attrs.update({'autocomplete': 'new-password'})
self.fields['user_type'].widget.attrs['disabled'] = True
self.fields['company_permissions'].widget.attrs['disabled'] = True
self.fields['employee_permissions'].widget.attrs['disabled'] = True
if self.data.get('user_type') in ( 'EM', 'BS'):
self.fields['company_permissions'].required = False
if self.data.get('user_type') in ('CL', 'CA', 'BS'):
self.fields['company_permissions'].required = False
def clean(self):
cleaned_data = super().clean()

@ -1,3 +1,4 @@
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import AbstractUser
from django.db import models
@ -13,11 +14,69 @@ class ClientPermission(models.Model):
('can_view_bookings', 'Can view bookings'),
('can_manage_company_users', 'Can manage company users'),
)
def __str__(self):
return self.name
class EmployeePermission(models.Model):
codename = models.CharField(max_length=100, default='')
name = models.CharField(max_length=255, default='')
class Meta:
managed = True
default_permissions = ()
permissions = (
('can_manage_containers', 'Can manage containers'),
('can_view_reports', 'Can view reports'),
('can_handle_operations', 'Can handle operations'),
)
def __str__(self):
return self.name
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Users must have an email address')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('user_type', 'AD') # Set user_type to admin
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(email, password, **extra_fields)
class DepotUser(AbstractUser):
class UserType(models.TextChoices):
BARRIER_STAFF = 'BS', 'Barrier Staff'
COMPANY_ADMIN = 'CA', 'Company Admin'
EMPLOYEE = 'EM', 'Employee'
CLIENT = 'CL', 'Client',
ADMIN = 'AD', 'Admin'
objects = CustomUserManager()
user_type = models.CharField(
max_length=2,
choices=UserType.choices,
default=UserType.CLIENT
)
phone_number = models.CharField(max_length=15, blank=True, null=True)
email = models.EmailField(unique=True, blank=False, null=False)
company = models.ForeignKey(
@ -36,13 +95,14 @@ class DepotUser(AbstractUser):
)
company_permissions = models.ManyToManyField('ClientPermission')
new_field1 = models.BooleanField(default=False)
is_company_admin = models.BooleanField(default=False)
employee_permissions = models.ManyToManyField('EmployeePermission', blank=True)
def has_company_perm(self, perm_codename):
if self.is_superuser:
return True
return self.company_permissions.filter(
codename=perm_codename,
is_client_permission=self.company
).exists()
return self.company_permissions.filter(codename=perm_codename).exists()
def has_employee_perm(self, perm_codename):
if self.is_superuser:
return True
return self.employee_permissions.filter(codename=perm_codename).exists()

@ -2,12 +2,17 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.views import LoginView
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView, FormView, ListView, UpdateView
from accounts.forms import LoginForm, RegisterForm
from accounts.models import DepotUser
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.mixins import AccessMixin
# Create your views here.
class DepotLoginView(LoginView):
template_name = 'registration/login.html'
# success_url = reverse_lazy('dashboard')
@ -15,19 +20,71 @@ class DepotLoginView(LoginView):
next_page = reverse_lazy('dashboard')
class RegisterView(FormView):
def is_company_admin(user):
return user.is_authenticated and user.is_company_admin
@method_decorator(login_required, name='dispatch')
class RegisterView(AccessMixin, FormView):
template_name = 'registration/register.html'
form_class = RegisterForm
# model = get_user_model()
success_url = reverse_lazy('dashboard')
def dispatch(self, request, *args, **kwargs):
user: DepotUser = request.user
if not (user.is_superuser or user.user_type == DepotUser.UserType.COMPANY_ADMIN):
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
# Create user from form data
user = form.save(commit=False)
user_type = form.cleaned_data['user_type']
# Clear irrelevant permissions based on user type
if user_type == DepotUser.UserType.CLIENT:
user.employee_permissions.clear()
elif user_type == DepotUser.UserType.EMPLOYEE:
user.company_permissions.clear()
# user.set_password(form.cleaned_data['password'])
user.save()
return super().form_valid(form)
def get_form(self, form_class = None):
form = super().get_form(form_class)
user: DepotUser = self.request.user
if user.is_superuser:
# Superuser can manage all permissions and user types
form.fields['user_type'].widget.attrs['disabled'] = False
form.fields['company_permissions'].widget.attrs['disabled'] = False
form.fields['employee_permissions'].widget.attrs['disabled'] = False
# Show relevant permissions based on selected user type
if form.initial.get('user_type') == DepotUser.UserType.CLIENT:
form.fields['employee_permissions'].widget.attrs['disabled'] = True
elif form.initial.get('user_type') == DepotUser.UserType.EMPLOYEE:
form.fields['company_permissions'].widget.attrs['disabled'] = True
elif user.user_type == DepotUser.UserType.COMPANY_ADMIN:
form.fields['company'].queryset = form.fields['company'].queryset.filter(pk=user.company.pk)
form.fields['company'].initial = user.company
form.fields['company'].widget.readonly = True # form.fields['line'].widget.attrs['disabled'] = True
form.fields['line'].queryset = form.fields['line'].queryset.filter(company=user.company.pk)
form.fields['user_type'].choices = [
(DepotUser.UserType.CLIENT, 'Client')
]
form.fields['user_type'].initial = DepotUser.UserType.CLIENT
form.fields['company_permissions'].widget.attrs['disabled'] = False
form.fields['employee_permissions'].widget.attrs['disabled'] = True
return form
class UserListView(ListView):
template_name = 'registration/register.html'
# form_class = RegisterForm

@ -1,10 +1,12 @@
from django.urls import path
from django.urls import path, include
from common import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('client/dashboard/', views.ClientDashboardView.as_view(), name='client_dashboard'),
path('barrier/dashboard/', views.BarrierDashboardView.as_view(), name='barrier_dashboard'),
path('dashboard/', views.DashboardRedirectView.as_view(), name='dashboard'),
path('dashboard/', include([
path('', views.DashboardRedirectView.as_view(), name='dashboard'),
path('client/', views.ClientDashboardView.as_view(), name='client_dashboard'),
path('barrier/', views.BarrierDashboardView.as_view(), name='barrier_dashboard'),
path('employee/', views.EmployeeDashboardView.as_view(), name='employee_dashboard'),
]))
]

@ -2,6 +2,11 @@ from django.urls import reverse_lazy
from django.views.generic import TemplateView, RedirectView
from django.shortcuts import render
from accounts.models import DepotUser
from booking.models import Booking
from containers.models import Container
from preinfo.models import Preinfo
# Create your views here.
class IndexView(TemplateView):
@ -21,12 +26,16 @@ class DashboardRedirectView(RedirectView):
def get_redirect_url(self, *args, **kwargs):
# if self.request.user.is_authenticated:
if self.request.user.username == 'client':
if self.request.user.user_type == DepotUser.UserType.COMPANY_ADMIN:
return reverse_lazy('client_dashboard')
elif self.request.user.username == 'clientadmin':
elif self.request.user.user_type == DepotUser.UserType.CLIENT:
return reverse_lazy('client_dashboard')
elif self.request.user.username == 'barrier':
elif self.request.user.user_type == DepotUser.UserType.BARRIER_STAFF:
return reverse_lazy('barrier_dashboard')
elif self.request.user.user_type == DepotUser.UserType.EMPLOYEE:
return reverse_lazy('employee_dashboard')
elif self.request.user.user_type == DepotUser.UserType.ADMIN:
return reverse_lazy('employee_dashboard')
return reverse_lazy('index')
@ -47,10 +56,26 @@ class BarrierDashboardView(TemplateView):
'description': 'This is the client dashboard page.',
}
def get(self, request, *args, **kwargs):
return render(request, self.template_name, self.extra_context)
class EmployeeDashboardView(TemplateView):
template_name = 'employee-dashboard-content.html'
extra_context = {
'title': 'Employee Dashboard',
'description': 'This is the depot employee dashboard page.',
}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
containers = Container.objects.filter(expedited=False).count()
preinfos = Preinfo.objects.filter(received=False).count()
bookings = Booking.objects.filter(status='active').count()
context['containers'] = containers
context['preinfos'] = preinfos
context['bookings'] = bookings
return context
# class ClientPreinfoView(TemplateView):
# template_name = 'client-preinfo-content.html'

@ -0,0 +1,149 @@
/* Basic form styling */
form {
max-width: 600px;
margin: 20px auto;
padding: 20px;
}
/* Label styling */
label {
display: block;
margin-bottom: 2px;
font-weight: 500;
color: #a57d52;
}
/* Input field styling */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="number"],
select,
textarea {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #a57d52;
border-radius: 4px;
box-sizing: border-box;
}
/* Submit button styling */
button[type="submit"] {
background-color: #a57d52;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
/*margin-top: 20px;*/
}
button[type="submit"]:hover {
background-color: #a67744;
}
/* Error messages */
.errorlist {
color: #dc3545;
list-style: none;
padding: 0;
margin: 5px 0;
font-size: 0.9em;
}
/* Help text */
.helptext {
color: #666;
font-size: 0.9em;
margin-bottom: 10px;
display: block;
}
.card {
margin-top: 24px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.card-header {
padding: 16px 24px;
border-bottom: 1px solid #ddd;
}
.card-header h3 {
margin: 0;
font-size: 18px;
font-weight: bold;
color: #333;
}
.card-body {
padding: 24px;
}
.table-container {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
}
thead {
background-color: #f9f9f9;
}
th, td {
padding: 12px 16px;
text-align: left;
font-size: 14px;
}
th {
font-weight: bold;
text-transform: uppercase;
color: #666;
border-bottom: 1px solid #ddd;
}
tbody tr {
border-bottom: 1px solid #eee;
}
.status {
display: inline-block;
padding: 4px 8px;
font-size: 12px;
font-weight: bold;
border-radius: 12px;
background-color: #e0f0ff;
color: #0066cc;
}
.actions button {
background: none;
border: none;
color: #0066cc;
font-size: 14px;
cursor: pointer;
margin-right: 10px;
}
.actions button:hover {
color: #004999;
}
.actions button:last-child {
color: #cc0000;
margin-right: 0;
}
.actions button:last-child:hover {
color: #990000;
}

@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Line Operator Dashboard | Container Depot</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@ -57,6 +58,7 @@
to { opacity: 1; transform: translateY(0); }
}
</style>
<link rel="stylesheet" href="{% static 'styles/forms.css' %}">
</head>
<body class="flex h-screen overflow-hidden">
<!-- Sidebar -->

@ -22,49 +22,93 @@
</div>
</div>
<div class="mt-6 bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-800">Recent Preinfo Submissions</h3>
</div>
<div class="p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Booking №</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container №</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container count</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Containers left</th>
{# <div class="mt-6 bg-white rounded-lg shadow">#}
{# <div class="px-6 py-4 border-b border-gray-200">#}
{# <h3 class="text-lg font-semibold text-gray-800">Recent Preinfo Submissions</h3>#}
{# </div>#}
{# <div class="p-6">#}
{# <div class="overflow-x-auto">#}
{# <table class="min-w-full divide-y divide-gray-200">#}
{# <thead>#}
{# <tr>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Booking №</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container №</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container count</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Containers left</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Vehicles</th>#}
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Vehicles</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{% for booking in recent %}
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">{{ booking.number }}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">{{ booking.container_number }}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.container_type }}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.container_count }}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.containers_left }}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.vehicles_left }}</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">{{ booking.status }}</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">
<button class="text-blue-600 hover:text-blue-800 mr-3">Edit</button>
<button class="text-red-600 hover:text-red-800">Cancel</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Vehicles</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>#}
{# <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>#}
{# </tr>#}
{# </thead>#}
{# <tbody class="divide-y divide-gray-200">#}
{# {% for booking in recent %}#}
{# <tr>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">{{ booking.number }}</td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">{{ booking.container_number }}</td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.container_type }}</td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.container_count }}</td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.containers_left }}</td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">{{ booking.vehicles_left }}</td>#}
{# #}
{# <td class="px-4 py-3 whitespace-nowrap">#}
{# <span class="px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">{{ booking.status }}</span>#}
{# </td>#}
{# <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">#}
{# <button class="text-blue-600 hover:text-blue-800 mr-3">Edit</button>#}
{# <button class="text-red-600 hover:text-red-800">Cancel</button>#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}
{# </tbody>#}
{# </table>#}
{# </div>#}
{# </div>#}
{# </div>#}
<div class="card">
<div class="card-header">
<h3>Recent Preinfo Submissions</h3>
</div>
<div class="card-body">
<div class="table-container">
<table>
<thead>
<tr>
<th>Booking №</th>
<th>Container №</th>
<th>Type</th>
<th>Container count</th>
<th>Containers left</th>
<th>Vehicles</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for booking in recent %}
<tr>
<td>{{ booking.number }}</td>
<td>{{ booking.container_number }}</td>
<td>{{ booking.container_type }}</td>
<td>{{ booking.container_count }}</td>
<td>{{ booking.containers_left }}</td>
<td>{{ booking.vehicles_left }}</td>
<td><span class="status">{{ booking.status }}</span></td>
<td class="actions">
<button>Edit</button>
<button>Cancel</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock content %}

@ -31,15 +31,18 @@
</svg>
Reports
</a>
{% if request.user.UserType.COMPANY_ADMIN %}
<div class="px-4 py-2 mt-6 text-xs text-blue-300 uppercase tracking-wider">Account</div>
<a href="#" class="nav-item flex items-center px-6 py-3 text-white">
<a href="{% url 'register' %}" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
Settings
</a>
{% endif %}
</nav>
<div class="p-4 border-t border-blue-700">
@ -51,7 +54,7 @@
<p class="text-sm font-medium">{{ request.user }}</p>
<p class="text-xs text-blue-300">{{ request.user.company }}</p>
</div>
<a href="{% url 'relogin' %}" class="ml-auto text-white" >
<a href="{% url 'login' %}" class="ml-auto text-white" >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>

@ -0,0 +1,196 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Employee Dashboard | Container Depot</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7fa;
}
.sidebar {
background: linear-gradient(180deg, #0f4c81 0%, #1a6baf 100%);
transition: all 0.3s;
}
.content-area {
transition: all 0.3s;
}
.nav-item {
transition: all 0.2s;
}
.nav-item:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.nav-item.active {
background-color: rgba(255, 255, 255, 0.2);
border-left: 4px solid white;
}
.card {
transition: all 0.3s;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.tab {
transition: all 0.2s;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.form-section {
animation: slideIn 0.5s ease-in-out;
}
@keyframes slideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<link rel="stylesheet" href="{% static 'styles/forms.css' %}">
</head>
<body class="flex h-screen overflow-hidden">
<!-- Sidebar -->
{% include 'employee-sidebar.html' %}
<!-- Main Content -->
<main class="content-area flex-1 overflow-y-auto">
<!-- Top Navigation -->
<header class="bg-white shadow-sm">
<div class="flex items-center justify-between px-6 py-4">
<div class="flex items-center">
<h2 class="text-xl font-semibold text-gray-800">Dashboard</h2>
</div>
<div class="flex items-center space-x-4">
<button class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<button class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</button>
</div>
</div>
</header>
<!-- Dashboard Content -->
<div class="p-6">
{% block content %}
{# {% include 'client-dashboard-content.html' %}#}
{# {% include 'client-preinfo-content.html' %}#}
{# {% include 'client-orders-content.html' %}#}
{% endblock content %}
</div>
</main>
{# <script>#}
{# // Tab Navigation#}
{# const dashboardContent = document.getElementById('dashboardContent');#}
{# const preinfoContent = document.getElementById('preinfoContent');#}
{# const ordersContent = document.getElementById('ordersContent');#}
{# #}
{# const preinfoNav = document.getElementById('preinfoNav');#}
{# const ordersNav = document.getElementById('ordersNav');#}
{# #}
{# preinfoNav.addEventListener('click', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // Update content visibility#}
{# dashboardContent.classList.remove('active');#}
{# preinfoContent.classList.add('active');#}
{# ordersContent.classList.remove('active');#}
{# #}
{# // Update navigation styling#}
{# document.querySelector('.nav-item.active').classList.remove('active');#}
{# preinfoNav.classList.add('active');#}
{# #}
{# // Update header title#}
{# document.querySelector('header h2').textContent = 'Container Preinfo';#}
{# });#}
{# #}
{# ordersNav.addEventListener('click', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // Update content visibility#}
{# dashboardContent.classList.remove('active');#}
{# preinfoContent.classList.remove('active');#}
{# ordersContent.classList.add('active');#}
{# #}
{# // Update navigation styling#}
{# document.querySelector('.nav-item.active').classList.remove('active');#}
{# ordersNav.classList.add('active');#}
{# #}
{# // Update header title#}
{# document.querySelector('header h2').textContent = 'Expedition Orders';#}
{# });#}
{# #}
{# // Damage checkbox toggle#}
{# const damageCheck = document.getElementById('damageCheck');#}
{# const damageDetails = document.getElementById('damageDetails');#}
{# #}
{# damageCheck.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# damageDetails.classList.remove('hidden');#}
{# } else {#}
{# damageDetails.classList.add('hidden');#}
{# }#}
{# });#}
{# #}
{# // Order type toggle#}
{# const specificContainer = document.getElementById('specificContainer');#}
{# const anyContainer = document.getElementById('anyContainer');#}
{# const specificContainerFields = document.getElementById('specificContainerFields');#}
{# const anyContainerFields = document.getElementById('anyContainerFields');#}
{# #}
{# specificContainer.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# specificContainerFields.classList.remove('hidden');#}
{# anyContainerFields.classList.add('hidden');#}
{# }#}
{# });#}
{# #}
{# anyContainer.addEventListener('change', function() {#}
{# if (this.checked) {#}
{# specificContainerFields.classList.add('hidden');#}
{# anyContainerFields.classList.remove('hidden');#}
{# }#}
{# });#}
{# #}
{# // Form submissions#}
{# document.getElementById('preinfoForm').addEventListener('submit', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // In a real app, this would send data to the server#}
{# alert('Preinfo submitted successfully!');#}
{# this.reset();#}
{# });#}
{# #}
{# document.getElementById('orderForm').addEventListener('submit', function(e) {#}
{# e.preventDefault();#}
{# #}
{# // In a real app, this would send data to the server#}
{# alert('Expedition order submitted successfully!');#}
{# this.reset();#}
{# });#}
{# #}
{# // Add more container button#}
{# document.getElementById('addMoreContainer').addEventListener('click', function() {#}
{# alert('In a real app, this would add fields for another container');#}
{# });#}
{# </script>#}
{#<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'947f86ac452d3130',t:'MTc0ODYyMTY4Mi4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>#}
</body>
</html>

@ -0,0 +1,162 @@
{% extends 'employee-base.html' %}
{% block content %}
<div id="dashboardContent" class="tab-content active">
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<div class="card bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-blue-100 text-blue-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-700">Active Containers</h3>
<p class="text-3xl font-bold text-gray-900">{{ containers }}</p>
<p class="text-sm text-green-600">+3 since last week</p>
</div>
</div>
</div>
<div class="card bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-green-100 text-green-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-700">Preinfo Sent</h3>
<p class="text-3xl font-bold text-gray-900">{{ preinfos }}</p>
<p class="text-sm text-green-600">+5 since last week</p>
</div>
</div>
</div>
<div class="card bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-orange-100 text-orange-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
</div>
<div class="ml-4">
<h3 class="text-lg font-semibold text-gray-700">Bookings</h3>
<p class="text-3xl font-bold text-gray-900">{{ bookings }}</p>
<p class="text-sm text-orange-600">2 require attention</p>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-800">Recent Container Activity</h3>
</div>
<div class="p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Container</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU1234567</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">40HC</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Received</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-15</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU7654321</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">20DV</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">Preinfo</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-14</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU2468135</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">40DV</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-orange-100 text-orange-800">Order</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-13</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">MSCU1357924</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">20RF</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">Expedited</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-12</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow">
<div class="px-6 py-4 border-b border-gray-200">
<h3 class="text-lg font-semibold text-gray-800">Payment Status</h3>
</div>
<div class="p-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Invoice</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Amount</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Due Date</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0042</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$1,250.00</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Paid</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-10</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0041</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$875.50</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 text-yellow-800">Pending</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-20</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0040</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$2,100.00</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">Overdue</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-06-05</td>
</tr>
<tr>
<td class="px-4 py-3 whitespace-nowrap text-sm font-medium text-gray-900">INV-2023-0039</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">$950.25</td>
<td class="px-4 py-3 whitespace-nowrap">
<span class="px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">Paid</span>
</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700">2023-05-28</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,64 @@
{% load static %}
<aside class="sidebar w-64 h-full text-white flex flex-col">
<div class="p-5 border-b border-blue-700">
<h1 class="text-xl font-bold">Container Depot</h1>
<p class="text-sm text-blue-200">Employee Portal</p>
</div>
<nav class="flex-grow py-4">
<div class="px-4 py-2 text-xs text-blue-300 uppercase tracking-wider">Main</div>
<a href="{% url 'dashboard' %}" class="nav-item active flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
Dashboard
</a>
<a href="{% url 'client_preinfo' %}" id="preinfoNav" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
Container Preinfo
</a>
<a href="{% url 'client_booking' %}" id="ordersNav" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
Bookings
</a>
<a href="#" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
Reports
</a>
{% if request.user.UserType.ADMIN %}
<div class="px-4 py-2 mt-6 text-xs text-blue-300 uppercase tracking-wider">Account</div>
<a href="{% url 'register' %}" class="nav-item flex items-center px-6 py-3 text-white">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
Settings
</a>
{% endif %}
</nav>
<div class="p-4 border-t border-blue-700">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">
LO
</div>
<div class="ml-3">
<p class="text-sm font-medium">{{ request.user }}</p>
<p class="text-xs text-blue-300">{{ request.user.company }}</p>
</div>
<a href="{% url 'login' %}" class="ml-auto text-white" >
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
</a>
</div>
</div>
</aside>

@ -0,0 +1,40 @@
<div class="card">
<div class="card-header">
<h3>Recent Preinfo Submissions</h3>
</div>
<div class="card-body">
<div class="table-container">
<table>
<thead>
<tr>
<th>Booking №</th>
<th>Container №</th>
<th>Type</th>
<th>Container count</th>
<th>Containers left</th>
<th>Vehicles</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for booking in recent %}
<tr>
<td>{{ booking.number }}</td>
<td>{{ booking.container_number }}</td>
<td>{{ booking.container_type }}</td>
<td>{{ booking.container_count }}</td>
<td>{{ booking.containers_left }}</td>
<td>{{ booking.vehicles_left }}</td>
<td><span class="status">{{ booking.status }}</span></td>
<td class="actions">
<button>Edit</button>
<button>Cancel</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>

@ -5,7 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Container Depot Management System</title>
<link rel="stylesheet" href="{% static '/css/styles.css' %}"/>
<link rel="stylesheet" href="{% static '/styles/styles.css' %}"/>
</head>
<body>
{# {{ title|default:"Container Depot Management System" }} {{ description|default:"Login to the Container Depot Management System" }}#}

@ -1,14 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register User</title>
</head>
<body>
{% extends 'client-base.html' %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{{ form }}
<button type="submit">Register</button>
</form>
</body>
</html>
<script>
document.addEventListener('DOMContentLoaded', function() {
const userTypeSelect = document.getElementById('id_user_type');
const companyPerms = document.getElementById('id_company_permissions');
const employeePerms = document.getElementById('id_employee_permissions');
function handleUserTypeChange(select) {
console.log('User type changed to:', userTypeSelect.value); // Add this line
// {#if (!userTypeSelect || !companyPerms || !employeePerms) return;#}
const isSuperuser = {{ user.is_superuser|yesno:"true,false" }};
const isCompanyAdmin = ('{{ user.user_type }}' === 'CA');
// Remove disabled attribute first
companyPerms.removeAttribute('disabled');
employeePerms.removeAttribute('disabled');
switch(userTypeSelect.value) {
case 'CL': // Client
companyPerms.disabled = false;
employeePerms.disabled = true;
break;
case 'EM': // Employee
companyPerms.disabled = true;
employeePerms.disabled = false;
break;
default:
companyPerms.disabled = true;
employeePerms.disabled = true;
break;
}
companyPerms.parentElement.hidden = companyPerms.disabled;
employeePerms.parentElement.hidden = employeePerms.disabled;
}
// Add change event listener
if (userTypeSelect) {
userTypeSelect.addEventListener('change', handleUserTypeChange);
// Initial call to set up the form correctly
handleUserTypeChange();
}
});
</script>
{% endblock content %}
Loading…
Cancel
Save