haikal/templates/schedule_calendar.html
2025-08-27 13:04:41 +03:00

255 lines
12 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block customCSS %}
<link href="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.css"
rel="stylesheet">
<link id="theme-link"
rel="stylesheet"
href="{% static 'css/calendar_dark.css' %}">
<style>
.schedule-list {
max-height: 80vh;
overflow-y: auto;
}
</style>
{% endblock customCSS %}
{% block content %}
<div class="container-fluid mt-4">
<div class="row">
<div class="col-md-8">
<div id="calendar"></div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h4>Upcoming Schedules</h4>
{% comment %} <button class="btn btn-phoenix-primary btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#scheduleModal">
<span class="fas fa-plus me-1"></span>{{ _("Add New Schedule") }}
</button> {% endcomment %}
</div>
<div class="card-body schedule-list">
<ul class="list-group">
{% for schedule in upcoming_schedules %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-1">{{ schedule.get_purpose }}</h6>
<p class="mb-1 text-muted">{{ schedule.scheduled_at|date:"F d, Y P" }}</p>
</div>
<button class="btn btn-info btn-sm view-schedule-btn"
data-toggle="modal"
data-target="#viewScheduleModal"
data-purpose="{{ schedule.get_purpose }}"
data-scheduled-type="{{ schedule.scheduled_type }}"
data-scheduled-at="{{ schedule.scheduled_at }}"
data-start-time="{{ schedule.start_time }}"
data-end-time="{{ schedule.end_time }}"
data-completed="{{ schedule.completed }}"
data-status="{{ schedule.status }}"
data-notes="{{ schedule.notes }}"
data-customer="{% if schedule.customer %}{{ schedule.customer.customer_name }}{% else %}N/A{% endif %}">
View
</button>
</li>
{% empty %}
<li class="list-group-item text-center text-muted">No schedules found.</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade"
id="addScheduleModal"
tabindex="-1"
role="dialog"
aria-labelledby="addScheduleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addScheduleModalLabel">Add New Schedule</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form action="{% url 'schedule_calendar' request.dealer.slug %}"
method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save Schedule</button>
</form>
</div>
</div>
</div>
</div>
<div class="modal fade"
id="viewScheduleModal"
tabindex="-1"
role="dialog"
aria-labelledby="viewScheduleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="viewScheduleTitle">Schedule Details</h5>
</div>
<div class="modal-body">
<p>
<strong>Purpose:</strong> <span id="modal-schedule-purpose"></span>
</p>
<p>
<strong>Scheduled Type:</strong> <span id="modal-schedule-type"></span>
</p>
<p>
<strong>Customer:</strong> <span id="modal-schedule-customer"></span>
</p>
<p>
<strong>Scheduled At:</strong> <span id="modal-schedule-at"></span>
</p>
<p>
<strong>Time:</strong> <span id="modal-schedule-time"></span>
</p>
<p>
<strong>Status:</strong> <span id="modal-schedule-status"></span>
</p>
<p>
<strong>Notes:</strong> <span id="modal-schedule-notes"></span>
</p>
<p>
<strong>Completed:</strong> <span id="modal-schedule-completed"></span>
</p>
</div>
</div>
</div>
</div>
{% endblock content %}
{% block customJS %}
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@5.10.1/main.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const themeToggle = document.getElementById('themeControlToggleSm');
const themeLink = document.getElementById('theme-link');
const savedTheme = localStorage.getItem('theme') || 'light';
function setTheme(theme) {
if (theme === 'dark') {
themeLink.href = '{% static "css/dark_theme.css" %}';
themeToggle.checked = true;
} else {
themeLink.href = '{% static "css/light_theme.css" %}';
themeToggle.checked = false;
}
localStorage.setItem('theme', theme);
}
// Set the initial theme on page load
setTheme(savedTheme);
// Listen for changes on the toggle switch
themeToggle.addEventListener('change', function() {
if (this.checked) {
setTheme('dark');
} else {
setTheme('light');
}
});
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
themeSystem: 'bootstrap',
locale: '{{ LANGUAGE_CODE }}',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: [
{% for schedule in schedules %}
{
title: '{{ schedule.get_purpose|escapejs }}',
start: '{{ schedule.scheduled_at|date:"Y-m-d" }}{% if schedule.start_time %}T{{ schedule.start_time|time:"H:i:s" }}{% endif %}',
end: '{{ schedule.scheduled_at|date:"Y-m-d" }}{% if schedule.end_time %}T{{ schedule.end_time|time:"H:i:s" }}{% endif %}',
backgroundColor: '{% if schedule.status == "completed" %}#1abc9c{% elif schedule.status == "canceled" %}#e74c3c{% else %}#3498db{% endif %}',
borderColor: '{% if schedule.status == "completed" %}#1abc9c{% elif schedule.status == "canceled" %}#e74c3c{% else %}#3498db{% endif %}',
extendedProps: {
scheduledType: '{{ schedule.scheduled_type|escapejs }}',
notes: '{{ schedule.notes|escapejs }}',
completed: '{{ schedule.completed }}',
status: '{{ schedule.status|escapejs }}',
customer: '{{ schedule.customer.customer_name|default:"N/A"|escapejs }}'
}
},
{% endfor %}
],
eventClick: function(info) {
// Populate the view modal with schedule details
$('#viewScheduleTitle').text(info.event.title);
$('#modal-schedule-purpose').text(info.event.title);
$('#modal-schedule-type').text(info.event.extendedProps.scheduledType);
$('#modal-schedule-customer').text(info.event.extendedProps.customer);
$('#modal-schedule-at').text(info.event.startStr.split('T')[0]);
let startTime = info.event.startStr.split('T')[1];
let endTime = info.event.endStr ? info.event.endStr.split('T')[1] : '';
let timeString = '';
if (startTime) {
timeString += startTime.substring(0, 5);
}
if (endTime) {
timeString += ' - ' + endTime.substring(0, 5);
}
$('#modal-schedule-time').text(timeString);
$('#modal-schedule-status').text(info.event.extendedProps.status);
$('#modal-schedule-notes').text(info.event.extendedProps.notes);
$('#modal-schedule-completed').text(info.event.extendedProps.completed === 'True' ? 'Yes' : 'No');
$('#viewScheduleModal').modal('show');
}
});
calendar.render();
});
// Handle view schedule buttons in the list
$('.view-schedule-btn').on('click', function() {
const purpose = $(this).data('purpose');
const scheduledType = $(this).data('scheduled-type');
const customer = $(this).data('customer');
const scheduledAt = $(this).data('scheduled-at');
const startTime = $(this).data('start-time');
const endTime = $(this).data('end-time');
const status = $(this).data('status');
const notes = $(this).data('notes');
const completed = $(this).data('completed');
$('#viewScheduleTitle').text(purpose);
$('#modal-schedule-purpose').text(purpose);
$('#modal-schedule-type').text(scheduledType);
$('#modal-schedule-customer').text(customer);
$('#modal-schedule-at').text(scheduledAt);
let timeString = '';
if (startTime) {
timeString += startTime.substring(0, 5);
}
if (endTime) {
if (timeString) {
timeString += ' - ';
}
timeString += endTime.substring(0, 5);
}
$('#modal-schedule-time').text(timeString);
$('#modal-schedule-status').text(status);
$('#modal-schedule-notes').text(notes);
$('#modal-schedule-completed').text(completed === true ? 'Yes' : 'No');
$('#viewScheduleModal').modal('show');
});
</script>
{% endblock customJS %}