HEX
Server: Microsoft-IIS/10.0
System: Windows NT ITPWINWEBSVR22 10.0 build 20348 (Windows Server 2022) AMD64
User: www.conferencesearch.co.uk (0)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: D:/web/hyperflight/apps/status/index - Copy (7).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))
  If LCase(Left(s, 5)) <> "sent " Then Exit Function

  c = Trim(Mid(s, 6))
  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 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 (no user input here) ---
sql = sql & "  SELECT " & vbCrLf
sql = sql & "    Status 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

' --- Sent by courier (range): Orders DESC, then Courier ASC ---
sql = sql & "  SELECT " & vbCrLf
sql = sql & "    CONCAT('Sent ', 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 */
    }

    .total-row .progress-bar{
      width: 100% !important;         /* always full-width for totals */
    }
        
    
  </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>
              </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-2">Last Updated:</span>
            <strong><%= FormatUkDateTime(lastUpdated) %></strong>
            <span class="ms-2">(<%= Session("RefreshCount") %>)</span>
            <span class="ms-2">Auto 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
                Do While Not rs.EOF
                  statusText  = rs("StatusText")
                  ordersCount = rs("Orders")

                  If IsNull(statusText) And IsNull(ordersCount) Then
              %>
                    <tr class="spacer-row"><td colspan="2">&nbsp;</td></tr>
              <%
                  Else
                    rowClass = ""
                    pct = BarPct(ordersCount, maxOrders)
                    logoHtml = CourierLogoHtml(statusText)

                    If Not IsNull(statusText) Then
                      If CStr(statusText) = "Total Sent" Then
                        rowClass = "total-row"
                        pct = 100 ' make the total bar read as a "summary"
                      End If
                    End If
              %>
                    <tr class="<%= rowClass %>">
                      <td class="status-big">
                        <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

                  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
%>