2025-08-12 13:33:25 +03:00

473 lines
23 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit Appointment{% else %}New Appointment{% endif %}{% endblock %}
{% block content %}
<div class="d-flex align-items-center mb-3">
<div>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'appointments:dashboard' %}">Appointments</a></li>
<li class="breadcrumb-item"><a href="{% url 'appointments:appointment_list' %}">Appointments</a></li>
<li class="breadcrumb-item active">{% if object %}Edit{% else %}New{% endif %}</li>
</ol>
<h1 class="page-header mb-0">
{% if object %}Edit Appointment{% else %}Schedule New Appointment{% endif %}
</h1>
</div>
<div class="ms-auto">
<a href="{% url 'appointments:appointment_list' %}" class="btn btn-secondary">
<i class="fas fa-arrow-left me-2"></i>Back to List
</a>
</div>
</div>
<div class="row">
<div class="col-xl-8">
<div class="card">
<div class="card-header">
<h4 class="card-title">
<i class="fas fa-calendar-plus me-2"></i>
Appointment Details
</h4>
</div>
<div class="card-body">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
<form method="post" novalidate>
{% csrf_token %}
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.patient.id_for_label }}" class="form-label">Patient *</label>
<select class="form-select {% if form.patient.errors %}is-invalid{% endif %}"
id="{{ form.patient.id_for_label }}"
name="{{ form.patient.name }}"
required>
<option value="">Select Patient</option>
{% for choice in form.patient.field.choices %}
{% if choice.0 %}
<option value="{{ choice.0 }}" {% if choice.0 == form.patient.value %}selected{% endif %}>
{{ choice.1 }}
</option>
{% endif %}
{% endfor %}
</select>
{% if form.patient.errors %}
<div class="invalid-feedback">
{{ form.patient.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.doctor.id_for_label }}" class="form-label">Doctor *</label>
<select class="form-select {% if form.doctor.errors %}is-invalid{% endif %}"
id="{{ form.doctor.id_for_label }}"
name="{{ form.doctor.name }}"
required>
<option value="">Select Doctor</option>
{% for choice in form.doctor.field.choices %}
{% if choice.0 %}
<option value="{{ choice.0 }}" {% if choice.0 == form.doctor.value %}selected{% endif %}>
{{ choice.1 }}
</option>
{% endif %}
{% endfor %}
</select>
{% if form.doctor.errors %}
<div class="invalid-feedback">
{{ form.doctor.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.appointment_date.id_for_label }}" class="form-label">Date *</label>
<input type="date"
class="form-control {% if form.appointment_date.errors %}is-invalid{% endif %}"
id="{{ form.appointment_date.id_for_label }}"
name="{{ form.appointment_date.name }}"
value="{{ form.appointment_date.value|default:'' }}"
required>
{% if form.appointment_date.errors %}
<div class="invalid-feedback">
{{ form.appointment_date.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.appointment_time.id_for_label }}" class="form-label">Time *</label>
<input type="time"
class="form-control {% if form.appointment_time.errors %}is-invalid{% endif %}"
id="{{ form.appointment_time.id_for_label }}"
name="{{ form.appointment_time.name }}"
value="{{ form.appointment_time.value|default:'' }}"
required>
{% if form.appointment_time.errors %}
<div class="invalid-feedback">
{{ form.appointment_time.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.appointment_type.id_for_label }}" class="form-label">Type *</label>
<select class="form-select {% if form.appointment_type.errors %}is-invalid{% endif %}"
id="{{ form.appointment_type.id_for_label }}"
name="{{ form.appointment_type.name }}"
required>
<option value="">Select Type</option>
{% for choice in form.appointment_type.field.choices %}
<option value="{{ choice.0 }}" {% if choice.0 == form.appointment_type.value %}selected{% endif %}>
{{ choice.1 }}
</option>
{% endfor %}
</select>
{% if form.appointment_type.errors %}
<div class="invalid-feedback">
{{ form.appointment_type.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.status.id_for_label }}" class="form-label">Status</label>
<select class="form-select {% if form.status.errors %}is-invalid{% endif %}"
id="{{ form.status.id_for_label }}"
name="{{ form.status.name }}">
{% for choice in form.status.field.choices %}
<option value="{{ choice.0 }}" {% if choice.0 == form.status.value %}selected{% endif %}>
{{ choice.1 }}
</option>
{% endfor %}
</select>
{% if form.status.errors %}
<div class="invalid-feedback">
{{ form.status.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label for="{{ form.reason.id_for_label }}" class="form-label">Reason for Visit *</label>
<textarea class="form-control {% if form.reason.errors %}is-invalid{% endif %}"
id="{{ form.reason.id_for_label }}"
name="{{ form.reason.name }}"
rows="3"
placeholder="Describe the reason for this appointment..."
required>{{ form.reason.value|default:'' }}</textarea>
{% if form.reason.errors %}
<div class="invalid-feedback">
{{ form.reason.errors.0 }}
</div>
{% endif %}
</div>
<div class="mb-3">
<label for="{{ form.notes.id_for_label }}" class="form-label">Additional Notes</label>
<textarea class="form-control {% if form.notes.errors %}is-invalid{% endif %}"
id="{{ form.notes.id_for_label }}"
name="{{ form.notes.name }}"
rows="3"
placeholder="Any additional notes or special instructions...">{{ form.notes.value|default:'' }}</textarea>
{% if form.notes.errors %}
<div class="invalid-feedback">
{{ form.notes.errors.0 }}
</div>
{% endif %}
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.duration.id_for_label }}" class="form-label">Duration (minutes)</label>
<input type="number"
class="form-control {% if form.duration.errors %}is-invalid{% endif %}"
id="{{ form.duration.id_for_label }}"
name="{{ form.duration.name }}"
value="{{ form.duration.value|default:'30' }}"
min="15"
max="240"
step="15">
{% if form.duration.errors %}
<div class="invalid-feedback">
{{ form.duration.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.priority.id_for_label }}" class="form-label">Priority</label>
<select class="form-select {% if form.priority.errors %}is-invalid{% endif %}"
id="{{ form.priority.id_for_label }}"
name="{{ form.priority.name }}">
{% for choice in form.priority.field.choices %}
<option value="{{ choice.0 }}" {% if choice.0 == form.priority.value %}selected{% endif %}>
{{ choice.1 }}
</option>
{% endfor %}
</select>
{% if form.priority.errors %}
<div class="invalid-feedback">
{{ form.priority.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
id="{{ form.is_follow_up.id_for_label }}"
name="{{ form.is_follow_up.name }}"
{% if form.is_follow_up.value %}checked{% endif %}>
<label class="form-check-label" for="{{ form.is_follow_up.id_for_label }}">
Follow-up Appointment
</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
id="{{ form.send_reminder.id_for_label }}"
name="{{ form.send_reminder.name }}"
{% if form.send_reminder.value %}checked{% endif %}>
<label class="form-check-label" for="{{ form.send_reminder.id_for_label }}">
Send Reminder
</label>
</div>
</div>
</div>
<div class="d-flex justify-content-between">
<div>
{% if object %}
<a href="{% url 'appointments:appointment_detail' object.pk %}" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>Cancel
</a>
{% else %}
<a href="{% url 'appointments:appointment_list' %}" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>Cancel
</a>
{% endif %}
</div>
<div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-2"></i>
{% if object %}Update Appointment{% else %}Schedule Appointment{% endif %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-xl-4">
<!-- Available Slots -->
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-clock me-2"></i>
Available Slots
</h5>
</div>
<div class="card-body">
<div id="available-slots">
<div class="text-center text-muted">
<i class="fas fa-calendar-alt fa-2x mb-2"></i>
<div>Select a doctor and date to view available slots</div>
</div>
</div>
</div>
</div>
<!-- Doctor Schedule -->
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-user-md me-2"></i>
Doctor Schedule
</h5>
</div>
<div class="card-body">
<div id="doctor-schedule">
<div class="text-center text-muted">
<i class="fas fa-stethoscope fa-2x mb-2"></i>
<div>Select a doctor to view their schedule</div>
</div>
</div>
</div>
</div>
<!-- Appointment Guidelines -->
<div class="card">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-info-circle me-2"></i>
Guidelines
</h5>
</div>
<div class="card-body">
<ul class="list-unstyled mb-0">
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Appointments should be scheduled at least 24 hours in advance
</li>
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Emergency cases should be marked as high priority
</li>
<li class="mb-2">
<i class="fas fa-check text-success me-2"></i>
Follow-up appointments are typically 15-30 minutes
</li>
<li>
<i class="fas fa-check text-success me-2"></i>
Reminders are sent 24 hours before the appointment
</li>
</ul>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const doctorSelect = document.getElementById('{{ form.doctor.id_for_label }}');
const dateInput = document.getElementById('{{ form.appointment_date.id_for_label }}');
const timeInput = document.getElementById('{{ form.appointment_time.id_for_label }}');
// Set minimum date to today
const today = new Date().toISOString().split('T')[0];
dateInput.min = today;
// Load available slots when doctor or date changes
function loadAvailableSlots() {
const doctorId = doctorSelect.value;
const selectedDate = dateInput.value;
if (doctorId && selectedDate) {
// Simulate loading available slots
const slotsContainer = document.getElementById('available-slots');
slotsContainer.innerHTML = `
<div class="text-center">
<div class="spinner-border spinner-border-sm text-primary mb-2" role="status"></div>
<div class="small">Loading available slots...</div>
</div>
`;
// Simulate API call
setTimeout(() => {
const slots = ['09:00', '09:30', '10:00', '10:30', '11:00', '14:00', '14:30', '15:00', '15:30'];
let slotsHtml = '<div class="row g-2">';
slots.forEach(slot => {
slotsHtml += `
<div class="col-6">
<button type="button" class="btn btn-outline-primary btn-sm w-100 slot-btn"
onclick="selectTimeSlot('${slot}')">
${slot}
</button>
</div>
`;
});
slotsHtml += '</div>';
slotsContainer.innerHTML = slotsHtml;
}, 1000);
}
}
// Load doctor schedule
function loadDoctorSchedule() {
const doctorId = doctorSelect.value;
if (doctorId) {
const scheduleContainer = document.getElementById('doctor-schedule');
scheduleContainer.innerHTML = `
<div class="small mb-2"><strong>Working Hours:</strong></div>
<div class="small text-muted mb-1">Monday - Friday: 9:00 AM - 5:00 PM</div>
<div class="small text-muted mb-1">Saturday: 9:00 AM - 1:00 PM</div>
<div class="small text-muted">Sunday: Closed</div>
<hr class="my-2">
<div class="small mb-2"><strong>Specializations:</strong></div>
<div class="small text-muted">General Medicine, Cardiology</div>
`;
}
}
doctorSelect.addEventListener('change', function() {
loadAvailableSlots();
loadDoctorSchedule();
});
dateInput.addEventListener('change', loadAvailableSlots);
// Select time slot function
window.selectTimeSlot = function(time) {
timeInput.value = time;
// Update button states
document.querySelectorAll('.slot-btn').forEach(btn => {
btn.classList.remove('btn-primary');
btn.classList.add('btn-outline-primary');
});
event.target.classList.remove('btn-outline-primary');
event.target.classList.add('btn-primary');
};
// Form validation
const form = document.querySelector('form');
form.addEventListener('submit', function(e) {
const requiredFields = form.querySelectorAll('[required]');
let isValid = true;
requiredFields.forEach(field => {
if (!field.value.trim()) {
field.classList.add('is-invalid');
isValid = false;
} else {
field.classList.remove('is-invalid');
}
});
if (!isValid) {
e.preventDefault();
alert('Please fill in all required fields.');
}
});
});
</script>
{% endblock %}