mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
Make SBP default and first top-up option (#389)
This commit is contained in:
@@ -10,7 +10,7 @@ import { checkRateLimit, getRateLimitResetTime, RATE_LIMIT_KEYS } from '../utils
|
|||||||
import { useCloseOnSuccessNotification } from '../store/successNotification';
|
import { useCloseOnSuccessNotification } from '../store/successNotification';
|
||||||
import { useHaptic, usePlatform } from '@/platform';
|
import { useHaptic, usePlatform } from '@/platform';
|
||||||
import { staggerContainer, staggerItem } from '@/components/motion/transitions';
|
import { staggerContainer, staggerItem } from '@/components/motion/transitions';
|
||||||
import type { PaymentMethod } from '../types';
|
import type { PaymentMethod, PaymentMethodOption } from '../types';
|
||||||
import BentoCard from '../components/ui/BentoCard';
|
import BentoCard from '../components/ui/BentoCard';
|
||||||
import { saveTopUpPendingInfo } from '../utils/topUpStorage';
|
import { saveTopUpPendingInfo } from '../utils/topUpStorage';
|
||||||
|
|
||||||
@@ -80,6 +80,44 @@ const getMethodIcon = (methodId: string) => {
|
|||||||
return <CardIcon />;
|
return <CardIcon />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getPreferredOptionId = (options?: PaymentMethod['options']) => {
|
||||||
|
if (!options || options.length === 0) return null;
|
||||||
|
|
||||||
|
const sbpOption = options.find((option) => {
|
||||||
|
const normalizedId = option.id.toLowerCase();
|
||||||
|
const normalizedName = option.name.toLowerCase();
|
||||||
|
return (
|
||||||
|
normalizedId.includes('sbp') ||
|
||||||
|
normalizedName.includes('сбп') ||
|
||||||
|
normalizedName.includes('sbp')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return sbpOption?.id ?? options[0].id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const sortOptionsWithSbpFirst = (options?: PaymentMethod['options']) => {
|
||||||
|
if (!options || options.length <= 1) return options ?? [];
|
||||||
|
|
||||||
|
const isPreferredOption = (option: PaymentMethodOption) => {
|
||||||
|
const normalizedId = option.id.toLowerCase();
|
||||||
|
const normalizedName = option.name.toLowerCase();
|
||||||
|
return (
|
||||||
|
normalizedId.includes('sbp') ||
|
||||||
|
normalizedName.includes('сбп') ||
|
||||||
|
normalizedName.includes('sbp')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return [...options].sort((left, right) => {
|
||||||
|
const leftIsPreferred = isPreferredOption(left);
|
||||||
|
const rightIsPreferred = isPreferredOption(right);
|
||||||
|
|
||||||
|
if (leftIsPreferred === rightIsPreferred) return 0;
|
||||||
|
return leftIsPreferred ? -1 : 1;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export default function TopUpAmount() {
|
export default function TopUpAmount() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -135,7 +173,7 @@ export default function TopUpAmount() {
|
|||||||
const [amount, setAmount] = useState(getInitialAmount);
|
const [amount, setAmount] = useState(getInitialAmount);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [selectedOption, setSelectedOption] = useState<string | null>(
|
const [selectedOption, setSelectedOption] = useState<string | null>(
|
||||||
method?.options && method.options.length > 0 ? method.options[0].id : null,
|
getPreferredOptionId(method?.options),
|
||||||
);
|
);
|
||||||
const [paymentUrl, setPaymentUrl] = useState<string | null>(null);
|
const [paymentUrl, setPaymentUrl] = useState<string | null>(null);
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
@@ -154,6 +192,20 @@ export default function TopUpAmount() {
|
|||||||
}
|
}
|
||||||
}, [cachedMethods, method, navigate, searchParams]);
|
}, [cachedMethods, method, navigate, searchParams]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!method?.options || method.options.length === 0) {
|
||||||
|
if (selectedOption !== null) {
|
||||||
|
setSelectedOption(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionExists = method.options.some((option) => option.id === selectedOption);
|
||||||
|
if (!optionExists) {
|
||||||
|
setSelectedOption(getPreferredOptionId(method.options));
|
||||||
|
}
|
||||||
|
}, [method?.id, method?.options, selectedOption]);
|
||||||
|
|
||||||
const starsPaymentMutation = useMutation({
|
const starsPaymentMutation = useMutation({
|
||||||
mutationFn: (amountKopeks: number) => balanceApi.createStarsInvoice(amountKopeks),
|
mutationFn: (amountKopeks: number) => balanceApi.createStarsInvoice(amountKopeks),
|
||||||
onSuccess: async (data) => {
|
onSuccess: async (data) => {
|
||||||
@@ -248,6 +300,7 @@ export default function TopUpAmount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasOptions = method.options && method.options.length > 0;
|
const hasOptions = method.options && method.options.length > 0;
|
||||||
|
const orderedOptions = sortOptionsWithSbpFirst(method.options);
|
||||||
const minRubles = method.min_amount_kopeks / 100;
|
const minRubles = method.min_amount_kopeks / 100;
|
||||||
const maxRubles = method.max_amount_kopeks / 100;
|
const maxRubles = method.max_amount_kopeks / 100;
|
||||||
const methodKey = method.id.toLowerCase().replace(/-/g, '_');
|
const methodKey = method.id.toLowerCase().replace(/-/g, '_');
|
||||||
@@ -344,11 +397,11 @@ export default function TopUpAmount() {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Payment options (if any) */}
|
{/* Payment options (if any) */}
|
||||||
{hasOptions && method.options && (
|
{hasOptions && orderedOptions.length > 0 && (
|
||||||
<motion.div variants={staggerItem} className="space-y-2">
|
<motion.div variants={staggerItem} className="space-y-2">
|
||||||
<label className="text-sm font-medium text-dark-400">{t('balance.paymentMethod')}</label>
|
<label className="text-sm font-medium text-dark-400">{t('balance.paymentMethod')}</label>
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
{method.options.map((opt) => (
|
{orderedOptions.map((opt) => (
|
||||||
<button
|
<button
|
||||||
key={opt.id}
|
key={opt.id}
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
Reference in New Issue
Block a user