313 lines
15 KiB
HTML
313 lines
15 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% if template %}Edit {{ template.name }}{% else %}Create Journey Template{% endif %} - PX360{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h2 class="mb-1">
|
|
{% if template %}
|
|
<i class="bi bi-pencil-square text-primary me-2"></i>Edit {{ template.name }}
|
|
{% else %}
|
|
<i class="bi bi-plus-circle text-primary me-2"></i>Create Journey Template
|
|
{% endif %}
|
|
</h2>
|
|
<p class="text-muted mb-0">Define stages and surveys for patient journeys</p>
|
|
</div>
|
|
<div>
|
|
<a href="{% url 'journeys:template_list' %}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-arrow-left me-1"></i> Back to Templates
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="post" id="templateForm">
|
|
{% csrf_token %}
|
|
|
|
<!-- Template Details -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">Template Details</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label for="{{ form.name.id_for_label }}" class="form-label">Name (English) *</label>
|
|
{{ form.name }}
|
|
{% if form.name.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.name.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label for="{{ form.name_ar.id_for_label }}" class="form-label">Name (Arabic)</label>
|
|
{{ form.name_ar }}
|
|
{% if form.name_ar.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.name_ar.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label for="{{ form.journey_type.id_for_label }}" class="form-label">Journey Type *</label>
|
|
{{ form.journey_type }}
|
|
{% if form.journey_type.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.journey_type.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="{{ form.hospital.id_for_label }}" class="form-label">Hospital *</label>
|
|
{{ form.hospital }}
|
|
{% if form.hospital.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.hospital.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="{{ form.is_active.id_for_label }}" class="form-label">Status</label>
|
|
<div class="form-check mt-2">
|
|
{{ form.is_active }}
|
|
<label class="form-check-label" for="{{ form.is_active.id_for_label }}">Active</label>
|
|
</div>
|
|
{% if form.is_active.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_active.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="{{ form.send_post_discharge_survey.id_for_label }}" class="form-label">Post-Discharge Survey</label>
|
|
<div class="form-check mt-2">
|
|
{{ form.send_post_discharge_survey }}
|
|
<label class="form-check-label" for="{{ form.send_post_discharge_survey.id_for_label }}">Send comprehensive survey after discharge</label>
|
|
</div>
|
|
{% if form.send_post_discharge_survey.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.send_post_discharge_survey.errors }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="{{ form.post_discharge_survey_delay_hours.id_for_label }}" class="form-label">Survey Delay (Hours)</label>
|
|
{{ form.post_discharge_survey_delay_hours }}
|
|
{% if form.post_discharge_survey_delay_hours.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.post_discharge_survey_delay_hours.errors }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Hours after discharge to send the survey</div>
|
|
</div>
|
|
</div>
|
|
|
|
<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>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stages -->
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0">Journey Stages</h5>
|
|
<button type="button" class="btn btn-sm btn-primary" id="addStageBtn">
|
|
<i class="bi bi-plus me-1"></i> Add Stage
|
|
</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="stages-container">
|
|
{{ formset.management_form }}
|
|
|
|
<table class="table table-bordered" id="stagesTable">
|
|
<thead>
|
|
<tr>
|
|
<th width="8%">Order</th>
|
|
<th width="25%">Name (EN)</th>
|
|
<th width="15%">Code</th>
|
|
<th width="20%">Trigger Event</th>
|
|
<th width="10%">Survey</th>
|
|
<th width="7%">Opt</th>
|
|
<th width="7%">Act</th>
|
|
<th width="8%">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="stages-body">
|
|
{% for form in formset %}
|
|
<tr class="stage-form" id="stage-{{ forloop.counter0 }}">
|
|
{{ form.id }}
|
|
<td>
|
|
{{ form.order }}
|
|
</td>
|
|
<td>
|
|
{{ form.name }}
|
|
<small class="text-muted d-block">{{ form.name_ar }}</small>
|
|
</td>
|
|
<td>
|
|
{{ form.code }}
|
|
</td>
|
|
<td>
|
|
{{ form.trigger_event_code }}
|
|
</td>
|
|
<td>
|
|
{{ form.survey_template }}
|
|
</td>
|
|
<td class="text-center">
|
|
<div class="form-check d-flex justify-content-center">
|
|
{{ form.is_optional }}
|
|
</div>
|
|
</td>
|
|
<td class="text-center">
|
|
<div class="form-check d-flex justify-content-center">
|
|
{{ form.is_active }}
|
|
</div>
|
|
</td>
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-sm btn-danger delete-stage-btn">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="text-muted small">
|
|
<i class="bi bi-info-circle me-1"></i>
|
|
<strong>Stages</strong>: Define stages for patient journeys. Each stage has a trigger event code that completes the stage.
|
|
Survey templates assigned here will have their questions merged into the post-discharge survey.
|
|
</div>
|
|
|
|
<div class="text-muted small">
|
|
<i class="bi bi-info-circle me-1"></i>
|
|
Stages will be executed in order. After creating the template, you can assign surveys to each stage.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="card">
|
|
<div class="card-body text-end">
|
|
<a href="{% url 'journeys:template_list' %}" class="btn btn-secondary me-2">
|
|
<i class="bi bi-x-circle me-1"></i> Cancel
|
|
</a>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="bi bi-check-circle me-1"></i>
|
|
{% if template %}Update Template{% else %}Create Template{% endif %}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const stagesBody = document.getElementById('stages-body');
|
|
const addStageBtn = document.getElementById('addStageBtn');
|
|
const totalFormsInput = document.getElementById('id_stagesset-TOTAL_FORMS');
|
|
|
|
// Delete stage button handler
|
|
stagesBody.addEventListener('click', function(e) {
|
|
if (e.target.closest('.delete-stage-btn')) {
|
|
const row = e.target.closest('tr');
|
|
const deleteInput = document.createElement('input');
|
|
deleteInput.type = 'hidden';
|
|
deleteInput.name = row.querySelector('[name$="-id"]').name.replace('id', 'DELETE');
|
|
deleteInput.value = 'on';
|
|
row.appendChild(deleteInput);
|
|
row.style.display = 'none';
|
|
updateStageOrders();
|
|
}
|
|
});
|
|
|
|
// Add new stage
|
|
addStageBtn.addEventListener('click', function() {
|
|
const formCount = parseInt(totalFormsInput.value);
|
|
const newRow = document.createElement('tr');
|
|
newRow.className = 'stage-form';
|
|
newRow.id = 'stage-' + formCount;
|
|
|
|
// Get survey template options from first row
|
|
let surveyOptions = '<option value="">-- No Survey --</option>';
|
|
const firstSurveySelect = document.querySelector('select[name$="-survey_template"]');
|
|
if (firstSurveySelect) {
|
|
surveyOptions = firstSurveySelect.innerHTML;
|
|
}
|
|
|
|
newRow.innerHTML = `
|
|
<input type="hidden" name="stagesset-${formCount}-id" id="id_stagesset-${formCount}-id">
|
|
<td>
|
|
<input type="number" name="stagesset-${formCount}-order"
|
|
id="id_stagesset-${formCount}-order"
|
|
class="form-control form-control-sm" value="${formCount + 1}" min="0">
|
|
</td>
|
|
<td>
|
|
<input type="text" name="stagesset-${formCount}-name"
|
|
id="id_stagesset-${formCount}-name"
|
|
class="form-control form-control-sm" placeholder="e.g., Admission">
|
|
<input type="text" name="stagesset-${formCount}-name_ar"
|
|
id="id_stagesset-${formCount}-name_ar"
|
|
class="form-control form-control-sm mt-1" placeholder="الاسم بالعربية" style="font-size: 0.8rem;">
|
|
</td>
|
|
<td>
|
|
<input type="text" name="stagesset-${formCount}-code"
|
|
id="id_stagesset-${formCount}-code"
|
|
class="form-control form-control-sm" placeholder="e.g., ADMISSION">
|
|
</td>
|
|
<td>
|
|
<input type="text" name="stagesset-${formCount}-trigger_event_code"
|
|
id="id_stagesset-${formCount}-trigger_event_code"
|
|
class="form-control form-control-sm" placeholder="e.g., OPD_VISIT_COMPLETED">
|
|
</td>
|
|
<td>
|
|
<select name="stagesset-${formCount}-survey_template"
|
|
id="id_stagesset-${formCount}-survey_template"
|
|
class="form-select form-select-sm">
|
|
${surveyOptions}
|
|
</select>
|
|
</td>
|
|
<td class="text-center">
|
|
<div class="form-check d-flex justify-content-center">
|
|
<input type="checkbox" name="stagesset-${formCount}-is_optional"
|
|
id="id_stagesset-${formCount}-is_optional"
|
|
class="form-check-input form-check-input-sm">
|
|
</div>
|
|
</td>
|
|
<td class="text-center">
|
|
<div class="form-check d-flex justify-content-center">
|
|
<input type="checkbox" name="stagesset-${formCount}-is_active"
|
|
id="id_stagesset-${formCount}-is_active"
|
|
class="form-check-input form-check-input-sm" checked>
|
|
</div>
|
|
</td>
|
|
<td class="text-center">
|
|
<button type="button" class="btn btn-sm btn-danger delete-stage-btn">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
`;
|
|
|
|
stagesBody.appendChild(newRow);
|
|
totalFormsInput.value = formCount + 1;
|
|
});
|
|
|
|
// Update stage orders when rows are deleted
|
|
function updateStageOrders() {
|
|
const visibleRows = Array.from(stagesBody.querySelectorAll('tr:not([style*="display: none"])'));
|
|
visibleRows.forEach((row, index) => {
|
|
const orderInput = row.querySelector('[name$="-order"]');
|
|
if (orderInput) {
|
|
orderInput.value = index;
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initial order update
|
|
updateStageOrders();
|
|
});
|
|
</script>
|
|
{% endblock %}
|