140 lines
4.9 KiB
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 }}
|