mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 09:33:46 +00:00
refactor: extract shared withdrawal utils and fix status badge fallbacks
- extract formatDate, statusBadgeConfig, getRiskColor to shared utils - use explicit unknown fallback for unrecognized status values - add missing 'unknown' i18n keys for withdrawal status
This commit is contained in:
@@ -1825,7 +1825,8 @@
|
||||
"approved": "Approved",
|
||||
"rejected": "Rejected",
|
||||
"completed": "Completed",
|
||||
"cancelled": "Cancelled"
|
||||
"cancelled": "Cancelled",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"detail": {
|
||||
"title": "Withdrawal",
|
||||
|
||||
@@ -2347,7 +2347,8 @@
|
||||
"approved": "Одобрено",
|
||||
"rejected": "Отклонено",
|
||||
"completed": "Выполнено",
|
||||
"cancelled": "Отменено"
|
||||
"cancelled": "Отменено",
|
||||
"unknown": "Неизвестно"
|
||||
},
|
||||
"detail": {
|
||||
"title": "Заявка на вывод",
|
||||
|
||||
@@ -29,6 +29,12 @@ const statusConfig: Record<string, { labelKey: string; color: string; bgColor: s
|
||||
},
|
||||
};
|
||||
|
||||
const unknownStatus = {
|
||||
labelKey: 'admin.partnerDetail.status.none',
|
||||
color: 'text-dark-400',
|
||||
bgColor: 'bg-dark-600',
|
||||
};
|
||||
|
||||
export default function AdminPartnerDetail() {
|
||||
const { t } = useTranslation();
|
||||
const { userId } = useParams<{ userId: string }>();
|
||||
@@ -82,7 +88,7 @@ export default function AdminPartnerDetail() {
|
||||
);
|
||||
}
|
||||
|
||||
const badge = statusConfig[partner.partner_status] || statusConfig.none;
|
||||
const badge = statusConfig[partner.partner_status] || unknownStatus;
|
||||
|
||||
return (
|
||||
<div className="animate-fade-in">
|
||||
|
||||
@@ -1,79 +1,15 @@
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { withdrawalApi } from '../api/withdrawals';
|
||||
import { AdminBackButton } from '../components/admin';
|
||||
import { useCurrency } from '../hooks/useCurrency';
|
||||
|
||||
// Locale mapping for formatting
|
||||
const localeMap: Record<string, string> = { ru: 'ru-RU', en: 'en-US', zh: 'zh-CN', fa: 'fa-IR' };
|
||||
|
||||
const formatDate = (date: string | null): string => {
|
||||
if (!date) return '-';
|
||||
const locale = localeMap[i18n.language] || 'ru-RU';
|
||||
return new Date(date).toLocaleDateString(locale, {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
// Status badge config
|
||||
const statusBadgeConfig: Record<string, { labelKey: string; color: string; bgColor: string }> = {
|
||||
pending: {
|
||||
labelKey: 'admin.withdrawals.status.pending',
|
||||
color: 'text-yellow-400',
|
||||
bgColor: 'bg-yellow-500/20',
|
||||
},
|
||||
approved: {
|
||||
labelKey: 'admin.withdrawals.status.approved',
|
||||
color: 'text-accent-400',
|
||||
bgColor: 'bg-accent-500/20',
|
||||
},
|
||||
rejected: {
|
||||
labelKey: 'admin.withdrawals.status.rejected',
|
||||
color: 'text-error-400',
|
||||
bgColor: 'bg-error-500/20',
|
||||
},
|
||||
completed: {
|
||||
labelKey: 'admin.withdrawals.status.completed',
|
||||
color: 'text-success-400',
|
||||
bgColor: 'bg-success-500/20',
|
||||
},
|
||||
cancelled: {
|
||||
labelKey: 'admin.withdrawals.status.cancelled',
|
||||
color: 'text-dark-400',
|
||||
bgColor: 'bg-dark-500/20',
|
||||
},
|
||||
};
|
||||
|
||||
// Risk score color helper
|
||||
function getRiskColor(score: number): { text: string; bg: string; bar: string } {
|
||||
if (score < 30)
|
||||
return { text: 'text-success-400', bg: 'bg-success-500/20', bar: 'bg-success-500' };
|
||||
if (score < 50) return { text: 'text-yellow-400', bg: 'bg-yellow-500/20', bar: 'bg-yellow-500' };
|
||||
if (score < 70) return { text: 'text-orange-400', bg: 'bg-orange-500/20', bar: 'bg-orange-500' };
|
||||
return { text: 'text-error-400', bg: 'bg-error-500/20', bar: 'bg-error-500' };
|
||||
}
|
||||
|
||||
// Risk level badge color
|
||||
function getRiskLevelColor(level: string): { text: string; bg: string } {
|
||||
switch (level) {
|
||||
case 'low':
|
||||
return { text: 'text-success-400', bg: 'bg-success-500/20' };
|
||||
case 'medium':
|
||||
return { text: 'text-yellow-400', bg: 'bg-yellow-500/20' };
|
||||
case 'high':
|
||||
return { text: 'text-orange-400', bg: 'bg-orange-500/20' };
|
||||
case 'critical':
|
||||
return { text: 'text-error-400', bg: 'bg-error-500/20' };
|
||||
default:
|
||||
return { text: 'text-dark-400', bg: 'bg-dark-500/20' };
|
||||
}
|
||||
}
|
||||
import {
|
||||
formatDate,
|
||||
getWithdrawalStatusBadge,
|
||||
getRiskColor,
|
||||
getRiskLevelColor,
|
||||
} from '../utils/withdrawalUtils';
|
||||
|
||||
// Type for parsed risk analysis
|
||||
interface RiskAnalysis {
|
||||
@@ -152,7 +88,7 @@ export default function AdminWithdrawalDetail() {
|
||||
);
|
||||
}
|
||||
|
||||
const badge = statusBadgeConfig[detail.status] || statusBadgeConfig.cancelled;
|
||||
const badge = getWithdrawalStatusBadge(detail.status);
|
||||
const riskColor = getRiskColor(detail.risk_score);
|
||||
|
||||
// Parse risk analysis
|
||||
|
||||
@@ -2,25 +2,10 @@ import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
import { withdrawalApi, AdminWithdrawalItem } from '../api/withdrawals';
|
||||
import { AdminBackButton } from '../components/admin';
|
||||
import { useCurrency } from '../hooks/useCurrency';
|
||||
|
||||
// Locale mapping for formatting
|
||||
const localeMap: Record<string, string> = { ru: 'ru-RU', en: 'en-US', zh: 'zh-CN', fa: 'fa-IR' };
|
||||
|
||||
const formatDate = (date: string | null): string => {
|
||||
if (!date) return '-';
|
||||
const locale = localeMap[i18n.language] || 'ru-RU';
|
||||
return new Date(date).toLocaleDateString(locale, {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
import { formatDate, getWithdrawalStatusBadge, getRiskColor } from '../utils/withdrawalUtils';
|
||||
|
||||
// Status filter tabs
|
||||
type StatusFilter = 'all' | 'pending' | 'approved' | 'rejected' | 'completed' | 'cancelled';
|
||||
@@ -34,43 +19,6 @@ const STATUS_FILTERS: StatusFilter[] = [
|
||||
'cancelled',
|
||||
];
|
||||
|
||||
// Status badge config
|
||||
const statusBadgeConfig: Record<string, { labelKey: string; color: string; bgColor: string }> = {
|
||||
pending: {
|
||||
labelKey: 'admin.withdrawals.status.pending',
|
||||
color: 'text-yellow-400',
|
||||
bgColor: 'bg-yellow-500/20',
|
||||
},
|
||||
approved: {
|
||||
labelKey: 'admin.withdrawals.status.approved',
|
||||
color: 'text-accent-400',
|
||||
bgColor: 'bg-accent-500/20',
|
||||
},
|
||||
rejected: {
|
||||
labelKey: 'admin.withdrawals.status.rejected',
|
||||
color: 'text-error-400',
|
||||
bgColor: 'bg-error-500/20',
|
||||
},
|
||||
completed: {
|
||||
labelKey: 'admin.withdrawals.status.completed',
|
||||
color: 'text-success-400',
|
||||
bgColor: 'bg-success-500/20',
|
||||
},
|
||||
cancelled: {
|
||||
labelKey: 'admin.withdrawals.status.cancelled',
|
||||
color: 'text-dark-400',
|
||||
bgColor: 'bg-dark-500/20',
|
||||
},
|
||||
};
|
||||
|
||||
// Risk score color helper
|
||||
function getRiskColor(score: number): { text: string; bg: string } {
|
||||
if (score < 30) return { text: 'text-success-400', bg: 'bg-success-500/20' };
|
||||
if (score < 50) return { text: 'text-yellow-400', bg: 'bg-yellow-500/20' };
|
||||
if (score < 70) return { text: 'text-orange-400', bg: 'bg-orange-500/20' };
|
||||
return { text: 'text-error-400', bg: 'bg-error-500/20' };
|
||||
}
|
||||
|
||||
export default function AdminWithdrawals() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
@@ -154,7 +102,7 @@ export default function AdminWithdrawals() {
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{items.map((item: AdminWithdrawalItem) => {
|
||||
const badge = statusBadgeConfig[item.status] || statusBadgeConfig.cancelled;
|
||||
const badge = getWithdrawalStatusBadge(item.status);
|
||||
const riskColor = getRiskColor(item.risk_score);
|
||||
|
||||
return (
|
||||
|
||||
83
src/utils/withdrawalUtils.ts
Normal file
83
src/utils/withdrawalUtils.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import i18n from '../i18n';
|
||||
|
||||
export const localeMap: Record<string, string> = {
|
||||
ru: 'ru-RU',
|
||||
en: 'en-US',
|
||||
zh: 'zh-CN',
|
||||
fa: 'fa-IR',
|
||||
};
|
||||
|
||||
export const formatDate = (date: string | null): string => {
|
||||
if (!date) return '-';
|
||||
const locale = localeMap[i18n.language] || 'ru-RU';
|
||||
return new Date(date).toLocaleDateString(locale, {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
export type StatusBadge = { labelKey: string; color: string; bgColor: string };
|
||||
|
||||
export const withdrawalStatusBadgeConfig: Record<string, StatusBadge> = {
|
||||
pending: {
|
||||
labelKey: 'admin.withdrawals.status.pending',
|
||||
color: 'text-yellow-400',
|
||||
bgColor: 'bg-yellow-500/20',
|
||||
},
|
||||
approved: {
|
||||
labelKey: 'admin.withdrawals.status.approved',
|
||||
color: 'text-accent-400',
|
||||
bgColor: 'bg-accent-500/20',
|
||||
},
|
||||
rejected: {
|
||||
labelKey: 'admin.withdrawals.status.rejected',
|
||||
color: 'text-error-400',
|
||||
bgColor: 'bg-error-500/20',
|
||||
},
|
||||
completed: {
|
||||
labelKey: 'admin.withdrawals.status.completed',
|
||||
color: 'text-success-400',
|
||||
bgColor: 'bg-success-500/20',
|
||||
},
|
||||
cancelled: {
|
||||
labelKey: 'admin.withdrawals.status.cancelled',
|
||||
color: 'text-dark-400',
|
||||
bgColor: 'bg-dark-500/20',
|
||||
},
|
||||
};
|
||||
|
||||
const unknownBadge: StatusBadge = {
|
||||
labelKey: 'admin.withdrawals.status.unknown',
|
||||
color: 'text-dark-400',
|
||||
bgColor: 'bg-dark-600',
|
||||
};
|
||||
|
||||
export function getWithdrawalStatusBadge(status: string): StatusBadge {
|
||||
return withdrawalStatusBadgeConfig[status] || unknownBadge;
|
||||
}
|
||||
|
||||
export function getRiskColor(score: number): { text: string; bg: string; bar: string } {
|
||||
if (score < 30)
|
||||
return { text: 'text-success-400', bg: 'bg-success-500/20', bar: 'bg-success-500' };
|
||||
if (score < 50) return { text: 'text-yellow-400', bg: 'bg-yellow-500/20', bar: 'bg-yellow-500' };
|
||||
if (score < 70) return { text: 'text-orange-400', bg: 'bg-orange-500/20', bar: 'bg-orange-500' };
|
||||
return { text: 'text-error-400', bg: 'bg-error-500/20', bar: 'bg-error-500' };
|
||||
}
|
||||
|
||||
export function getRiskLevelColor(level: string): { text: string; bg: string } {
|
||||
switch (level) {
|
||||
case 'low':
|
||||
return { text: 'text-success-400', bg: 'bg-success-500/20' };
|
||||
case 'medium':
|
||||
return { text: 'text-yellow-400', bg: 'bg-yellow-500/20' };
|
||||
case 'high':
|
||||
return { text: 'text-orange-400', bg: 'bg-orange-500/20' };
|
||||
case 'critical':
|
||||
return { text: 'text-error-400', bg: 'bg-error-500/20' };
|
||||
default:
|
||||
return { text: 'text-dark-400', bg: 'bg-dark-500/20' };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user