new list page addded"
This commit is contained in:
parent
d8a7442b9d
commit
ff42e35855
Binary file not shown.
Binary file not shown.
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -242,6 +242,14 @@ class JobPosting(Base):
|
|||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
|
class JobPostingImage(models.Model):
|
||||||
|
job=models.ForeignKey('JobPosting',on_delete=models.CASCADE,related_name='post_images')
|
||||||
|
post_image = models.ImageField(upload_to='post/',
|
||||||
|
height_field='photo_height',
|
||||||
|
width_field='photo_width')
|
||||||
|
post_image_height = models.PositiveIntegerField(null=True, blank=True)
|
||||||
|
post_image_width = models.PositiveIntegerField(null=True, blank=True)
|
||||||
|
|
||||||
class Candidate(Base):
|
class Candidate(Base):
|
||||||
class Stage(models.TextChoices):
|
class Stage(models.TextChoices):
|
||||||
APPLIED = "Applied", _("Applied")
|
APPLIED = "Applied", _("Applied")
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
{% load static i18n crispy_forms_tags %}
|
{% load static i18n crispy_forms_tags %}
|
||||||
{% load partials %}
|
{% load partials %}
|
||||||
|
|
||||||
{% block title %}Form Templates - ATS{% endblock %}
|
{% block title %}Form Templates - {{ block.super }}{% endblock %}
|
||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
/* ================================================= */
|
/* ================================================= */
|
||||||
/* UI Variables (Matching Job List) */
|
/* UI Variables (Matching Standard Theme) */
|
||||||
/* ================================================= */
|
/* ================================================= */
|
||||||
:root {
|
:root {
|
||||||
--kaauh-teal: #00636e;
|
--kaauh-teal: #00636e;
|
||||||
@ -20,23 +20,22 @@
|
|||||||
/* --- Typography and Color Overrides --- */
|
/* --- Typography and Color Overrides --- */
|
||||||
.text-primary { color: var(--kaauh-teal) !important; }
|
.text-primary { color: var(--kaauh-teal) !important; }
|
||||||
|
|
||||||
/* --- Button Base Styles (Matching Job List) --- */
|
/* --- Button Base Styles (Consistent) --- */
|
||||||
.btn-main-action {
|
.btn-main-action {
|
||||||
background-color: var(--kaauh-teal);
|
background-color: var(--kaauh-teal);
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0.375rem 0.75rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.4rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
.btn-main-action:hover {
|
.btn-main-action:hover {
|
||||||
background-color: var(--kaauh-teal-dark);
|
background-color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-teal-dark);
|
border-color: var(--kaauh-teal-dark);
|
||||||
transform: translateY(-1px);
|
transform: none; /* Removed translate to match other lists */
|
||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
@ -51,18 +50,17 @@
|
|||||||
color: white;
|
color: white;
|
||||||
border-color: var(--kaauh-teal-dark);
|
border-color: var(--kaauh-teal-dark);
|
||||||
}
|
}
|
||||||
|
/* Primary Outline for View/Preview */
|
||||||
/* Size Utilities (matching Bootstrap convention) */
|
.btn-outline-primary {
|
||||||
.btn-lg {
|
color: var(--kaauh-teal);
|
||||||
padding: 0.75rem 1.5rem;
|
border-color: var(--kaauh-teal);
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
}
|
||||||
.btn-sm {
|
.btn-outline-primary:hover {
|
||||||
font-size: 0.8rem;
|
background-color: var(--kaauh-teal);
|
||||||
padding: 0.3rem 0.6rem;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Card and Layout Styles (Matching Job List) --- */
|
/* --- Card and Layout Styles (Consistent) --- */
|
||||||
.card {
|
.card {
|
||||||
border: 1px solid var(--kaauh-border);
|
border: 1px solid var(--kaauh-border);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
@ -70,42 +68,24 @@
|
|||||||
background-color: white;
|
background-color: white;
|
||||||
transition: transform 0.2s, box-shadow 0.2s;
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
|
.card:not(.no-hover):hover {
|
||||||
/* Template Card Hover Effect (Consistent with job list card hover) */
|
|
||||||
.template-card {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.template-card:hover {
|
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 6px 16px rgba(0,0,0,0.1) !important;
|
box-shadow: 0 6px 16px rgba(0,0,0,0.1) !important;
|
||||||
}
|
}
|
||||||
|
.card.no-hover:hover {
|
||||||
/* Card Header Theming */
|
transform: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card Header (For Search/Filter Card) */
|
||||||
.card-header {
|
.card-header {
|
||||||
/* FIX: Use !important to override default white/light backgrounds from Bootstrap */
|
|
||||||
background-color: var(--kaauh-teal-dark) !important;
|
|
||||||
border-bottom: 1px solid var(--kaauh-border);
|
|
||||||
color: white !important; /* Base color for header text */
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 1rem 1.25rem;
|
padding: 1.25rem;
|
||||||
border-radius: 0.75rem 0.75rem 0 0;
|
border-bottom: 1px solid var(--kaauh-border);
|
||||||
}
|
background-color: var(--kaauh-gray-light);
|
||||||
|
|
||||||
/* Ensure all elements within the header are visible */
|
|
||||||
.card-header h3 {
|
|
||||||
color: white !important;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.card-header .fas {
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
.card-header .small {
|
|
||||||
color: rgba(255, 255, 255, 0.7) !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stats Theming */
|
/* Stats Theming */
|
||||||
|
|
||||||
/* --- Content Styles (Stats, Description) --- */
|
|
||||||
.stat-value {
|
.stat-value {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
@ -116,58 +96,28 @@
|
|||||||
color: var(--kaauh-primary-text);
|
color: var(--kaauh-primary-text);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.card-description {
|
|
||||||
min-height: 60px;
|
|
||||||
color: var(--kaauh-primary-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search Input Theming */
|
/* Table Styling (Consistent) */
|
||||||
.form-control {
|
.table-view .table thead th {
|
||||||
border-radius: 0.5rem 0 0 0.5rem;
|
background-color: var(--kaauh-teal-dark);
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
border-radius: 0 0.5rem 0.5rem 0;
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
.form-control-search:focus {
|
.table-view .table tbody td {
|
||||||
border-color: var(--kaauh-teal);
|
vertical-align: middle;
|
||||||
box-shadow: 0 0 0 0.1rem rgba(0, 99, 110, 0.25);
|
padding: 1rem;
|
||||||
}
|
|
||||||
.input-group-search .input-group-text {
|
|
||||||
background-color: white;
|
|
||||||
border-right: none;
|
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
border-radius: 0.5rem 0 0 0.5rem;
|
|
||||||
}
|
}
|
||||||
.input-group-search .form-control {
|
.table-view .table tbody tr:hover {
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Danger Outline (Delete) --- */
|
|
||||||
.btn-outline-danger {
|
|
||||||
--bs-btn-color: #dc3545;
|
|
||||||
--bs-btn-border-color: #dc3545;
|
|
||||||
--bs-btn-hover-bg: #dc3545;
|
|
||||||
--bs-btn-hover-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Empty State Theming */
|
|
||||||
.empty-state {
|
|
||||||
text-align: center;
|
|
||||||
padding: 3rem 1rem;
|
|
||||||
color: var(--kaauh-primary-text);
|
|
||||||
border: 2px dashed var(--kaauh-border);
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
background-color: var(--kaauh-gray-light);
|
background-color: var(--kaauh-gray-light);
|
||||||
}
|
}
|
||||||
.empty-state i {
|
|
||||||
font-size: 3.5rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
color: var(--kaauh-teal-dark);
|
|
||||||
}
|
|
||||||
.empty-state .btn-main-action .fas {
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Pagination Styling (Matching Job List) --- */
|
/* Pagination Styling (Consistent) */
|
||||||
.pagination .page-item .page-link {
|
.pagination .page-item .page-link {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
@ -180,30 +130,40 @@
|
|||||||
.pagination .page-item:hover .page-link:not(.active) {
|
.pagination .page-item:hover .page-link:not(.active) {
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
|
/* Empty State Icon Color */
|
||||||
|
.empty-state i, .text-center i.fa-3x {
|
||||||
|
color: var(--kaauh-teal-dark) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter Buttons Container */
|
||||||
|
.filter-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4 pb-2 border-bottom border-primary">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<h1 class="h3 mb-0 fw-bold" style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
<h1 class="h3 mb-0" style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
||||||
<i class="fas fa-file-alt me-2"></i>{% trans "Form Templates" %}
|
<i class="fas fa-file-alt me-2"></i>{% trans "Form Templates" %}
|
||||||
</h1>
|
</h1>
|
||||||
<button type="button" class="btn btn-main-action" data-bs-toggle="modal" data-bs-target="#createTemplateModal">
|
<button type="button" class="btn btn-main-action" data-bs-toggle="modal" data-bs-target="#createTemplateModal">
|
||||||
<i class="fas fa-plus me-1"></i> Create New Template
|
<i class="fas fa-plus me-1"></i> {% trans "Create New Template" %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Search/Filter Area - Matching Job List Structure #}
|
{# Search/Filter Area - Matching Standard Structure #}
|
||||||
<div class="card mb-4 shadow-sm no-hover">
|
<div class="card mb-4 shadow-sm no-hover">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title text-muted mb-3" style="font-weight: 500;">Search Templates</h5>
|
|
||||||
<form method="get" class="row g-3 align-items-end">
|
<form method="get" class="row g-3 align-items-end">
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="search" class="form-label small text-muted">Search by Template Name</label>
|
<label for="searchInput" class="form-label small text-muted">{% trans "Search by Template Name" %}</label>
|
||||||
<div class="input-group input-group-lg input-group-search">
|
<div class="input-group input-group-lg">
|
||||||
<span class="input-group-text"><i class="fas fa-search text-muted"></i></span>
|
<span class="input-group-text"><i class="fas fa-search text-muted"></i></span>
|
||||||
<input type="text" name="q" id="searchInput" class="form-control form-control-search"
|
<input type="text" name="q" id="searchInput" class="form-control form-control-search"
|
||||||
placeholder="{% trans 'Search templates by name...' %}"
|
placeholder="{% trans 'Search templates by name...' %}"
|
||||||
@ -214,13 +174,13 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="filter-buttons">
|
<div class="filter-buttons">
|
||||||
<button type="submit" class="btn btn-main-action btn-lg">
|
<button type="submit" class="btn btn-main-action btn-lg">
|
||||||
<i class="fas fa-filter me-1"></i> Search
|
<i class="fas fa-filter me-1"></i> {% trans "Search" %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{# Show Clear button if search is active #}
|
{# Show Clear button if search is active #}
|
||||||
{% if query %}
|
{% if query %}
|
||||||
<a href="{% url 'form_templates_list' %}" class="btn btn-outline-danger btn-sm">
|
<a href="{% url 'form_templates_list' %}" class="btn btn-outline-secondary btn-lg">
|
||||||
<i class="fas fa-times me-1"></i> Clear Search
|
<i class="fas fa-times me-1"></i> {% trans "Clear Search" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -239,59 +199,62 @@
|
|||||||
<div class="card-view active row g-4">
|
<div class="card-view active row g-4">
|
||||||
{% for template in templates %}
|
{% for template in templates %}
|
||||||
<div class="col-lg-4 col-md-6">
|
<div class="col-lg-4 col-md-6">
|
||||||
<div class="card template-card h-100">
|
<div class="card template-card h-100 shadow-sm">
|
||||||
<div class="card-header ">
|
|
||||||
<h3 class="h5 mb-2">{{ template.name }}</h3>
|
|
||||||
<span><i class="fas fa-sync-alt me-1"></i> {{ template.job }}</span>
|
|
||||||
<div class="d-flex justify-content-between text-muted small">
|
|
||||||
<span><i class="fas fa-calendar me-1"></i> {{ template.created_at|date:"M d, Y" }}</span>
|
|
||||||
<span><i class="fas fa-sync-alt me-1"></i> {{ template.updated_at|timesince }} {% trans "ago" %}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
|
<h5 class="card-title fw-bold" style="color: var(--kaauh-teal-dark);">{{ template.name }}</h5>
|
||||||
{# Content area - includes stats and description #}
|
<span class="text-muted small mb-3">
|
||||||
<div class="flex-grow-1">
|
<i class="fas fa-briefcase me-1"></i> {{ template.job|default:"N/A" }}
|
||||||
<div class="row text-center mb-3">
|
</span>
|
||||||
<div class="col-6">
|
|
||||||
<div class="stat-value">{{ template.get_stage_count }}</div>
|
{# Stats #}
|
||||||
<div class="stat-label">{% trans "Stages" %}</div>
|
<div class="row text-center mb-3">
|
||||||
</div>
|
<div class="col-6 border-end">
|
||||||
<div class="col-6">
|
<div class="stat-value">{{ template.get_stage_count }}</div>
|
||||||
<div class="stat-value">{{ template.get_field_count }}</div>
|
<div class="stat-label">{% trans "Stages" %}</div>
|
||||||
<div class="stat-label">{% trans "Fields" %}</div>
|
</div>
|
||||||
</div>
|
<div class="col-6">
|
||||||
|
<div class="stat-value">{{ template.get_field_count }}</div>
|
||||||
|
<div class="stat-label">{% trans "Fields" %}</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="card-text card-description small">
|
|
||||||
{% if template.description %}
|
|
||||||
{{ template.description|truncatewords:20 }}
|
|
||||||
{% else %}
|
|
||||||
<em class="text-muted">{% trans "No description provided" %}</em>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# Description #}
|
||||||
|
<p class="card-text small text-muted flex-grow-1">
|
||||||
|
{% if template.description %}
|
||||||
|
{{ template.description|truncatewords:20 }}
|
||||||
|
{% else %}
|
||||||
|
<em class="text-muted">{% trans "No description provided" %}</em>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
|
||||||
{# Action area - visually separated with pt-2 border-top #}
|
{# Action area #}
|
||||||
<div class="mt-auto pt-2 border-top">
|
<div class="mt-auto pt-2 border-top">
|
||||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
<div class="d-flex gap-2 justify-content-end">
|
||||||
|
|
||||||
<a href="{% url 'form_wizard' template.id %}" class="btn btn-outline-secondary btn-sm action-btn">
|
<a href="{% url 'form_wizard' template.id %}" class="btn btn-outline-primary btn-sm" title="{% trans 'Preview' %}">
|
||||||
<i class="fas fa-eye me-1"></i> {% trans "Preview" %}
|
<i class="fas fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'form_builder' template.id %}" class="btn btn-outline-secondary btn-sm action-btn">
|
<a href="{% url 'form_builder' template.id %}" class="btn btn-outline-secondary btn-sm" title="{% trans 'Edit' %}">
|
||||||
<i class="fas fa-edit me-1"></i> {% trans "Edit" %}
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'form_template_submissions_list' template.slug %}" class="btn btn-outline-secondary btn-sm action-btn">
|
<a href="{% url 'form_template_submissions_list' template.slug %}" class="btn btn-outline-secondary btn-sm" title="{% trans 'Submissions' %}">
|
||||||
<i class="fas fa-file-alt me-1"></i> {% trans "Submissions" %}
|
<i class="fas fa-file-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-outline-danger btn-sm action-btn delete"
|
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
||||||
data-template-id="{{ template.id }}"
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
data-template-name="{{ template.name }}">
|
data-delete-url="#"
|
||||||
<i class="fas fa-trash me-1"></i> {% trans "Delete" %}
|
data-item-name="{{ template.name }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-footer bg-light text-muted small">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<span><i class="fas fa-calendar-alt me-1"></i> {% trans "Created:" %} {{ template.created_at|date:"M d, Y" }}</span>
|
||||||
|
<span><i class="fas fa-sync-alt me-1"></i> {{ template.updated_at|timesince }} {% trans "ago" %}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -300,23 +263,23 @@
|
|||||||
{# Table View #}
|
{# Table View #}
|
||||||
<div class="table-view">
|
<div class="table-view">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{% trans "Template Name" %}</th>
|
<th scope="col" style="width: 30%;">{% trans "Template Name" %}</th>
|
||||||
<th scope="col">{% trans "Job" %}</th>
|
<th scope="col" style="width: 15%;">{% trans "Job" %}</th>
|
||||||
<th scope="col">{% trans "Stages" %}</th>
|
<th scope="col" style="width: 8%;">{% trans "Stages" %}</th>
|
||||||
<th scope="col">{% trans "Fields" %}</th>
|
<th scope="col" style="width: 8%;">{% trans "Fields" %}</th>
|
||||||
<th scope="col">{% trans "Created" %}</th>
|
<th scope="col" style="width: 15%;">{% trans "Created" %}</th>
|
||||||
<th scope="col">{% trans "Last Updated" %}</th>
|
<th scope="col" style="width: 15%;">{% trans "Last Updated" %}</th>
|
||||||
<th scope="col" class="text-end">{% trans "Actions" %}</th>
|
<th scope="col" style="width: 9%;" class="text-end">{% trans "Actions" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for template in templates %}
|
{% for template in templates %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="fw-medium">{{ template.name }}</td>
|
<td class="fw-medium text-primary">{{ template.name }}</td>
|
||||||
<td>{{ template.job }}</td>
|
<td>{{ template.job|default:"N/A" }}</td>
|
||||||
<td>{{ template.get_stage_count }}</td>
|
<td>{{ template.get_stage_count }}</td>
|
||||||
<td>{{ template.get_field_count }}</td>
|
<td>{{ template.get_field_count }}</td>
|
||||||
<td>{{ template.created_at|date:"M d, Y" }}</td>
|
<td>{{ template.created_at|date:"M d, Y" }}</td>
|
||||||
@ -329,11 +292,14 @@
|
|||||||
<a href="{% url 'form_builder' template.id %}" class="btn btn-outline-secondary" title="{% trans 'Edit' %}">
|
<a href="{% url 'form_builder' template.id %}" class="btn btn-outline-secondary" title="{% trans 'Edit' %}">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'form_template_submissions_list' template.slug %}" class="btn btn-outline-info" title="{% trans 'Submissions' %}">
|
<a href="{% url 'form_template_submissions_list' template.slug %}" class="btn btn-outline-secondary" title="{% trans 'Submissions' %}">
|
||||||
<i class="fas fa-file-alt"></i>
|
<i class="fas fa-file-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
<button class="btn btn-outline-danger delete-btn" data-bs-toggle="modal" data-bs-target="#deleteModal" data-template-id="{{ template.id }}" data-template-name="{{ template.name }}" title="{% trans 'Delete' %}">
|
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
||||||
<i class="fas fa-trash"></i>
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
|
data-delete-url="#"
|
||||||
|
data-item-name="{{ template.name }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -345,10 +311,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# Pagination (Standardized) #}
|
||||||
{% if templates.has_other_pages %}
|
{% if templates.has_other_pages %}
|
||||||
<nav aria-label="Page navigation" class="mt-4">
|
<nav aria-label="Page navigation" class="mt-4">
|
||||||
<ul class="pagination justify-content-center">
|
<ul class="pagination justify-content-center">
|
||||||
{# Previous page logic #}
|
|
||||||
{% if templates.has_previous %}
|
{% if templates.has_previous %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page=1{% if query %}&q={{ query }}{% endif %}">First</a>
|
<a class="page-link" href="?page=1{% if query %}&q={{ query }}{% endif %}">First</a>
|
||||||
@ -358,12 +324,10 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Current Page #}
|
|
||||||
<li class="page-item active">
|
<li class="page-item active">
|
||||||
<span class="page-link">{{ templates.number }} of {{ templates.paginator.num_pages }}</span>
|
<span class="page-link">{{ templates.number }} of {{ templates.paginator.num_pages }}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{# Next page logic #}
|
|
||||||
{% if templates.has_next %}
|
{% if templates.has_next %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ templates.next_page_number }}{% if query %}&q={{ query }}{% endif %}">Next</a>
|
<a class="page-link" href="?page={{ templates.next_page_number }}{% if query %}&q={{ query }}{% endif %}">Next</a>
|
||||||
@ -387,9 +351,9 @@
|
|||||||
{% trans "You haven't created any form templates yet." %}
|
{% trans "You haven't created any form templates yet." %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
<a href="{% url 'form_builder' %}" class="btn btn-main-action mt-3">
|
<button type="button" class="btn btn-main-action mt-3" data-bs-toggle="modal" data-bs-target="#createTemplateModal">
|
||||||
<i class="fas fa-plus me-1 text-white"></i> {% trans "Create Your First Template" %}
|
<i class="fas fa-plus me-1"></i> {% trans "Create Your First Template" %}
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -398,13 +362,12 @@
|
|||||||
|
|
||||||
{% include 'includes/delete_modal.html' %}
|
{% include 'includes/delete_modal.html' %}
|
||||||
|
|
||||||
<!-- Create Template Modal -->
|
|
||||||
<div class="modal fade" id="createTemplateModal" tabindex="-1" aria-labelledby="createTemplateModalLabel" aria-hidden="true">
|
<div class="modal fade" id="createTemplateModal" tabindex="-1" aria-labelledby="createTemplateModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header bg-light">
|
||||||
<h5 class="modal-title" id="createTemplateModalLabel">
|
<h5 class="modal-title" id="createTemplateModalLabel">
|
||||||
<i class="fas fa-file-alt me-2"></i>Create New Form Template
|
<i class="fas fa-file-alt me-2"></i>{% trans "Create New Form Template" %}
|
||||||
</h5>
|
</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
@ -416,12 +379,12 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
||||||
<button type="submit" form="createTemplateForm" class="btn btn-primary">
|
<button type="submit" form="createTemplateForm" class="btn btn-main-action">
|
||||||
<i class="fas fa-save me-1"></i>Create Template
|
<i class="fas fa-save me-1"></i>{% trans "Create Template" %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -10,6 +10,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* --- View Switcher Styles (Consolidated & Corrected) --- */
|
||||||
|
|
||||||
/* View Toggle Styles */
|
/* View Toggle Styles */
|
||||||
.view-toggle {
|
.view-toggle {
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
@ -28,13 +30,17 @@
|
|||||||
/* Hide elements by default */
|
/* Hide elements by default */
|
||||||
.table-view,
|
.table-view,
|
||||||
.card-view {
|
.card-view {
|
||||||
display: none;
|
display: none !important; /* Use !important to ensure hiding works */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show active view */
|
/* Show active view */
|
||||||
.table-view.active,
|
.table-view.active {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
.card-view.active {
|
.card-view.active {
|
||||||
display: block;
|
/* Rely on the 'row' class which uses display: flex for proper column alignment. */
|
||||||
|
display: flex !important; /* rows often use display: flex in Bootstrap */
|
||||||
|
flex-wrap: wrap !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card View Styles */
|
/* Card View Styles */
|
||||||
@ -105,16 +111,19 @@
|
|||||||
.table-view .table tbody tr {
|
.table-view .table tbody tr {
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
}
|
}
|
||||||
|
/* NOTE: We need to assume var(--kaauh-gray-light) is defined in base.html or job_list.html */
|
||||||
.table-view .table tbody tr:hover {
|
.table-view .table tbody tr:hover {
|
||||||
background-color: var(--kaauh-gray-light);
|
background-color: #f0f0f0; /* Fallback color for hover */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Get the list ID from the data attribute
|
const listContainer = document.getElementById('{{ list_id }}');
|
||||||
const listId = document.querySelector('.view-toggle').getAttribute('data-list-id');
|
if (!listContainer) return; // Exit if container isn't found
|
||||||
const listContainer = document.getElementById(listId);
|
|
||||||
|
// Get list ID from the data attribute (or use the variable from Django context if the button is loaded)
|
||||||
|
const listId = listContainer.id;
|
||||||
|
|
||||||
// Get saved view preference from localStorage
|
// Get saved view preference from localStorage
|
||||||
const savedView = localStorage.getItem(`list_view_${listId}`) || 'table';
|
const savedView = localStorage.getItem(`list_view_${listId}`) || 'table';
|
||||||
@ -124,15 +133,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
// Add click event listeners to view toggle buttons
|
// Add click event listeners to view toggle buttons
|
||||||
document.querySelectorAll('.view-toggle').forEach(button => {
|
document.querySelectorAll('.view-toggle').forEach(button => {
|
||||||
button.addEventListener('click', function() {
|
// Ensure the button belongs to this list (optional check)
|
||||||
const view = this.getAttribute('data-view');
|
if (button.getAttribute('data-list-id') === listId) {
|
||||||
setView(view);
|
button.addEventListener('click', function() {
|
||||||
});
|
const view = this.getAttribute('data-view');
|
||||||
|
setView(view);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function setView(view) {
|
function setView(view) {
|
||||||
// Update button states
|
// Update button states
|
||||||
document.querySelectorAll('.view-toggle').forEach(button => {
|
document.querySelectorAll('.view-toggle[data-list-id="{{ list_id }}"]').forEach(button => {
|
||||||
if (button.getAttribute('data-view') === view) {
|
if (button.getAttribute('data-view') === view) {
|
||||||
button.classList.add('active');
|
button.classList.add('active');
|
||||||
} else {
|
} else {
|
||||||
@ -144,16 +156,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const tableView = listContainer.querySelector('.table-view');
|
const tableView = listContainer.querySelector('.table-view');
|
||||||
const cardView = listContainer.querySelector('.card-view');
|
const cardView = listContainer.querySelector('.card-view');
|
||||||
|
|
||||||
|
// Apply active class to the correct container
|
||||||
if (view === 'table') {
|
if (view === 'table') {
|
||||||
tableView.classList.add('active');
|
if (tableView) tableView.classList.add('active');
|
||||||
cardView.classList.remove('active');
|
if (cardView) cardView.classList.remove('active');
|
||||||
} else {
|
} else {
|
||||||
tableView.classList.remove('active');
|
if (tableView) tableView.classList.remove('active');
|
||||||
cardView.classList.add('active');
|
if (cardView) cardView.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save preference to localStorage
|
// Save preference to localStorage
|
||||||
localStorage.setItem(`list_view_${listId}`, view);
|
localStorage.setItem(`list_view_${listId}`, view);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -261,7 +261,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<span class="badge bg-success status-badge">
|
<span class="badge status-badge">
|
||||||
|
{% if job.status == "ACTIVE" %}
|
||||||
|
<span class="badge bg-success status-badge">
|
||||||
|
{% elif job.status == "DRAFT" %}
|
||||||
|
<span class="badge bg-secondary status-badge">
|
||||||
|
{% elif job.status == "CLOSED" %}
|
||||||
|
<span class="badge bg-warning status-badge">
|
||||||
|
{% elif job.status == "CANCELLED" %}
|
||||||
|
<span class="badge bg-danger status-badge">
|
||||||
|
{% elif job.status == "ARCHIVED" %}
|
||||||
|
<span class="badge bg-secondary status-badge">
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary status-badge">
|
||||||
|
{% endif %}
|
||||||
{{ job.get_status_display }}
|
{{ job.get_status_display }}
|
||||||
<button type="button" class="btn btn-outline-light btn-sm ms-2" data-bs-toggle="modal" data-bs-target="#editStatusModal">
|
<button type="button" class="btn btn-outline-light btn-sm ms-2" data-bs-toggle="modal" data-bs-target="#editStatusModal">
|
||||||
<i class="fas fa-edit text-primary"></i>
|
<i class="fas fa-edit text-primary"></i>
|
||||||
@ -550,7 +563,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--image modal class-->
|
||||||
{% include "jobs/partials/image_upload.html" %}
|
{% include "jobs/partials/image_upload.html" %}
|
||||||
|
|
||||||
<!-- JOB STATUS MODAL-->
|
<!-- JOB STATUS MODAL-->
|
||||||
|
|||||||
@ -171,7 +171,7 @@
|
|||||||
{# Card View (Default) #}
|
{# Card View (Default) #}
|
||||||
<div class="card-view active row">
|
<div class="card-view active row">
|
||||||
{% for job in page_obj %}
|
{% for job in page_obj %}
|
||||||
<div class="col-md-6 col-lg-4 mb-4">
|
<div class="col-md-6 col-lg-4 mb-4 ">
|
||||||
<div class="card job-card h-100">
|
<div class="card job-card h-100">
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||||
|
|||||||
@ -2,11 +2,11 @@
|
|||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="myModalLabel">Add New Comment</h5>
|
<h5 class="modal-title" id="myModalLabel">Add New Image</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form method="post" action="{% url 'job_create' %}">
|
<form method="post" action="{% url 'job_detail' job.slug %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ image_form }}
|
{{ image_form }}
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
@ -2,199 +2,120 @@
|
|||||||
{% load static i18n %}
|
{% load static i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Zoom Meetings" %} - {{ block.super }}{% endblock %}
|
{% block title %}{% trans "Zoom Meetings" %} - {{ block.super }}{% endblock %}
|
||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
/* UI Variables for the KAAT-S Theme */
|
/* UI Variables for the KAAT-S Theme (Consistent with Reference) */
|
||||||
:root {
|
:root {
|
||||||
--kaauh-teal: #00636e;
|
--kaauh-teal: #00636e;
|
||||||
--kaauh-teal-dark: #004a53;
|
--kaauh-teal-dark: #004a53;
|
||||||
--kaauh-border: #eaeff3;
|
--kaauh-border: #eaeff3;
|
||||||
--kaauh-primary-text: #343a40;
|
--kaauh-primary-text: #343a40;
|
||||||
--kaauh-gray: #6c757d;
|
--kaauh-gray-light: #f8f9fa;
|
||||||
|
|
||||||
/* Status Colors based on KAAT-S example */
|
|
||||||
--kaauh-success: var(--kaauh-teal);
|
|
||||||
--kaauh-warning: #ffc107;
|
|
||||||
--kaauh-danger: #dc3545;
|
|
||||||
--kaauh-secondary: #6c757d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base style for all buttons to inherit Bootstrap's basic structure/reset */
|
/* Enhanced Card Styling (Consistent) */
|
||||||
.btn-base {
|
.card {
|
||||||
display: inline-block;
|
border: 1px solid var(--kaauh-border);
|
||||||
text-align: center;
|
border-radius: 0.75rem;
|
||||||
vertical-align: middle;
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
cursor: pointer;
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
user-select: none;
|
background-color: white;
|
||||||
padding: 0.375rem 0.75rem; /* Standard default padding */
|
}
|
||||||
font-size: 1rem;
|
.card:not(.no-hover):hover {
|
||||||
line-height: 1.5;
|
transform: translateY(-2px);
|
||||||
border-radius: 0.25rem;
|
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
|
||||||
border: 1px solid transparent;
|
}
|
||||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
.card.no-hover:hover {
|
||||||
/* FIX: Remove link underline for anchor tags used as buttons */
|
transform: none;
|
||||||
text-decoration: none;
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Small Button Size */
|
/* Main Action Button Style (Teal Theme) */
|
||||||
.btn-sm {
|
|
||||||
padding: 0.3rem 0.6rem;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main Action Button (Create Meeting) */
|
|
||||||
.btn-main-action {
|
.btn-main-action {
|
||||||
background-color: var(--kaauh-teal);
|
background-color: var(--kaauh-teal);
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-main-action:hover {
|
.btn-main-action:hover {
|
||||||
background-color: var(--kaauh-teal-dark);
|
background-color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-teal-dark);
|
border-color: var(--kaauh-teal-dark);
|
||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
text-decoration: none; /* Ensure no hover underline if base fails */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outline Primary (View/Join buttons) */
|
/* Secondary Button Style (For Edit/Outline - Consistent) */
|
||||||
.btn-kaats-outline-primary {
|
.btn-outline-secondary {
|
||||||
|
color: var(--kaauh-teal-dark);
|
||||||
|
border-color: var(--kaauh-teal);
|
||||||
|
}
|
||||||
|
.btn-outline-secondary:hover {
|
||||||
|
background-color: var(--kaauh-teal-dark);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--kaauh-teal-dark);
|
||||||
|
}
|
||||||
|
/* Primary Outline for View/Join */
|
||||||
|
.btn-outline-primary {
|
||||||
color: var(--kaauh-teal);
|
color: var(--kaauh-teal);
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
.btn-kaats-outline-primary:hover {
|
.btn-outline-primary:hover {
|
||||||
background-color: var(--kaauh-teal);
|
background-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outline Secondary (Update button) */
|
/* Meeting Card Specifics (Adapted to Standard Card View) */
|
||||||
.btn-kaats-outline-secondary {
|
.meeting-card .card-title {
|
||||||
color: var(--kaauh-secondary);
|
|
||||||
border-color: var(--kaauh-secondary);
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.btn-kaats-outline-secondary:hover {
|
|
||||||
background-color: var(--kaauh-secondary);
|
|
||||||
color: white;
|
|
||||||
border-color: var(--kaauh-secondary);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Outline Danger (Delete button) */
|
|
||||||
.btn-kaats-outline-danger {
|
|
||||||
color: var(--kaauh-danger);
|
|
||||||
border-color: var(--kaauh-danger);
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
.btn-kaats-outline-danger:hover {
|
|
||||||
background-color: var(--kaauh-danger);
|
|
||||||
color: white;
|
|
||||||
border-color: var(--kaauh-danger);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- General UI Styles (Unchanged) --- */
|
|
||||||
|
|
||||||
/* CARD GRID STYLES */
|
|
||||||
.meetings-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
||||||
gap: 1.5rem;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
.meeting-card {
|
|
||||||
background: white;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border: 1px solid var(--kaauh-border);
|
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.meeting-card:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TOPIC AND DETAILS STYLES */
|
|
||||||
.meeting-topic {
|
|
||||||
font-size: 1.15rem;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
margin-bottom: 1rem;
|
|
||||||
border-bottom: 1px solid var(--kaauh-border);
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
.meeting-detail {
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
.detail-label {
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
min-width: 80px;
|
font-size: 1.15rem;
|
||||||
color: var(--kaauh-gray);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
.detail-value {
|
.meeting-card .card-text i {
|
||||||
flex: 1;
|
color: var(--kaauh-teal);
|
||||||
font-size: 0.9rem;
|
width: 1.25rem;
|
||||||
word-break: break-word;
|
|
||||||
color: var(--kaauh-primary-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STATUS BADGE STYLES */
|
/* Status Badges (Standardized) */
|
||||||
.status-badge {
|
.status-badge {
|
||||||
display: inline-block;
|
font-size: 0.8rem;
|
||||||
font-size: 0.75rem;
|
|
||||||
font-weight: 700;
|
|
||||||
padding: 0.4em 0.8em;
|
padding: 0.4em 0.8em;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.bg-warning {
|
|
||||||
background: var(--kaauh-warning) !important;
|
|
||||||
color: var(--kaauh-primary-text) !important;
|
|
||||||
}
|
|
||||||
.bg-success {
|
|
||||||
background: var(--kaauh-success) !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
.bg-danger {
|
|
||||||
background: var(--kaauh-danger) !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ACTION AREA STYLES */
|
|
||||||
.actions {
|
|
||||||
margin-top: 1rem;
|
|
||||||
display: flex;
|
|
||||||
gap: 0.5rem;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header Styling */
|
|
||||||
.card-header h1 {
|
|
||||||
color: var(--kaauh-teal-dark);
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.7px;
|
||||||
}
|
}
|
||||||
.card {
|
/* Status Badge Mapping */
|
||||||
border: 1px solid var(--kaauh-border);
|
.bg-waiting { background-color: #ffc107 !important; color: var(--kaauh-primary-text) !important;}
|
||||||
border-radius: 0.75rem;
|
.bg-started { background-color: var(--kaauh-teal) !important; color: white !important;}
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
.bg-ended { background-color: #dc3545 !important; color: white !important;}
|
||||||
}
|
|
||||||
|
|
||||||
/* Empty State Icon Color */
|
/* Table Styling (Consistent with Reference) */
|
||||||
.text-muted.mb-3 {
|
.table-view .table thead th {
|
||||||
color: var(--kaauh-teal-dark) !important;
|
background-color: var(--kaauh-teal-dark);
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
.table-view .table tbody td {
|
||||||
/* Pagination Link Styling */
|
vertical-align: middle;
|
||||||
|
padding: 1rem;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
}
|
||||||
|
.table-view .table tbody tr:hover {
|
||||||
|
background-color: var(--kaauh-gray-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination Link Styling (Consistent) */
|
||||||
.pagination .page-item .page-link {
|
.pagination .page-item .page-link {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
@ -208,120 +129,123 @@
|
|||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RESPONSIVE STYLES */
|
/* Filter & Search Layout Adjustments */
|
||||||
@media (max-width: 768px) {
|
.filter-buttons {
|
||||||
.meetings-grid {
|
display: flex;
|
||||||
grid-template-columns: 1fr;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
.meeting-detail {
|
|
||||||
flex-direction: column;
|
/* Icon color for empty state */
|
||||||
gap: 0.25rem;
|
.text-muted.fa-3x {
|
||||||
}
|
color: var(--kaauh-teal-dark) !important;
|
||||||
.detail-label {
|
|
||||||
min-width: auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="card">
|
<div class="container-fluid py-4">
|
||||||
<div class="card-header">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<h1 style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
||||||
<h1 class="h3 mb-0">
|
<i class="fas fa-video me-2"></i> {% trans "Zoom Meetings" %}
|
||||||
{% include "icons/meeting.html" %}
|
</h1>
|
||||||
{% trans "Zoom Meetings" %}
|
<a href="{% url 'create_meeting' %}" class="btn btn-main-action">
|
||||||
</h1>
|
<i class="fas fa-plus me-1"></i> {% trans "Create Meeting" %}
|
||||||
<div class="d-flex gap-2 align-items-center">
|
</a>
|
||||||
{% include "includes/search_form.html" with search_query=search_query %}
|
</div>
|
||||||
|
|
||||||
<a href="{% url 'create_meeting' %}" class="btn-base btn-main-action">
|
<div class="card mb-4 shadow-sm no-hover">
|
||||||
<svg class="heroicon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<div class="card-body">
|
||||||
<path d="M12 4v16m8-8H4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
<div class="row">
|
||||||
</svg>
|
<div class="col-md-4">
|
||||||
{% trans "Create Meeting" %}
|
<label for="search" class="form-label small text-muted">{% trans "Search by Topic" %}</label>
|
||||||
</a>
|
<div class="input-group input-group-lg mb-3">
|
||||||
|
<form method="get" action="" class="w-100">
|
||||||
|
{% include "includes/search_form.html" with search_query=search_query %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<form method="GET" class="row g-3 align-items-end" >
|
||||||
|
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label for="status" class="form-label small text-muted">{% trans "Filter by Status" %}</label>
|
||||||
|
<select name="status" id="status" class="form-select form-select-sm">
|
||||||
|
<option value="">{% trans "All Statuses" %}</option>
|
||||||
|
<option value="waiting" {% if status_filter == 'waiting' %}selected{% endif %}>{% trans "Waiting" %}</option>
|
||||||
|
<option value="started" {% if status_filter == 'started' %}selected{% endif %}>{% trans "Started" %}</option>
|
||||||
|
<option value="ended" {% if status_filter == 'ended' %}selected{% endif %}>{% trans "Ended" %}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="filter-buttons">
|
||||||
|
<button type="submit" class="btn btn-main-action btn-lg">
|
||||||
|
<i class="fas fa-filter me-1"></i> {% trans "Apply Filters" %}
|
||||||
|
</button>
|
||||||
|
{% if status_filter or search_query %}
|
||||||
|
<a href="{% url 'meeting_list' %}" class="btn btn-outline-secondary btn-lg">
|
||||||
|
<i class="fas fa-times me-1"></i> {% trans "Clear" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if meetings %}
|
{% if meetings %}
|
||||||
<div id="meetings-list">
|
<div id="meetings-list">
|
||||||
{# View Switcher #}
|
{# View Switcher #}
|
||||||
{% include "includes/_list_view_switcher.html" with list_id="meetings-list" %}
|
{% include "includes/_list_view_switcher.html" with list_id="meetings-list" %}
|
||||||
|
|
||||||
{# Card View (Default) #}
|
{# Card View #}
|
||||||
<div class="card-view active">
|
<div class="card-view active row">
|
||||||
<div class="meetings-grid">
|
{% for meeting in meetings %}
|
||||||
{% for meeting in meetings %}
|
<div class="col-md-6 col-lg-4 mb-4">
|
||||||
<div class="meeting-card">
|
<div class="card meeting-card h-100 shadow-sm">
|
||||||
<div class="meeting-topic">{{ meeting.topic }}</div>
|
<div class="card-body d-flex flex-column">
|
||||||
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||||
<div class="meeting-detail">
|
<h5 class="card-title flex-grow-1 me-3">{{ meeting.topic }}</h5>
|
||||||
<div class="detail-label">{% trans "ID" %}:</div>
|
<span class="status-badge bg-{{ meeting.status }}">
|
||||||
<div class="detail-value">{{ meeting.meeting_id|default:meeting.id }}</div>
|
{{ meeting.status|title }}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="meeting-detail">
|
|
||||||
<div class="detail-label">{% trans "Start Time" %}:</div>
|
|
||||||
<div class="detail-value">{{ meeting.start_time|date:"M d, Y H:i" }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="meeting-detail">
|
|
||||||
<div class="detail-label">{% trans "Duration" %}:</div>
|
|
||||||
<div class="detail-value">{{ meeting.duration }} minutes</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="meeting-detail">
|
|
||||||
<div class="detail-label">{% trans "Status" %}:</div>
|
|
||||||
<div class="detail-value">
|
|
||||||
<span class="status-badge {% if meeting.status == 'waiting' %}bg-warning{% elif meeting.status == 'started' %}bg-success{% elif meeting.status == 'ended' %}bg-danger{% endif %}">
|
|
||||||
{% if meeting.status == 'waiting' %}
|
|
||||||
{% trans "Waiting" %}
|
|
||||||
{% elif meeting.status == 'started' %}
|
|
||||||
{% trans "Started" %}
|
|
||||||
{% elif meeting.status == 'ended' %}
|
|
||||||
{% trans "Ended" %}
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if meeting.join_url %}
|
<p class="card-text text-muted small mb-3">
|
||||||
<div class="meeting-detail">
|
<i class="fas fa-hashtag"></i> {% trans "ID" %}: {{ meeting.meeting_id|default:meeting.id }}<br>
|
||||||
<div class="detail-label">{% trans "Join URL" %}:</div>
|
<i class="fas fa-clock"></i> {% trans "Start" %}: {{ meeting.start_time|date:"M d, Y H:i" }}<br>
|
||||||
<div class="detail-value">
|
<i class="fas fa-stopwatch"></i> {% trans "Duration" %}: {{ meeting.duration }} minutes
|
||||||
<a href="{{ meeting.join_url }}" target="_blank" class="btn-base btn-kaats-outline-primary btn-sm">
|
</p>
|
||||||
{% trans "Join Meeting" %}
|
|
||||||
|
<div class="mt-auto pt-2 border-top">
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<a href="{% url 'meeting_details' meeting.pk %}" class="btn btn-sm btn-outline-primary">
|
||||||
|
<i class="fas fa-eye"></i> {% trans "View" %}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
{% if meeting.join_url %}
|
||||||
|
<a href="{{ meeting.join_url }}" target="_blank" class="btn btn-sm btn-main-action">
|
||||||
|
<i class="fas fa-link"></i> {% trans "Join" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<a href="{% url 'update_meeting' meeting.pk %}" class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
|
data-delete-url="{% url 'delete_meeting' meeting.pk %}"
|
||||||
|
data-item-name="{{ meeting.topic }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="actions">
|
|
||||||
<a href="{% url 'meeting_details' meeting.pk %}" class="btn-base btn-kaats-outline-primary btn-sm" title="{% trans 'View' %}">
|
|
||||||
<svg class="heroicon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
<path d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0 8.268-2.943-9.542-7z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a href="{% url 'update_meeting' meeting.pk %}" class="btn-base btn-kaats-outline-secondary btn-sm" title="{% trans 'Update' %}">
|
|
||||||
<svg class="heroicon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn-base btn-kaats-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
|
||||||
data-bs-toggle="deleteModal"
|
|
||||||
data-delete-url="{% url 'delete_meeting' meeting.pk %}"
|
|
||||||
data-item-name="{{ meeting.topic }}">
|
|
||||||
<svg class="heroicon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Table View #}
|
{# Table View #}
|
||||||
@ -330,34 +254,33 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{% trans "Topic" %}</th>
|
<th scope="col" style="width: 30%;">{% trans "Topic" %}</th>
|
||||||
<th scope="col">{% trans "ID" %}</th>
|
<th scope="col" style="width: 15%;">{% trans "ID" %}</th>
|
||||||
<th scope="col">{% trans "Start Time" %}</th>
|
<th scope="col" style="width: 20%;">{% trans "Start Time" %}</th>
|
||||||
<th scope="col">{% trans "Duration" %}</th>
|
<th scope="col" style="width: 10%;">{% trans "Duration" %}</th>
|
||||||
<th scope="col">{% trans "Status" %}</th>
|
<th scope="col" style="width: 15%;">{% trans "Status" %}</th>
|
||||||
<th scope="col" class="text-end">{% trans "Actions" %}</th>
|
<th scope="col" style="width: 10%;" class="text-end">{% trans "Actions" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for meeting in meetings %}
|
{% for meeting in meetings %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{{ meeting.topic }}</strong></td>
|
<td><strong class="text-primary">{{ meeting.topic }}</strong></td>
|
||||||
<td>{{ meeting.meeting_id|default:meeting.id }}</td>
|
<td>{{ meeting.meeting_id|default:meeting.id }}</td>
|
||||||
<td>{{ meeting.start_time|date:"M d, Y H:i" }}</td>
|
<td>{{ meeting.start_time|date:"M d, Y H:i" }}</td>
|
||||||
<td>{{ meeting.duration }} minutes</td>
|
<td>{{ meeting.duration }} min</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="status-badge {% if meeting.status == 'waiting' %}bg-warning{% elif meeting.status == 'started' %}bg-success{% elif meeting.status == 'ended' %}bg-danger{% endif %}">
|
<span class="status-badge bg-{{ meeting.status }}">
|
||||||
{% if meeting.status == 'waiting' %}
|
{{ meeting.status|title }}
|
||||||
{% trans "Waiting" %}
|
|
||||||
{% elif meeting.status == 'started' %}
|
|
||||||
{% trans "Started" %}
|
|
||||||
{% elif meeting.status == 'ended' %}
|
|
||||||
{% trans "Ended" %}
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
<div class="btn-group btn-group-sm" role="group">
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
|
{% if meeting.join_url %}
|
||||||
|
<a href="{{ meeting.join_url }}" target="_blank" class="btn btn-main-action" title="{% trans 'Join' %}">
|
||||||
|
<i class="fas fa-sign-in-alt"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
<a href="{% url 'meeting_details' meeting.pk %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
<a href="{% url 'meeting_details' meeting.pk %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
@ -365,10 +288,10 @@
|
|||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
||||||
data-bs-toggle="deleteModal"
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
data-delete-url="{% url 'delete_meeting' meeting.pk %}"
|
data-delete-url="{% url 'delete_meeting' meeting.pk %}"
|
||||||
data-item-name="{{ meeting.topic }}">
|
data-item-name="{{ meeting.topic }}">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@ -380,52 +303,45 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# Pagination (Standardized) #}
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<nav aria-label="Page navigation" class="mt-4">
|
<nav aria-label="Page navigation" class="mt-4">
|
||||||
<ul class="pagination justify-content-center">
|
<ul class="pagination justify-content-center">
|
||||||
{% if page_obj.has_previous %}
|
{% if page_obj.has_previous %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}&search={{ search_query }}" aria-label="Previous">
|
<a class="page-link" href="?page=1{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">First</a>
|
||||||
<span aria-hidden="true">«</span>
|
</li>
|
||||||
</a>
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">Previous</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for num in page_obj.paginator.page_range %}
|
<li class="page-item active">
|
||||||
{% if page_obj.number == num %}
|
<span class="page-link">{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
|
||||||
<li class="page-item active"><span class="page-link">{{ num }}</span></li>
|
</li>
|
||||||
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="?page={{ num }}&search={{ search_query }}">{{ num }}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if page_obj.has_next %}
|
{% if page_obj.has_next %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}&search={{ search_query }}" aria-label="Next">
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">Next</a>
|
||||||
<span aria-hidden="true">»</span>
|
</li>
|
||||||
</a>
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}">Last</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="text-center py-5">
|
<div class="text-center py-5 card shadow-sm">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="text-muted mb-3" style="width: 80px;">
|
<div class="card-body">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
|
<i class="fas fa-video fa-3x mb-3" style="color: var(--kaauh-teal-dark);"></i>
|
||||||
</svg>
|
<h3>{% trans "No Zoom meetings found" %}</h3>
|
||||||
<p class="text-muted">{% trans "No meetings found." %}</p>
|
<p class="text-muted">{% trans "Create your first meeting or adjust your filters." %}</p>
|
||||||
{% if user.is_staff %}
|
<a href="{% url 'create_meeting' %}" class="btn btn-main-action mt-3">
|
||||||
<a href="{% url 'create_meeting' %}" class="btn-base btn-main-action mt-3">
|
<i class="fas fa-plus me-1"></i> {% trans "Create Your First Meeting" %}
|
||||||
<svg class="heroicon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M12 4v16m8-8H4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
</svg>
|
|
||||||
{% trans "Create Your First Meeting" %}
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -115,8 +115,8 @@
|
|||||||
color: var(--kaauh-teal);
|
color: var(--kaauh-teal);
|
||||||
}
|
}
|
||||||
.main-tabs .nav-link.active {
|
.main-tabs .nav-link.active {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark) !important;
|
||||||
background-color: white;
|
background-color: white !important;
|
||||||
border-bottom: 3px solid var(--kaauh-teal);
|
border-bottom: 3px solid var(--kaauh-teal);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@ -141,8 +141,8 @@
|
|||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
.right-column-card .nav-link.active {
|
.right-column-card .nav-link.active {
|
||||||
background-color: white;
|
background-color: white !important;
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark) !important;
|
||||||
border-bottom: 3px solid var(--kaauh-teal);
|
border-bottom: 3px solid var(--kaauh-teal);
|
||||||
border-right-color: transparent;
|
border-right-color: transparent;
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
|
|||||||
@ -5,15 +5,16 @@
|
|||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
/* UI Variables for the KAAT-S Theme */
|
/* UI Variables for the KAAT-S Theme (Consistent with Reference) */
|
||||||
:root {
|
:root {
|
||||||
--kaauh-teal: #00636e;
|
--kaauh-teal: #00636e;
|
||||||
--kaauh-teal-dark: #004a53;
|
--kaauh-teal-dark: #004a53;
|
||||||
--kaauh-border: #eaeff3;
|
--kaauh-border: #eaeff3;
|
||||||
--kaauh-primary-text: #343a40;
|
--kaauh-primary-text: #343a40;
|
||||||
|
--kaauh-gray-light: #f8f9fa; /* Added for hover/background consistency */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enhanced Card Styling */
|
/* Enhanced Card Styling (Consistent) */
|
||||||
.card {
|
.card {
|
||||||
border: 1px solid var(--kaauh-border);
|
border: 1px solid var(--kaauh-border);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
@ -21,19 +22,15 @@
|
|||||||
transition: transform 0.2s, box-shadow 0.2s;
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
.card:hover {
|
.card:not(.no-hover):hover { /* Use no-hover class for main structure cards */
|
||||||
/* Remove hover effect from the main list card to avoid visual noise */
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.card.no-hover:hover {
|
||||||
transform: none;
|
transform: none;
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-header {
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 1.25rem;
|
|
||||||
border-bottom: 1px solid var(--kaauh-border);
|
|
||||||
background-color: #f8f9fa; /* Light header background */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main Action Button Style (Teal Theme) */
|
/* Main Action Button Style (Teal Theme) */
|
||||||
.btn-main-action {
|
.btn-main-action {
|
||||||
background-color: var(--kaauh-teal);
|
background-color: var(--kaauh-teal);
|
||||||
@ -53,50 +50,63 @@
|
|||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Secondary Action Buttons (used in table) */
|
/* Secondary Button Style (For Edit/Outline - Consistent) */
|
||||||
.btn-group .btn-outline-primary {
|
.btn-outline-secondary {
|
||||||
color: var(--kaauh-teal);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-border);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
.btn-group .btn-outline-primary:hover {
|
|
||||||
background-color: var(--kaauh-teal);
|
|
||||||
color: white;
|
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
}
|
}
|
||||||
|
.btn-outline-secondary:hover {
|
||||||
/* Table Styling */
|
background-color: var(--kaauh-teal-dark);
|
||||||
.table thead th {
|
color: white;
|
||||||
|
border-color: var(--kaauh-teal-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Card Specifics (Adapted from Job Card to Candidate Card) */
|
||||||
|
.candidate-card .card-title {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-bottom: 2px solid var(--kaauh-teal); /* Highlight bottom border */
|
font-size: 1.15rem;
|
||||||
vertical-align: middle;
|
}
|
||||||
padding: 0.75rem 1rem;
|
.candidate-card .card-text i {
|
||||||
font-size: 0.95rem;
|
color: var(--kaauh-teal);
|
||||||
|
width: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table tbody tr:hover {
|
/* Table & Card Badge Styling (Unified) */
|
||||||
background-color: #f3f9f9; /* Light teal hover for rows */
|
|
||||||
}
|
|
||||||
|
|
||||||
.table tbody td {
|
|
||||||
vertical-align: middle;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Badge Styling */
|
|
||||||
.badge {
|
.badge {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0.4em 0.7em;
|
padding: 0.4em 0.7em;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status Badge Mapping */
|
/* Status Badge Mapping (Using standard Bootstrap names where possible) */
|
||||||
.table .bg-primary { background-color: var(--kaauh-teal) !important; color: white !important;} /* Job Title Badge */
|
.bg-primary { background-color: var(--kaauh-teal) !important; color: white !important;} /* Main job/stage badge */
|
||||||
.table .bg-success { background-color: #28a745 !important; } /* Applied: Yes */
|
.bg-success { background-color: #28a745 !important; color: white !important;}
|
||||||
.table .bg-warning { background-color: #ffc107 !important; } /* Applied: No */
|
.bg-warning { background-color: #ffc107 !important; color: #343a40 !important;}
|
||||||
|
|
||||||
/* Pagination Link Styling */
|
/* Table Styling (Consistent with Reference) */
|
||||||
|
.table-view .table thead th {
|
||||||
|
background-color: var(--kaauh-teal-dark); /* Dark header background */
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.table-view .table tbody td {
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 1rem;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
}
|
||||||
|
.table-view .table tbody tr:hover {
|
||||||
|
background-color: var(--kaauh-gray-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination Link Styling (Consistent) */
|
||||||
.pagination .page-item .page-link {
|
.pagination .page-item .page-link {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
@ -109,189 +119,213 @@
|
|||||||
.pagination .page-item:hover .page-link:not(.active) {
|
.pagination .page-item:hover .page-link:not(.active) {
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icon Sizing in Buttons */
|
/* Filter & Search Layout Adjustments */
|
||||||
.btn-group .btn-sm svg {
|
.filter-buttons {
|
||||||
width: 1rem;
|
display: flex;
|
||||||
height: 1rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="card shadow-sm">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
<div class="card-header">
|
<h1 style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<i class="fas fa-users me-2"></i> {% trans "Candidate Profiles" %}
|
||||||
<h1 class="h3 mb-0" style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
</h1>
|
||||||
<i class="fas fa-users me-2"></i>
|
{% if user.is_staff %}
|
||||||
{% trans "Candidate Profiles" %}
|
<a href="{% url 'candidate_create' %}" class="btn btn-main-action">
|
||||||
</h1>
|
<i class="fas fa-plus me-1"></i> {% trans "Add New Candidate" %}
|
||||||
<div class="d-flex gap-3 align-items-center">
|
</a>
|
||||||
{# The search form structure should be updated to align with the job_list style if possible #}
|
{% endif %}
|
||||||
{% include "includes/search_form.html" with search_query=search_query %}
|
</div>
|
||||||
|
|
||||||
{% if user.is_staff %}
|
<div class="card mb-4 shadow-sm no-hover">
|
||||||
<a href="{% url 'candidate_create' %}" class="btn btn-main-action">
|
<div class="card-body">
|
||||||
<i class="fas fa-plus"></i>
|
<div class="row">
|
||||||
{% trans "Add New Candidate" %}
|
<div class="col-md-4">
|
||||||
</a>
|
<label for="search" class="form-label small text-muted">{% trans "Search by Name or Email" %}</label>
|
||||||
{% endif %}
|
<div class="input-group input-group-lg mb-3">
|
||||||
|
<form method="get" action="" class="w-100">
|
||||||
|
{% include 'includes/search_form.html' %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
{% url 'candidate_list' as candidate_list_url %}
|
||||||
|
|
||||||
|
<form method="GET" class="row g-3 align-items-end" >
|
||||||
|
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label for="job_filter" class="form-label small text-muted">{% trans "Filter by Job" %}</label>
|
||||||
|
<select name="job" id="job_filter" class="form-select form-select-sm">
|
||||||
|
<option value="">{% trans "All Jobs" %}</option>
|
||||||
|
{% for job in available_jobs %} {# Assuming you pass a context variable 'available_jobs' #}
|
||||||
|
<option value="{{ job.slug }}" {% if job_filter == job.slug %}selected{% endif %}>{{ job.title }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="filter-buttons">
|
||||||
|
<button type="submit" class="btn btn-main-action btn-lg">
|
||||||
|
<i class="fas fa-filter me-1"></i> {% trans "Apply Filters" %}
|
||||||
|
</button>
|
||||||
|
{% if job_filter or search_query %}
|
||||||
|
<a href="{% url 'candidate_list' %}" class="btn btn-outline-secondary btn-lg">
|
||||||
|
<i class="fas fa-times me-1"></i> {% trans "Clear" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if candidates %}
|
||||||
|
<div id="candidate-list">
|
||||||
|
{# View Switcher - list_id must match the container ID #}
|
||||||
|
{% include "includes/_list_view_switcher.html" with list_id="candidate-list" %}
|
||||||
|
|
||||||
{% if candidates %}
|
{# Table View (Default) #}
|
||||||
<div id="candidate-list">
|
<div class="table-view active">
|
||||||
{# View Switcher #}
|
<div class="table-responsive">
|
||||||
{% include "includes/_list_view_switcher.html" with list_id="candidate-list" %}
|
<table class="table table-hover mb-0">
|
||||||
|
<thead>
|
||||||
{# Table View (Default) #}
|
<tr>
|
||||||
<div class="table-view active">
|
<th scope="col" style="width: 20%;">{% trans "Name" %}</th>
|
||||||
<div class="table-responsive">
|
<th scope="col" style="width: 20%;">{% trans "Email" %}</th>
|
||||||
<table class="table table-hover mb-0">
|
<th scope="col" style="width: 15%;">{% trans "Phone" %}</th>
|
||||||
<thead>
|
<th scope="col" style="width: 15%;">{% trans "Job" %}</th>
|
||||||
|
<th scope="col" style="width: 10%;">{% trans "Stage" %}</th>
|
||||||
|
<th scope="col" style="width: 10%;">{% trans "Created" %}</th>
|
||||||
|
<th scope="col" style="width: 10%;" class="text-end">{% trans "Actions" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for candidate in candidates %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" style="width: 20%;">{% trans "Name" %}</th>
|
<td class="fw-medium">{{ candidate.name }}</td>
|
||||||
<th scope="col" style="width: 20%;">{% trans "Email" %}</th>
|
<td>{{ candidate.email }}</td>
|
||||||
<th scope="col" style="width: 15%;">{% trans "Phone" %}</th>
|
<td>{{ candidate.phone }}</td>
|
||||||
<th scope="col" style="width: 15%;">{% trans "Job" %}</th>
|
<td> <span class="badge bg-primary">{{ candidate.job.title }}</span></td>
|
||||||
<th scope="col" style="width: 10%;">{% trans "Stage" %}</th>
|
<td>
|
||||||
<th scope="col" style="width: 10%;">{% trans "Created" %}</th>
|
<span class="badge bg-primary">
|
||||||
<th scope="col" style="width: 10%;" class="text-center">{% trans "Actions" %}</th>
|
{{ candidate.stage }}
|
||||||
</tr>
|
</span>
|
||||||
</thead>
|
</td>
|
||||||
<tbody>
|
<td>{{ candidate.created_at|date:"M d, Y" }}</td>
|
||||||
{% for candidate in candidates %}
|
<td class="text-end">
|
||||||
<tr>
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
<td><strong>{{ candidate.name }}</strong></td>
|
<a href="{% url 'candidate_detail' candidate.slug %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
||||||
<td>{{ candidate.email }}</td>
|
<i class="fas fa-eye"></i>
|
||||||
<td>{{ candidate.phone }}</td>
|
|
||||||
<td> <span class="badge bg-primary">{{ candidate.job.title }}</span></td>
|
|
||||||
<td>
|
|
||||||
<span class="badge bg-primary">
|
|
||||||
{{ candidate.stage }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>{{ candidate.created_at|date:"M d, Y" }}</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="btn-group btn-group-sm" role="group">
|
|
||||||
<a href="{% url 'candidate_detail' candidate.slug %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
{% if user.is_staff %}
|
|
||||||
<a href="{% url 'candidate_update' candidate.slug %}" class="btn btn-outline-primary" title="{% trans 'Edit' %}">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
|
||||||
data-bs-toggle="deleteModal"
|
|
||||||
data-delete-url="{% url 'candidate_delete' candidate.slug %}"
|
|
||||||
data-item-name="{{ candidate.name }}">
|
|
||||||
<i class="fas fa-trash-alt"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Card View #}
|
|
||||||
<div class="card-view">
|
|
||||||
<div class="row g-4">
|
|
||||||
{% for candidate in candidates %}
|
|
||||||
<div class="col-md-6 col-lg-4">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="h5 mb-1">{{ candidate.name }}</h5>
|
|
||||||
<small class="text-white-50">{{ candidate.email }}</small>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">
|
|
||||||
<strong>{% trans "Phone" %}:</strong> {{ candidate.phone|default:"N/A" }}<br>
|
|
||||||
<strong>{% trans "Job" %}:</strong> <span class="badge bg-primary">{{ candidate.job.title }}</span><br>
|
|
||||||
<strong>{% trans "Stage" %}:</strong> <span class="badge bg-primary">{{ candidate.stage }}</span><br>
|
|
||||||
<strong>{% trans "Created" %}:</strong> {{ candidate.created_at|date:"M d, Y" }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<div class="d-flex gap-2">
|
|
||||||
<a href="{% url 'candidate_detail' candidate.slug %}" class="btn btn-sm btn-outline-primary w-100">
|
|
||||||
<i class="fas fa-eye"></i> {% trans "View" %}
|
|
||||||
</a>
|
</a>
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
<div class="btn-group w-100" role="group">
|
<a href="{% url 'candidate_update' candidate.slug %}" class="btn btn-outline-secondary" title="{% trans 'Edit' %}">
|
||||||
<a href="{% url 'candidate_update' candidate.slug %}" class="btn btn-sm btn-outline-secondary" title="{% trans 'Edit' %}">
|
<i class="fas fa-edit"></i>
|
||||||
<i class="fas fa-edit"></i>
|
</a>
|
||||||
</a>
|
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
||||||
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
data-bs-toggle="modal" data-bs-target="#deleteModal" {# Updated to standard Bootstrap usage #}
|
||||||
data-bs-toggle="deleteModal"
|
data-delete-url="{% url 'candidate_delete' candidate.slug %}"
|
||||||
data-delete-url="{% url 'candidate_delete' candidate.slug %}"
|
data-item-name="{{ candidate.name }}">
|
||||||
data-item-name="{{ candidate.name }}">
|
<i class="fas fa-trash-alt"></i>
|
||||||
<i class="fas fa-trash-alt"></i>
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Card View #}
|
||||||
|
<div class="card-view row"> {# Added 'row' class for grid structure #}
|
||||||
|
{% for candidate in candidates %}
|
||||||
|
<div class="col-md-6 col-lg-4 mb-4"> {# Column wrapper for grid #}
|
||||||
|
<div class="card candidate-card h-100 shadow-sm">
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||||
|
<h5 class="card-title flex-grow-1 me-3">{{ candidate.name }}</h5>
|
||||||
|
<span class="badge bg-primary">{{ candidate.stage }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="card-text text-muted small">
|
||||||
|
<i class="fas fa-envelope"></i> {{ candidate.email }}<br>
|
||||||
|
<i class="fas fa-phone-alt"></i> {{ candidate.phone|default:"N/A" }}<br>
|
||||||
|
<i class="fas fa-briefcase"></i> <span class="badge bg-primary">{{ candidate.job.title }}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mt-auto pt-2 border-top">
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<a href="{% url 'candidate_detail' candidate.slug %}" class="btn btn-sm btn-main-action">
|
||||||
|
<i class="fas fa-eye"></i> {% trans "View" %}
|
||||||
|
</a>
|
||||||
|
{% if user.is_staff %}
|
||||||
|
<a href="{% url 'candidate_update' candidate.slug %}" class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="fas fa-edit"></i> {% trans "Edit" %}
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
|
data-delete-url="{% url 'candidate_delete' candidate.slug %}"
|
||||||
|
data-item-name="{{ candidate.name }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if is_paginated %}
|
{# Pagination (Standardized to Reference) #}
|
||||||
<div class="card-footer bg-white border-top">
|
{% if is_paginated %}
|
||||||
<nav aria-label="Page navigation">
|
<nav aria-label="Page navigation" class="mt-4">
|
||||||
<ul class="pagination justify-content-center mb-0">
|
<ul class="pagination justify-content-center">
|
||||||
{% if page_obj.has_previous %}
|
{% if page_obj.has_previous %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}" aria-label="Previous">
|
<a class="page-link" href="?page=1{% if search_query %}&q={{ search_query }}{% endif %}{% if job_filter %}&job={{ job_filter }}{% endif %}">First</a>
|
||||||
<span aria-hidden="true">«</span>
|
</li>
|
||||||
</a>
|
<li class="page-item">
|
||||||
</li>
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}{% if job_filter %}&job={{ job_filter }}{% endif %}">Previous</a>
|
||||||
{% endif %}
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# Simplified pagination logic for theme consistency #}
|
<li class="page-item active">
|
||||||
{% for num in page_obj.paginator.page_range %}
|
<span class="page-link">{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
|
||||||
{% if page_obj.number == num %}
|
</li>
|
||||||
<li class="page-item active"><span class="page-link">{{ num }}</span></li>
|
|
||||||
{% elif num > page_obj.number|add:'-2' and num < page_obj.number|add:'2' %}
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="?page={{ num }}{% if search_query %}&q={{ search_query }}{% endif %}">{{ num }}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if page_obj.has_next %}
|
{% if page_obj.has_next %}
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}" aria-label="Next">
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}{% if job_filter %}&job={{ job_filter }}{% endif %}">Next</a>
|
||||||
<span aria-hidden="true">»</span>
|
</li>
|
||||||
</a>
|
<li class="page-item">
|
||||||
</li>
|
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if search_query %}&q={{ search_query }}{% endif %}{% if job_filter %}&job={{ job_filter }}{% endif %}">Last</a>
|
||||||
{% endif %}
|
</li>
|
||||||
</ul>
|
{% endif %}
|
||||||
</nav>
|
</ul>
|
||||||
</div>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="text-center py-5">
|
<div class="text-center py-5 card shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
<i class="fas fa-users fa-3x mb-3" style="color: var(--kaauh-teal-dark);"></i>
|
<i class="fas fa-users fa-3x mb-3" style="color: var(--kaauh-teal-dark);"></i>
|
||||||
<h4 class="text-muted">{% trans "No candidates found." %}</h4>
|
<h3>{% trans "No candidate profiles found" %}</h3>
|
||||||
<p class="text-muted">{% trans "Start by adding a new profile or adjusting your search filters." %}</p>
|
<p class="text-muted">{% trans "Create your first candidate profile or adjust your filters." %}</p>
|
||||||
{% if user.is_staff %}
|
{% if user.is_staff %}
|
||||||
<a href="{% url 'candidate_create' %}" class="btn btn-main-action mt-3">
|
<a href="{% url 'candidate_create' %}" class="btn btn-main-action mt-3">
|
||||||
<i class="fas fa-plus me-1"></i>
|
<i class="fas fa-plus me-1"></i> {% trans "Add Candidate" %}
|
||||||
{% trans "Add Your First Candidate" %}
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -5,48 +5,53 @@
|
|||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
/* ================================================= */
|
/* UI Variables for the KAAT-S Theme (Consistent with Reference) */
|
||||||
/* THEME VARIABLES AND GLOBAL STYLES (FROM JOB DETAIL) */
|
|
||||||
/* ================================================= */
|
|
||||||
:root {
|
:root {
|
||||||
--kaauh-teal: #00636e;
|
--kaauh-teal: #00636e;
|
||||||
--kaauh-teal-dark: #004a53;
|
--kaauh-teal-dark: #004a53;
|
||||||
--kaauh-border: #eaeff3;
|
--kaauh-border: #eaeff3;
|
||||||
--kaauh-primary-text: #343a40;
|
--kaauh-primary-text: #343a40;
|
||||||
|
--kaauh-gray-light: #f8f9fa; /* Added for hover/background consistency */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Primary Color Overrides */
|
/* Enhanced Card Styling (Consistent) */
|
||||||
.text-primary { color: var(--kaauh-teal) !important; }
|
.card {
|
||||||
|
border: 1px solid var(--kaauh-border);
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
/* Standard card hover effect for list items */
|
||||||
|
.card:not(.no-hover):hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.card.no-hover:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||||||
|
}
|
||||||
|
|
||||||
/* Main Action Button Style (Applied to .btn-primary) */
|
/* Main Action Button Style (Teal Theme) */
|
||||||
.btn-main-action, .btn-primary {
|
.btn-main-action {
|
||||||
background-color: var(--kaauh-teal);
|
background-color: var(--kaauh-teal);
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0.6rem 1.2rem;
|
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.4rem;
|
||||||
text-decoration: none; /* Ensure links look like buttons */
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
.btn-main-action:hover, .btn-primary:hover {
|
|
||||||
|
.btn-main-action:hover {
|
||||||
background-color: var(--kaauh-teal-dark);
|
background-color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-teal-dark);
|
border-color: var(--kaauh-teal-dark);
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outlined Button Styles for Table Actions */
|
/* Secondary Button Style (For Edit/Outline - Consistent) */
|
||||||
.btn-outline-primary {
|
|
||||||
color: var(--kaauh-teal);
|
|
||||||
border-color: var(--kaauh-teal);
|
|
||||||
}
|
|
||||||
.btn-outline-primary:hover {
|
|
||||||
background-color: var(--kaauh-teal);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.btn-outline-secondary {
|
.btn-outline-secondary {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
@ -56,54 +61,44 @@
|
|||||||
color: white;
|
color: white;
|
||||||
border-color: var(--kaauh-teal-dark);
|
border-color: var(--kaauh-teal-dark);
|
||||||
}
|
}
|
||||||
/* Danger button remains standard for deletion */
|
.btn-outline-primary {
|
||||||
|
color: var(--kaauh-teal);
|
||||||
/* Card enhancements */
|
border-color: var(--kaauh-teal);
|
||||||
.card {
|
|
||||||
border: 1px solid var(--kaauh-border);
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
|
||||||
background-color: white;
|
|
||||||
}
|
}
|
||||||
|
.btn-outline-primary:hover {
|
||||||
/* Colored Header Card */
|
background-color: var(--kaauh-teal);
|
||||||
.list-header-card {
|
|
||||||
background: linear-gradient(135deg, var(--kaauh-teal), #004d57);
|
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: 0.75rem 0.75rem 0 0;
|
|
||||||
padding: 1.5rem;
|
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
|
|
||||||
}
|
|
||||||
.list-header-card h1 {
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
}
|
|
||||||
.heroicon {
|
|
||||||
width: 1.25rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
stroke: currentColor;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table Styling */
|
/* Training Card Specifics */
|
||||||
.table thead th {
|
.training-card .card-title {
|
||||||
background-color: #f8f9fa;
|
color: var(--kaauh-teal-dark);
|
||||||
color: var(--kaauh-primary-text);
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-bottom: 2px solid var(--kaauh-border);
|
font-size: 1.15rem;
|
||||||
}
|
|
||||||
.table tbody tr:hover {
|
|
||||||
background-color: #f0f8ff; /* Light hover color */
|
|
||||||
}
|
|
||||||
.btn-group .btn-sm {
|
|
||||||
padding: 0.35rem 0.6rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pagination Styling */
|
/* Table Styling (Consistent with Reference) */
|
||||||
.pagination .page-link {
|
.table-view .table thead th {
|
||||||
|
background-color: var(--kaauh-teal-dark); /* Dark header background */
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.table-view .table tbody td {
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 1rem;
|
||||||
|
border-color: var(--kaauh-border);
|
||||||
|
}
|
||||||
|
.table-view .table tbody tr:hover {
|
||||||
|
background-color: var(--kaauh-gray-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination Link Styling (Consistent) */
|
||||||
|
.pagination .page-item .page-link {
|
||||||
color: var(--kaauh-teal-dark);
|
color: var(--kaauh-teal-dark);
|
||||||
border-color: var(--kaauh-border);
|
border-color: var(--kaauh-border);
|
||||||
}
|
}
|
||||||
@ -112,173 +107,179 @@
|
|||||||
border-color: var(--kaauh-teal);
|
border-color: var(--kaauh-teal);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
.pagination .page-item:hover .page-link:not(.active) {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter & Search Layout Adjustments */
|
||||||
|
.filter-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
/* Override for the primary text color being used for card-titles in table */
|
||||||
|
.text-primary { color: var(--kaauh-teal) !important; }
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
<div class="card shadow-sm">
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h1 style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
||||||
|
<i class="fas fa-graduation-cap me-2"></i> {% trans "Training Materials" %}
|
||||||
|
</h1>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a href="{% url 'training_create' %}" class="btn btn-main-action">
|
||||||
|
<i class="fas fa-plus me-1"></i> {% trans "Add New Material" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="list-header-card">
|
<div class="card mb-4 shadow-sm no-hover">
|
||||||
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
<div class="card-body">
|
||||||
<h1 class="h3 mb-0">
|
<div class="row">
|
||||||
<i class="fas fa-graduation-cap me-2"></i>
|
<div class="col-md-6">
|
||||||
{% trans "Training Materials" %}
|
<label for="search" class="form-label small text-muted">{% trans "Search by Title or Creator" %}</label>
|
||||||
</h1>
|
<div class="input-group input-group-lg mb-3">
|
||||||
<div class="d-flex gap-3 align-items-center mt-2 mt-md-0">
|
<form method="get" action="" class="w-100">
|
||||||
|
{% include "includes/search_form.html" with search_query=search_query %}
|
||||||
<div class="order-3 order-md-1">
|
</form>
|
||||||
{% include "includes/search_form.html" with search_query=search_query %}
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 d-flex align-items-end">
|
||||||
|
{# Additional Filters can go here if needed #}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if materials %}
|
||||||
|
<div id="training-materials-list">
|
||||||
|
{# View Switcher - list_id must match the container ID #}
|
||||||
|
{% include "includes/_list_view_switcher.html" with list_id="training-materials-list" %}
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
{# Card View (Default) - Must have 'row' class for grid layout #}
|
||||||
<a href="{% url 'training_create' %}" class="btn btn-main-action btn-sm order-1 order-md-2" title="{% trans 'Add New Material' %}">
|
<div class="card-view active row">
|
||||||
<i class="fas fa-plus"></i>
|
{% for material in materials %}
|
||||||
<span class="d-none d-sm-inline">{% trans "Add New Material" %}</span>
|
<div class="col-md-6 col-lg-4 mb-4">
|
||||||
</a>
|
<div class="card training-card h-100 shadow-sm">
|
||||||
{% endif %}
|
<div class="card-body d-flex flex-column">
|
||||||
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||||
|
<h5 class="card-title flex-grow-1 me-3">{{ material.title }}</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="card-text text-muted small">
|
||||||
|
<i class="fas fa-user-edit"></i> {% trans "Created By" %}: {{ material.created_by.username|default:"Anonymous" }}<br>
|
||||||
|
<i class="fas fa-calendar-alt"></i> {% trans "Created On" %}: {{ material.created_at|date:"M d, Y" }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mt-auto pt-2 border-top">
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<a href="{% url 'training_detail' material.pk %}" class="btn btn-sm btn-main-action">
|
||||||
|
<i class="fas fa-eye"></i> {% trans "View" %}
|
||||||
|
</a>
|
||||||
|
{% if user.is_authenticated and material.created_by == user %}
|
||||||
|
<a href="{% url 'training_update' material.pk %}" class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="fas fa-edit"></i> {% trans "Edit" %}
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#deleteModal" {# Assuming standard Bootstrap modal trigger #}
|
||||||
|
data-delete-url="{% url 'training_delete' material.pk %}"
|
||||||
|
data-item-name="{{ material.title }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Table View #}
|
||||||
|
<div class="table-view">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" style="width: 40%;">{% trans "Title" %}</th>
|
||||||
|
<th scope="col" style="width: 30%;">{% trans "Created By" %}</th>
|
||||||
|
<th scope="col" style="width: 20%;">{% trans "Created" %}</th>
|
||||||
|
<th scope="col" style="width: 10%;" class="text-end">{% trans "Actions" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for material in materials %}
|
||||||
|
<tr>
|
||||||
|
<td><strong class="text-primary">{{ material.title }}</strong></td>
|
||||||
|
<td>{{ material.created_by.username|default:"Anonymous" }}</td>
|
||||||
|
<td>{{ material.created_at|date:"M d, Y" }}</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
|
<a href="{% url 'training_detail' material.pk %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
{% if user.is_authenticated and material.created_by == user %}
|
||||||
|
<a href="{% url 'training_update' material.pk %}" class="btn btn-outline-secondary" title="{% trans 'Edit' %}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#deleteModal"
|
||||||
|
data-delete-url="{% url 'training_delete' material.pk %}"
|
||||||
|
data-item-name="{{ material.title }}">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{# Pagination (Standardized to Reference) #}
|
||||||
|
{% if is_paginated %}
|
||||||
|
<nav aria-label="Page navigation" class="mt-4">
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
{% if page_obj.has_previous %}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page=1{% if search_query %}&q={{ search_query }}{% endif %}">First</a>
|
||||||
|
</li>
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}">Previous</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if materials %}
|
<li class="page-item active">
|
||||||
<div id="training-materials-list">
|
<span class="page-link">{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
|
||||||
{# View Switcher #}
|
</li>
|
||||||
{% include "includes/_list_view_switcher.html" with list_id="training-materials-list" %}
|
|
||||||
|
|
||||||
{# Table View (Default) #}
|
{% if page_obj.has_next %}
|
||||||
<div class="table-view active">
|
<li class="page-item">
|
||||||
<div class="table-responsive">
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if search_query %}&q={{ search_query }}{% endif %}">Next</a>
|
||||||
<table class="table table-hover align-middle mb-0">
|
</li>
|
||||||
<thead>
|
<li class="page-item">
|
||||||
<tr>
|
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if search_query %}&q={{ search_query }}{% endif %}">Last</a>
|
||||||
<th scope="col">{% trans "Title" %}</th>
|
</li>
|
||||||
<th scope="col">{% trans "Created By" %}</th>
|
{% endif %}
|
||||||
<th scope="col">{% trans "Created" %}</th>
|
</ul>
|
||||||
<th scope="col" class="text-center">{% trans "Actions" %}</th>
|
</nav>
|
||||||
</tr>
|
{% endif %}
|
||||||
</thead>
|
{% else %}
|
||||||
<tbody>
|
<div class="text-center py-5 card shadow-sm">
|
||||||
{% for material in materials %}
|
<div class="card-body">
|
||||||
<tr>
|
<i class="fas fa-graduation-cap fa-3x mb-3" style="color: var(--kaauh-teal-dark);"></i>
|
||||||
<td><strong class="text-primary">{{ material.title }}</strong></td>
|
<h3>{% trans "No training materials found" %}</h3>
|
||||||
<td>{{ material.created_by.username|default:"Anonymous" }}</td>
|
<p class="text-muted">{% trans "It looks like there are no materials yet. Start by adding one!" %}</p>
|
||||||
<td>{{ material.created_at|date:"M d, Y" }}</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="btn-group btn-group-sm" role="group">
|
|
||||||
<a href="{% url 'training_detail' material.pk %}" class="btn btn-outline-primary" title="{% trans 'View' %}">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
{% if user.is_authenticated and material.created_by == user %}
|
|
||||||
<a href="{% url 'training_update' material.pk %}" class="btn btn-outline-secondary" title="{% trans 'Edit' %}">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-outline-danger" title="{% trans 'Delete' %}"
|
|
||||||
data-bs-toggle="deleteModal"
|
|
||||||
data-delete-url="{% url 'training_delete' material.pk %}"
|
|
||||||
data-item-name="{{ material.title }}">
|
|
||||||
<i class="fas fa-trash-alt"></i>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Card View #}
|
|
||||||
<div class="card-view">
|
|
||||||
<div class="row g-4">
|
|
||||||
{% for material in materials %}
|
|
||||||
<div class="col-md-6 col-lg-4">
|
|
||||||
<div class="card h-100">
|
|
||||||
<div class="card-header">
|
|
||||||
<h5 class="h5 mb-1">{{ material.title }}</h5>
|
|
||||||
<small class="text-white-50">{{ material.created_by.username|default:"Anonymous" }}</small>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">
|
|
||||||
<strong>{% trans "Created" %}:</strong> {{ material.created_at|date:"M d, Y" }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<div class="d-flex gap-2">
|
|
||||||
<a href="{% url 'training_detail' material.pk %}" class="btn btn-sm btn-outline-primary w-100">
|
|
||||||
<i class="fas fa-eye"></i> {% trans "View" %}
|
|
||||||
</a>
|
|
||||||
{% if user.is_authenticated and material.created_by == user %}
|
|
||||||
<div class="btn-group w-100" role="group">
|
|
||||||
<a href="{% url 'training_update' material.pk %}" class="btn btn-sm btn-outline-secondary" title="{% trans 'Edit' %}">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-outline-danger btn-sm" title="{% trans 'Delete' %}"
|
|
||||||
data-bs-toggle="deleteModal"
|
|
||||||
data-delete-url="{% url 'training_delete' material.pk %}"
|
|
||||||
data-item-name="{{ material.title }}">
|
|
||||||
<i class="fas fa-trash-alt"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if is_paginated %}
|
|
||||||
<div class="card-footer bg-light border-top">
|
|
||||||
<nav aria-label="Page navigation">
|
|
||||||
<ul class="pagination justify-content-center mb-0">
|
|
||||||
{% if page_obj.has_previous %}
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
|
|
||||||
<span aria-hidden="true">«</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for num in page_obj.paginator.page_range %}
|
|
||||||
{% if page_obj.number == num %}
|
|
||||||
<li class="page-item active"><span class="page-link">{{ num }}</span></li>
|
|
||||||
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if page_obj.has_next %}
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
|
|
||||||
<span aria-hidden="true">»</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<div class="text-center py-5">
|
|
||||||
<i class="fas fa-book-open fa-3x text-muted mb-3"></i>
|
|
||||||
<h5 class="mb-3">{% trans "No training materials found." %}</h5>
|
|
||||||
<p class="text-muted mb-4">{% trans "It looks like there are no materials yet. Start by adding one!" %}</p>
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<a href="{% url 'training_create' %}" class="btn btn-main-action">
|
<a href="{% url 'training_create' %}" class="btn btn-main-action mt-3">
|
||||||
<i class="fas fa-plus me-1"></i>
|
<i class="fas fa-plus me-1"></i> {% trans "Create Your First Material" %}
|
||||||
{% trans "Create Your First Material" %}
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user