255 lines
12 KiB
HTML
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">×</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 %}
|