refactor: add hydrogen station drilldown

This commit is contained in:
kkfluous
2026-08-07 14:41:29 +08:00
parent d53257c65c
commit 71d0091457
9 changed files with 361 additions and 25 deletions
@@ -0,0 +1,104 @@
import type { CustomerType } from './types';
export type HydrogenDrillLevel = 'overview' | 'station' | 'customer';
export interface HydrogenDrillContext {
level: HydrogenDrillLevel;
year?: number;
stationId?: number;
stationName?: string;
customerName?: string;
vehicleScope: CustomerType;
startDate?: string;
endDate?: string;
}
interface LocationParts {
pathname: string;
search: string;
hash: string;
}
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
function validDate(value: string | null): string | undefined {
if (!value || !DATE_PATTERN.test(value)) return undefined;
const timestamp = Date.parse(`${value}T00:00:00+08:00`);
return Number.isFinite(timestamp) ? value : undefined;
}
function positiveInteger(value: string | null): number | undefined {
if (!value || !/^\d+$/.test(value)) return undefined;
const parsed = Number(value);
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
}
function stationId(value: string | null): number | undefined {
if (!value || !/^\d+$/.test(value)) return undefined;
const parsed = Number(value);
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : undefined;
}
export function parseHydrogenDrillContext(search: string): HydrogenDrillContext {
const params = new URLSearchParams(search);
const requestedLevel = params.get('hydrogenLevel');
const parsedStationId = stationId(params.get('hydrogenStation'));
const parsedStationName = params.get('hydrogenStationName')?.trim() || undefined;
const customerName = params.get('hydrogenCustomer')?.trim() || undefined;
const context: HydrogenDrillContext = {
level: requestedLevel === 'station' && parsedStationId !== undefined
? 'station'
: requestedLevel === 'customer' && customerName
? 'customer'
: 'overview',
vehicleScope: params.get('hydrogenScope') === 'external' ? 'external' : 'lingniu',
};
const year = positiveInteger(params.get('hydrogenYear'));
if (year && year >= 2000 && year <= 2100) context.year = year;
if (context.level === 'station') {
context.stationId = parsedStationId;
if (parsedStationName) context.stationName = parsedStationName;
}
if (context.level === 'customer') context.customerName = customerName;
const startDate = validDate(params.get('hydrogenStart'));
const endDate = validDate(params.get('hydrogenEnd'));
if (startDate) context.startDate = startDate;
if (endDate) context.endDate = endDate;
return context;
}
export function buildHydrogenDrillUrl(
location: LocationParts,
context: HydrogenDrillContext,
): string {
const params = new URLSearchParams(location.search);
for (const key of [
'hydrogenLevel',
'hydrogenYear',
'hydrogenStation',
'hydrogenStationName',
'hydrogenCustomer',
'hydrogenScope',
'hydrogenStart',
'hydrogenEnd',
]) {
params.delete(key);
}
if (context.level !== 'overview') params.set('hydrogenLevel', context.level);
if (context.year) params.set('hydrogenYear', String(context.year));
if (context.level === 'station' && context.stationId !== undefined) {
params.set('hydrogenStation', String(context.stationId));
if (context.stationName) params.set('hydrogenStationName', context.stationName);
}
if (context.level === 'customer' && context.customerName) {
params.set('hydrogenCustomer', context.customerName);
}
params.set('hydrogenScope', context.vehicleScope);
if (context.startDate) params.set('hydrogenStart', context.startDate);
if (context.endDate) params.set('hydrogenEnd', context.endDate);
const query = params.toString();
return `${location.pathname}${query ? `?${query}` : ''}${location.hash}`;
}