fix: format peer metrics with contracted units

This commit is contained in:
2026-08-20 20:06:48 +03:30
parent d8c7e7263c
commit 23147cd60d
5 changed files with 60 additions and 2 deletions

View File

@@ -4,6 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f1f1f3" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<script>
(() => {
try {

View File

@@ -10,6 +10,7 @@
type ReportingPeriod,
} from '$lib/api/client';
import { formatDate, formatMilliseconds, formatMoney, formatPercent, formatValue } from '$lib/format';
import { formatPeerMetric, peerMetricLabel } from '$lib/peer-metrics';
import DetailsPanel from './DetailsPanel.svelte';
import MetricCard from './MetricCard.svelte';
import SectionFrame from './SectionFrame.svelte';
@@ -414,8 +415,8 @@
{#each peers.data.metrics as metric}<div
class="grid grid-cols-[1fr_auto_auto] items-center gap-3 border-t border-[var(--border)] p-4 text-sm"
>
<span class="ltr text-left">{metric.metricId}</span><span
>{formatPercent(metric.cohortMedian)}</span
<span>{peerMetricLabel(metric.metricId)}</span><span
>{formatPeerMetric(metric.metricId, metric.cohortMedian)}</span
><strong class="text-[var(--brand)]"
>{formatPercent(metric.merchantPerformancePercentile)}</strong
>

View File

@@ -0,0 +1,21 @@
import { describe, expect, it } from 'vitest';
import { formatPeerMetric, peerMetricLabel } from './peer-metrics';
describe('peer metric presentation', () => {
it('formats timing medians in milliseconds instead of percent', () => {
expect(formatPeerMetric('init_time_ms_p50', '1240')).toBe('۱٬۲۴۰ میلی‌ثانیه');
expect(formatPeerMetric('verify_time_ms_p95', '980')).toBe('۹۸۰ میلی‌ثانیه');
});
it('formats rate medians as percentages', () => {
expect(formatPeerMetric('payment_success_rate', '87.25')).toBe('۸۷٫۲۵٪');
expect(formatPeerMetric('paid_fee_rate', '0.5')).toBe('۰٫۵٪');
});
it('provides Persian labels for every contracted peer metric', () => {
expect(peerMetricLabel('payment_success_rate')).toBe('نرخ موفقیت پرداخت');
expect(peerMetricLabel('init_time_ms_p95')).toBe('زمان آغاز پرداخت — صدک ۹۵');
expect(peerMetricLabel('verify_time_ms_p50')).toBe('زمان تأیید — میانه');
});
});

30
src/lib/peer-metrics.ts Normal file
View File

@@ -0,0 +1,30 @@
import type { components } from '$lib/api/schema';
import { formatMilliseconds, formatPercent } from '$lib/format';
export type PeerMetricId = components['schemas']['PeerMetric']['metricId'];
const labels = {
payment_success_rate: 'نرخ موفقیت پرداخت',
verification_completion_rate: 'نرخ تکمیل تأیید',
retry_recovery_rate: 'نرخ بازیابی تلاش مجدد',
init_time_ms_p50: 'زمان آغاز پرداخت — میانه',
init_time_ms_p95: 'زمان آغاز پرداخت — صدک ۹۵',
verify_time_ms_p50: 'زمان تأیید — میانه',
verify_time_ms_p95: 'زمان تأیید — صدک ۹۵',
paid_fee_rate: 'نرخ کارمزد پرداخت‌شده',
} satisfies Record<PeerMetricId, string>;
const timingMetrics = new Set<PeerMetricId>([
'init_time_ms_p50',
'init_time_ms_p95',
'verify_time_ms_p50',
'verify_time_ms_p95',
]);
export function peerMetricLabel(metricId: PeerMetricId): string {
return labels[metricId];
}
export function formatPeerMetric(metricId: PeerMetricId, value: string): string {
return timingMetrics.has(metricId) ? formatMilliseconds(Number(value)) : formatPercent(value);
}