284 lines
13 KiB
HTML
284 lines
13 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% load i18n %}
|
|
|
|
{% block title %}{% if is_create %}{% trans "Create QI Project" %}{% else %}{% trans "Edit QI Project" %}{% endif %} - PX360{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Back Button -->
|
|
<div class="mb-6">
|
|
<a href="{% url 'projects:project_list' %}" class="inline-flex items-center gap-2 text-slate hover:text-navy transition">
|
|
<i data-lucide="arrow-left" class="w-4 h-4"></i>
|
|
<span class="text-sm font-medium">{% trans "Back to Projects" %}</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Header -->
|
|
<header class="mb-6">
|
|
<div class="flex justify-between items-start">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-navy flex items-center gap-3">
|
|
<i data-lucide="kanban" class="w-6 h-6"></i>
|
|
{% if is_create %}{% trans "Create QI Project" %}{% else %}{% trans "Edit QI Project" %}{% endif %}
|
|
</h1>
|
|
<p class="text-sm text-slate mt-1">
|
|
{% if is_create %}
|
|
{% trans "Start a new quality improvement initiative" %}
|
|
{% else %}
|
|
{% trans "Update project details and settings" %}
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Form Card -->
|
|
<div class="bg-white rounded-2xl border shadow-sm overflow-hidden">
|
|
<div class="px-6 py-4 border-b">
|
|
<h2 class="text-sm font-bold text-navy">{% trans "Project Information" %}</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
{% if template %}
|
|
<!-- Template Preview -->
|
|
<div class="mb-6 bg-blue-50 border border-blue-100 rounded-xl p-4">
|
|
<div class="flex items-start gap-3">
|
|
<i data-lucide="copy" class="w-5 h-5 text-blue mt-0.5"></i>
|
|
<div class="flex-1">
|
|
<h3 class="text-sm font-bold text-navy mb-1">
|
|
{% trans "Creating from Template:" %} {{ template.name }}
|
|
</h3>
|
|
{% if template.tasks.exists %}
|
|
<p class="text-xs text-slate mb-2">
|
|
{% trans "This template includes" %} {{ template.tasks.count }} {% trans "task(s) that will be copied to your new project." %}
|
|
</p>
|
|
<ul class="text-xs text-slate space-y-1">
|
|
{% for task in template.tasks.all|slice:":5" %}
|
|
<li class="flex items-center gap-2">
|
|
<i data-lucide="check" class="w-3 h-3 text-green-600"></i>
|
|
{{ task.title }}
|
|
</li>
|
|
{% endfor %}
|
|
{% if template.tasks.count > 5 %}
|
|
<li class="text-slate-500 italic">
|
|
{% trans "and" %} {{ template.tasks.count|add:"-5" }} {% trans "more..." %}
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
{% else %}
|
|
<p class="text-xs text-slate">{% trans "No predefined tasks in this template." %}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<form method="post" novalidate>
|
|
{% csrf_token %}
|
|
|
|
{% if template %}
|
|
<input type="hidden" name="template_id" value="{{ template.pk }}">
|
|
{% endif %}
|
|
|
|
<div class="grid grid-cols-2 gap-6">
|
|
<!-- Project Name -->
|
|
<div>
|
|
<label for="{{ form.name.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Project Name" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
{{ form.name }}
|
|
{% if form.name.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.name.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Project Name (Arabic) -->
|
|
<div>
|
|
<label for="{{ form.name_ar.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Project Name (Arabic)" %}
|
|
</label>
|
|
{{ form.name_ar }}
|
|
{% if form.name_ar.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.name_ar.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div class="mt-6">
|
|
<label for="{{ form.description.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Description" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
{{ form.description }}
|
|
{% if form.description.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.description.errors.0 }}</p>
|
|
{% endif %}
|
|
<p class="text-xs text-slate mt-1">{% trans "Describe the project objectives and scope" %}</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-6 mt-6">
|
|
<!-- Hospital -->
|
|
<div>
|
|
<label for="{{ form.hospital.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Hospital" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
{{ form.hospital }}
|
|
{% if form.hospital.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.hospital.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Department -->
|
|
<div>
|
|
<label for="{{ form.department.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Department" %}
|
|
</label>
|
|
{{ form.department }}
|
|
{% if form.department.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.department.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-6 mt-6">
|
|
<!-- Project Lead -->
|
|
<div>
|
|
<label for="{{ form.project_lead.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Project Lead" %}
|
|
</label>
|
|
{{ form.project_lead }}
|
|
{% if form.project_lead.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.project_lead.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Status -->
|
|
<div>
|
|
<label for="{{ form.status.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Status" %} <span class="text-red-500">*</span>
|
|
</label>
|
|
{{ form.status }}
|
|
{% if form.status.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.status.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Team Members -->
|
|
<div class="mt-6">
|
|
<label for="{{ form.team_members.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Team Members" %}
|
|
</label>
|
|
{{ form.team_members }}
|
|
{% if form.team_members.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.team_members.errors.0 }}</p>
|
|
{% endif %}
|
|
<p class="text-xs text-slate mt-1">{% trans "Hold Ctrl/Cmd to select multiple team members" %}</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-6 mt-6">
|
|
<!-- Start Date -->
|
|
<div>
|
|
<label for="{{ form.start_date.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Start Date" %}
|
|
</label>
|
|
{{ form.start_date }}
|
|
{% if form.start_date.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.start_date.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Target Completion Date -->
|
|
<div>
|
|
<label for="{{ form.target_completion_date.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Target Completion Date" %}
|
|
</label>
|
|
{{ form.target_completion_date }}
|
|
{% if form.target_completion_date.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.target_completion_date.errors.0 }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Outcome Description (only show for existing projects) -->
|
|
{% if not is_create %}
|
|
<div class="mt-6">
|
|
<label for="{{ form.outcome_description.id_for_label }}" class="block text-xs font-bold text-slate uppercase tracking-wider mb-2">
|
|
{% trans "Outcome Description" %}
|
|
</label>
|
|
{{ form.outcome_description }}
|
|
{% if form.outcome_description.errors %}
|
|
<p class="text-red-500 text-xs mt-1">{{ form.outcome_description.errors.0 }}</p>
|
|
{% endif %}
|
|
<p class="text-xs text-slate mt-1">{% trans "Document project outcomes and results" %}</p>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Submit Buttons -->
|
|
<div class="flex items-center gap-3 mt-8 pt-6 border-t">
|
|
<button type="submit" class="bg-navy text-white px-5 py-2.5 rounded-xl text-sm font-bold shadow-lg shadow-navy/20 hover:bg-blue flex items-center gap-2 transition">
|
|
<i data-lucide="save" class="w-4 h-4"></i>
|
|
{% if is_create %}{% trans "Create Project" %}{% else %}{% trans "Save Changes" %}{% endif %}
|
|
</button>
|
|
<a href="{% url 'projects:project_list' %}" class="bg-slate-100 text-slate px-5 py-2.5 rounded-xl text-sm font-bold hover:bg-slate-200 transition">
|
|
{% trans "Cancel" %}
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
// Dynamic department and staff filtering based on hospital selection
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const hospitalSelect = document.getElementById('{{ form.hospital.id_for_label }}');
|
|
const departmentSelect = document.getElementById('{{ form.department.id_for_label }}');
|
|
const projectLeadSelect = document.getElementById('{{ form.project_lead.id_for_label }}');
|
|
const teamMembersSelect = document.getElementById('{{ form.team_members.id_for_label }}');
|
|
|
|
if (hospitalSelect) {
|
|
hospitalSelect.addEventListener('change', function() {
|
|
const hospitalId = this.value;
|
|
if (!hospitalId) return;
|
|
|
|
// Fetch departments and staff for selected hospital
|
|
fetch(`/api/organizations/hospitals/${hospitalId}/departments/`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
// Update departments
|
|
departmentSelect.innerHTML = '<option value="">---------</option>';
|
|
data.departments.forEach(dept => {
|
|
const option = document.createElement('option');
|
|
option.value = dept.id;
|
|
option.textContent = dept.name;
|
|
departmentSelect.appendChild(option);
|
|
});
|
|
});
|
|
|
|
// Fetch staff
|
|
fetch(`/api/organizations/hospitals/${hospitalId}/staff/`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
// Update project lead
|
|
projectLeadSelect.innerHTML = '<option value="">---------</option>';
|
|
data.staff.forEach(staff => {
|
|
const option = document.createElement('option');
|
|
option.value = staff.id;
|
|
option.textContent = `${staff.first_name} ${staff.last_name}`;
|
|
projectLeadSelect.appendChild(option);
|
|
});
|
|
|
|
// Update team members
|
|
teamMembersSelect.innerHTML = '';
|
|
data.staff.forEach(staff => {
|
|
const option = document.createElement('option');
|
|
option.value = staff.id;
|
|
option.textContent = `${staff.first_name} ${staff.last_name}`;
|
|
teamMembersSelect.appendChild(option);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |