File: D:/web/hyperflight/apps/status/index - Copy (10).asp
<%@ Language=VBScript %>
<% Option Explicit %>
<%
Response.Buffer = True
'==========================================================
' SETTINGS
'==========================================================
Dim refreshSeconds
refreshSeconds = 60 ' 1 minute
' Session-based refresh count
If IsEmpty(Session("RefreshCount")) Or IsNull(Session("RefreshCount")) Then
Session("RefreshCount") = 0
End If
Session("RefreshCount") = CLng(Session("RefreshCount")) + 1
'==========================================================
' HELPERS (VBScript)
'==========================================================
Function IIf(ByVal expr, ByVal truePart, ByVal falsePart)
If expr Then IIf = truePart Else IIf = falsePart
End Function
Function HtmlEncode(ByVal s)
If IsNull(s) Then HtmlEncode = "" Else HtmlEncode = Server.HTMLEncode(CStr(s))
End Function
Function FormatUkDateTime(ByVal dt)
Dim d, m, y, hh, nn, ss
d = Right("0" & Day(dt), 2)
m = Right("0" & Month(dt), 2)
y = Year(dt)
hh = Right("0" & Hour(dt), 2)
nn = Right("0" & Minute(dt), 2)
ss = Right("0" & Second(dt), 2)
FormatUkDateTime = d & "/" & m & "/" & y & " " & hh & ":" & nn & ":" & ss
End Function
Function BarPct(ByVal v, ByVal maxV)
If IsNull(v) Or IsNull(maxV) Then
BarPct = 0
ElseIf CDbl(maxV) <= 0 Then
BarPct = 0
Else
BarPct = (CDbl(v) / CDbl(maxV)) * 100
If BarPct < 0 Then BarPct = 0
If BarPct > 100 Then BarPct = 100
End If
End Function
Function JsNum(ByVal v)
JsNum = Replace(CStr(v), ",", ".")
End Function
'==========================================================
' LOGOS (relative paths because app is under /apps/status)
'==========================================================
Function CourierLogoHtml(ByVal statusText)
Dim s, c, src, alt
CourierLogoHtml = ""
If IsNull(statusText) Then Exit Function
s = Trim(CStr(statusText))
' Ignore non-courier rows
If s = "" Then Exit Function
If s = "Total Sent" Then Exit Function
If s = "__HEADING_SENT__" Then Exit Function
c = s
alt = c
src = ""
Select Case LCase(c)
Case "royal mail", "royalmail", "rm"
src = "assets/couriers/royalmail.svg"
Case "fedex", "fed ex"
src = "assets/couriers/fedex.svg"
Case "dhl ecommerce", "dhl e-commerce", "dhl ecommerce"
src = "assets/couriers/dhl-ecommerce.svg"
Case "dhl express"
src = "assets/couriers/dhl-express.svg"
Case "dhl"
src = "assets/couriers/dhl.svg"
Case "ups"
src = "assets/couriers/ups.svg"
Case "tnt"
src = "assets/couriers/tnt.svg"
Case "other"
src = "assets/couriers/delivery-logo.svg"
Case Else
src = ""
End Select
If Len(src) > 0 Then
CourierLogoHtml = "<img src=""" & src & """ alt=""" & Server.HTMLEncode(alt) & _
""" class=""courier-logo"" loading=""lazy"">"
End If
End Function
'==========================================================
' DATE RANGE (for "Sent" sections only) - WHITELISTED
'==========================================================
Dim rangeKey, rangeDays, rangeLabel
rangeKey = LCase(Trim(Request.QueryString("range")))
Select Case rangeKey
Case "today"
rangeDays = 0 : rangeLabel = "Today"
Case "yesterday"
rangeDays = 1 : rangeLabel = "Yesterday"
Case "2days", "past2days", "2"
rangeDays = 2 : rangeLabel = "Past 2 days"
Case "week", "pastweek", "7"
rangeDays = 7 : rangeLabel = "Past week"
Case "30days", "past30days", "30"
rangeDays = 30 : rangeLabel = "Past 30 days"
Case "60days", "past60days", "60"
rangeDays = 60 : rangeLabel = "Past 60 days"
Case "90days", "past90days", "90"
rangeDays = 90 : rangeLabel = "Past 90 days"
Case "120days", "past120days", "120"
rangeDays = 120 : rangeLabel = "Past 120 days"
Case "180days", "past180days", "180"
rangeDays = 180 : rangeLabel = "Past 180 days"
Case "year", "pastyear", "365"
rangeDays = 365 : rangeLabel = "Past year"
Case Else
rangeKey = "today"
rangeDays = 0
rangeLabel = "Today"
End Select
' Match your earlier logic:
' start >= CURDATE()-INTERVAL n DAY and end < CURDATE()+INTERVAL 1 DAY
Dim startDate, endDate
startDate = DateAdd("d", -CLng(rangeDays), Date()) ' midnight today minus n days
endDate = DateAdd("d", 1, Date()) ' midnight tomorrow
'==========================================================
' CONNECTION (DSN)
'==========================================================
Dim cn
Set cn = Server.CreateObject("ADODB.Connection")
cn.Open "DSN=MySQL_hyperflight;"
'==========================================================
' SQL (PARAMETERISED for Sent sections)
'==========================================================
Dim sql
sql = ""
sql = sql & "SELECT StatusText, Orders, SortOrder " & vbCrLf
sql = sql & "FROM ( " & vbCrLf
' --- Payment statuses: fixed display order + mixed case display ---
sql = sql & " SELECT " & vbCrLf
sql = sql & " CASE Status " & vbCrLf
sql = sql & " WHEN 'PAYMENT RECEIVED' THEN 'Payment Received' " & vbCrLf
sql = sql & " WHEN 'PAYMENT ON ACCOUNT' THEN 'On Hold' " & vbCrLf
sql = sql & " WHEN 'AWAITING PAYMENT' THEN 'Payment Due' " & vbCrLf
sql = sql & " ELSE Status " & vbCrLf
sql = sql & " END AS StatusText, " & vbCrLf
sql = sql & " COUNT(*) AS Orders, " & vbCrLf
sql = sql & " CASE Status " & vbCrLf
sql = sql & " WHEN 'PAYMENT RECEIVED' THEN 10 " & vbCrLf
sql = sql & " WHEN 'PAYMENT ON ACCOUNT' THEN 20 " & vbCrLf
sql = sql & " WHEN 'AWAITING PAYMENT' THEN 30 " & vbCrLf
sql = sql & " ELSE 99 " & vbCrLf
sql = sql & " END AS SortOrder " & vbCrLf
sql = sql & " FROM orders " & vbCrLf
sql = sql & " WHERE Status IN ('PAYMENT RECEIVED','PAYMENT ON ACCOUNT','AWAITING PAYMENT') " & vbCrLf
sql = sql & " GROUP BY Status " & vbCrLf
sql = sql & " UNION ALL " & vbCrLf
' --- Spacer row ---
sql = sql & " SELECT NULL AS StatusText, NULL AS Orders, 1000 AS SortOrder " & vbCrLf
sql = sql & " UNION ALL " & vbCrLf
' --- Section heading row (marker) ---
sql = sql & " SELECT '__HEADING_SENT__' AS StatusText, NULL AS Orders, 1050 AS SortOrder " & vbCrLf
sql = sql & " UNION ALL " & vbCrLf
' --- Shipped by courier (range): NOTE no 'Sent ' prefix now ---
sql = sql & " SELECT " & vbCrLf
sql = sql & " Courier AS StatusText, " & vbCrLf
sql = sql & " Orders, " & vbCrLf
sql = sql & " 1100 + rn AS SortOrder " & vbCrLf
sql = sql & " FROM ( " & vbCrLf
sql = sql & " SELECT " & vbCrLf
sql = sql & " Courier, " & vbCrLf
sql = sql & " COUNT(*) AS Orders, " & vbCrLf
sql = sql & " ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC, Courier ASC) AS rn " & vbCrLf
sql = sql & " FROM orders " & vbCrLf
sql = sql & " WHERE Status='COMPLETED' AND DateTimeCompleted >= ? AND DateTimeCompleted < ? " & vbCrLf
sql = sql & " GROUP BY Courier " & vbCrLf
sql = sql & " ) s " & vbCrLf
sql = sql & " UNION ALL " & vbCrLf
' --- Total sent (range): parameterised start/end again ---
sql = sql & " SELECT 'Total Sent' AS StatusText, COUNT(*) AS Orders, 1999 AS SortOrder " & vbCrLf
sql = sql & " FROM orders " & vbCrLf
sql = sql & " WHERE Status='COMPLETED' AND DateTimeCompleted >= ? AND DateTimeCompleted < ? " & vbCrLf
sql = sql & ") x " & vbCrLf
sql = sql & "ORDER BY SortOrder; "
'==========================================================
' RUN (ADO Command + parameters) => SQL injection safe
'==========================================================
Dim cmd, rs
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cn
cmd.CommandType = 1 ' adCmdText
cmd.CommandText = sql
cmd.Prepared = True
' Parameters (4): start/end for courier section, start/end for total section
' adDBTimeStamp = 135 (safe for DATETIME)
cmd.Parameters.Append cmd.CreateParameter("pStart1", 135, 1, , CDate(startDate))
cmd.Parameters.Append cmd.CreateParameter("pEnd1", 135, 1, , CDate(endDate))
cmd.Parameters.Append cmd.CreateParameter("pStart2", 135, 1, , CDate(startDate))
cmd.Parameters.Append cmd.CreateParameter("pEnd2", 135, 1, , CDate(endDate))
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient
rs.Open cmd, , 3, 1 ' adOpenStatic, adLockReadOnly
Dim lastUpdated : lastUpdated = Now()
'==========================================================
' CALC MAX (for bar widths)
'==========================================================
Dim maxOrders : maxOrders = 0
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do While Not rs.EOF
If Not IsNull(rs("Orders")) Then
If CLng(rs("Orders")) > CLng(maxOrders) Then maxOrders = CLng(rs("Orders"))
End If
rs.MoveNext
Loop
rs.MoveFirst
End If
Dim selfUrl
selfUrl = Request.ServerVariables("SCRIPT_NAME")
%>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Fallback refresh if JS disabled -->
<meta http-equiv="refresh" content="<%= refreshSeconds %>">
<title>Order Status</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.status-table td, .status-table th { vertical-align: middle; }
.status-big { font-weight: 800; font-size: clamp(1.05rem, 2.2vw, 1.45rem); }
.count-big { font-weight: 800; font-size: clamp(1.05rem, 2.2vw, 1.45rem); text-align: right; }
.spacer-row td { padding: 0.6rem; background: #fff; }
.total-row td { font-weight: 800; }
/* Bigger logos */
.courier-logo {
width: 44px;
height: 44px;
object-fit: contain;
vertical-align: middle;
}
/* Status cell: text left, logo right (only appears for Sent rows) */
.status-flex {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.status-text { flex: 1 1 auto; }
.status-logo { flex: 0 0 auto; text-align: right; }
.orders-cell { min-width: 220px; }
.orders-top { display: flex; align-items: center; justify-content: flex-end; gap: .5rem; }
.progress { height: 8px; }
.toolbar { display:flex; flex-direction:column; gap:.5rem; }
@media (min-width: 576px) { .toolbar { flex-direction:row; align-items:center; justify-content:space-between; } }
/* Make Total Sent stand out */
.total-row td{
background: #f1f7ff; /* subtle highlight */
border-top: 2px solid #b6d4fe; /* separator line */
font-weight: 800;
}
.total-row .progress{
height: 10px; /* slightly taller bar */
}
.section-row td{
background: #f8f9fa;
font-weight: 800;
letter-spacing: .5px;
}
@media (max-width: 576px){
.status-tight-mobile{
font-size: 1em; /* tweak as needed */
white-space: nowrap; /* keep on one line */
}
}
/* Tighter right padding on the left/status column (all sizes) */
td.status-cell{
padding-right: .1rem !important; /* was ~.75rem in Bootstrap tables */
}
/* Optional: slightly tighten the Orders column too */
td.orders-cell{
padding-right: .45rem !important;
}
/* Optional: reduce the gap between status text and logo */
.status-flex{
gap: 8px;
}
</style>
</head>
<body class="bg-light">
<div class="container py-3" style="max-width:900px;">
<div class="card shadow-sm">
<div class="card-body">
<div class="toolbar mb-3">
<div class="d-flex align-items-center gap-2 flex-wrap">
<form method="get" action="<%= HtmlEncode(selfUrl) %>" class="m-0">
<input type="hidden" name="range" value="<%= HtmlEncode(rangeKey) %>">
<button type="submit" class="btn btn-outline-secondary btn-sm">Refresh</button>
</form>
<form method="get" action="<%= HtmlEncode(selfUrl) %>" class="m-0">
<select name="range" class="form-select form-select-sm" onchange="this.form.submit()">
<option value="today" <%= IIf(rangeKey="today","selected","") %>>Today</option>
<option value="yesterday" <%= IIf(rangeKey="yesterday","selected","") %>>Yesterday</option>
<option value="2days" <%= IIf(rangeKey="2days" Or rangeKey="past2days" Or rangeKey="2","selected","") %>>Past 2 days</option>
<option value="week" <%= IIf(rangeKey="week" Or rangeKey="pastweek" Or rangeKey="7","selected","") %>>Past week</option>
<option value="30days" <%= IIf(rangeKey="30days" Or rangeKey="past30days" Or rangeKey="30","selected","") %>>Past 30 days</option>
<option value="60days" <%= IIf(rangeKey="60days" Or rangeKey="past60days" Or rangeKey="60","selected","") %>>Past 60 days</option>
<option value="90days" <%= IIf(rangeKey="90days" Or rangeKey="past90days" Or rangeKey="90","selected","") %>>Past 90 days</option>
<option value="120days" <%= IIf(rangeKey="120days" Or rangeKey="past120days" Or rangeKey="120","selected","") %>>Past 120 days</option>
<option value="180days" <%= IIf(rangeKey="180days" Or rangeKey="past180days" Or rangeKey="180","selected","") %>>Past 180 days</option>
<option value="year" <%= IIf(rangeKey="year" Or rangeKey="pastyear" Or rangeKey="365","selected","") %>>Past year</option>
</select>
</form>
<!--<span class="text-muted small">Sent range: <strong><%= HtmlEncode(rangeLabel) %></strong></span>-->
</div>
<div class="text-muted small text-sm-end">
<span class="me-0">Updated:</span>
<strong><%= FormatUkDateTime(lastUpdated) %></strong>
<span class="ms-1">(<%= Session("RefreshCount") %>)</span>
<span class="ms-2">Refresh in: <strong id="countdown"><%= refreshSeconds %></strong>s</span>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-sm status-table mb-0 bg-white">
<thead class="table-light">
<tr>
<th style="width:70%;">Status</th>
<th style="width:30%;" class="text-end">Orders</th>
</tr>
</thead>
<tbody>
<%
If rs.EOF Then
%>
<tr><td colspan="2" class="text-center text-muted py-4">No data returned.</td></tr>
<%
Else
Dim statusText, ordersCount, rowClass, pct, logoHtml
Dim skipRow
Dim statusClass
Do While Not rs.EOF
statusText = rs("StatusText")
ordersCount = rs("Orders")
skipRow = False
statusClass = "status-big"
If Not IsNull(statusText) Then
If statusText = "Payment Received" Then
statusClass = statusClass & " status-tight-mobile"
End If
End If
If IsNull(statusText) And IsNull(ordersCount) Then
%>
<tr class="spacer-row"><td colspan="2"> </td></tr>
<%
Else
rowClass = ""
If Not IsNull(statusText) Then
If CStr(statusText) = "__HEADING_SENT__" Then
%>
<tr class="section-row">
<td colspan="2">
<div class="d-flex align-items-center justify-content-between">
<span>Sent</span>
<span class="badge text-bg-light border text-secondary"><%= HtmlEncode(rangeLabel) %></span>
</div>
</td>
</tr>
<%
skipRow = True
End If
End If
If Not skipRow Then
pct = BarPct(ordersCount, maxOrders)
logoHtml = CourierLogoHtml(statusText)
If Not IsNull(statusText) Then
If statusText = "Total Sent" Then
rowClass = "total-row"
If IsNull(ordersCount) Or CLng(ordersCount) = 0 Then
pct = 0
Else
pct = 100
End If
End If
End If
%>
<tr class="<%= rowClass %>">
<td class="<%= statusClass %> status-cell">
<div class="status-flex">
<div class="status-text"><%= HtmlEncode(statusText) %></div>
<div class="status-logo"><%= logoHtml %></div>
</div>
</td>
<td class="orders-cell">
<div class="orders-top">
<div class="count-big"><%= ordersCount %></div>
</div>
<div class="progress mt-1" role="progressbar" aria-label="Orders bar">
<div class="progress-bar" style="width:<%= JsNum(pct) %>%"></div>
</div>
</td>
</tr>
<%
End If
End If
rs.MoveNext
Loop
End If
%>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
(function () {
var secs = <%= refreshSeconds %>;
var el = document.getElementById('countdown');
if (!el) return;
function tick() {
secs -= 1;
if (secs <= 0) {
el.textContent = '0';
// preserve selected range
var url = new URL(window.location.href);
if (!url.searchParams.get('range')) {
url.searchParams.set('range', '<%= HtmlEncode(rangeKey) %>');
}
window.location.href = url.toString();
return;
}
el.textContent = String(secs);
}
el.textContent = String(secs);
window.setInterval(tick, 1000);
})();
</script>
</body>
</html>
<%
'==========================================================
' CLEANUP
'==========================================================
On Error Resume Next
If Not rs Is Nothing Then
If rs.State <> 0 Then rs.Close
End If
Set rs = Nothing
Set cmd = Nothing
If Not cn Is Nothing Then
If cn.State <> 0 Then cn.Close
End If
Set cn = Nothing
On Error GoTo 0
%>