{% extends "base.html" %} {% block content %}

Dashboard

Overview of today's activity, current sessions, and system health.

Sales Today
₱{{ data.sales_today_pesos }}
{{ data.sales_today_count }} voucher{{ '' if data.sales_today_count == 1 else 's' }}
Lifetime
₱{{ data.sales_lifetime_pesos }}
{{ data.sales_lifetime_count }} voucher{{ '' if data.sales_lifetime_count == 1 else 's' }} total
Active
{{ data.active_sessions }}
{{ data.paused_sessions }} paused
Uptime
{{ data.system.uptime }}
since last boot

Sales figures show this server vendo only — each ESP sub-vendo reports its own sales directly to vendorawifi.com.

Network

Connected customers and your sub-vendo fleet.

{% if data.wan_collision and data.wan_collision.collision %}
Your internet (WAN) is on the same IP range as your customer network ({{ data.wan_collision.wan_subnet }}) — nobody can reach the internet. Change LAN subnet →
{% endif %}
Connected customers
currently authorized on the AP
Sub-vendos
{{ data.sub_vendo_count }}
{% if data.sub_vendo_count %}ESP VLANs · view fleet{% else %}none configured{% endif %}

WAN Throughput

Live upstream usage. Updates every 3 seconds.

Download
— Mbps
of — Mbps WAN cap
Upload
— Mbps
of — Mbps WAN cap
{# Traffic history — rolling WAN usage from the tiered ring buffers in common/traffic_history.py. The range picker selects a resolution tier, so a 7-day view is 168 points, not thousands: the chart stays light on the SBC and light in the browser. #}

Traffic History

Upstream usage over time. Kept for 7 days.

Megabits per second
Download Upload
{# System Health — ring gauges (CPU / Memory / Disk) + a live per-core CPU equalizer. A single pegged core, which the CPU average hides, stands out in red on the equalizer. All three rings + the equalizer animate on the 5s /api/network-status poll. Styles scoped to this section. #}

System Health

CPU{% if data.system.cpu_cores %} · {{ data.system.cpu_cores | length }} cores{% endif %}
{{ data.system.cpu_used_pct }}% {% if data.system.cpu_temp_c is not none %}{{ data.system.cpu_temp_c }}°C{% else %}usage{% endif %}
{% for c in data.system.cpu_cores %}
= 90 %} style="color:var(--danger);font-weight:700;"{% endif %}>{{ c }}%
C{{ loop.index0 }}
{% endfor %}
Memory
{{ data.system.mem_used_pct }}%
{{ data.system.mem_available }} free of {{ data.system.mem_total }}
Disk
{{ data.system.disk_used_pct }}%
{{ data.system.disk_free }} free of {{ data.system.disk_total }}

Server Clock

{{ data.clock.tz }}
{% if data.clock.ntp_synced %} ✓ NTP synced{% if data.clock.last_sync_age_s is not none %} · {{ (data.clock.last_sync_age_s // 60) | duration if data.clock.last_sync_age_s >= 60 else (data.clock.last_sync_age_s ~ 's') }} ago{% endif %} {% else %} ⚠ NTP NOT synced — clock may be off {% endif %}
{# Business review. Every figure here is aggregated on demand from the vouchers table — no sampler, no stored series, so it costs the SD card nothing. #}

Business Review

Sales report →
Earned
sales · avg
Customers
came back
Best hour
Time used
of minutes sold
Earnings
per day
now
Earning hours
When customers actually buy
12amnoon11pm
What they buy
Session quality
Minutes sold
Minutes actually used
Repeat customers
Average sale

Recent Vouchers

View all →
{% if data.recent %}
{% for v in data.recent %} {% endfor %}
Code Status Time Paid MAC Created
{{ v.code }} {{ v.status }} {{ v.minutes_total | duration }} ₱{{ v.paid_pesos }} {% if v.mac %}{{ v.mac }}{% else %}{% endif %} {{ v.created }}
{% else %}
No vouchers yet.
Drop a coin into the slot to generate the first one.
{% endif %}
{% endblock %}