HH/templates/journeys/template_form.html
2026-01-24 15:27:30 +03:00

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 %}