feat: polish BI dashboards and bump version
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Hono } from 'hono';
|
||||
import { getCache, queryDateMileage, buildDateFilters } from './cache.js';
|
||||
import { getCache, queryDateMileage, queryRangeMileage, buildDateFilters } from './cache.js';
|
||||
import { filterByPermission, maskCustomerNames } from '../../auth/permissions.js';
|
||||
import type { AuthUser } from '../../auth/types.js';
|
||||
import type { CachedVehicle, MonitoringFilters, MonitoringResponse } from './types.js';
|
||||
@@ -64,12 +64,40 @@ function parseTargetNames(reqUrl: string): string[] {
|
||||
return Array.from(new Set(names));
|
||||
}
|
||||
|
||||
function parseYmd(value: string): Date | null {
|
||||
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
||||
if (!match) return null;
|
||||
const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
|
||||
date.setHours(0, 0, 0, 0);
|
||||
return Number.isFinite(date.getTime()) ? date : null;
|
||||
}
|
||||
|
||||
function fmtYmd(date: Date): string {
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function normalizeRange(startQuery: string, endQuery: string): { start: string; end: string } | null {
|
||||
if (!startQuery && !endQuery) return null;
|
||||
const start = parseYmd(startQuery || endQuery);
|
||||
const end = parseYmd(endQuery || startQuery);
|
||||
if (!start || !end) return null;
|
||||
const a = start <= end ? start : end;
|
||||
let b = start <= end ? end : start;
|
||||
const span = Math.round((b.getTime() - a.getTime()) / 86400000) + 1;
|
||||
if (span > 366) {
|
||||
b = new Date(a);
|
||||
b.setDate(a.getDate() + 365);
|
||||
}
|
||||
return { start: fmtYmd(a), end: fmtYmd(b) };
|
||||
}
|
||||
|
||||
app.get('/', async (c) => {
|
||||
const sortBy = c.req.query('sortBy') || 'today';
|
||||
const sortOrder = c.req.query('sortOrder') || 'desc';
|
||||
const limit = Number(c.req.query('limit')) || 50;
|
||||
const page = Number(c.req.query('page')) || 1;
|
||||
const date = c.req.query('date') || '';
|
||||
const range = normalizeRange(c.req.query('startDate') || '', c.req.query('endDate') || '');
|
||||
|
||||
const filterParams = {
|
||||
search: c.req.query('search') || '',
|
||||
@@ -88,8 +116,21 @@ app.get('/', async (c) => {
|
||||
|
||||
let allVehicles: CachedVehicle[];
|
||||
let filters: MonitoringFilters;
|
||||
let rangeDailyTotals: { date: string; totalKm: number }[] | undefined;
|
||||
let dateRange: { start: string; end: string } | undefined;
|
||||
|
||||
if (date) {
|
||||
if (range) {
|
||||
try {
|
||||
const result = await queryRangeMileage(range.start, range.end);
|
||||
allVehicles = result.vehicles;
|
||||
rangeDailyTotals = result.dailyTotals;
|
||||
dateRange = { start: result.start, end: result.end };
|
||||
filters = buildDateFilters(allVehicles);
|
||||
} catch (e: unknown) {
|
||||
console.error('monitoring range query error:', e);
|
||||
return c.json(EMPTY_RESPONSE, 500);
|
||||
}
|
||||
} else if (date) {
|
||||
try {
|
||||
allVehicles = await queryDateMileage(date);
|
||||
filters = buildDateFilters(allVehicles);
|
||||
@@ -118,6 +159,12 @@ app.get('/', async (c) => {
|
||||
}
|
||||
|
||||
const filtered = applyFilters(allVehicles, filterParams);
|
||||
if (rangeDailyTotals && filtered.length !== allVehicles.length) {
|
||||
rangeDailyTotals = rangeDailyTotals.map(item => ({
|
||||
...item,
|
||||
totalKm: filtered.reduce((sum, vehicle) => sum + (vehicle.dailyMileage?.[item.date] || 0), 0),
|
||||
}));
|
||||
}
|
||||
|
||||
const stats = {
|
||||
totalToday: filtered.reduce((sum, v) => sum + v.dailyKm, 0),
|
||||
@@ -140,10 +187,12 @@ app.get('/', async (c) => {
|
||||
vehicles: maskCustomerNames(paged),
|
||||
stats,
|
||||
filters,
|
||||
rangeDailyTotals,
|
||||
dateRange,
|
||||
total,
|
||||
page,
|
||||
totalPages: Math.ceil(total / limit),
|
||||
updatedAt: date || getCache()?.updatedAt || new Date().toISOString(),
|
||||
updatedAt: dateRange?.end || date || getCache()?.updatedAt || new Date().toISOString(),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user