573 lines
31 KiB
HTML
573 lines
31 KiB
HTML
{% extends 'layouts/base.html' %}
|
|
{% load i18n %}
|
|
{% load rca_filters %}
|
|
|
|
{% block title %}{{ rca.title }} - {% trans "RCA" %} - PX360{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.timeline {
|
|
position: relative;
|
|
padding-left: 30px;
|
|
}
|
|
.timeline::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 8px;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 2px;
|
|
background: #e2e8f0;
|
|
}
|
|
.timeline-item {
|
|
position: relative;
|
|
padding-bottom: 24px;
|
|
}
|
|
.timeline-item::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: -26px;
|
|
top: 5px;
|
|
width: 14px;
|
|
height: 14px;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
border: 3px solid #005696;
|
|
z-index: 1;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Breadcrumb & Header -->
|
|
<header class="mb-6">
|
|
<div class="flex items-center gap-2 text-sm text-slate mb-2">
|
|
<a href="{% url 'rca:rca_list' %}" class="hover:text-navy">{% trans "RCA" %}</a>
|
|
<i data-lucide="chevron-right" class="w-4 h-4"></i>
|
|
<span class="font-bold text-navy">{{ rca.title|truncatechars:40 }}</span>
|
|
<span class="ml-2 px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider {{ rca.status|status_color }}">
|
|
{{ rca.get_status_display }}
|
|
</span>
|
|
</div>
|
|
<div class="flex items-center justify-between flex-wrap gap-3">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-navy">{{ rca.title }}</h1>
|
|
{% if related_item %}
|
|
<a href="{{ related_item.get_absolute_url }}" class="inline-flex items-center gap-1.5 mt-1 text-xs text-blue hover:text-navy transition">
|
|
<i data-lucide="link" class="w-3 h-3"></i>
|
|
{% trans "Linked to" %} {{ related_item_type|title }}: {{ related_item }}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
{% if rca.status != 'closed' %}
|
|
<a href="{% url 'rca:rca_update' rca.pk %}" class="text-slate hover:text-navy px-3 py-2 text-sm font-semibold flex items-center gap-2 border rounded-lg hover:bg-light transition">
|
|
<i data-lucide="pencil" class="w-4 h-4"></i> {% trans "Edit" %}
|
|
</a>
|
|
{% endif %}
|
|
{% if rca.status == 'review' %}
|
|
<form method="post" action="{% url 'rca:rca_approve' rca.pk %}" class="inline">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="approval_notes" value="">
|
|
<button type="submit" class="bg-green-500 text-white px-4 py-2 rounded-lg text-sm font-bold shadow-md hover:bg-green-600 transition inline-flex items-center gap-2">
|
|
<i data-lucide="check" class="w-4 h-4"></i> {% trans "Approve" %}
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if rca.status == 'approved' or rca.status == 'in_progress' %}
|
|
<form method="post" action="{% url 'rca:rca_close' rca.pk %}" class="inline">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="closure_notes" value="Closed via detail page">
|
|
<input type="hidden" name="actual_completion_date" value="{% now 'Y-m-d' %}">
|
|
<button type="submit" class="bg-slate-500 text-white px-4 py-2 rounded-lg text-sm font-bold shadow-md hover:bg-slate-600 transition inline-flex items-center gap-2">
|
|
<i data-lucide="x-circle" class="w-4 h-4"></i> {% trans "Close" %}
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if rca.status != 'closed' %}
|
|
<form method="post" action="{% url 'rca:rca_delete' rca.pk %}" class="inline" onsubmit="return confirm('{% trans "Are you sure?" %}');">
|
|
{% csrf_token %}
|
|
<button type="submit" class="bg-red-500 text-white px-4 py-2 rounded-lg text-sm font-bold shadow-md hover:bg-red-600 transition inline-flex items-center gap-2">
|
|
<i data-lucide="trash-2" class="w-4 h-4"></i> {% trans "Delete" %}
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Grid -->
|
|
<div class="grid grid-cols-12 gap-6">
|
|
<!-- Left Column -->
|
|
<div class="col-span-8">
|
|
<!-- Incident Details -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 mb-6">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center gap-3">
|
|
<div class="p-2 bg-purple-500/10 rounded-lg">
|
|
<i data-lucide="info" class="w-5 h-5 text-purple-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Incident Details" %}</h3>
|
|
</div>
|
|
<div class="p-6">
|
|
<div class="grid grid-cols-4 gap-6 mb-6">
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Status" %}</label>
|
|
<p class="mt-1">
|
|
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase {{ rca.status|status_color }}">
|
|
{{ rca.get_status_display }}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Severity" %}</label>
|
|
<p class="mt-1">
|
|
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase {{ rca.severity|severity_color }}">
|
|
{{ rca.get_severity_display }}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Priority" %}</label>
|
|
<p class="mt-1">
|
|
<span class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase
|
|
{% if rca.priority == 'critical' %}bg-red-500 text-white
|
|
{% elif rca.priority == 'high' %}bg-orange-100 text-orange-700
|
|
{% elif rca.priority == 'medium' %}bg-yellow-100 text-yellow-700
|
|
{% else %}bg-green-100 text-green-700{% endif %}">
|
|
{{ rca.get_priority_display }}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Assigned To" %}</label>
|
|
<p class="mt-1 text-sm font-bold text-navy">{{ rca.assigned_to.get_full_name|default:"—" }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-4 gap-6 mb-6">
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Hospital" %}</label>
|
|
<p class="mt-1 text-sm text-slate-700">{{ rca.hospital }}</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Department" %}</label>
|
|
<p class="mt-1 text-sm text-slate-700">{{ rca.department|default:"—" }}</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Created" %}</label>
|
|
<p class="mt-1 text-sm text-slate-700">{{ rca.created_at|date:"M d, Y" }}</p>
|
|
</div>
|
|
<div>
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Target Completion" %}</label>
|
|
<p class="mt-1 text-sm text-slate-700">{{ rca.target_completion_date|default:"—" }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div class="mb-4">
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Description" %}</label>
|
|
<div class="mt-1 bg-light/40 p-4 rounded-xl border-l-4 border-blue text-sm text-slate-700 leading-relaxed">
|
|
{{ rca.description|linebreaks }}
|
|
</div>
|
|
</div>
|
|
{% if rca.background %}
|
|
<div class="mb-4">
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Background" %}</label>
|
|
<div class="mt-1 bg-light/40 p-4 rounded-xl border-l-4 border-slate-300 text-sm text-slate-700 leading-relaxed">
|
|
{{ rca.background|linebreaks }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if rca.root_cause_summary %}
|
|
<div class="mb-4">
|
|
<label class="text-[10px] font-bold text-slate uppercase">{% trans "Root Cause Summary" %}</label>
|
|
<div class="mt-1 bg-light/40 p-4 rounded-xl border-l-4 border-green-400 text-sm text-slate-700 leading-relaxed">
|
|
{{ rca.root_cause_summary|linebreaks }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status Timeline -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-slate-100">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-blue-500/10 rounded-lg">
|
|
<i data-lucide="activity" class="w-5 h-5 text-blue-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Status Timeline" %}</h3>
|
|
</div>
|
|
{% if rca.status != 'closed' %}
|
|
<form method="post" action="{% url 'rca:rca_status_change' rca.pk %}" id="statusChangeForm">
|
|
{% csrf_token %}
|
|
<div class="flex items-center gap-2">
|
|
<select name="new_status" class="px-3 py-1.5 bg-white border rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-navy">
|
|
{% for choice in status_choices %}
|
|
{% if choice.0 != rca.status %}
|
|
<option value="{{ choice.0 }}">{{ choice.1 }}</option>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</select>
|
|
<button type="submit" class="px-3 py-1.5 bg-navy text-white rounded-lg text-xs font-bold hover:bg-blue transition">{% trans "Update" %}</button>
|
|
</div>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
<div class="p-6">
|
|
{% if status_logs %}
|
|
<div class="timeline">
|
|
{% for log in status_logs %}
|
|
<div class="timeline-item">
|
|
<div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="px-2.5 py-0.5 rounded-full text-[10px] font-bold uppercase {{ log.new_status|status_color }}">
|
|
{{ log.get_new_status_display }}
|
|
</span>
|
|
<span class="text-xs text-slate">{{ log.created_at|date:"M d, Y H:i" }}</span>
|
|
{% if log.changed_by %}
|
|
<span class="text-xs text-slate">by <strong>{{ log.changed_by }}</strong></span>
|
|
{% endif %}
|
|
</div>
|
|
{% if log.notes %}
|
|
<p class="text-sm text-slate-500 mt-1">{{ log.notes }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-6">
|
|
<i data-lucide="clock" class="w-10 h-10 mx-auto text-slate-300 mb-2"></i>
|
|
<p class="text-slate text-sm">{% trans "No status changes recorded." %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column -->
|
|
<div class="col-span-4">
|
|
<!-- Root Causes -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 mb-6">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-orange-500/10 rounded-lg">
|
|
<i data-lucide="target" class="w-5 h-5 text-orange-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Root Causes" %}</h3>
|
|
<span class="bg-slate-100 text-slate-600 text-[10px] font-bold px-2 py-0.5 rounded-full">{{ root_causes|length }}</span>
|
|
</div>
|
|
{% if rca.status != 'closed' %}
|
|
<button onclick="openModal('rootCauseModal')" class="p-1.5 text-navy hover:bg-light rounded-lg transition" title="{% trans 'Add Root Cause' %}">
|
|
<i data-lucide="plus" class="w-4 h-4"></i>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
<div class="p-4">
|
|
{% if root_causes %}
|
|
<div class="space-y-3">
|
|
{% for rc in root_causes %}
|
|
<div class="bg-slate-50 rounded-xl p-3 border border-slate-100">
|
|
<div class="flex items-start justify-between mb-1.5">
|
|
<span class="px-2 py-0.5 bg-slate-200 text-slate-600 text-[10px] font-bold rounded-md uppercase">{{ rc.get_category_display }}</span>
|
|
<div class="flex items-center gap-1">
|
|
{% if rc.risk_score %}
|
|
<span class="text-[10px] font-bold text-slate">Risk: {{ rc.risk_score }}</span>
|
|
{% endif %}
|
|
{% if rca.status != 'closed' %}
|
|
<form method="post" action="{% url 'rca:rca_root_cause_delete' rca.pk rc.pk %}" onsubmit="return confirm('Delete this root cause?');">
|
|
{% csrf_token %}
|
|
<button type="submit" class="p-1 text-red-400 hover:text-red-600 rounded transition">
|
|
<i data-lucide="trash-2" class="w-3 h-3"></i>
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<p class="text-sm text-slate-700">{{ rc.description }}</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-6">
|
|
<i data-lucide="target" class="w-10 h-10 mx-auto text-slate-300 mb-2"></i>
|
|
<p class="text-slate text-sm">{% trans "No root causes added." %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Corrective Actions -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 mb-6">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-green-500/10 rounded-lg">
|
|
<i data-lucide="check-square" class="w-5 h-5 text-green-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Corrective Actions" %}</h3>
|
|
<span class="bg-slate-100 text-slate-600 text-[10px] font-bold px-2 py-0.5 rounded-full">{{ corrective_actions|length }}</span>
|
|
</div>
|
|
{% if rca.status != 'closed' %}
|
|
<button onclick="openModal('actionModal')" class="p-1.5 text-navy hover:bg-light rounded-lg transition" title="{% trans 'Add Action' %}">
|
|
<i data-lucide="plus" class="w-4 h-4"></i>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
<div class="p-4">
|
|
{% if corrective_actions %}
|
|
<div class="space-y-3">
|
|
{% for action in corrective_actions %}
|
|
<div class="bg-slate-50 rounded-xl p-3 border border-slate-100">
|
|
<div class="flex items-start justify-between mb-1.5">
|
|
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold uppercase {{ action.status|action_status_color }}">
|
|
{{ action.get_status_display }}
|
|
</span>
|
|
<div class="flex items-center gap-1">
|
|
{% if rca.status != 'closed' %}
|
|
<form method="post" action="{% url 'rca:rca_action_delete' rca.pk action.pk %}" onsubmit="return confirm('Delete this action?');">
|
|
{% csrf_token %}
|
|
<button type="submit" class="p-1 text-red-400 hover:text-red-600 rounded transition">
|
|
<i data-lucide="trash-2" class="w-3 h-3"></i>
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<p class="text-sm text-slate-700">{{ action.description }}</p>
|
|
<div class="flex items-center gap-3 mt-2 text-[10px] text-slate">
|
|
<span class="font-medium">{{ action.get_action_type_display }}</span>
|
|
{% if action.responsible_person %}
|
|
<span class="flex items-center gap-1"><i data-lucide="user" class="w-3 h-3"></i>{{ action.responsible_person }}</span>
|
|
{% endif %}
|
|
{% if action.target_date %}
|
|
<span class="flex items-center gap-1"><i data-lucide="calendar" class="w-3 h-3"></i>{{ action.target_date|date:"M d, Y" }}</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-6">
|
|
<i data-lucide="check-square" class="w-10 h-10 mx-auto text-slate-300 mb-2"></i>
|
|
<p class="text-slate text-sm">{% trans "No corrective actions added." %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notes -->
|
|
<div class="bg-white rounded-2xl shadow-sm border border-slate-100">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="p-2 bg-yellow-500/10 rounded-lg">
|
|
<i data-lucide="sticky-note" class="w-5 h-5 text-yellow-600"></i>
|
|
</div>
|
|
<h3 class="font-bold text-navy">{% trans "Notes" %}</h3>
|
|
<span class="bg-slate-100 text-slate-600 text-[10px] font-bold px-2 py-0.5 rounded-full">{{ notes|length }}</span>
|
|
</div>
|
|
{% if rca.status != 'closed' %}
|
|
<button onclick="openModal('noteModal')" class="p-1.5 text-navy hover:bg-light rounded-lg transition" title="{% trans 'Add Note' %}">
|
|
<i data-lucide="plus" class="w-4 h-4"></i>
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
<div class="p-4">
|
|
{% if notes %}
|
|
<div class="space-y-3">
|
|
{% for note in notes %}
|
|
<div class="bg-slate-50 rounded-xl p-3 border border-slate-100">
|
|
<p class="text-sm text-slate-700 mb-2">{{ note.note }}</p>
|
|
<div class="flex items-center justify-between text-[10px] text-slate">
|
|
<span>{{ note.created_by }} — {{ note.created_at|date:"M d, Y H:i" }}</span>
|
|
{% if note.is_internal %}<span class="px-1.5 py-0.5 bg-yellow-100 text-yellow-700 font-bold rounded-md">Internal</span>{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center py-6">
|
|
<i data-lucide="sticky-note" class="w-10 h-10 mx-auto text-slate-300 mb-2"></i>
|
|
<p class="text-slate text-sm">{% trans "No notes added." %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if rca.status != 'closed' %}
|
|
<!-- Root Cause Modal -->
|
|
<div id="rootCauseModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
|
|
<div class="bg-white rounded-2xl p-6 w-full max-w-lg mx-4 shadow-2xl">
|
|
<div class="flex items-center gap-3 mb-4">
|
|
<div class="w-10 h-10 bg-orange-100 rounded-full flex items-center justify-center">
|
|
<i data-lucide="target" class="w-5 h-5 text-orange-500"></i>
|
|
</div>
|
|
<h3 class="text-xl font-bold text-navy">{% trans "Add Root Cause" %}</h3>
|
|
</div>
|
|
<form method="post" action="{% url 'rca:rca_root_cause_add' rca.pk %}">
|
|
{% csrf_token %}
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Category" %} <span class="text-red-500">*</span></label>
|
|
<select name="category" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" required>
|
|
<option value="">Select...</option>
|
|
<option value="process">Process/Procedure</option>
|
|
<option value="people">People/Training</option>
|
|
<option value="equipment">Equipment/Resources</option>
|
|
<option value="communication">Communication</option>
|
|
<option value="policy">Policy/Regulation</option>
|
|
<option value="environment">Environment</option>
|
|
<option value="technology">Technology/Systems</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Description" %} <span class="text-red-500">*</span></label>
|
|
<textarea name="description" rows="3" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" required></textarea>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Likelihood" %} (1-5)</label>
|
|
<input type="number" name="likelihood" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" min="1" max="5">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Impact" %} (1-5)</label>
|
|
<input type="number" name="impact" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" min="1" max="5">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Contributing Factors" %}</label>
|
|
<textarea name="contributing_factors" rows="2" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 mt-6">
|
|
<button type="button" onclick="closeModal('rootCauseModal')" class="flex-1 px-4 py-2 border border-slate-200 text-slate rounded-xl font-semibold hover:bg-slate-50 transition">{% trans "Cancel" %}</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-navy text-white rounded-xl font-semibold hover:bg-blue transition flex items-center justify-center gap-2">
|
|
<i data-lucide="plus" class="w-4 h-4"></i> {% trans "Add Root Cause" %}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Corrective Action Modal -->
|
|
<div id="actionModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
|
|
<div class="bg-white rounded-2xl p-6 w-full max-w-lg mx-4 shadow-2xl">
|
|
<div class="flex items-center gap-3 mb-4">
|
|
<div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center">
|
|
<i data-lucide="check-square" class="w-5 h-5 text-green-600"></i>
|
|
</div>
|
|
<h3 class="text-xl font-bold text-navy">{% trans "Add Corrective Action" %}</h3>
|
|
</div>
|
|
<form method="post" action="{% url 'rca:rca_action_add' rca.pk %}">
|
|
{% csrf_token %}
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Description" %} <span class="text-red-500">*</span></label>
|
|
<textarea name="description" rows="3" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" required></textarea>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Action Type" %}</label>
|
|
<select name="action_type" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none">
|
|
<option value="corrective">Corrective</option>
|
|
<option value="preventive">Preventive</option>
|
|
<option value="immediate">Immediate Action</option>
|
|
<option value="long_term">Long-term Solution</option>
|
|
</select>
|
|
</div>
|
|
{% if root_causes %}
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Related Root Cause" %}</label>
|
|
<select name="root_cause" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none">
|
|
<option value="">Select...</option>
|
|
{% for rc in root_causes %}
|
|
<option value="{{ rc.pk }}">{{ rc.description|truncatechars:50 }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% endif %}
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Status" %}</label>
|
|
<select name="status" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none">
|
|
<option value="not_started">Not Started</option>
|
|
<option value="in_progress">In Progress</option>
|
|
<option value="completed">Completed</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Target Date" %}</label>
|
|
<input type="date" name="target_date" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 mt-6">
|
|
<button type="button" onclick="closeModal('actionModal')" class="flex-1 px-4 py-2 border border-slate-200 text-slate rounded-xl font-semibold hover:bg-slate-50 transition">{% trans "Cancel" %}</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-navy text-white rounded-xl font-semibold hover:bg-blue transition flex items-center justify-center gap-2">
|
|
<i data-lucide="plus" class="w-4 h-4"></i> {% trans "Add Action" %}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Note Modal -->
|
|
<div id="noteModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center">
|
|
<div class="bg-white rounded-2xl p-6 w-full max-w-lg mx-4 shadow-2xl">
|
|
<div class="flex items-center gap-3 mb-4">
|
|
<div class="w-10 h-10 bg-yellow-100 rounded-full flex items-center justify-center">
|
|
<i data-lucide="sticky-note" class="w-5 h-5 text-yellow-600"></i>
|
|
</div>
|
|
<h3 class="text-xl font-bold text-navy">{% trans "Add Note" %}</h3>
|
|
</div>
|
|
<form method="post" action="{% url 'rca:rca_note_add' rca.pk %}">
|
|
{% csrf_token %}
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-slate mb-2">{% trans "Note" %} <span class="text-red-500">*</span></label>
|
|
<textarea name="note" rows="3" class="w-full border border-slate-200 rounded-xl p-3 text-sm focus:ring-2 focus:ring-navy/20 outline-none" required></textarea>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<input type="checkbox" name="is_internal" id="noteInternal" checked class="w-4 h-4 rounded border-slate-300 text-navy focus:ring-navy">
|
|
<label for="noteInternal" class="text-sm text-slate-700">{% trans "Internal note" %}</label>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-3 mt-6">
|
|
<button type="button" onclick="closeModal('noteModal')" class="flex-1 px-4 py-2 border border-slate-200 text-slate rounded-xl font-semibold hover:bg-slate-50 transition">{% trans "Cancel" %}</button>
|
|
<button type="submit" class="flex-1 px-4 py-2 bg-navy text-white rounded-xl font-semibold hover:bg-blue transition flex items-center justify-center gap-2">
|
|
<i data-lucide="plus" class="w-4 h-4"></i> {% trans "Add Note" %}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<script>
|
|
function openModal(id) {
|
|
document.getElementById(id).classList.remove('hidden');
|
|
}
|
|
|
|
function closeModal(modalId) {
|
|
document.getElementById(modalId).classList.add('hidden');
|
|
}
|
|
|
|
window.onclick = function(event) {
|
|
if (event.target.classList.contains('fixed')) {
|
|
event.target.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') {
|
|
document.querySelectorAll('.fixed.inset-0').forEach(function(modal) {
|
|
if (!modal.classList.contains('hidden')) {
|
|
modal.classList.add('hidden');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|