hospital-management/templates/hr/training_record_form.html
2025-08-12 13:33:25 +03:00

703 lines
36 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}
{% if form.instance.id %}Edit{% else %}Create{% endif %} Training Record | HR Management
{% endblock %}
{% block css %}
<!-- Select2 CSS -->
<link href="{% static 'plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
<!-- DateRangePicker CSS -->
<link href="{% static 'plugins/bootstrap-daterangepicker/daterangepicker.css' %}" rel="stylesheet" />
<!-- Summernote CSS -->
<link href="{% static 'plugins/summernote/dist/summernote-lite.css' %}" rel="stylesheet" />
<style>
.form-section {
background-color: #f8f9fa;
border-radius: 5px;
padding: 20px;
margin-bottom: 20px;
}
.form-section-title {
border-bottom: 1px solid #dee2e6;
padding-bottom: 10px;
margin-bottom: 20px;
}
.help-sidebar {
position: sticky;
top: 20px;
}
.help-card {
border-left: 4px solid #2d62ed;
}
.select2-container--default .select2-selection--single {
height: 38px;
border: 1px solid #ced4da;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
line-height: 38px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 36px;
}
.objective-row {
background-color: #f8f9fa;
border-radius: 5px;
padding: 15px;
margin-bottom: 10px;
}
.remove-objective {
color: #dc3545;
cursor: pointer;
}
.certificate-row {
background-color: #f8f9fa;
border-radius: 5px;
padding: 15px;
margin-bottom: 10px;
}
.remove-certificate {
color: #dc3545;
cursor: pointer;
}
</style>
{% endblock %}
{% block content %}
<!-- begin breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Home</a></li>
<li class="breadcrumb-item"><a href="{% url 'hr:dashboard' %}">HR</a></li>
<li class="breadcrumb-item"><a href="{% url 'hr:training_record_list' %}">Training Records</a></li>
<li class="breadcrumb-item active">
{% if form.instance.id %}Edit{% else %}Create{% endif %} Training Record
</li>
</ol>
<!-- end breadcrumb -->
<!-- begin page-header -->
<h1 class="page-header">
{% if form.instance.id %}Edit{% else %}Create{% endif %} Training Record
</h1>
<!-- end page-header -->
<!-- begin row -->
<div class="row">
<!-- begin col-9 -->
<div class="col-xl-9">
<!-- begin panel -->
<div class="panel panel-inverse">
<!-- begin panel-heading -->
<div class="panel-heading">
<h4 class="panel-title">
{% if form.instance.id %}Edit{% else %}Create{% endif %} Training Record
</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<!-- end panel-heading -->
<!-- begin panel-body -->
<div class="panel-body">
<!-- Form Errors -->
{% if form.errors %}
<div class="alert alert-danger">
<h5><i class="fas fa-exclamation-circle"></i> Please correct the errors below:</h5>
<ul class="mb-0">
{% for field in form %}
{% for error in field.errors %}
<li>{{ field.label }}: {{ error }}</li>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form method="post" id="trainingForm" enctype="multipart/form-data">
{% csrf_token %}
<!-- Basic Information Section -->
<div class="form-section">
<h5 class="form-section-title">Basic Information</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.employee.id_for_label }}" class="form-label">Employee <span class="text-danger">*</span></label>
{{ form.employee }}
{% if form.employee.errors %}
<div class="invalid-feedback d-block">{{ form.employee.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.title.id_for_label }}" class="form-label">Training Title <span class="text-danger">*</span></label>
{{ form.title }}
{% if form.title.errors %}
<div class="invalid-feedback d-block">{{ form.title.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.training_type.id_for_label }}" class="form-label">Training Type <span class="text-danger">*</span></label>
{{ form.training_type }}
{% if form.training_type.errors %}
<div class="invalid-feedback d-block">{{ form.training_type.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.provider.id_for_label }}" class="form-label">Provider <span class="text-danger">*</span></label>
{{ form.provider }}
{% if form.provider.errors %}
<div class="invalid-feedback d-block">{{ form.provider.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.start_date.id_for_label }}" class="form-label">Start Date <span class="text-danger">*</span></label>
{{ form.start_date }}
{% if form.start_date.errors %}
<div class="invalid-feedback d-block">{{ form.start_date.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.end_date.id_for_label }}" class="form-label">End Date <span class="text-danger">*</span></label>
{{ form.end_date }}
{% if form.end_date.errors %}
<div class="invalid-feedback d-block">{{ form.end_date.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.status.id_for_label }}" class="form-label">Status <span class="text-danger">*</span></label>
{{ form.status }}
{% if form.status.errors %}
<div class="invalid-feedback d-block">{{ form.status.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<div class="form-check form-switch mt-4">
{{ form.is_mandatory }}
<label class="form-check-label" for="{{ form.is_mandatory.id_for_label }}">
Mandatory Training
</label>
</div>
{% if form.is_mandatory.errors %}
<div class="invalid-feedback d-block">{{ form.is_mandatory.errors }}</div>
{% endif %}
</div>
</div>
</div>
<!-- Description Section -->
<div class="form-section">
<h5 class="form-section-title">Description</h5>
<div class="row">
<div class="col-md-12 mb-3">
<label for="{{ form.description.id_for_label }}" class="form-label">Description</label>
{{ form.description }}
{% if form.description.errors %}
<div class="invalid-feedback d-block">{{ form.description.errors }}</div>
{% endif %}
</div>
</div>
<h6 class="mt-3">Learning Objectives</h6>
<div id="objectives-container">
<!-- Objectives will be added here dynamically -->
{% if objectives %}
{% for objective in objectives %}
<div class="objective-row" data-objective-id="{{ objective.id }}">
<div class="row">
<div class="col-md-10 mb-2">
<input type="text" class="form-control objective-text" name="objective_text[]" value="{{ objective.text }}" placeholder="Enter learning objective">
<input type="hidden" class="objective-id" name="objective_id[]" value="{{ objective.id }}">
</div>
<div class="col-md-2 mb-2 text-end">
<button type="button" class="btn btn-sm btn-danger remove-objective">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
<div class="text-center mt-3">
<button type="button" class="btn btn-sm btn-success" id="add-objective">
<i class="fas fa-plus"></i> Add Learning Objective
</button>
</div>
</div>
<!-- Completion Details Section -->
<div class="form-section" id="completion-section">
<h5 class="form-section-title">Completion Details</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.completion_date.id_for_label }}" class="form-label">Completion Date</label>
{{ form.completion_date }}
{% if form.completion_date.errors %}
<div class="invalid-feedback d-block">{{ form.completion_date.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.score_grade.id_for_label }}" class="form-label">Score/Grade</label>
{{ form.score_grade }}
{% if form.score_grade.errors %}
<div class="invalid-feedback d-block">{{ form.score_grade.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.hours_completed.id_for_label }}" class="form-label">Hours Completed</label>
{{ form.hours_completed }}
{% if form.hours_completed.errors %}
<div class="invalid-feedback d-block">{{ form.hours_completed.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3" id="completion-percentage-container">
<label for="{{ form.completion_percentage.id_for_label }}" class="form-label">Completion Percentage</label>
<div class="input-group">
{{ form.completion_percentage }}
<span class="input-group-text">%</span>
</div>
{% if form.completion_percentage.errors %}
<div class="invalid-feedback d-block">{{ form.completion_percentage.errors }}</div>
{% endif %}
</div>
<div class="col-md-12 mb-3">
<label for="{{ form.completion_notes.id_for_label }}" class="form-label">Completion Notes</label>
{{ form.completion_notes }}
{% if form.completion_notes.errors %}
<div class="invalid-feedback d-block">{{ form.completion_notes.errors }}</div>
{% endif %}
</div>
</div>
</div>
<!-- Certification Section -->
<div class="form-section" id="certification-section">
<h5 class="form-section-title">Certification</h5>
<div class="row">
<div class="col-md-12 mb-3">
<div class="form-check form-switch">
{{ form.is_certified }}
<label class="form-check-label" for="{{ form.is_certified.id_for_label }}">
This training provides certification
</label>
</div>
{% if form.is_certified.errors %}
<div class="invalid-feedback d-block">{{ form.is_certified.errors }}</div>
{% endif %}
</div>
</div>
<div id="certification-details" class="{% if not form.instance.is_certified %}d-none{% endif %}">
<div class="row">
<div class="col-md-6 mb-3">
<label for="{{ form.certificate_number.id_for_label }}" class="form-label">Certificate Number</label>
{{ form.certificate_number }}
{% if form.certificate_number.errors %}
<div class="invalid-feedback d-block">{{ form.certificate_number.errors }}</div>
{% endif %}
</div>
<div class="col-md-6 mb-3">
<label for="{{ form.expiration_date.id_for_label }}" class="form-label">Expiration Date</label>
{{ form.expiration_date }}
{% if form.expiration_date.errors %}
<div class="invalid-feedback d-block">{{ form.expiration_date.errors }}</div>
{% endif %}
</div>
</div>
<h6 class="mt-3">Certificate Files</h6>
<div id="certificates-container">
<!-- Certificates will be added here dynamically -->
{% if certificates %}
{% for certificate in certificates %}
<div class="certificate-row" data-certificate-id="{{ certificate.id }}">
<div class="row">
<div class="col-md-5 mb-2">
<label class="form-label">Title</label>
<input type="text" class="form-control certificate-title" name="certificate_title[]" value="{{ certificate.title }}">
<input type="hidden" class="certificate-id" name="certificate_id[]" value="{{ certificate.id }}">
</div>
<div class="col-md-5 mb-2">
<label class="form-label">File</label>
<div class="input-group">
<input type="text" class="form-control" value="{{ certificate.file.name|split:'//'|last }}" readonly>
<a href="{{ certificate.file.url }}" class="btn btn-outline-secondary" target="_blank">
<i class="fas fa-eye"></i>
</a>
</div>
</div>
<div class="col-md-2 mb-2 text-end">
<label class="form-label">&nbsp;</label>
<div>
<button type="button" class="btn btn-sm btn-danger remove-certificate">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
<div class="row mt-3">
<div class="col-md-5 mb-3">
<label for="new_certificate_title" class="form-label">Certificate Title</label>
<input type="text" class="form-control" id="new_certificate_title" name="new_certificate_title">
</div>
<div class="col-md-5 mb-3">
<label for="new_certificate_file" class="form-label">Certificate File</label>
<input type="file" class="form-control" id="new_certificate_file" name="new_certificate_file">
</div>
<div class="col-md-2 mb-3 d-flex align-items-end">
<button type="button" class="btn btn-sm btn-success" id="add-certificate">
<i class="fas fa-plus"></i> Add
</button>
</div>
</div>
</div>
</div>
<!-- Attachments Section -->
<div class="form-section">
<h5 class="form-section-title">Attachments</h5>
<div class="row">
<div class="col-md-12 mb-3">
<label for="{{ form.attachments.id_for_label }}" class="form-label">Attachments</label>
{{ form.attachments }}
<div class="form-text">You can upload multiple files (PDF, Word, Excel, etc.)</div>
{% if form.attachments.errors %}
<div class="invalid-feedback d-block">{{ form.attachments.errors }}</div>
{% endif %}
</div>
</div>
{% if existing_attachments %}
<div class="mt-3">
<h6>Existing Attachments</h6>
<div class="list-group">
{% for attachment in existing_attachments %}
<div class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
<div>
<i class="fas fa-file me-2"></i>
<a href="{{ attachment.file.url }}" target="_blank">{{ attachment.title }}</a>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="delete_attachment_{{ attachment.id }}" id="delete_attachment_{{ attachment.id }}">
<label class="form-check-label" for="delete_attachment_{{ attachment.id }}">
Delete
</label>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
<!-- Additional Notes Section -->
<div class="form-section">
<h5 class="form-section-title">Additional Notes</h5>
<div class="row">
<div class="col-md-12 mb-3">
<label for="{{ form.notes.id_for_label }}" class="form-label">Notes</label>
{{ form.notes }}
{% if form.notes.errors %}
<div class="invalid-feedback d-block">{{ form.notes.errors }}</div>
{% endif %}
</div>
</div>
</div>
<!-- Form Actions -->
<div class="d-flex justify-content-between">
<a href="{% url 'hr:training_record_list' %}" class="btn btn-secondary">
<i class="fas fa-times"></i> Cancel
</a>
<div>
<button type="submit" name="save_draft" class="btn btn-info">
<i class="fas fa-save"></i> Save as Draft
</button>
<button type="submit" name="save" class="btn btn-primary">
<i class="fas fa-check"></i> Save Record
</button>
</div>
</div>
</form>
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- end col-9 -->
<!-- begin col-3 -->
<div class="col-xl-3">
<div class="help-sidebar">
<!-- Help Card -->
<div class="card help-card mb-4">
<div class="card-header">
<h5 class="card-title mb-0">Help & Guidelines</h5>
</div>
<div class="card-body">
<h6>Training Record Guidelines</h6>
<p>Follow these steps to create a comprehensive training record:</p>
<ol>
<li>Fill in the basic information about the training</li>
<li>Add a detailed description and learning objectives</li>
<li>If the training is completed, add completion details</li>
<li>For certifications, add certificate information and files</li>
<li>Attach any relevant documents</li>
<li>Add any additional notes</li>
</ol>
<h6>Training Types</h6>
<ul>
<li><strong>Certification:</strong> Formal qualification with certificate</li>
<li><strong>Course:</strong> Structured learning program</li>
<li><strong>Workshop:</strong> Hands-on practical training</li>
<li><strong>Seminar:</strong> Educational presentation</li>
<li><strong>Conference:</strong> Industry event with multiple sessions</li>
<li><strong>Mandatory:</strong> Required by regulation or policy</li>
</ul>
<h6>Status Definitions</h6>
<ul>
<li><strong>Scheduled:</strong> Planned but not yet started</li>
<li><strong>In Progress:</strong> Currently underway</li>
<li><strong>Completed:</strong> Successfully finished</li>
<li><strong>Expired:</strong> Certification has expired</li>
<li><strong>Upcoming:</strong> Scheduled to start soon</li>
</ul>
</div>
</div>
<!-- Tips Card -->
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title mb-0">Tips</h5>
</div>
<div class="card-body">
<ul>
<li>For mandatory trainings, be sure to include expiration dates if applicable</li>
<li>Learning objectives should be specific and measurable</li>
<li>Upload certificates as soon as they are available</li>
<li>For in-progress trainings, update the completion percentage regularly</li>
<li>Use the notes section for any special considerations or follow-up requirements</li>
</ul>
</div>
</div>
</div>
</div>
<!-- end col-3 -->
</div>
<!-- end row -->
{% endblock %}
{% block js %}
<!-- Select2 JS -->
<script src="{% static 'plugins/select2/dist/js/select2.min.js' %}"></script>
<!-- DateRangePicker JS -->
<script src="{% static 'plugins/moment/min/moment.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-daterangepicker/daterangepicker.js' %}"></script>
<!-- Summernote JS -->
<script src="{% static 'plugins/summernote/dist/summernote-lite.min.js' %}"></script>
<script>
$(document).ready(function() {
// Initialize Select2
$('#{{ form.employee.id_for_label }}, #{{ form.training_type.id_for_label }}, #{{ form.status.id_for_label }}').select2({
placeholder: "Select an option",
allowClear: true,
width: '100%'
});
// Initialize DatePickers
$('#{{ form.start_date.id_for_label }}, #{{ form.end_date.id_for_label }}, #{{ form.completion_date.id_for_label }}, #{{ form.expiration_date.id_for_label }}').daterangepicker({
singleDatePicker: true,
showDropdowns: true,
autoUpdateInput: false,
locale: {
format: 'YYYY-MM-DD'
}
});
// Set initial values for date pickers if they exist
var startDate = $('#{{ form.start_date.id_for_label }}').val();
if (startDate) {
$('#{{ form.start_date.id_for_label }}').val(moment(startDate).format('YYYY-MM-DD'));
}
var endDate = $('#{{ form.end_date.id_for_label }}').val();
if (endDate) {
$('#{{ form.end_date.id_for_label }}').val(moment(endDate).format('YYYY-MM-DD'));
}
var completionDate = $('#{{ form.completion_date.id_for_label }}').val();
if (completionDate) {
$('#{{ form.completion_date.id_for_label }}').val(moment(completionDate).format('YYYY-MM-DD'));
}
var expirationDate = $('#{{ form.expiration_date.id_for_label }}').val();
if (expirationDate) {
$('#{{ form.expiration_date.id_for_label }}').val(moment(expirationDate).format('YYYY-MM-DD'));
}
// Handle date picker apply event
$('#{{ form.start_date.id_for_label }}, #{{ form.end_date.id_for_label }}, #{{ form.completion_date.id_for_label }}, #{{ form.expiration_date.id_for_label }}').on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format('YYYY-MM-DD'));
});
// Initialize Summernote for rich text editors
$('#{{ form.description.id_for_label }}, #{{ form.completion_notes.id_for_label }}, #{{ form.notes.id_for_label }}').summernote({
height: 150,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['para', ['ul', 'ol', 'paragraph']],
['insert', ['link']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
// Show/hide completion percentage based on status
$('#{{ form.status.id_for_label }}').change(function() {
var status = $(this).val();
if (status === 'IN_PROGRESS') {
$('#completion-percentage-container').show();
} else {
$('#completion-percentage-container').hide();
}
});
// Trigger status change event on page load
$('#{{ form.status.id_for_label }}').trigger('change');
// Show/hide certification details based on is_certified checkbox
$('#{{ form.is_certified.id_for_label }}').change(function() {
if ($(this).is(':checked')) {
$('#certification-details').removeClass('d-none');
} else {
$('#certification-details').addClass('d-none');
}
});
// Add new learning objective
$('#add-objective').click(function() {
var objectiveId = 'new_' + new Date().getTime();
var objectiveHtml = `
<div class="objective-row" data-objective-id="${objectiveId}">
<div class="row">
<div class="col-md-10 mb-2">
<input type="text" class="form-control objective-text" name="objective_text[]" placeholder="Enter learning objective">
<input type="hidden" class="objective-id" name="objective_id[]" value="${objectiveId}">
</div>
<div class="col-md-2 mb-2 text-end">
<button type="button" class="btn btn-sm btn-danger remove-objective">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
`;
$('#objectives-container').append(objectiveHtml);
});
// Remove learning objective
$(document).on('click', '.remove-objective', function() {
$(this).closest('.objective-row').remove();
});
// Add certificate to list
$('#add-certificate').click(function() {
var title = $('#new_certificate_title').val();
var file = $('#new_certificate_file').val();
if (!title || !file) {
alert('Please enter both title and select a file.');
return;
}
var fileName = file.split('\\').pop();
var certificateId = 'new_' + new Date().getTime();
var certificateHtml = `
<div class="certificate-row" data-certificate-id="${certificateId}">
<div class="row">
<div class="col-md-5 mb-2">
<label class="form-label">Title</label>
<input type="text" class="form-control certificate-title" name="new_certificate_titles[]" value="${title}">
</div>
<div class="col-md-5 mb-2">
<label class="form-label">File</label>
<div class="input-group">
<input type="text" class="form-control" value="${fileName}" readonly>
</div>
<input type="hidden" name="new_certificate_files_index[]" value="${$('#certificates-container .certificate-row').length}">
</div>
<div class="col-md-2 mb-2 text-end">
<label class="form-label">&nbsp;</label>
<div>
<button type="button" class="btn btn-sm btn-danger remove-certificate">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
`;
$('#certificates-container').append(certificateHtml);
// Clear the inputs
$('#new_certificate_title').val('');
$('#new_certificate_file').val('');
});
// Remove certificate
$(document).on('click', '.remove-certificate', function() {
$(this).closest('.certificate-row').remove();
});
// Form validation
$('#trainingForm').submit(function(e) {
var isValid = true;
// Check if end date is after start date
var startDate = $('#{{ form.start_date.id_for_label }}').val();
var endDate = $('#{{ form.end_date.id_for_label }}').val();
if (startDate && endDate && moment(endDate).isBefore(moment(startDate))) {
alert('End date must be after start date.');
isValid = false;
}
// Check if completion date is between start and end date
var completionDate = $('#{{ form.completion_date.id_for_label }}').val();
if (completionDate && startDate && moment(completionDate).isBefore(moment(startDate))) {
alert('Completion date must be after start date.');
isValid = false;
}
// Check if expiration date is after completion date
var expirationDate = $('#{{ form.expiration_date.id_for_label }}').val();
if (expirationDate && completionDate && moment(expirationDate).isBefore(moment(completionDate))) {
alert('Expiration date must be after completion date.');
isValid = false;
}
if (!isValid) {
e.preventDefault();
}
});
});
</script>
{% endblock %}