ATS/templates/meetings/list_meetings.html
2026-01-29 14:19:03 +03:00

333 lines
22 KiB
HTML

{% extends "base.html" %}
{% load static i18n %}
{% block title %}{% trans "Interviews & Meetings" %} - {{ block.super }}{% endblock %}
{% block content %}
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<!-- Header -->
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6">
<h1 class="text-2xl sm:text-3xl font-bold flex items-center gap-3 text-gray-900">
<div class="w-12 h-12 rounded-xl flex items-center justify-center" style="background-color: rgba(157, 34, 53, 0.1);">
<i data-lucide="calendar" class="w-6 h-6" style="color: #9d2235;"></i>
</div>
{% trans "Interviews & Meetings" %}
</h1>
</div>
<!-- Filter Card -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200 mb-6">
<div class="px-6 py-4 border-b border-gray-100" style="background-color: linear-gradient(to right, #9d2235, #7a1a29);">
<h2 class="text-lg font-bold flex items-center gap-2 text-white">
<i data-lucide="filter" class="w-5 h-5"></i>
{% trans "Filter Meetings" %}
</h2>
</div>
<div class="p-6">
<form method="get" action="" class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- Search -->
<div>
<label for="search" class="block text-sm font-semibold text-gray-700 mb-2">{% trans "Search by Topic" %}</label>
<div class="relative">
<input type="text" name="q" id="search" value="{{ search_query }}"
class="w-full px-4 py-2.5 pl-10 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition"
placeholder="{% trans 'Search topic...' %}">
<i data-lucide="search" class="w-4 h-4 text-gray-400 absolute left-3 top-1/2 transform -translate-y-1/2"></i>
</div>
</div>
<!-- Type Filter -->
<div>
<label for="type_filter" class="block text-sm font-semibold text-gray-700 mb-2">{% trans "Interview Type" %}</label>
<select name="type" id="type_filter"
class="w-full px-4 py-2.5 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition bg-white">
<option value="">{% trans "All Types" %}</option>
<option value="Remote" {% if type_filter == 'Remote' %}selected{% endif %}>{% trans "Remote" %}</option>
<option value="Onsite" {% if type_filter == 'Onsite' %}selected{% endif %}>{% trans "Onsite" %}</option>
</select>
</div>
<!-- Status Filter -->
<div>
<label for="status" class="block text-sm font-semibold text-gray-700 mb-2">{% trans "Filter by Status" %}</label>
<select name="status" id="status"
class="w-full px-4 py-2.5 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition bg-white">
<option value="">{% trans "All Statuses" %}</option>
{% for choice, display in status_choices %}
<option value="{{ choice }}" {% if status_filter == choice %}selected{% endif %}>{{ display }}</option>
{% endfor %}
</select>
</div>
<!-- Candidate Name Filter -->
<div>
<label for="candidate_name" class="block text-sm font-semibold text-gray-700 mb-2">{% trans "Candidate Name" %}</label>
<input type="text" name="candidate_name" id="candidate_name" value="{{ candidate_name_filter }}"
class="w-full px-4 py-2.5 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition"
placeholder="{% trans 'Search by candidate...' %}">
</div>
</div>
<!-- Filter Actions -->
<div class="flex flex-wrap gap-2">
<button type="submit"
class="inline-flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-medium text-white transition-all duration-200"
style="background-color: #9d2235;"
onmouseover="this.style.backgroundColor='#7a1a29'"
onmouseout="this.style.backgroundColor='#9d2235'">
<i data-lucide="filter" class="w-4 h-4"></i>
{% trans "Apply Filters" %}
</button>
{% if status_filter or search_query or candidate_name_filter or type_filter %}
<a href="{% url 'list_meetings' %}"
class="inline-flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-medium border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="x" class="w-4 h-4"></i>
{% trans "Clear All" %}
</a>
{% endif %}
</div>
</form>
</div>
</div>
{% if meetings_data %}
<div id="meetings-list">
<!-- View Switcher -->
{% include "includes/_list_view_switcher.html" with list_id="meetings-list" %}
<!-- Card View -->
<div class="card-view active grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{% for meeting in meetings_data %}
<div class="bg-white rounded-xl shadow-sm border border-gray-200 hover:shadow-md transition-shadow duration-200 overflow-hidden">
<div class="p-6 flex flex-col h-full">
<!-- Header -->
<div class="flex justify-between items-start mb-4">
<div class="flex-1">
<h5 class="text-lg font-bold mb-2" style="color: #9d2235;">
{{ meeting.topic }}
</h5>
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold {% if meeting.type == 'Remote' %}bg-green-100 text-green-800{% else %}bg-blue-100 text-blue-800{% endif %}">
{{ meeting.type|title }}
</span>
</div>
</div>
<!-- Details -->
<div class="flex-1 space-y-3 mb-4">
<div class="flex items-start gap-3 text-sm">
<i data-lucide="user" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Candidate" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.interview.application.person.full_name|default:"N/A" }}</span>
</div>
</div>
<div class="flex items-start gap-3 text-sm">
<i data-lucide="briefcase" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Job" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.interview.job.title|default:"N/A" }}</span>
</div>
</div>
{% if meeting.type == 'Remote' %}
<div class="flex items-start gap-3 text-sm">
<i data-lucide="link" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Remote ID" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.meeting_id|default:meeting.location.id }}</span>
</div>
</div>
{% elif meeting.type == 'Onsite' %}
<div class="flex items-start gap-3 text-sm">
<i data-lucide="map-pin" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Location" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.details.room_number|default:meeting.details.physical_address|truncatechars:30 }}</span>
</div>
</div>
{% endif %}
<div class="flex items-start gap-3 text-sm">
<i data-lucide="clock" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Start" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.start_time|date:"M d, Y H:i" }}</span>
</div>
</div>
<div class="flex items-start gap-3 text-sm">
<i data-lucide="timer" class="w-4 h-4 text-gray-500 flex-shrink-0 mt-0.5"></i>
<div>
<span class="text-gray-600">{% trans "Duration" %}:</span>
<span class="text-gray-900 ml-1">{{ meeting.duration }} min</span>
</div>
</div>
</div>
<!-- Status Badge -->
<div class="mb-4">
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800">
{{ meeting.interview.get_status_display }}
</span>
</div>
<!-- Actions -->
<div class="pt-4 border-t border-gray-200 flex flex-wrap gap-2">
<a href="{% url 'meeting_details' meeting.slug %}"
class="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg text-xs font-medium border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="eye" class="w-3.5 h-3.5"></i>
{% trans "View" %}
</a>
{% if meeting.type == 'Remote' and meeting.join_url %}
<a href="{{ meeting.join_url }}" target="_blank"
class="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg text-xs font-medium text-white transition-all duration-200"
style="background-color: #9d2235;"
onmouseover="this.style.backgroundColor='#7a1a29'"
onmouseout="this.style.backgroundColor='#9d2235'">
<i data-lucide="sign-in" class="w-3.5 h-3.5"></i>
{% trans "Join" %}
</a>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
<!-- Table View -->
<div class="table-view hidden">
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
<div class="overflow-x-auto">
<table class="w-full">
<thead class="text-xs font-semibold text-left uppercase" style="background-color: #9d2235; color: white;">
<tr>
<th class="px-6 py-4">{% trans "Topic" %}</th>
<th class="px-6 py-4">{% trans "Type" %}</th>
<th class="px-6 py-4">{% trans "Candidate" %}</th>
<th class="px-6 py-4">{% trans "Job" %}</th>
<th class="px-6 py-4">{% trans "Start Time" %}</th>
<th class="px-6 py-4">{% trans "Duration" %}</th>
<th class="px-6 py-4">{% trans "Status" %}</th>
<th class="px-6 py-4 text-right">{% trans "Actions" %}</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{% for meeting in meetings_data %}
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-6 py-4">
<span class="font-semibold" style="color: #9d2235;">{{ meeting.topic }}</span>
</td>
<td class="px-6 py-4">
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold {% if meeting.type == 'Remote' %}bg-green-100 text-green-800{% else %}bg-blue-100 text-blue-800{% endif %}">
{{ meeting.type|title }}
</span>
</td>
<td class="px-6 py-4">
<a href="{% url 'application_detail' meeting.interview.application.person.slug %}"
class="hover:underline" style="color: #9d2235;">
{{ meeting.interview.application.person.full_name }}
</a>
</td>
<td class="px-6 py-4">
<a href="{% url 'job_detail' meeting.interview.job.slug %}"
class="hover:underline" style="color: #9d2235;">
{{ meeting.interview.job.title }}
</a>
</td>
<td class="px-6 py-4 text-gray-700">{{ meeting.start_time|date:"M d, Y H:i" }}</td>
<td class="px-6 py-4 text-gray-700">{{ meeting.duration }} min</td>
<td class="px-6 py-4">
<span class="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-green-100 text-green-800">
{{ meeting.interview.get_status_display }}
</span>
</td>
<td class="px-6 py-4 text-right">
<div class="flex justify-end gap-2">
{% if meeting.type == 'Remote' and meeting.join_url %}
<a href="{{ meeting.join_url }}" target="_blank"
class="inline-flex items-center justify-center w-8 h-8 rounded text-white transition-all duration-200"
style="background-color: #9d2235;"
onmouseover="this.style.backgroundColor='#7a1a29'"
onmouseout="this.style.backgroundColor='#9d2235'">
<i data-lucide="sign-in" class="w-4 h-4"></i>
</a>
{% endif %}
<a href="{% url 'meeting_details' meeting.slug %}"
class="inline-flex items-center justify-center w-8 h-8 rounded border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="eye" class="w-4 h-4"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Pagination -->
{% if is_paginated %}
<nav aria-label="Page navigation" class="mt-6">
<ul class="flex justify-center items-center gap-2">
{% if page_obj.has_previous %}
<li>
<a href="?page=1{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}{% if type_filter %}&type={{ type_filter }}{% endif %}{% if candidate_name_filter %}&candidate_name={{ candidate_name_filter }}{% endif %}"
class="inline-flex items-center justify-center w-10 h-10 rounded-lg border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="chevrons-left" class="w-4 h-4"></i>
</a>
</li>
<li>
<a href="?page={{ page_obj.previous_page_number }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}{% if type_filter %}&type={{ type_filter }}{% endif %}{% if candidate_name_filter %}&candidate_name={{ candidate_name_filter }}{% endif %}"
class="inline-flex items-center justify-center w-10 h-10 rounded-lg border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="chevron-left" class="w-4 h-4"></i>
</a>
</li>
{% endif %}
<li class="px-4 py-2">
<span class="text-gray-700 font-medium">{{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
</li>
{% if page_obj.has_next %}
<li>
<a href="?page={{ page_obj.next_page_number }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}{% if type_filter %}&type={{ type_filter }}{% endif %}{% if candidate_name_filter %}&candidate_name={{ candidate_name_filter }}{% endif %}"
class="inline-flex items-center justify-center w-10 h-10 rounded-lg border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="chevron-right" class="w-4 h-4"></i>
</a>
</li>
<li>
<a href="?page={{ page_obj.paginator.num_pages }}{% if status_filter %}&status={{ status_filter }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}{% if type_filter %}&type={{ type_filter }}{% endif %}{% if candidate_name_filter %}&candidate_name={{ candidate_name_filter }}{% endif %}"
class="inline-flex items-center justify-center w-10 h-10 rounded-lg border-2 border-gray-300 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="chevrons-right" class="w-4 h-4"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<!-- Empty State -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200 py-16 text-center">
<div class="w-20 h-20 mx-auto mb-6 rounded-full flex items-center justify-center" style="background-color: rgba(157, 34, 53, 0.1);">
<i data-lucide="calendar" class="w-10 h-10" style="color: #9d2235;"></i>
</div>
<h3 class="text-xl font-bold text-gray-900 mb-2">{% trans "No interviews or meetings found" %}</h3>
<p class="text-gray-600">{% trans "Create your first interview or adjust your filters." %}</p>
</div>
{% endif %}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
</script>
{% endblock %}