InvoiceParser/wwwroot/changes.html

159 lines
5.3 KiB
HTML
Raw Normal View History

2026-09-30 18:50:04 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Product Changes</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/jquery-3.5.1.min.js"></script>
<style>
#changesPanel { flex: 1; overflow: auto; }
#changesPanel th { position: sticky; top: 0; z-index: 1; }
#changesPanel td.num, #changesPanel th.num { text-align: right; }
.chg-new { color: #88ff88; font-weight: bold; }
.chg-cost { color: #ffcc44; font-weight: bold; }
</style>
</head>
<body class="archive-page">
<h1>
Product Changes
<a href="index.html">Home / Upload</a>
<a href="pending.html">Pending</a>
<a href="archive.html">Archive</a>
<a href="changes.html" class="active">Changes</a>
</h1>
<div id="filterPanel">
<form id="filterForm" onsubmit="return false">
<div class="filter-field">
<label>From</label>
<input type="date" id="fDateFrom">
</div>
<div class="filter-field">
<label>To</label>
<input type="date" id="fDateTo">
</div>
<div class="filter-field">
<label>Type</label>
<select id="fType">
<option value="">All</option>
<option value="NEW">New products</option>
<option value="COST">Cost changes</option>
</select>
</div>
<div class="filter-actions">
<button class="filter-btn primary" id="btnFilter" type="submit">Show</button>
<button class="filter-btn" id="btnReset" type="button">Last 7 days</button>
<span id="resultCount" class="result-count"></span>
</div>
</form>
</div>
<div id="changesPanel">
<table class="list">
<thead>
<tr>
<th>Date</th>
<th>Type</th>
<th>UPC</th>
<th>Description</th>
<th>Vendor</th>
<th>Invoice #</th>
<th>PO #</th>
<th>Batch #</th>
<th class="num">Old Cost</th>
<th class="num">New Cost</th>
<th class="num">Retail</th>
<th class="num">Pack</th>
</tr>
</thead>
<tbody id="changesBody"></tbody>
</table>
</div>
<script>
var CHANGES_LIMIT = 2000 // TOP 2000 in DataService.ProductChanges
$(document).ready(function () {
setLastWeek()
loadChanges()
$('#btnFilter').on('click', loadChanges)
$('#fType').on('change', loadChanges)
$('#btnReset').on('click', function () { setLastWeek(); loadChanges() })
})
function isoDate(d) {
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0')
}
function setLastWeek() {
var to = new Date(), from = new Date()
from.setDate(to.getDate() - 6)
$('#fDateFrom').val(isoDate(from))
$('#fDateTo').val(isoDate(to))
}
async function loadChanges() {
var params = new URLSearchParams({
date_from: $('#fDateFrom').val() || '',
date_to: $('#fDateTo').val() || '',
type: $('#fType').val() || ''
})
$('#resultCount').text('Loading...')
try {
var list = await (await fetch('/api/changes?' + params)).json()
if (list.error) throw new Error(list.error)
$('#dbWarning').hide()
render(list)
} catch (e) {
$('#resultCount').text('')
$('#changesBody').empty()
showDbError('Could not load changes: ' + e.message)
}
}
function render(list) {
var body = $('#changesBody').empty()
var nNew = 0, nCost = 0
list.forEach(function (r) {
if (r.type === 'NEW') nNew++; else if (r.type === 'COST') nCost++
body.append('<tr>' +
'<td>' + esc(r.date) + '</td>' +
'<td class="' + (r.type === 'NEW' ? 'chg-new' : 'chg-cost') + '">' + (r.type === 'NEW' ? 'New' : r.type === 'COST' ? 'Cost' : esc(r.type)) + '</td>' +
'<td>' + esc(r.upc) + '</td>' +
'<td>' + esc(r.description) + '</td>' +
'<td>' + esc(r.vendor_name || r.vendor) + '</td>' +
'<td>' + esc(r.invoice_number) + '</td>' +
'<td>' + esc(r.po_number) + '</td>' +
'<td>' + esc(r.batch_no) + '</td>' +
'<td class="num">' + money(r.old_cost) + '</td>' +
'<td class="num">' + money(r.new_cost) + '</td>' +
'<td class="num">' + money(r.retail) + '</td>' +
'<td class="num">' + (r.pack != null ? r.pack : '') + '</td>' +
'</tr>')
})
if (!list.length)
body.append('<tr><td colspan="12" style="color:#777;text-align:center;padding:12px">No changes in this range.</td></tr>')
$('#resultCount').text(list.length >= CHANGES_LIMIT
? 'Showing the newest ' + CHANGES_LIMIT + ' - narrow the dates to see the rest'
: list.length + ' change' + (list.length === 1 ? '' : 's') + ' - ' + nNew + ' new, ' + nCost + ' cost')
}
function money(v) {
return v != null && v !== '' ? '$' + parseFloat(v).toFixed(3).replace(/0$/, '') : ''
}
function showDbError(msg) {
var el = $('#dbWarning')
if (!el.length) el = $('<div id="dbWarning" class="db-warning"></div>').insertAfter('h1')
el.text(msg).show()
}
function esc(s) {
return String(s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
}
</script>
</body>
</html>