feat: redesign routed ZarinPal merchant dashboard

This commit is contained in:
2026-08-20 21:41:18 +03:30
parent d8eeff57cd
commit 9ce2e6ec83
183 changed files with 7991 additions and 1569 deletions

View File

@@ -0,0 +1,68 @@
export type DashboardRange = 'day' | 'week' | 'month' | 'season';
export type TransactionStatus = 'all' | 'Paid' | 'Verified' | 'Failed' | 'Reversed';
export interface DashboardFilters {
range: DashboardRange;
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']);
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 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: rawRange && ranges.has(rawRange) ? rawRange : 'month',
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',
};