From 0e3cf303414430ac1ec3109347aa24851b179fe9 Mon Sep 17 00:00:00 2001 From: firewookie Date: Tue, 10 Mar 2026 15:28:46 +0500 Subject: [PATCH] FIX PR Problems --- src/api/balance.ts | 8 +-- src/components/icons/index.tsx | 24 ++++++++ src/pages/AdminUserDetail.tsx | 3 +- src/pages/Balance.tsx | 18 +----- src/pages/Referral.tsx | 102 ++++++++++++++++----------------- src/pages/SavedCards.tsx | 60 +++++++++++++++---- src/types/index.ts | 5 ++ 7 files changed, 136 insertions(+), 84 deletions(-) diff --git a/src/api/balance.ts b/src/api/balance.ts index 933ca97..85e164d 100644 --- a/src/api/balance.ts +++ b/src/api/balance.ts @@ -6,7 +6,7 @@ import type { PaginatedResponse, PendingPayment, ManualCheckResponse, - SavedCard, + SavedCardsResponse, } from '../types'; export const balanceApi = { @@ -124,10 +124,8 @@ export const balanceApi = { }, // Get saved payment methods (cards) for recurrent payments - getSavedCards: async (): Promise<{ cards: SavedCard[]; recurrent_enabled: boolean }> => { - const response = await apiClient.get<{ cards: SavedCard[]; recurrent_enabled: boolean }>( - '/cabinet/balance/saved-cards', - ); + getSavedCards: async (): Promise => { + const response = await apiClient.get('/cabinet/balance/saved-cards'); return response.data; }, diff --git a/src/components/icons/index.tsx b/src/components/icons/index.tsx index 8b9e26e..f65513b 100644 --- a/src/components/icons/index.tsx +++ b/src/components/icons/index.tsx @@ -33,6 +33,30 @@ export const BackIcon = ({ className }: IconProps) => ( ); +export const ArrowLeftIcon = ({ className }: IconProps) => ( + + + +); + +export const ChevronRightIcon = ({ className }: IconProps) => ( + + + +); + export const MenuIcon = ({ className }: IconProps) => ( { if (!userId) return; + const action = overrideAction || subAction; + if ((action === 'extend' || action === 'shorten') && toNumber(subDays, 0) <= 0) return; setActionLoading(true); try { - const action = overrideAction || subAction; const data: UpdateSubscriptionRequest = { action: action as UpdateSubscriptionRequest['action'], ...(action === 'extend' || action === 'shorten' ? { days: toNumber(subDays, 30) } : {}), diff --git a/src/pages/Balance.tsx b/src/pages/Balance.tsx index a02d30a..6ea57b9 100644 --- a/src/pages/Balance.tsx +++ b/src/pages/Balance.tsx @@ -13,21 +13,9 @@ import type { PaginatedResponse, Transaction } from '../types'; import { Card } from '@/components/data-display/Card'; import { Button } from '@/components/primitives/Button'; +import { ChevronDownIcon, ChevronRightIcon } from '@/components/icons'; import { staggerContainer, staggerItem } from '@/components/motion/transitions'; -// Icons -const ChevronDownIcon = ({ className = 'h-5 w-5' }: { className?: string }) => ( - - - -); - -const ChevronRightIcon = ({ className = 'h-5 w-5' }: { className?: string }) => ( - - - -); - const WalletIcon = ({ className = 'h-8 w-8' }: { className?: string }) => ( 0 && ( - +

{t('balance.topUpBalance')} @@ -435,7 +423,7 @@ export default function Balance() { {/* Saved Cards Navigation */} {savedCardsData?.recurrent_enabled && ( - + navigate('/balance/saved-cards')}>
diff --git a/src/pages/Referral.tsx b/src/pages/Referral.tsx index b5d50d2..99b2381 100644 --- a/src/pages/Referral.tsx +++ b/src/pages/Referral.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { useNavigate } from 'react-router'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; @@ -164,6 +164,55 @@ export default function Referral() { }, }); + const programTerms = useMemo(() => { + if (!terms) return null; + const showNewUserBonus = terms.first_topup_bonus_kopeks > 0; + const showInviterBonus = terms.inviter_bonus_kopeks > 0; + const cardCount = 2 + (showNewUserBonus ? 1 : 0) + (showInviterBonus ? 1 : 0); + const gridColsMap: Record = { + 2: 'md:grid-cols-2', + 3: 'md:grid-cols-3', + 4: 'md:grid-cols-4', + }; + const gridCols = gridColsMap[cardCount] ?? 'md:grid-cols-4'; + + return ( +
+

{t('referral.terms.title')}

+
+
+
{t('referral.terms.commission')}
+
+ {terms.commission_percent}% +
+
+
+
{t('referral.terms.minTopup')}
+
+ {formatAmount(terms.minimum_topup_rubles)} {currencySymbol} +
+
+ {showNewUserBonus && ( +
+
{t('referral.terms.newUserBonus')}
+
+ {formatPositive(terms.first_topup_bonus_rubles)} +
+
+ )} + {showInviterBonus && ( +
+
{t('referral.terms.inviterBonus')}
+
+ {formatPositive(terms.inviter_bonus_rubles)} +
+
+ )} +
+
+ ); + }, [terms, t, formatAmount, formatPositive, currencySymbol]); + const copyLink = async () => { if (!referralLink) return; try { @@ -302,56 +351,7 @@ export default function Referral() {
{/* Program Terms */} - {terms && - (() => { - const showNewUserBonus = terms.first_topup_bonus_kopeks > 0; - const showInviterBonus = terms.inviter_bonus_kopeks > 0; - const cardCount = 2 + (showNewUserBonus ? 1 : 0) + (showInviterBonus ? 1 : 0); - const gridCols = - cardCount <= 2 - ? 'md:grid-cols-2' - : cardCount === 3 - ? 'md:grid-cols-3' - : 'md:grid-cols-4'; - - return ( -
-

- {t('referral.terms.title')} -

-
-
-
{t('referral.terms.commission')}
-
- {terms.commission_percent}% -
-
-
-
{t('referral.terms.minTopup')}
-
- {formatAmount(terms.minimum_topup_rubles)} {currencySymbol} -
-
- {showNewUserBonus && ( -
-
{t('referral.terms.newUserBonus')}
-
- {formatPositive(terms.first_topup_bonus_rubles)} -
-
- )} - {showInviterBonus && ( -
-
{t('referral.terms.inviterBonus')}
-
- {formatPositive(terms.inviter_bonus_rubles)} -
-
- )} -
-
- ); - })()} + {programTerms} {/* Referrals List */}
diff --git a/src/pages/SavedCards.tsx b/src/pages/SavedCards.tsx index e7b4454..eb73d3a 100644 --- a/src/pages/SavedCards.tsx +++ b/src/pages/SavedCards.tsx @@ -6,24 +6,31 @@ import { motion } from 'framer-motion'; import { balanceApi } from '../api/balance'; import { useToast } from '../components/Toast'; +import { useDestructiveConfirm } from '../platform/hooks/useNativeDialog'; import { Card } from '@/components/data-display/Card'; import { Button } from '@/components/primitives/Button'; +import { ArrowLeftIcon } from '@/components/icons'; import { staggerContainer, staggerItem } from '@/components/motion/transitions'; -const ArrowLeftIcon = ({ className = 'h-5 w-5' }: { className?: string }) => ( - - - -); +function formatCardDate(dateStr: string): string { + try { + const date = new Date(dateStr); + if (isNaN(date.getTime())) return dateStr; + return date.toLocaleDateString(); + } catch { + return dateStr; + } +} export default function SavedCards() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const { showToast } = useToast(); + const confirmDelete = useDestructiveConfirm(); - const { data: savedCardsData, refetch: refetchSavedCards } = useQuery({ + const { data: savedCardsData, isLoading } = useQuery({ queryKey: ['saved-cards'], queryFn: balanceApi.getSavedCards, }); @@ -32,12 +39,16 @@ export default function SavedCards() { const [deletingCardId, setDeletingCardId] = useState(null); const handleDeleteCard = async (cardId: number) => { - if (!confirm(t('balance.savedCards.confirmUnlink'))) return; + if (deletingCardId !== null) return; + const confirmed = await confirmDelete( + t('balance.savedCards.confirmUnlink'), + t('balance.savedCards.unlink'), + ); + if (!confirmed) return; setDeletingCardId(cardId); try { await balanceApi.deleteSavedCard(cardId); - await refetchSavedCards(); - queryClient.invalidateQueries({ queryKey: ['saved-cards'] }); + await queryClient.invalidateQueries({ queryKey: ['saved-cards'] }); showToast({ type: 'success', title: t('balance.savedCards.unlinkSuccess'), @@ -76,8 +87,33 @@ export default function SavedCards() {

+ {/* Loading state */} + {isLoading && ( + + +
+ {[1, 2].map((i) => ( +
+
+
+
+
+
+
+
+
+
+ ))} +
+ + + )} + {/* Cards List */} - {savedCards && savedCards.length > 0 ? ( + {!isLoading && savedCards && savedCards.length > 0 ? (
@@ -95,7 +131,7 @@ export default function SavedCards() {
{t('balance.savedCards.linkedAt', { - date: new Date(card.created_at).toLocaleDateString(), + date: formatCardDate(card.created_at), })}
@@ -114,7 +150,7 @@ export default function SavedCards() {
- ) : savedCards ? ( + ) : !isLoading && savedCards ? ( /* Empty state - only show when data loaded and empty */ diff --git a/src/types/index.ts b/src/types/index.ts index 08ddb30..933318b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -586,6 +586,11 @@ export interface SavedCard { created_at: string; } +export interface SavedCardsResponse { + cards: SavedCard[]; + recurrent_enabled: boolean; +} + // Ticket notifications types export interface TicketNotification { id: number;