mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
feat: add dedicated TopUpResult page for payment return flow
Replace toast-based payment return with animated result page showing pending/success/failed/timeout states. Extract shared Spinner, AnimatedCheckmark and AnimatedCrossmark components. Add sessionStorage persistence with validation and TTL for cross-redirect payment data. Unify ProtectedRoute with withLayout prop, add aria-live accessibility.
This commit is contained in:
63
src/utils/topUpStorage.ts
Normal file
63
src/utils/topUpStorage.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
const STORAGE_KEY = 'topup_pending_payment';
|
||||
const MAX_AGE_MS = 30 * 60 * 1000; // 30 minutes
|
||||
|
||||
export interface TopUpPendingInfo {
|
||||
amount_kopeks: number;
|
||||
method_id: string;
|
||||
method_name: string;
|
||||
payment_id: string;
|
||||
created_at: number; // Date.now()
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null;
|
||||
}
|
||||
|
||||
export function saveTopUpPendingInfo(info: TopUpPendingInfo) {
|
||||
try {
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(info));
|
||||
} catch {
|
||||
// sessionStorage unavailable (private mode, quota, etc.)
|
||||
}
|
||||
}
|
||||
|
||||
export function loadTopUpPendingInfo(): TopUpPendingInfo | null {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
const parsed: unknown = JSON.parse(raw);
|
||||
if (
|
||||
!isRecord(parsed) ||
|
||||
typeof parsed.amount_kopeks !== 'number' ||
|
||||
typeof parsed.method_id !== 'string' ||
|
||||
typeof parsed.method_name !== 'string' ||
|
||||
typeof parsed.payment_id !== 'string' ||
|
||||
typeof parsed.created_at !== 'number' ||
|
||||
parsed.amount_kopeks <= 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
// Discard stale entries
|
||||
if (Date.now() - (parsed.created_at as number) > MAX_AGE_MS) {
|
||||
clearTopUpPendingInfo();
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
amount_kopeks: parsed.amount_kopeks as number,
|
||||
method_id: parsed.method_id as string,
|
||||
method_name: parsed.method_name as string,
|
||||
payment_id: parsed.payment_id as string,
|
||||
created_at: parsed.created_at as number,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function clearTopUpPendingInfo() {
|
||||
try {
|
||||
sessionStorage.removeItem(STORAGE_KEY);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user