05/24 Fix UI/UX
This commit is contained in:
@@ -164,6 +164,9 @@
|
||||
var _activeBidId = null;
|
||||
var _activeStatus = '';
|
||||
var _allBids = []; // cached from last load
|
||||
var _bidOffset = 0;
|
||||
var _hasMore = false;
|
||||
var _PAGE_SIZE = 50;
|
||||
var _currentUserId = {{ session['user']['id'] }};
|
||||
var _isAdmin = {{ 'true' if session['user']['role'] == 'admin' else 'false' }};
|
||||
|
||||
@@ -189,12 +192,21 @@ var STATUS_BADGE = {
|
||||
Load / render bid list
|
||||
══════════════════════════════════════════════════════════ */
|
||||
function loadBids() {
|
||||
fetch('/bids/list/json?status=' + encodeURIComponent(_activeStatus))
|
||||
_bidOffset = 0;
|
||||
_allBids = [];
|
||||
_hasMore = false;
|
||||
_fetchBids(false);
|
||||
}
|
||||
|
||||
function _fetchBids(append) {
|
||||
fetch('/bids/list/json?status=' + encodeURIComponent(_activeStatus) + '&offset=' + _bidOffset)
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(bids) {
|
||||
_allBids = bids;
|
||||
renderBidList(bids);
|
||||
// Restore selection
|
||||
if (!Array.isArray(bids)) return;
|
||||
_allBids = append ? _allBids.concat(bids) : bids;
|
||||
_bidOffset += bids.length;
|
||||
_hasMore = bids.length >= _PAGE_SIZE;
|
||||
renderBidList(_allBids);
|
||||
if (_activeBidId) {
|
||||
var row = document.querySelector('.bt-row[data-id="' + _activeBidId + '"]');
|
||||
if (row) row.classList.add('active');
|
||||
@@ -220,21 +232,42 @@ function renderBidList(bids) {
|
||||
return;
|
||||
}
|
||||
|
||||
var today = new Date(); today.setHours(0, 0, 0, 0);
|
||||
|
||||
list.innerHTML = filtered.map(function(b) {
|
||||
var due = b.due_date ? b.due_date.slice(0, 10) : '—';
|
||||
var badge = STATUS_BADGE[b.status] || 'badge-muted';
|
||||
var label = STATUS_LABELS[b.status] || b.status;
|
||||
var active = b.id === _activeBidId ? ' active' : '';
|
||||
var upds = b.update_count || 0;
|
||||
|
||||
var urgencyBadge = '';
|
||||
if (b.due_date) {
|
||||
var dueD = new Date(b.due_date.slice(0, 10)); dueD.setHours(0, 0, 0, 0);
|
||||
var diff = Math.round((dueD - today) / 86400000);
|
||||
if (diff < 0) {
|
||||
urgencyBadge = '<span class="badge badge-danger badge-sm">Overdue</span>';
|
||||
} else if (diff <= 7) {
|
||||
urgencyBadge = '<span class="badge badge-warning badge-sm">Due Soon</span>';
|
||||
}
|
||||
}
|
||||
|
||||
return '<div class="bt-row' + active + '" data-id="' + b.id + '" onclick="selectBid(' + b.id + ')">'
|
||||
+ '<div class="bt-row-title">' + esc(b.title) + '</div>'
|
||||
+ '<div class="bt-row-meta">'
|
||||
+ '<span class="badge ' + badge + ' badge-sm">' + label + '</span>'
|
||||
+ '<span class="text-muted text-xs">Due: ' + due + '</span>'
|
||||
+ urgencyBadge
|
||||
+ (upds ? '<span class="text-muted text-xs">💬 ' + upds + '</span>' : '')
|
||||
+ '</div>'
|
||||
+ '</div>';
|
||||
}).join('');
|
||||
|
||||
if (_hasMore && !q) {
|
||||
list.innerHTML += '<div class="bt-load-more">'
|
||||
+ '<button class="btn btn-secondary btn-sm" onclick="_fetchBids(true)">Load more…</button>'
|
||||
+ '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════════
|
||||
@@ -533,6 +566,9 @@ loadBids();
|
||||
.bt-upd-body{font-size:.875rem;color:var(--text-secondary);line-height:1.6;
|
||||
white-space:pre-wrap}
|
||||
|
||||
/* ── Load more ─────────────────────────────────────────────── */
|
||||
.bt-load-more{padding:.75rem 1rem;text-align:center;border-top:1px solid var(--border)}
|
||||
|
||||
@media(max-width:900px){
|
||||
.bt-layout{grid-template-columns:1fr;grid-template-rows:auto auto}
|
||||
.bt-right{min-height:300px}
|
||||
|
||||
Reference in New Issue
Block a user