feat: implement route planning dashboard including KPIs, user workload tracking, and route assignment management features
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
export function normalizeHeader(value: string): string {
|
||||
return value
|
||||
.toLowerCase()
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/[^a-z0-9 ]/gi, '')
|
||||
.trim()
|
||||
.replace(/\s+/g, '_');
|
||||
}
|
||||
|
||||
export function cleanNum(value: unknown): number {
|
||||
if (value === null || value === undefined || value === '') return NaN;
|
||||
if (typeof value === 'number') return value;
|
||||
const str = String(value).trim().replace(/[^0-9.\-]/g, '');
|
||||
if (str === '' || str === '-' || str === '.') return NaN;
|
||||
const num = Number(str);
|
||||
return Number.isFinite(num) ? num : NaN;
|
||||
}
|
||||
|
||||
export function normalizeRow(row: Record<string, unknown>): Record<string, unknown> {
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const key in row) {
|
||||
const newKey = normalizeHeader(key);
|
||||
let val = row[key];
|
||||
if (typeof val === 'string') val = val.trim();
|
||||
out[newKey] = val;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user