2026-02-01 13:38:06 +03:00

205 lines
8.2 KiB
HTML

{% load i18n crispy_forms_tags %}
<div class="p-4">
<form hx-boost="true" id="noteform" action="{{ url }}" method="post" hx-select=".note-table-body" hx-target=".note-table-body" hx-swap="outerHTML" hx-push-url="false">
{% csrf_token %}
<!-- Crispy Form for rendering -->
<div class="space-y-4">
<div>
{{ form|crispy }}
</div>
<!-- Form Actions -->
<div class="flex justify-end gap-2 pt-4 border-t-2 border-gray-200">
<button type="submit" class="px-4 py-2 bg-temple-red text-white rounded-lg hover:bg-temple-red/90 transition text-sm font-medium" id="saveNoteBtn">
<i data-lucide="save" class="w-4 h-4 inline mr-1"></i>
{% trans "Save Note" %}
</button>
</div>
</div>
</form>
</div>
<!-- Notes Table Section -->
<div class="mt-6">
<!-- Table Header -->
<div class="bg-gray-50 border border-gray-200 rounded-xl overflow-hidden">
<table class="w-full border-collapse" id="notesTable">
<thead>
<tr class="border-b-2 border-temple-red">
<th class="px-4 py-3 text-left text-xs font-semibold text-temple-dark">
<i data-lucide="user" class="w-3 h-3 inline mr-1"></i>
{% trans "Author" %}
</th>
<th class="px-4 py-3 text-left text-xs font-semibold text-temple-dark" style="width: 60%;">
<i data-lucide="sticky-note" class="w-3 h-3 inline mr-1"></i>
{% trans "Note" %}
</th>
<th class="px-4 py-3 text-left text-xs font-semibold text-temple-dark">
<i data-lucide="calendar" class="w-3 h-3 inline mr-1"></i>
{% trans "Created" %}
</th>
<th class="px-4 py-3 text-right text-xs font-semibold text-temple-dark">
<i data-lucide="trash-2" class="w-3 h-3 inline mr-1"></i>
{% trans "Actions" %}
</th>
</tr>
</thead>
<tbody class="note-table-body">
{% if notes %}
{% for note in notes %}
<tr id="note-{{ note.id }}" class="hover:bg-gray-50 transition-colors border-b border-gray-200">
<td class="px-4 py-3">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-full bg-temple-red text-white flex items-center justify-center text-sm font-bold">
{{ note.author.first_name.0|default:note.author.username.0|upper }}
</div>
<div>
<div class="font-medium text-temple-dark text-sm">
{{ note.author.get_full_name|default:note.author.username }}
</div>
</div>
</div>
</td>
<td class="px-4 py-3">
<div class="text-sm text-gray-700 bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
{{ note.content|linebreaksbr }}
</div>
</td>
<td class="px-4 py-3 whitespace-nowrap">
<div class="text-xs text-gray-500">
<i data-lucide="clock" class="w-3 h-3 inline mr-1"></i>
{{ note.created_at|date:"SHORT_DATETIME_FORMAT" }}
</div>
</td>
<td class="px-4 py-3 text-right">
<button hx-delete="{% url 'delete_note' note.slug %}"
hx-target="#note-{{ note.id }}"
hx-swap="delete"
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-confirm="{% trans 'Are you sure you want to delete this note?' %}"
type="button"
class="px-3 py-1.5 border-2 border-red-500 text-red-500 rounded-lg hover:bg-red-500 hover:text-white transition text-xs font-medium delete-note-btn inline-flex items-center gap-1"
title="{% trans 'Delete Note' %}">
<i data-lucide="trash-2" class="w-3 h-3"></i>
{% trans "Delete" %}
</button>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4" class="text-center py-8 text-gray-500">
<div class="flex flex-col items-center gap-2">
<i data-lucide="sticky-note" class="w-12 h-12 text-gray-400"></i>
<span class="text-sm">{% trans "No notes yet." %}</span>
</div>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
<!-- Add custom styling for crispy form -->
<style>
#noteform textarea {
width: 100%;
padding:1rem 1.25rem;
background-color: white;
border: 2px solid #e5e7eb;
border-radius: 1rem;
font-size: 0.875rem;
color: #374151;
transition: all 0.3s;
resize: none;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
#noteform textarea:focus {
border-color: #dc2626;
outline: none;
box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.1);
background-color: #fef2f2;
}
#noteform textarea::placeholder {
color: #9ca3af;
}
#noteform textarea:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
border-color: #d1d5db;
}
#noteform label {
display: block;
font-size: 0.875rem;
font-weight: 600;
color: #1f2937;
margin-bottom: 0.5rem;
}
#noteform .help-block,
#noteform .helptext {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.5rem;
}
#noteform .text-danger,
#noteform .errorlist {
font-size: 0.75rem;
color: #dc2626;
background-color: #fef2f2;
border: 2px solid #fca5a5;
border-radius: 0.75rem;
padding: 0.75rem;
margin-top: 0.75rem;
}
</style>
<script>
// Reinitialize Lucide icons after HTMX updates
document.addEventListener('htmx:afterSwap', function(evt) {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
// Function to close the modal
function closeModal() {
const modal = document.getElementById('noteModal');
if (modal) {
const modalInstance = bootstrap.Modal.getInstance(modal);
if (modalInstance) {
modalInstance.hide();
} else {
new bootstrap.Modal(modal).hide();
}
}
}
// Cancel button click handler - attached to document to catch dynamically added buttons
document.body.addEventListener('click', function(e) {
const cancelBtn = e.target.closest('#cancelNoteBtn')
if (cancelBtn) {
e.preventDefault();
closeModal();
}
});
// Re-attach cancel button listener after HTMX updates (for the form submit cancel)
document.addEventListener('htmx:afterSwap', function(evt) {
const cancelBtn = document.getElementById('cancelNoteBtn');
if (cancelBtn) {
cancelBtn.addEventListener('click', function(e) {
e.preventDefault();
closeModal();
});
}
});
</script>