diff --git a/usage-dashboard/README.md b/usage-dashboard/README.md
index 2ed7110..b23cf32 100644
--- a/usage-dashboard/README.md
+++ b/usage-dashboard/README.md
@@ -154,6 +154,8 @@ Dropdown **Range** cho phép lọc dữ liệu:
- **Last 5 hours**: 5 giờ qua
- **Last 24 hours**: 24 giờ qua
- **Last 7 days**: 7 ngày qua
+- **Last 30 days**: 30 ngày qua
+- **Lifetime**: Trọn đời (tất cả dữ liệu từ đầu)
### 2. Refresh dữ liệu
@@ -378,6 +380,11 @@ print(f"refresh_quota: saved quota for {email}", flush=True)
## 📝 Changelog
+### Minor Update (2026-08-11)
+
+- ✅ Thêm time range **Lifetime** (trọn đời - xem tất cả record trong database)
+- ✅ Thêm time range **30 days**
+
### Minor Update
- ✅ Bổ sung thêm theo dõi request và token từ Gemini
diff --git a/usage-dashboard/usage-dashboard.html b/usage-dashboard/usage-dashboard.html
index 90038bb..872eb60 100644
--- a/usage-dashboard/usage-dashboard.html
+++ b/usage-dashboard/usage-dashboard.html
@@ -215,6 +215,7 @@
+
@@ -334,6 +335,7 @@ const STRINGS = {
title: "CLIProxyAPI Usage Dashboard",
rangeToday:"Today", range1h:"Last 1 hour", range5h:"Last 5 hours",
range24h:"Last 24 hours", range7d:"Last 7 days", range30d:"Last 30 days",
+ rangeLifetime:"Lifetime",
btnRefresh:"Refresh", btnQuota:"Refresh Quota",
kpiRequests:"Requests / Tasks", kpiTotal:"Total Tokens",
kpiTotalSub:"Input + Output + Reasoning", kpiInput:"Input Tokens",
@@ -356,6 +358,7 @@ const STRINGS = {
title: "Thống Kê Sử Dụng CLIProxyAPI",
rangeToday:"Hôm nay", range1h:"1 giờ qua", range5h:"5 giờ qua",
range24h:"24 giờ qua", range7d:"7 ngày qua", range30d:"30 ngày qua",
+ rangeLifetime:"Trọn đời",
btnRefresh:"Làm mới", btnQuota:"Làm mới hạn mức",
kpiRequests:"Yêu cầu / Tác vụ", kpiTotal:"Tổng Tokens",
kpiTotalSub:"Đầu vào + Đầu ra + Suy luận", kpiInput:"Tokens đầu vào",
diff --git a/usage-dashboard/usage-dashboard.py b/usage-dashboard/usage-dashboard.py
index 158cc19..c1c6f85 100644
--- a/usage-dashboard/usage-dashboard.py
+++ b/usage-dashboard/usage-dashboard.py
@@ -588,6 +588,8 @@ def range_bounds(name):
start = now - dt.timedelta(days=7)
elif name == "30d":
start = now - dt.timedelta(days=30)
+ elif name == "lifetime":
+ start = dt.datetime(1970, 1, 1, tzinfo=LOCAL_TZ) # epoch start - all records
else:
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
return start.astimezone(dt.timezone.utc).timestamp(), now.astimezone(dt.timezone.utc).timestamp()
@@ -837,7 +839,7 @@ def main():
quota_p = sub.add_parser("quota", help="Show current quota snapshots")
quota_p.add_argument("--force", action="store_true")
report_p = sub.add_parser("report", help="Print usage summary as JSON")
- report_p.add_argument("range", choices=["today", "1h", "5h", "24h", "7d", "30d"])
+ report_p.add_argument("range", choices=["today", "1h", "5h", "24h", "7d", "30d", "lifetime"])
args = parser.parse_args()
if args.cmd == "init":
init_db()