fix: format peer metrics with contracted units
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
>
|
||||
|
||||
21
src/lib/peer-metrics.test.ts
Normal file
21
src/lib/peer-metrics.test.ts
Normal 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
30
src/lib/peer-metrics.ts
Normal 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);
|
||||
}
|
||||
5
static/favicon.svg
Normal file
5
static/favicon.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="تحلیل زرینپال">
|
||||
<rect width="64" height="64" rx="16" fill="#ffd400"/>
|
||||
<path d="M17 18h30v8H28l19 20H17v-8h19L17 18Z" fill="#19191a"/>
|
||||
<circle cx="47" cy="18" r="5" fill="#0a33ff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 292 B |
Reference in New Issue
Block a user