80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
export type DashboardRange = 'day' | 'week' | 'month' | 'season';
|
|
export type TransactionStatus = 'all' | 'Paid' | 'Verified' | 'Failed' | 'Reversed';
|
|
|
|
export interface DashboardFilters {
|
|
range: DashboardRange;
|
|
period: string;
|
|
terminal: string;
|
|
status: TransactionStatus;
|
|
minAmount: number | null;
|
|
maxAmount: number | null;
|
|
}
|
|
|
|
const ranges = new Set<DashboardRange>(['day', 'week', 'month', 'season']);
|
|
const statuses = new Set<TransactionStatus>(['all', 'Paid', 'Verified', 'Failed', 'Reversed']);
|
|
|
|
const periodPatterns: Record<DashboardRange, RegExp> = {
|
|
day: /^d-\d{4}-\d{2}-\d{2}$/,
|
|
week: /^w-\d{4}-\d{2}-\d{2}$/,
|
|
month: /^jm-\d{4}-\d{2}$/,
|
|
season: /^ps-\d{4}-(?:01|04|07|10)$/,
|
|
};
|
|
|
|
function positiveAmount(value: string | null): number | null {
|
|
if (!value) return null;
|
|
const parsed = Number(value);
|
|
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
|
|
}
|
|
|
|
export function parseDashboardFilters(
|
|
query: URLSearchParams,
|
|
terminalIds: readonly string[] = [],
|
|
): DashboardFilters {
|
|
const rawRange = query.get('range') as DashboardRange | null;
|
|
const range = rawRange && ranges.has(rawRange) ? rawRange : 'month';
|
|
const rawPeriod = query.get('period');
|
|
const rawStatus = query.get('status') as TransactionStatus | null;
|
|
const rawTerminal = query.get('terminal');
|
|
let minAmount = positiveAmount(query.get('minAmount'));
|
|
let maxAmount = positiveAmount(query.get('maxAmount'));
|
|
|
|
if (minAmount !== null && maxAmount !== null && minAmount > maxAmount) {
|
|
[minAmount, maxAmount] = [maxAmount, minAmount];
|
|
}
|
|
|
|
return {
|
|
range,
|
|
period: rawPeriod && periodPatterns[range].test(rawPeriod) ? rawPeriod : '',
|
|
terminal: rawTerminal && terminalIds.includes(rawTerminal) ? rawTerminal : 'all',
|
|
status: rawStatus && statuses.has(rawStatus) ? rawStatus : 'all',
|
|
minAmount,
|
|
maxAmount,
|
|
};
|
|
}
|
|
|
|
export function setDashboardQuery(
|
|
current: URL,
|
|
updates: Partial<Record<keyof DashboardFilters, string | number | null>>,
|
|
): URL {
|
|
const next = new URL(current);
|
|
for (const [key, value] of Object.entries(updates)) {
|
|
if (value === null || value === '' || value === 'all') next.searchParams.delete(key);
|
|
else next.searchParams.set(key, String(value));
|
|
}
|
|
return next;
|
|
}
|
|
|
|
export const rangeLabels: Record<DashboardRange, string> = {
|
|
day: 'روزانه',
|
|
week: 'هفتگی',
|
|
month: 'ماهانه',
|
|
season: 'فصلی',
|
|
};
|
|
|
|
export const rangePeriodTypes: Record<DashboardRange, string> = {
|
|
day: 'DAY',
|
|
week: 'WEEK',
|
|
month: 'JALALI_MONTH',
|
|
season: 'PERSIAN_SEASON',
|
|
};
|