Files
website/web/templates/account/messages/index.html

140 lines
4.9 KiB
HTML

{{ define "content" }}
<div class="container py-5">
<h2>Your Inbox</h2>
{{ if .Messages }}
<ul class="list-group mb-4">
{{ range .Messages }}
<li class="list-group-item d-flex justify-content-between align-items-center {{ if .IsRead }}read{{ end }}" data-msg-id="{{ .ID }}">
<div>
<a href="/account/messages/read?id={{ .ID }}" class="fw-bold text-dark">{{ .Subject }}</a><br>
<small class="text-muted">{{ .CreatedAt.Format "02 Jan 2006 15:04" }}</small>
</div>
<div class="d-flex gap-2 align-items-center">
{{/* Archive form (existing) */}}
<form method="POST" action="/account/messages/archive" class="m-0">
<input type="hidden" name="csrf_token" value="{{ $.CSRFToken }}">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" class="btn btn-sm btn-outline-secondary">Archive</button>
</form>
{{/* Mark-read: only show when unread */}}
{{ if not .IsRead }}
<!-- Non-AJAX fallback form (submit will refresh) -->
<form method="POST" action="/account/messages/mark-read" class="m-0 d-inline-block mark-read-form">
<input type="hidden" name="csrf_token" value="{{ $.CSRFToken }}">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" class="btn btn-sm btn-outline-primary mark-read-btn"
data-msg-id="{{ .ID }}"
data-csrf="{{ $.CSRFToken }}">Mark read</button>
</form>
{{ end }}
</div>
</li>
{{ end }}
</ul>
<nav>
<ul class="pagination">
{{ if gt .CurrentPage 1 }}
<li class="page-item">
<a class="page-link" href="?page={{ sub .CurrentPage 1 }}">Previous</a>
</li>
{{ end }}
{{ range $i := .PageRange }}
<li class="page-item {{ if eq $i $.CurrentPage }}active{{ end }}">
<a class="page-link" href="?page={{ $i }}">{{ $i }}</a>
</li>
{{ end }}
{{ if lt .CurrentPage .TotalPages }}
<li class="page-item">
<a class="page-link" href="?page={{ add .CurrentPage 1 }}">Next</a>
</li>
{{ end }}
</ul>
</nav>
{{ else }}
<div class="alert alert-info text-center">No messages found.</div>
{{ end }}
<div class="mt-3">
<a href="/account/messages/send" class="btn btn-primary">Compose Message</a>
<a href="/account/messages/archive" class="btn btn-outline-secondary ms-2">View Archived</a>
</div>
</div>
{{/* AJAX enhancement: unobtrusive — safe fallback to regular form when JS disabled */}}
<script>
;(function(){
// Ensure browser supports fetch + FormData; otherwise we fallback to regular form submit.
if (!window.fetch || !window.FormData) return;
// Helper to decrement topbar message count badge (assumes badge element id="message-count")
function decrementMessageCount() {
var el = document.getElementById('message-count');
if (!el) return;
var current = parseInt(el.textContent || el.innerText || '0', 10) || 0;
var next = Math.max(0, current - 1);
if (next <= 0) {
// remove badge or hide it
el.remove();
} else {
el.textContent = String(next);
}
}
// Handle clicks on mark-read buttons, submit via fetch, update DOM
document.addEventListener('click', function(e){
var btn = e.target.closest('.mark-read-btn');
if (!btn) return;
// Prevent the default form POST (non-AJAX fallback)
e.preventDefault();
var msgID = btn.dataset.msgId;
var csrf = btn.dataset.csrf;
if (!msgID) {
// fallback to normal submit if something's wrong
var frm = btn.closest('form');
if (frm) frm.submit();
return;
}
// Build urlencoded body like a regular form
var body = new URLSearchParams();
body.append('id', msgID);
if (csrf) body.append('csrf_token', csrf);
fetch('/account/messages/mark-read', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body.toString(),
credentials: 'same-origin'
}).then(function(resp){
if (resp.ok) {
// UI update: remove the mark-read button, give item a .read class, update topbar count
var li = document.querySelector('li[data-msg-id="' + msgID + '"]');
if (li) {
li.classList.add('read');
// remove any mark-read form/button inside
var form = li.querySelector('.mark-read-form');
if (form) form.remove();
}
decrementMessageCount();
} else {
// If server returned non-2xx, fall back to full reload to show flash
resp.text().then(function(){ window.location.reload(); }).catch(function(){ window.location.reload(); });
}
}).catch(function(){ window.location.reload(); });
}, false);
})();
</script>
{{ end }}