diff --git a/src/components/InsufficientBalancePrompt.tsx b/src/components/InsufficientBalancePrompt.tsx
index 75ebae1..1f4de9e 100644
--- a/src/components/InsufficientBalancePrompt.tsx
+++ b/src/components/InsufficientBalancePrompt.tsx
@@ -2,6 +2,7 @@ import { useState } from 'react';
import { useNavigate, useLocation } from 'react-router';
import { useTranslation } from 'react-i18next';
import { useCurrency } from '../hooks/useCurrency';
+import { InfoIcon, WalletIcon, PlusIcon } from '@/components/icons';
interface InsufficientBalancePromptProps {
/** Amount missing in kopeks */
@@ -55,19 +56,7 @@ export default function InsufficientBalancePrompt({
className={`flex items-center justify-between gap-3 rounded-xl border border-error-500/30 bg-error-500/10 p-3 ${className}`}
>
-
-
-
+
{message || t('balance.insufficientFunds')}:{' '}
@@ -96,19 +85,7 @@ export default function InsufficientBalancePrompt({
>
{t('balance.insufficientFunds')}
@@ -132,15 +109,7 @@ export default function InsufficientBalancePrompt({
) : (
<>
-
-
-
+
{t('balance.topUpBalance')}
>
)}
diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx
index 218b9f6..45585f3 100644
--- a/src/components/LanguageSwitcher.tsx
+++ b/src/components/LanguageSwitcher.tsx
@@ -1,6 +1,7 @@
import { useTranslation } from 'react-i18next';
import { useState, useRef, useEffect } from 'react';
import { infoApi, type LanguageInfo } from '@/api/info';
+import { ChevronDownIcon } from '@/components/icons';
export default function LanguageSwitcher() {
const { i18n } = useTranslation();
@@ -57,14 +58,9 @@ export default function LanguageSwitcher() {
>
{currentLang.flag}
{currentLang.code.toUpperCase()}
-
-
-
+ />
{isOpen && (
diff --git a/src/components/ProviderIcon.tsx b/src/components/ProviderIcon.tsx
index 758f0b3..ca7a98f 100644
--- a/src/components/ProviderIcon.tsx
+++ b/src/components/ProviderIcon.tsx
@@ -1,4 +1,5 @@
import { cn } from '@/lib/utils';
+import { EmailIcon as CentralEmailIcon } from '@/components/icons';
import OAuthProviderIcon from './OAuthProviderIcon';
export function TelegramIcon({ className = 'h-5 w-5' }: { className?: string }) {
@@ -13,22 +14,7 @@ export function TelegramIcon({ className = 'h-5 w-5' }: { className?: string })
}
export function EmailIcon({ className = 'h-5 w-5' }: { className?: string }) {
- return (
-
-
-
- );
+ return
;
}
export default function ProviderIcon({
diff --git a/src/components/Toast.tsx b/src/components/Toast.tsx
index 06f551f..dfd0493 100644
--- a/src/components/Toast.tsx
+++ b/src/components/Toast.tsx
@@ -8,6 +8,8 @@ import {
ReactNode,
} from 'react';
+import { CheckIcon, XIcon, ExclamationIcon, InfoIcon } from '@/components/icons';
+
interface ToastOptions {
type?: 'success' | 'error' | 'info' | 'warning';
message: string;
@@ -163,58 +165,10 @@ function ToastItem({ toast, onClose }: { toast: Toast; onClose: () => void }) {
};
const defaultIcons = {
- success: (
-
-
-
- ),
- error: (
-
-
-
- ),
- warning: (
-
-
-
- ),
- info: (
-
-
-
- ),
+ success:
,
+ error:
,
+ warning:
,
+ info:
,
};
return (
diff --git a/src/components/admin/AnalyticsTab.tsx b/src/components/admin/AnalyticsTab.tsx
index 4065eea..0a1ba98 100644
--- a/src/components/admin/AnalyticsTab.tsx
+++ b/src/components/admin/AnalyticsTab.tsx
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { brandingApi } from '../../api/branding';
-import { CheckIcon, CloseIcon } from './icons';
+import { CheckIcon, CloseIcon, PencilIcon } from './icons';
export function AnalyticsTab() {
const { t } = useTranslation();
@@ -143,19 +143,7 @@ export function AnalyticsTab() {
}}
className="rounded-lg p-1.5 text-dark-400 transition-colors hover:bg-dark-700 hover:text-dark-200"
>
-
-
-
+
)}
@@ -294,19 +282,7 @@ export function AnalyticsTab() {
}}
className="rounded-lg p-1.5 text-dark-400 transition-colors hover:bg-dark-700 hover:text-dark-200"
>
-
-
-
+
)}
@@ -360,19 +336,7 @@ export function AnalyticsTab() {
}}
className="rounded-lg p-1.5 text-dark-400 transition-colors hover:bg-dark-700 hover:text-dark-200"
>
-
-
-
+
)}
diff --git a/src/components/admin/ButtonsTab.tsx b/src/components/admin/ButtonsTab.tsx
index 0d3eefe..5d1ec29 100644
--- a/src/components/admin/ButtonsTab.tsx
+++ b/src/components/admin/ButtonsTab.tsx
@@ -9,6 +9,7 @@ import {
ButtonSection,
BOT_LOCALES,
} from '../../api/buttonStyles';
+import { ChevronDownIcon } from '@/components/icons';
import { Toggle } from './Toggle';
import { useNotify } from '../../platform/hooks/useNotify';
import { useNativeDialog } from '../../platform/hooks/useNativeDialog';
@@ -284,15 +285,9 @@ export function ButtonsTab() {
{t('admin.buttons.customLabels')}
{hasCustomLabels && }
-
-
-
+ />
{isExpanded && (
diff --git a/src/components/admin/ColoredItemCombobox.tsx b/src/components/admin/ColoredItemCombobox.tsx
index 2c05260..d023f7b 100644
--- a/src/components/admin/ColoredItemCombobox.tsx
+++ b/src/components/admin/ColoredItemCombobox.tsx
@@ -1,5 +1,6 @@
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
+import { CheckIcon, ChevronDownIcon, CloseIcon, PlusIcon } from '@/components/icons';
import { cn } from '../../lib/utils';
import { useHapticFeedback } from '../../platform/hooks/useHaptic';
@@ -209,9 +210,7 @@ export function ColoredItemCombobox({
className="shrink-0 rounded p-0.5 text-dark-500 transition-colors hover:text-dark-300"
aria-label={t('news.admin.combobox.clear')}
>
-
-
-
+
>
) : (
@@ -222,16 +221,12 @@ export function ColoredItemCombobox({
>
)}
-
-
-
+ />
{/* Dropdown */}
@@ -279,13 +274,7 @@ export function ColoredItemCombobox({
/>
{item.name}
{value?.id === item.id && (
-
-
-
+
)}
{onDelete && (
) : (
-
-
-
+
)}
)}
@@ -365,9 +352,7 @@ export function ColoredItemCombobox({
) : (
<>
-
-
-
+
{t('news.admin.combobox.create')}
>
)}
diff --git a/src/components/admin/SortableSelectedMethodCard.tsx b/src/components/admin/SortableSelectedMethodCard.tsx
index e0bc956..90af4a3 100644
--- a/src/components/admin/SortableSelectedMethodCard.tsx
+++ b/src/components/admin/SortableSelectedMethodCard.tsx
@@ -4,6 +4,7 @@ import { useSortable } from '@dnd-kit/sortable';
import { PiCaretDown } from 'react-icons/pi';
import { CSS } from '@dnd-kit/utilities';
import { cn } from '../../lib/utils';
+import { CheckIcon } from '@/components/icons';
import { GripIcon, TrashIcon } from '../icons/LandingIcons';
import type { AdminLandingPaymentMethod, EditableMethodField } from '../../api/landings';
import type { PaymentMethodSubOptionInfo } from '../../types';
@@ -218,17 +219,7 @@ export function SortableSelectedMethodCard({
: 'border border-dark-600 bg-dark-700',
)}
>
- {enabled && (
-
-
-
- )}
+ {enabled &&
}
{opt.name}
diff --git a/src/components/admin/bulkActions/ActionModal.tsx b/src/components/admin/bulkActions/ActionModal.tsx
index 8c14c51..3371b36 100644
--- a/src/components/admin/bulkActions/ActionModal.tsx
+++ b/src/components/admin/bulkActions/ActionModal.tsx
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
-import { CheckIcon, XCloseIcon } from '@/components/icons';
+import { CheckIcon, ChevronDownIcon, XCloseIcon, XIcon } from '@/components/icons';
import { useFocusTrap } from '@/hooks/useFocusTrap';
import { DropdownSelect } from './DropdownSelect';
import type { UserListItem } from '../../../api/adminUsers';
@@ -98,31 +98,11 @@ function ProgressView({ progress }: { progress: ProgressState }) {
{entry.success ? (
-
-
-
+
) : (
-
-
-
+
)}
@@ -159,18 +139,12 @@ function ErrorDetails({ result }: { result: BulkActionResult }) {
{t('admin.bulkActions.errors.title', { count: result.error_count })}
-
-
-
+ />
{expanded && (
@@ -178,15 +152,7 @@ function ErrorDetails({ result }: { result: BulkActionResult }) {
{result.errors.map((err, idx) => (
-
-
-
+
{err.username ? `@${err.username}` : `#${err.user_id}`}
diff --git a/src/components/admin/bulkActions/FloatingActionBar.tsx b/src/components/admin/bulkActions/FloatingActionBar.tsx
index cbc7df0..3808c06 100644
--- a/src/components/admin/bulkActions/FloatingActionBar.tsx
+++ b/src/components/admin/bulkActions/FloatingActionBar.tsx
@@ -1,6 +1,7 @@
import { useEffect, useRef, useState, type ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
+import { TrashIcon } from '@/components/icons';
import { ChevronDownIcon } from './DropdownSelect';
import { isSubscriptionLevelAction } from './actionTargets';
import type { BulkActionType } from '../../../api/adminBulkActions';
@@ -112,21 +113,7 @@ export function FloatingActionBar({
{
type: 'delete_subscription',
labelKey: 'admin.bulkActions.actions.deleteSubscription',
- icon: (
-
-
-
- ),
+ icon: ,
colorClass: 'text-error-400 hover:bg-error-500/10',
},
{
diff --git a/src/components/admin/bulkActions/MultiSelectDropdown.tsx b/src/components/admin/bulkActions/MultiSelectDropdown.tsx
index e2fc165..b4db3da 100644
--- a/src/components/admin/bulkActions/MultiSelectDropdown.tsx
+++ b/src/components/admin/bulkActions/MultiSelectDropdown.tsx
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
+import { CheckIcon } from '@/components/icons';
import { ChevronDownIcon } from './DropdownSelect';
// ──────────────────────────────────────────────────────────────────
@@ -135,21 +136,7 @@ export function MultiSelectDropdown({
: 'border-dark-500 bg-dark-700/60',
)}
>
- {isChecked && (
-
-
-
- )}
+ {isChecked && }
{option.label}
diff --git a/src/components/admin/bulkActions/SubscriptionSubRow.tsx b/src/components/admin/bulkActions/SubscriptionSubRow.tsx
index c03cae3..387ff02 100644
--- a/src/components/admin/bulkActions/SubscriptionSubRow.tsx
+++ b/src/components/admin/bulkActions/SubscriptionSubRow.tsx
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
+import { CheckIcon } from '@/components/icons';
import type { UserListItemSubscription } from '../../../api/adminUsers';
// ──────────────────────────────────────────────────────────────────
@@ -68,17 +69,7 @@ export function SubscriptionSubRow({
: t('admin.bulkActions.selectUser', { name: subscription.tariff_name || '' })
}
>
- {isSelected && (
-
-
-
- )}
+ {isSelected && }
)}
diff --git a/src/components/admin/trafficUsage/filters/CountryFilter.tsx b/src/components/admin/trafficUsage/filters/CountryFilter.tsx
index 391897a..97f9b43 100644
--- a/src/components/admin/trafficUsage/filters/CountryFilter.tsx
+++ b/src/components/admin/trafficUsage/filters/CountryFilter.tsx
@@ -1,4 +1,5 @@
import { useEffect, useRef, useState } from 'react';
+import { CheckIcon } from '@/components/icons';
import { ChevronDownIcon, GlobeIcon } from '../TrafficIcons';
import { getFlagEmoji } from '../trafficUsageHelpers';
@@ -71,17 +72,7 @@ export function CountryFilter({
allSelected ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {allSelected && (
-
-
-
- )}
+ {allSelected && }
All
@@ -102,21 +93,7 @@ export function CountryFilter({
checked ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {checked && (
-
-
-
- )}
+ {checked &&
}
{getFlagEmoji(code)} {code.toUpperCase()}
{count}
diff --git a/src/components/admin/trafficUsage/filters/NodeFilter.tsx b/src/components/admin/trafficUsage/filters/NodeFilter.tsx
index 1a23e39..a690110 100644
--- a/src/components/admin/trafficUsage/filters/NodeFilter.tsx
+++ b/src/components/admin/trafficUsage/filters/NodeFilter.tsx
@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ChevronDownIcon, ServerIcon } from '../TrafficIcons';
+import { CheckIcon } from '@/components/icons';
import { getFlagEmoji } from '../trafficUsageHelpers';
import type { TrafficNodeInfo } from '../../../../api/adminTraffic';
@@ -75,17 +76,7 @@ export function NodeFilter({
allSelected ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {allSelected && (
-
-
-
- )}
+ {allSelected &&
}
{t('admin.trafficUsage.allNodes')}
@@ -106,21 +97,7 @@ export function NodeFilter({
checked ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {checked && (
-
-
-
- )}
+ {checked &&
}
{getFlagEmoji(node.country_code)} {node.node_name}
diff --git a/src/components/admin/trafficUsage/filters/StatusFilter.tsx b/src/components/admin/trafficUsage/filters/StatusFilter.tsx
index dc00641..78e2350 100644
--- a/src/components/admin/trafficUsage/filters/StatusFilter.tsx
+++ b/src/components/admin/trafficUsage/filters/StatusFilter.tsx
@@ -1,5 +1,6 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { CheckIcon } from '@/components/icons';
import { ChevronDownIcon, StatusIcon } from '../TrafficIcons';
// Status colour pills shared with the StatusFilter dropdown.
@@ -86,17 +87,7 @@ export function StatusFilter({
allSelected ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {allSelected && (
-
-
-
- )}
+ {allSelected &&
}
{t('admin.trafficUsage.allStatuses')}
@@ -117,21 +108,7 @@ export function StatusFilter({
checked ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {checked && (
-
-
-
- )}
+ {checked &&
}
{statusLabel(s)}
diff --git a/src/components/admin/trafficUsage/filters/TariffFilter.tsx b/src/components/admin/trafficUsage/filters/TariffFilter.tsx
index ccdaaee..e67627b 100644
--- a/src/components/admin/trafficUsage/filters/TariffFilter.tsx
+++ b/src/components/admin/trafficUsage/filters/TariffFilter.tsx
@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ChevronDownIcon, FilterIcon } from '../TrafficIcons';
+import { CheckIcon } from '@/components/icons';
export function TariffFilter({
available,
@@ -73,17 +74,7 @@ export function TariffFilter({
allSelected ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {allSelected && (
-
-
-
- )}
+ {allSelected &&
}
{t('admin.trafficUsage.allTariffs')}
@@ -104,21 +95,7 @@ export function TariffFilter({
checked ? 'border-accent-500 bg-accent-500' : 'border-dark-600'
}`}
>
- {checked && (
-
-
-
- )}
+ {checked &&
}
{tariff}
diff --git a/src/components/admin/userDetail/GiftsTab.tsx b/src/components/admin/userDetail/GiftsTab.tsx
index 2247089..b053aff 100644
--- a/src/components/admin/userDetail/GiftsTab.tsx
+++ b/src/components/admin/userDetail/GiftsTab.tsx
@@ -1,4 +1,5 @@
import { useTranslation } from 'react-i18next';
+import { SendIcon } from '@/components/icons';
import { useCurrency } from '../../../hooks/useCurrency';
import type { AdminUserGiftItem, AdminUserGiftsResponse } from '../../../api/adminUsers';
@@ -224,19 +225,7 @@ export function GiftsTab({ giftsLoading, giftsData, locale, onNavigateToUser }:
{/* Sent Gifts */}
-
-
-
+
{t('admin.users.detail.gifts.sentTitle')}
({giftsData.sent_total})
diff --git a/src/components/admin/userDetail/InfoTab.tsx b/src/components/admin/userDetail/InfoTab.tsx
index 358afb5..226687d 100644
--- a/src/components/admin/userDetail/InfoTab.tsx
+++ b/src/components/admin/userDetail/InfoTab.tsx
@@ -9,6 +9,7 @@ import type {
UserSubscriptionInfo,
} from '../../../api/adminUsers';
import type { PromoGroup } from '../../../api/promocodes';
+import { ServerIcon } from '@/components/icons';
// ──────────────────────────────────────────────────────────────────
// Local status badge (parent has its own — duplicating here to keep
@@ -260,19 +261,7 @@ export function InfoTab(props: InfoTabProps) {
{t('admin.users.detail.lastNode')}
-
-
-
+
{panelInfo.last_connected_node_name}
diff --git a/src/components/admin/userDetail/ReferralsTab.tsx b/src/components/admin/userDetail/ReferralsTab.tsx
index a745df3..05acd29 100644
--- a/src/components/admin/userDetail/ReferralsTab.tsx
+++ b/src/components/admin/userDetail/ReferralsTab.tsx
@@ -5,6 +5,7 @@ import { useNavigate } from 'react-router';
import { useCurrency } from '../../../hooks/useCurrency';
import { useNotify } from '../../../platform/hooks/useNotify';
import { adminUsersApi, type UserDetailResponse, type UserListItem } from '../../../api/adminUsers';
+import { XIcon } from '@/components/icons';
// ──────────────────────────────────────────────────────────────────
// Referrals tab — top-of-graph referrer + stats + referrals list,
@@ -481,15 +482,7 @@ export function ReferralsTab({ user, userId, onUserRefresh }: ReferralsTabProps)
className="rounded-lg p-2 text-dark-500 transition-colors hover:bg-error-500/10 hover:text-error-400 disabled:opacity-50"
title={t('admin.users.detail.referrals.removeReferral')}
>
-
-
-
+
))}
diff --git a/src/components/admin/userDetail/SubscriptionTab.tsx b/src/components/admin/userDetail/SubscriptionTab.tsx
index b382c1d..b6fec90 100644
--- a/src/components/admin/userDetail/SubscriptionTab.tsx
+++ b/src/components/admin/userDetail/SubscriptionTab.tsx
@@ -1,5 +1,15 @@
import { useTranslation } from 'react-i18next';
-import { MinusIcon, PlusIcon, RefreshIcon } from '@/components/icons';
+import {
+ BackIcon,
+ CheckIcon,
+ ChevronDownIcon,
+ ChevronRightIcon,
+ EditIcon,
+ MinusIcon,
+ PlusIcon,
+ RefreshIcon,
+ XIcon,
+} from '@/components/icons';
import { DEVICE_ALIAS_MAX_LENGTH } from '../../../constants/devices';
import { createNumberInputHandler } from '../../../utils/inputHelpers';
import { getFlagEmoji } from '../../../utils/subscriptionHelpers';
@@ -217,19 +227,7 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
-
-
-
+
@@ -309,15 +307,7 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
onClick={() => onSubscriptionDetailViewChange(false)}
className="flex items-center gap-1.5 text-sm text-dark-400 transition-colors hover:text-dark-200"
>
-
-
-
+
{t('admin.users.detail.subscription.backToList', 'Все подписки')}
)}
@@ -943,19 +933,7 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
)}
aria-label={t('admin.users.detail.devices.renameSave', 'Сохранить')}
>
-
-
-
+
-
-
-
+
>
) : (
@@ -995,19 +961,7 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
title={t('admin.users.detail.devices.rename', 'Переименовать')}
aria-label={t('admin.users.detail.devices.rename', 'Переименовать')}
>
-
-
-
+
@@ -1060,19 +1014,9 @@ export function SubscriptionTab(props: SubscriptionTabProps) {
)}
-
-
-
+ />
{requestHistoryExpanded && (
diff --git a/src/components/admin/userDetail/TicketsTab.tsx b/src/components/admin/userDetail/TicketsTab.tsx
index 3a16b8d..0dbd4f0 100644
--- a/src/components/admin/userDetail/TicketsTab.tsx
+++ b/src/components/admin/userDetail/TicketsTab.tsx
@@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query';
import { adminApi, type AdminTicket, type AdminTicketDetail } from '../../../api/admin';
import { MessageMediaGrid } from '../../tickets/MessageMediaGrid';
import { linkifyText } from '../../../utils/linkify';
+import { ChatIcon, BackIcon, SendIcon } from '@/components/icons';
// ──────────────────────────────────────────────────────────────────
// Tickets tab — list view + chat view (selected ticket replaces list).
@@ -155,19 +156,7 @@ function EmptyState() {
const { t } = useTranslation();
return (
-
-
-
+
{t('admin.users.detail.noTickets')}
);
@@ -265,15 +254,7 @@ function ChatView({
aria-label={t('common.back', 'Back')}
className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-dark-800 transition-colors hover:bg-dark-700 sm:h-8 sm:w-8"
>
-
-
-
+
@@ -372,19 +353,7 @@ function ChatView({
{replySending ? (
) : (
-
-
-
+
)}
diff --git a/src/components/blocking/AccountDeletedScreen.tsx b/src/components/blocking/AccountDeletedScreen.tsx
index d94faf5..fb2e319 100644
--- a/src/components/blocking/AccountDeletedScreen.tsx
+++ b/src/components/blocking/AccountDeletedScreen.tsx
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next';
import { usePlatform } from '@/platform';
+import { InfoIcon } from '@/components/icons';
import { useBlockingStore } from '../../store/blocking';
import { useFocusTrap } from '../../hooks/useFocusTrap';
@@ -55,20 +56,7 @@ export default function AccountDeletedScreen() {
diff --git a/src/components/blocking/BlacklistedScreen.tsx b/src/components/blocking/BlacklistedScreen.tsx
index 2bb99e7..de533f5 100644
--- a/src/components/blocking/BlacklistedScreen.tsx
+++ b/src/components/blocking/BlacklistedScreen.tsx
@@ -1,6 +1,7 @@
import { useTranslation } from 'react-i18next';
import { useBlockingStore } from '../../store/blocking';
import { useFocusTrap } from '../../hooks/useFocusTrap';
+import { BanIcon } from '@/components/icons';
export default function BlacklistedScreen() {
const { t } = useTranslation();
@@ -20,19 +21,7 @@ export default function BlacklistedScreen() {
{/* Icon */}
diff --git a/src/components/blocking/ChannelSubscriptionScreen.tsx b/src/components/blocking/ChannelSubscriptionScreen.tsx
index a4c78e8..e213c6c 100644
--- a/src/components/blocking/ChannelSubscriptionScreen.tsx
+++ b/src/components/blocking/ChannelSubscriptionScreen.tsx
@@ -4,6 +4,7 @@ import { useBlockingStore } from '../../store/blocking';
import { apiClient, isChannelSubscriptionError } from '../../api/client';
import { usePlatform } from '../../platform';
import { useFocusTrap } from '../../hooks/useFocusTrap';
+import { TelegramIcon, ClockIcon, CheckIcon } from '@/components/icons';
const CHECK_COOLDOWN_SECONDS = 5;
@@ -96,9 +97,7 @@ export default function ChannelSubscriptionScreen() {
{/* Icon */}
@@ -183,31 +182,12 @@ export default function ChannelSubscriptionScreen() {
>
) : cooldown > 0 ? (
<>
-
-
-
+
{t('blocking.channel.waitSeconds', { seconds: cooldown })}
>
) : (
<>
-
-
-
+
{t('blocking.channel.checkSubscription')}
>
)}
diff --git a/src/components/blocking/MaintenanceScreen.tsx b/src/components/blocking/MaintenanceScreen.tsx
index 6adc56f..2326a33 100644
--- a/src/components/blocking/MaintenanceScreen.tsx
+++ b/src/components/blocking/MaintenanceScreen.tsx
@@ -1,6 +1,7 @@
import { useTranslation } from 'react-i18next';
import { useBlockingStore } from '../../store/blocking';
import { useFocusTrap } from '../../hooks/useFocusTrap';
+import { AdjustmentsIcon } from '@/components/icons';
export default function MaintenanceScreen() {
const { t } = useTranslation();
@@ -20,19 +21,7 @@ export default function MaintenanceScreen() {
{/* Icon */}
diff --git a/src/components/connection/InstallationGuide.tsx b/src/components/connection/InstallationGuide.tsx
index 73d4e19..8e79c74 100644
--- a/src/components/connection/InstallationGuide.tsx
+++ b/src/components/connection/InstallationGuide.tsx
@@ -12,7 +12,7 @@ import { useTheme } from '@/hooks/useTheme';
import { CardsBlock, TimelineBlock, AccordionBlock, MinimalBlock, BlockButtons } from './blocks';
import type { BlockRendererProps } from './blocks';
import TvQuickConnect from './TvQuickConnect';
-import { BackIcon } from '@/components/icons';
+import { BackIcon, ChevronIcon, DocumentIcon } from '@/components/icons';
const platformOrder = ['ios', 'android', 'windows', 'macos', 'linux', 'androidTV', 'appleTV'];
@@ -259,15 +259,7 @@ export default function InstallationGuide({
))}
)}
@@ -315,19 +307,7 @@ export default function InstallationGuide({
rel="noopener noreferrer"
className="btn-secondary w-full justify-center"
>
-
-
-
+
{getBaseTranslation('tutorial', 'subscription.connection.tutorial')}
)}
diff --git a/src/components/connection/blocks/AccordionBlock.tsx b/src/components/connection/blocks/AccordionBlock.tsx
index fd46c36..d07bcad 100644
--- a/src/components/connection/blocks/AccordionBlock.tsx
+++ b/src/components/connection/blocks/AccordionBlock.tsx
@@ -1,4 +1,5 @@
import { useState } from 'react';
+import { ChevronDownIcon } from '@/components/icons';
import { getColorGradient } from '@/utils/colorParser';
import { ThemeIcon } from './ThemeIcon';
import type { BlockRendererProps } from './types';
@@ -52,15 +53,9 @@ export function AccordionBlock({
{getLocalizedText(block.title)}
-
-
-
+ />
{/* Panel */}
{/* Gift icon */}
{/* Content */}
diff --git a/src/components/dashboard/SubscriptionCardActive.tsx b/src/components/dashboard/SubscriptionCardActive.tsx
index 7f947f9..6aa7be5 100644
--- a/src/components/dashboard/SubscriptionCardActive.tsx
+++ b/src/components/dashboard/SubscriptionCardActive.tsx
@@ -10,7 +10,7 @@ import { useTrafficZone } from '../../hooks/useTrafficZone';
import { formatTraffic } from '../../utils/formatTraffic';
import { getGlassColors } from '../../utils/glassTheme';
import { HoverBorderGradient } from '../ui/hover-border-gradient';
-import { RefreshIcon } from '@/components/icons';
+import { CalendarIcon, RefreshIcon } from '@/components/icons';
import { useHaptic } from '../../platform';
import type { Subscription } from '../../types';
@@ -309,20 +309,14 @@ export default function SubscriptionCardActive({
background: daysLeft <= 3 ? 'rgba(var(--color-warning-400), 0.1)' : g.hoverBg,
}}
>
-
-
-
-
+
+
{t('dashboard.remaining')}
diff --git a/src/components/dashboard/SubscriptionCardExpired.tsx b/src/components/dashboard/SubscriptionCardExpired.tsx
index 8fec23c..5431944 100644
--- a/src/components/dashboard/SubscriptionCardExpired.tsx
+++ b/src/components/dashboard/SubscriptionCardExpired.tsx
@@ -10,7 +10,7 @@ import { useCurrency } from '../../hooks/useCurrency';
import { useHapticFeedback } from '../../platform/hooks/useHaptic';
import { getGlassColors } from '../../utils/glassTheme';
import { getInsufficientBalanceError } from '../../utils/subscriptionHelpers';
-import { SubscriptionIcon } from '@/components/icons';
+import { ClockIcon, ExclamationIcon, PlusIcon, SubscriptionIcon } from '@/components/icons';
interface SubscriptionCardExpiredProps {
subscription: Subscription;
@@ -168,39 +168,13 @@ export default function SubscriptionCardExpired({
style={{
background: `rgba(${accent.r},${accent.g},${accent.b},0.1)`,
border: `1px solid rgba(${accent.r},${accent.g},${accent.b},0.15)`,
+ color: accent.hex,
}}
>
{isLimited ? (
-
-
-
-
-
+
) : (
-
-
-
-
+
)}
@@ -275,19 +249,7 @@ export default function SubscriptionCardExpired({
boxShadow: `0 4px 20px rgba(${accent.r},${accent.g},${accent.b},0.2)`,
}}
>
-
-
-
+
{t('subscription.buyTraffic')}
) : (
@@ -330,19 +292,7 @@ export default function SubscriptionCardExpired({
boxShadow: `0 4px 20px rgba(${accent.r},${accent.g},${accent.b},0.2)`,
}}
>
-
-
-
+
{t('dashboard.expired.topUp')}
)}
diff --git a/src/components/dashboard/TrialOfferCard.tsx b/src/components/dashboard/TrialOfferCard.tsx
index 4afba16..025ca01 100644
--- a/src/components/dashboard/TrialOfferCard.tsx
+++ b/src/components/dashboard/TrialOfferCard.tsx
@@ -5,6 +5,7 @@ import type { TrialInfo } from '../../types';
import { useCurrency } from '../../hooks/useCurrency';
import { useTheme } from '../../hooks/useTheme';
import { getGlassColors } from '../../utils/glassTheme';
+import { BoltIcon, SparklesIcon } from '@/components/icons';
interface TrialOfferCardProps {
trialInfo: TrialInfo;
@@ -94,37 +95,21 @@ export default function TrialOfferCard({
}}
>
{isFree ? (
-
-
-
+
+
) : (
-
-
-
+
+
)}
{/* Glow effect */}
{t('news.title')}
diff --git a/src/components/subscription/PurchaseCTAButton.tsx b/src/components/subscription/PurchaseCTAButton.tsx
index 1ca1402..3d3b515 100644
--- a/src/components/subscription/PurchaseCTAButton.tsx
+++ b/src/components/subscription/PurchaseCTAButton.tsx
@@ -1,7 +1,7 @@
import { Link } from 'react-router';
import { useTranslation } from 'react-i18next';
import { HoverBorderGradient } from '../ui/hover-border-gradient';
-import { SubscriptionIcon } from '@/components/icons';
+import { ChevronRightIcon, SubscriptionIcon } from '@/components/icons';
import type { Subscription } from '../../types';
interface PurchaseCTAButtonProps {
@@ -86,20 +86,7 @@ export default function PurchaseCTAButton({
{/* Right: chevron */}
-
-
-
+
diff --git a/src/components/subscription/SubscriptionListCard.tsx b/src/components/subscription/SubscriptionListCard.tsx
index 1f6bb14..3d4b101 100644
--- a/src/components/subscription/SubscriptionListCard.tsx
+++ b/src/components/subscription/SubscriptionListCard.tsx
@@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next';
import { useTheme } from '../../hooks/useTheme';
import { getGlassColors } from '../../utils/glassTheme';
import { useHaptic } from '../../platform';
+import { CalendarIcon, CheckIcon, ChevronRightIcon, DevicesIcon } from '@/components/icons';
import type { SubscriptionListItem } from '../../types';
function formatDate(iso: string | null, locale?: string): string {
@@ -136,15 +137,7 @@ export default function SubscriptionListCard({
-
-
-
+
{/* Traffic mini progress bar */}
@@ -177,29 +170,11 @@ export default function SubscriptionListCard({
style={{ color: g.textSecondary }}
>
-
-
-
-
+
{subscription.device_limit}
-
-
-
-
+
{formatDate(subscription.end_date, i18n.language)}
{!isTrial &&
@@ -213,19 +188,19 @@ export default function SubscriptionListCard({
-
- {enabled ? (
-
- ) : (
+ {enabled ? (
+
+ ) : (
+
- )}
-
+
+ )}
{label}
);
diff --git a/src/components/subscription/purchase/TariffPickerGrid.tsx b/src/components/subscription/purchase/TariffPickerGrid.tsx
index a22ade2..b1204ad 100644
--- a/src/components/subscription/purchase/TariffPickerGrid.tsx
+++ b/src/components/subscription/purchase/TariffPickerGrid.tsx
@@ -4,6 +4,7 @@ import { useTheme } from '../../../hooks/useTheme';
import { useCurrency } from '../../../hooks/useCurrency';
import { usePromoDiscount } from '../../../hooks/usePromoDiscount';
import { getGlassColors } from '../../../utils/glassTheme';
+import { ArrowDownIcon, DevicesIcon, RestartIcon } from '@/components/icons';
import type { Tariff, Subscription, PurchaseOptions } from '../../../types';
// ──────────────────────────────────────────────────────────────────
@@ -169,35 +170,11 @@ export function TariffPickerGrid({
-
-
-
+
{tariff.traffic_limit_label}
-
-
-
+
{tariff.device_limit === 0
? '∞'
@@ -206,19 +183,7 @@ export function TariffPickerGrid({
{tariff.traffic_reset_mode && tariff.traffic_reset_mode !== 'NO_RESET' && (
-
-
-
+
{t(`subscription.trafficReset.${tariff.traffic_reset_mode}`)}
diff --git a/src/components/subscription/sheets/DeleteSubscriptionSheet.tsx b/src/components/subscription/sheets/DeleteSubscriptionSheet.tsx
index b00c46f..23243f9 100644
--- a/src/components/subscription/sheets/DeleteSubscriptionSheet.tsx
+++ b/src/components/subscription/sheets/DeleteSubscriptionSheet.tsx
@@ -1,5 +1,6 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { TrashIcon } from '@/components/icons';
import { subscriptionApi } from '../../../api/subscription';
import { usePlatform } from '../../../platform';
import { useDestructiveConfirm } from '../../../platform/hooks/useNativeDialog';
@@ -72,19 +73,7 @@ export function DeleteSubscriptionSheet({
disabled={deleteLoading}
className="flex w-full items-center justify-center gap-2 rounded-2xl border border-error-400/20 bg-error-400/5 p-3.5 text-sm font-medium text-error-400 transition-colors hover:bg-error-400/10 disabled:opacity-50"
>
-
-
-
+
{t('subscription.delete', 'Удалить подписку')}
);
diff --git a/src/components/tickets/MessageMediaGrid.tsx b/src/components/tickets/MessageMediaGrid.tsx
index 267454c..df3496f 100644
--- a/src/components/tickets/MessageMediaGrid.tsx
+++ b/src/components/tickets/MessageMediaGrid.tsx
@@ -1,5 +1,8 @@
import { useState, useCallback, useEffect } from 'react';
import { createPortal } from 'react-dom';
+
+import { ChevronLeftIcon, ChevronRightIcon, DocumentIcon, XIcon } from '@/components/icons';
+
import { ticketsApi } from '../../api/tickets';
export interface MediaItem {
@@ -150,19 +153,7 @@ export function MessageMediaGrid({
rel="noopener noreferrer"
className="inline-flex items-center gap-2 rounded-lg bg-dark-700 px-3 py-2 text-sm text-dark-200 transition-colors hover:bg-dark-600"
>
-
-
-
+
{item.caption || `Download ${item.type}`}
);
@@ -180,15 +171,7 @@ export function MessageMediaGrid({
className="absolute right-4 top-4 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white text-black shadow-xl transition-colors hover:bg-gray-200"
onClick={closeFullscreen}
>
-
-
-
+
{photoItems.length > 1 && (
@@ -199,15 +182,7 @@ export function MessageMediaGrid({
onClick={() => setFullscreenIndex(fullscreenIndex - 1)}
className="absolute left-4 top-1/2 z-10 flex h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full bg-white/90 text-black shadow-xl transition-colors hover:bg-white disabled:opacity-30"
>
-
-
-
+
setFullscreenIndex(fullscreenIndex + 1)}
className="absolute right-4 top-1/2 z-10 flex h-12 w-12 -translate-y-1/2 items-center justify-center rounded-full bg-white/90 text-black shadow-xl transition-colors hover:bg-white disabled:opacity-30"
>
-
-
-
+
{fullscreenIndex + 1} / {photoItems.length}
diff --git a/src/pages/AdminApps.tsx b/src/pages/AdminApps.tsx
index fb7abe2..a69c416 100644
--- a/src/pages/AdminApps.tsx
+++ b/src/pages/AdminApps.tsx
@@ -3,6 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { adminAppsApi } from '../api/adminApps';
import { usePlatform } from '../platform/hooks/usePlatform';
+import { BackIcon } from '@/components/icons';
export default function AdminApps() {
const { t } = useTranslation();
@@ -45,15 +46,7 @@ export default function AdminApps() {
onClick={() => navigate('/admin')}
className="flex h-10 w-10 items-center justify-center rounded-xl border border-dark-700 bg-dark-800 transition-colors hover:border-dark-600"
>
-
-
-
+
)}
{t('admin.apps.title')}
diff --git a/src/pages/AdminBanSystem.tsx b/src/pages/AdminBanSystem.tsx
index 62a1cbf..46d9842 100644
--- a/src/pages/AdminBanSystem.tsx
+++ b/src/pages/AdminBanSystem.tsx
@@ -34,6 +34,9 @@ import {
TrafficIcon,
ReportIcon,
HealthIcon,
+ ExclamationIcon,
+ BackIcon,
+ XIcon,
} from '@/components/icons';
type TabType =
@@ -393,34 +396,10 @@ export default function AdminBanSystem() {
@@ -454,19 +433,7 @@ export default function AdminBanSystem() {
onClick={() => window.history.back()}
className="flex w-full items-center justify-center gap-2 rounded-lg border border-dark-600 bg-dark-700 px-4 py-2 text-sm font-medium text-dark-200 transition-all duration-200 hover:border-dark-500 hover:bg-dark-600 hover:text-dark-100"
>
-
-
-
+
{t('common.back')}
@@ -1444,14 +1411,7 @@ export default function AdminBanSystem() {
aria-label={t('common.close')}
className="text-dark-400 hover:text-dark-200"
>
-
-
-
+
diff --git a/src/pages/AdminCampaignCreate.tsx b/src/pages/AdminCampaignCreate.tsx
index a88d75b..3195831 100644
--- a/src/pages/AdminCampaignCreate.tsx
+++ b/src/pages/AdminCampaignCreate.tsx
@@ -13,7 +13,7 @@ import { partnerApi } from '../api/partners';
import { AdminBackButton } from '../components/admin';
import { createNumberInputHandler, toNumber } from '../utils/inputHelpers';
import Twemoji from 'react-twemoji';
-import { CampaignIcon, CheckIcon, RefreshIcon } from '@/components/icons';
+import { CampaignIcon, CheckIcon, LinkIcon, RefreshIcon } from '@/components/icons';
// Bonus type config
const bonusTypeConfig: Record<
@@ -273,19 +273,7 @@ export default function AdminCampaignCreate() {
{partnerId && partner && (
-
-
-
+
{t('admin.campaigns.form.partnerAutoAssign', {
name: partner.first_name || partner.username || `#${partnerId}`,
diff --git a/src/pages/AdminCampaignStats.tsx b/src/pages/AdminCampaignStats.tsx
index cb2644c..e4eb79b 100644
--- a/src/pages/AdminCampaignStats.tsx
+++ b/src/pages/AdminCampaignStats.tsx
@@ -10,7 +10,7 @@ import { PARTNER_STATS } from '../constants/partner';
import { useCurrency } from '../hooks/useCurrency';
import { copyToClipboard } from '../utils/clipboard';
import { useHaptic } from '../platform';
-import { ChartIcon, CopyIcon, LinkIcon, UsersIcon } from '@/components/icons';
+import { ChartIcon, ChevronDownIcon, CopyIcon, LinkIcon, UsersIcon } from '@/components/icons';
// Bonus type config
const bonusTypeConfig: Record<
@@ -449,15 +449,9 @@ export default function AdminCampaignStats() {
{t('admin.campaigns.stats.users')} ({stats.registrations})
-
-
-
+ />
{showUsers && (
diff --git a/src/pages/AdminPartnerDetail.tsx b/src/pages/AdminPartnerDetail.tsx
index 20159b7..a50a50b 100644
--- a/src/pages/AdminPartnerDetail.tsx
+++ b/src/pages/AdminPartnerDetail.tsx
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { partnerApi } from '../api/partners';
import { AdminBackButton } from '../components/admin';
import { useCurrency } from '../hooks/useCurrency';
+import { XIcon } from '@/components/icons';
// Status badge config — keys must match backend PartnerStatus enum values
const statusConfig: Record
= {
@@ -259,19 +260,7 @@ export default function AdminPartnerDetail() {
className="rounded p-1 text-dark-500 transition-colors hover:bg-error-500/10 hover:text-error-400"
title={t('admin.partnerDetail.campaigns.unassign')}
>
-
-
-
+
diff --git a/src/pages/AdminPartners.tsx b/src/pages/AdminPartners.tsx
index 7aa063e..b1d07fe 100644
--- a/src/pages/AdminPartners.tsx
+++ b/src/pages/AdminPartners.tsx
@@ -9,6 +9,7 @@ import {
} from '../api/partners';
import { AdminBackButton } from '../components/admin';
import { useCurrency } from '../hooks/useCurrency';
+import { ChevronRightIcon, SettingsIcon } from '@/components/icons';
export default function AdminPartners() {
const { t } = useTranslation();
@@ -50,24 +51,7 @@ export default function AdminPartners() {
className="rounded-lg bg-dark-800 p-2 text-dark-400 transition-colors hover:bg-dark-700 hover:text-dark-200"
title={t('admin.partners.settings')}
>
-
-
-
-
+
@@ -167,19 +151,7 @@ export default function AdminPartners() {
-
-
-
+
))}
diff --git a/src/pages/AdminPayments.tsx b/src/pages/AdminPayments.tsx
index 7630e20..76daaab 100644
--- a/src/pages/AdminPayments.tsx
+++ b/src/pages/AdminPayments.tsx
@@ -6,7 +6,13 @@ import { adminPaymentsApi, type SearchStats } from '../api/adminPayments';
import { useCurrency } from '../hooks/useCurrency';
import type { PendingPayment, PaginatedResponse } from '../types';
import { usePlatform } from '../platform/hooks/usePlatform';
-import { BackIcon, SearchIcon, CalendarIcon } from '@/components/icons';
+import {
+ BackIcon,
+ SearchIcon,
+ CalendarIcon,
+ RefreshIcon,
+ CheckCircleIcon,
+} from '@/components/icons';
interface StatusBadgeProps {
status: string;
@@ -210,19 +216,7 @@ export default function AdminPayments() {
refetch()} className="btn-secondary flex items-center gap-2">
-
-
-
+
{t('common.refresh')}
@@ -574,19 +568,7 @@ export default function AdminPayments() {
) : (
{t('admin.payments.noPayments')}
diff --git a/src/pages/AdminPolicyEdit.tsx b/src/pages/AdminPolicyEdit.tsx
index e3f6504..87c8893 100644
--- a/src/pages/AdminPolicyEdit.tsx
+++ b/src/pages/AdminPolicyEdit.tsx
@@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { rbacApi, AccessPolicy, CreatePolicyPayload, UpdatePolicyPayload } from '@/api/rbac';
import { AdminBackButton } from '@/components/admin';
+import { XIcon } from '@/components/icons';
// === Types ===
@@ -150,15 +151,7 @@ function IpTagInput({ values, onChange }: IpTagInputProps) {
className="text-dark-400 transition-colors hover:text-dark-200"
aria-label={t('admin.policies.conditions.removeIp', { ip })}
>
-
-
-
+
))}
diff --git a/src/pages/AdminPromoOfferSend.tsx b/src/pages/AdminPromoOfferSend.tsx
index 4e72e2e..2c8f5a2 100644
--- a/src/pages/AdminPromoOfferSend.tsx
+++ b/src/pages/AdminPromoOfferSend.tsx
@@ -19,6 +19,7 @@ import {
UserIcon,
SearchIcon,
CloseIcon,
+ XIcon,
} from '@/components/icons';
const getOfferTypeIcon = (offerType: string): string => {
@@ -188,25 +189,9 @@ export default function AdminPromoOfferSend() {
}`}
>
{result.isSuccess ? (
-
-
-
+
) : (
-
-
-
+
)}
{result.title}
diff --git a/src/pages/AdminTariffs.tsx b/src/pages/AdminTariffs.tsx
index f92fb2d..dc139c2 100644
--- a/src/pages/AdminTariffs.tsx
+++ b/src/pages/AdminTariffs.tsx
@@ -105,19 +105,7 @@ function SortableTariffCard({
)}
{tariff.show_in_gift && (
-
-
-
+
{t('admin.tariffs.giftBadge')}
)}
diff --git a/src/pages/AdminTickets.tsx b/src/pages/AdminTickets.tsx
index 73eaa58..d33bc9d 100644
--- a/src/pages/AdminTickets.tsx
+++ b/src/pages/AdminTickets.tsx
@@ -9,7 +9,7 @@ import { adminApi, AdminTicket, AdminTicketDetail } from '../api/admin';
import { ticketsApi } from '../api/tickets';
import { copyToClipboard as copyText } from '../utils/clipboard';
import { usePlatform } from '../platform/hooks/usePlatform';
-import { BackIcon } from '@/components/icons';
+import { BackIcon, SettingsIcon, TicketIcon, XIcon } from '@/components/icons';
interface MediaAttachment {
id: string;
@@ -270,24 +270,7 @@ export default function AdminTickets() {
onClick={() => navigate('/admin/tickets/settings')}
className="btn-secondary flex items-center gap-2"
>
-
-
-
-
+
{t('admin.tickets.settings')}
@@ -433,19 +416,7 @@ export default function AdminTickets() {
{!selectedTicketId ? (
{t('admin.tickets.selectTicket')}
@@ -593,19 +564,7 @@ export default function AdminTickets() {
onClick={() => removeAttachment(idx)}
className="absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-dark-600 text-dark-300 hover:bg-error-500 hover:text-white"
>
-
-
-
+
))}
diff --git a/src/pages/AdminWithdrawalDetail.tsx b/src/pages/AdminWithdrawalDetail.tsx
index 6dbb260..b292bc3 100644
--- a/src/pages/AdminWithdrawalDetail.tsx
+++ b/src/pages/AdminWithdrawalDetail.tsx
@@ -3,6 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { withdrawalApi } from '../api/withdrawals';
import { AdminBackButton } from '../components/admin';
+import { WarningIcon } from '@/components/icons';
import { useCurrency } from '../hooks/useCurrency';
import {
formatDate,
@@ -237,19 +238,7 @@ export default function AdminWithdrawalDetail() {
key={index}
className="flex items-start gap-2 rounded-lg bg-error-500/10 px-3 py-2"
>
-
-
-
+
{flag}
))}
diff --git a/src/pages/AdminWithdrawals.tsx b/src/pages/AdminWithdrawals.tsx
index a09814a..2af61d6 100644
--- a/src/pages/AdminWithdrawals.tsx
+++ b/src/pages/AdminWithdrawals.tsx
@@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { withdrawalApi, AdminWithdrawalItem } from '../api/withdrawals';
import { AdminBackButton } from '../components/admin';
+import { ChevronRightIcon } from '@/components/icons';
import { useCurrency } from '../hooks/useCurrency';
import { formatDate, getWithdrawalStatusBadge, getRiskColor } from '../utils/withdrawalUtils';
@@ -150,19 +151,7 @@ export default function AdminWithdrawals() {
{/* Chevron right */}
-
-
-
+
);
diff --git a/src/pages/AutoLogin.tsx b/src/pages/AutoLogin.tsx
index 0587951..44731dd 100644
--- a/src/pages/AutoLogin.tsx
+++ b/src/pages/AutoLogin.tsx
@@ -3,6 +3,7 @@ import { useSearchParams, useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import { authApi } from '../api/auth';
import { useAuthStore } from '../store/auth';
+import { XIcon } from '@/components/icons';
export default function AutoLogin() {
const { t } = useTranslation();
@@ -51,15 +52,7 @@ export default function AutoLogin() {
{error ? (
{t('landing.autoLoginFailed')}
{isAdmin && (
-
-
-
-
+
{t('subscription.connection.goToApps')}
)}
diff --git a/src/pages/Contests.tsx b/src/pages/Contests.tsx
index 36a7fb8..c15196a 100644
--- a/src/pages/Contests.tsx
+++ b/src/pages/Contests.tsx
@@ -2,7 +2,7 @@ import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { contestsApi, ContestInfo, ContestGameData } from '../api/contests';
-import { GamepadIcon, TrophyIcon } from '@/components/icons';
+import { GamepadIcon, TrophyIcon, XIcon } from '@/components/icons';
export default function Contests() {
const { t } = useTranslation();
@@ -87,14 +87,7 @@ export default function Contests() {
{selectedContest.name}
-
-
-
+
diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx
index dcc1202..18db455 100644
--- a/src/pages/Dashboard.tsx
+++ b/src/pages/Dashboard.tsx
@@ -21,7 +21,7 @@ import { promoApi } from '../api/promo';
import PendingGiftCard from '../components/dashboard/PendingGiftCard';
import SubscriptionListCard from '../components/subscription/SubscriptionListCard';
import { API } from '../config/constants';
-import { ChevronRightIcon } from '@/components/icons';
+import { ChevronRightIcon, StarIcon } from '@/components/icons';
export default function Dashboard() {
const { t } = useTranslation();
@@ -263,16 +263,7 @@ export default function Dashboard() {
color: 'rgb(var(--color-accent-400))',
}}
>
-
-
-
+
{promoGroupData.group_name}
)}
diff --git a/src/pages/DeepLinkRedirect.tsx b/src/pages/DeepLinkRedirect.tsx
index f77317e..7422e35 100644
--- a/src/pages/DeepLinkRedirect.tsx
+++ b/src/pages/DeepLinkRedirect.tsx
@@ -4,6 +4,13 @@ import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { brandingApi } from '../api/branding';
import { copyToClipboard } from '../utils/clipboard';
+import {
+ CheckIcon,
+ CopyIcon,
+ ExclamationIcon,
+ ExternalLinkIcon,
+ LinkIcon,
+} from '@/components/icons';
type Status = 'countdown' | 'fallback' | 'error';
@@ -209,19 +216,7 @@ export default function DeepLinkRedirect() {
onClick={openDeepLink}
className="btn-primary flex w-full items-center justify-center gap-2 py-3"
>
-
-
-
+
{t('deepLink.openApp')}
@@ -243,36 +238,12 @@ export default function DeepLinkRedirect() {
>
{copied ? (
<>
-
-
-
+
{t('deepLink.copied')}
>
) : (
<>
-
-
-
+
{t('deepLink.copyLink')}
>
)}
@@ -283,19 +254,7 @@ export default function DeepLinkRedirect() {
onClick={openDeepLink}
className="btn-secondary flex w-full items-center justify-center gap-2"
>
-
-
-
+
{t('deepLink.tryAgain')}
@@ -327,19 +286,7 @@ export default function DeepLinkRedirect() {
{status === 'error' && (
{t('deepLink.errorTitle')}
{t('deepLink.errorDesc')}
@@ -351,19 +298,7 @@ export default function DeepLinkRedirect() {
{/* Footer */}
-
-
-
+
VPN Config Redirect
diff --git a/src/pages/GiftResult.tsx b/src/pages/GiftResult.tsx
index a9f2bb8..6b78350 100644
--- a/src/pages/GiftResult.tsx
+++ b/src/pages/GiftResult.tsx
@@ -9,6 +9,7 @@ import { AnimatedCheckmark } from '@/components/ui/AnimatedCheckmark';
import { AnimatedCrossmark } from '@/components/ui/AnimatedCrossmark';
import { cn } from '@/lib/utils';
import { copyToClipboard } from '@/utils/clipboard';
+import { CheckIcon, CopyIcon, InfoIcon, ExclamationIcon, ClockIcon } from '@/components/icons';
const MAX_POLL_MS = 10 * 60 * 1000; // 10 minutes
@@ -147,32 +148,12 @@ function CodeOnlySuccessState({
>
{copied ? (
<>
-
-
-
+
{t('common.copied', 'Copied!')}
>
) : (
<>
-
-
-
+
{t('gift.copyMessage', 'Copy message')}
>
)}
@@ -272,19 +253,7 @@ function PendingActivationState({
>
{/* Info icon */}
@@ -372,19 +341,7 @@ function PollErrorState() {
className="flex flex-col items-center gap-6 text-center"
>
@@ -420,19 +377,7 @@ function PollTimedOutState({ onRetry }: { onRetry: () => void }) {
className="flex flex-col items-center gap-6 text-center"
>
@@ -467,19 +412,7 @@ function NoTokenState() {
className="flex flex-col items-center gap-6 text-center"
>
{t('gift.noToken', 'Invalid link')}
diff --git a/src/pages/GiftSubscription.tsx b/src/pages/GiftSubscription.tsx
index 151d5cb..d1e4650 100644
--- a/src/pages/GiftSubscription.tsx
+++ b/src/pages/GiftSubscription.tsx
@@ -21,6 +21,7 @@ import { getApiErrorMessage } from '../utils/api-error';
import { formatPrice } from '../utils/format';
import { useCurrency } from '../hooks/useCurrency';
import { usePlatform, useHaptic } from '@/platform';
+import { SparklesIcon } from '@/components/icons';
function GiftIcon({ className }: { className?: string }) {
return (
@@ -686,17 +687,7 @@ function BuyTabContent({
{config.promo_group_name && (
@@ -713,17 +704,7 @@ function BuyTabContent({
{config.active_discount_percent != null && config.active_discount_percent > 0 && (
{t('promo.discountApplied')} -{config.active_discount_percent}%
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx
index 7cf03f9..4fa0b0d 100644
--- a/src/pages/Login.tsx
+++ b/src/pages/Login.tsx
@@ -23,6 +23,7 @@ import TelegramLoginButton from '../components/TelegramLoginButton';
import OAuthProviderIcon from '../components/OAuthProviderIcon';
import { saveOAuthState } from '../utils/oauth';
import { getPendingReferralCode } from '../utils/referral';
+import { UsersIcon, EmailIcon, RefreshIcon, ChevronDownIcon } from '@/components/icons';
export default function Login() {
const { t } = useTranslation();
@@ -362,19 +363,7 @@ export default function Login() {
{referralCode && isEmailAuthEnabled && (
-
-
-
+
{t('auth.referralInvite')}
@@ -385,19 +374,7 @@ export default function Login() {
{registeredEmail ? (
{t('auth.checkEmail', 'Check your email')}
@@ -447,19 +424,7 @@ export default function Login() {
onClick={handleRetryTelegramAuth}
className="btn-primary mx-auto flex items-center gap-2 px-5 py-2.5"
>
-
-
-
+
{t('auth.tryAgain')}
@@ -516,29 +481,11 @@ export default function Login() {
onClick={() => setShowEmailForm(!showEmailForm)}
className="flex items-center gap-1.5 rounded-full border border-dark-700 bg-dark-800/60 px-3.5 py-1.5 text-xs font-medium text-dark-300 transition-all hover:border-dark-600 hover:bg-dark-700 hover:text-dark-200"
>
-
-
-
+
{t('auth.loginWithEmail')}
-
-
-
+ />
@@ -557,19 +504,7 @@ export default function Login() {
forgotPasswordSent ? (
{t('auth.checkEmail', 'Check your email')}
diff --git a/src/pages/OAuthCallback.tsx b/src/pages/OAuthCallback.tsx
index 42aaa21..1f36b59 100644
--- a/src/pages/OAuthCallback.tsx
+++ b/src/pages/OAuthCallback.tsx
@@ -11,6 +11,7 @@ import {
getErrorDetail,
} from '../utils/oauth';
import type { ServerCompleteResponse } from '../types';
+import { CheckIcon, ExclamationIcon } from '@/components/icons';
type CallbackMode = 'login' | 'link-browser' | 'link-server';
@@ -145,15 +146,7 @@ export default function OAuthCallback() {
{t('profile.accounts.linkSuccess')}
@@ -209,19 +202,7 @@ export default function OAuthCallback() {
{t('auth.loginFailed')}
{error}
diff --git a/src/pages/Polls.tsx b/src/pages/Polls.tsx
index f71c4d1..2b46fba 100644
--- a/src/pages/Polls.tsx
+++ b/src/pages/Polls.tsx
@@ -3,7 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { pollsApi, PollInfo, PollQuestion } from '../api/polls';
import { useFocusTrap } from '../hooks/useFocusTrap';
-import { ClipboardIcon, GiftIcon, CheckIcon } from '@/components/icons';
+import { ClipboardIcon, GiftIcon, CheckIcon, CloseIcon } from '@/components/icons';
export default function Polls() {
const { t } = useTranslation();
@@ -135,14 +135,7 @@ export default function Polls() {
aria-label={t('common.close')}
className="text-dark-400 hover:text-dark-200"
>
-
-
-
+
diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx
index bb12b92..fe82370 100644
--- a/src/pages/Profile.tsx
+++ b/src/pages/Profile.tsx
@@ -319,15 +319,7 @@ export default function Profile() {
{t('profile.accounts.subtitle')}
-
-
-
+
diff --git a/src/pages/PurchaseSuccess.tsx b/src/pages/PurchaseSuccess.tsx
index 0f27b1a..8afddd9 100644
--- a/src/pages/PurchaseSuccess.tsx
+++ b/src/pages/PurchaseSuccess.tsx
@@ -8,6 +8,7 @@ import { landingApi } from '../api/landings';
import { authApi } from '../api/auth';
import { useAuthStore } from '../store/auth';
import { copyToClipboard } from '../utils/clipboard';
+import { CheckIcon, ClipboardIcon, ClockIcon, ExclamationIcon } from '@/components/icons';
import { Spinner } from '@/components/ui/Spinner';
import { AnimatedCheckmark } from '@/components/ui/AnimatedCheckmark';
import { AnimatedCrossmark } from '@/components/ui/AnimatedCrossmark';
@@ -299,32 +300,12 @@ function SuccessState({
>
{copied ? (
<>
-
-
-
+
{t('landing.copied', 'Copied!')}
>
) : (
<>
-
-
-
+
{t('landing.copyLink', 'Copy link')}
>
)}
@@ -383,19 +364,7 @@ function PendingActivationState({
>
{/* Warning icon */}
@@ -560,19 +529,7 @@ function PollTimedOutState({ onRetry }: { onRetry: () => void }) {
className="flex flex-col items-center gap-6 text-center"
>
diff --git a/src/pages/QuickPurchase.tsx b/src/pages/QuickPurchase.tsx
index c373ee6..6504a8a 100644
--- a/src/pages/QuickPurchase.tsx
+++ b/src/pages/QuickPurchase.tsx
@@ -15,6 +15,7 @@ import type {
PurchaseRequest,
} from '../api/landings';
import { StaticBackgroundRenderer } from '../components/backgrounds/BackgroundRenderer';
+import { CheckCircleIcon, CheckIcon, DevicesIcon, DownloadIcon } from '@/components/icons';
import LanguageSwitcher from '../components/LanguageSwitcher';
import { cn } from '../lib/utils';
import { getApiErrorMessage } from '../utils/api-error';
@@ -285,52 +286,18 @@ function TariffCard({
isSelected ? 'border-accent-500 bg-accent-500' : 'border-dark-600',
)}
>
- {isSelected && (
-
-
-
- )}
+ {isSelected && }
{/* Info row */}
-
-
-
+
{tariff.traffic_limit_gb === 0 ? '∞' : tariff.traffic_limit_gb} {t('landing.gb', 'GB')}
-
-
-
+
{tariff.device_limit} {t('landing.devices', 'devices')}
@@ -550,15 +517,7 @@ function SummaryCard({
{config.features.map((feature, idx) => (
{feature.title}
diff --git a/src/pages/Referral.tsx b/src/pages/Referral.tsx
index eac094a..e669e67 100644
--- a/src/pages/Referral.tsx
+++ b/src/pages/Referral.tsx
@@ -14,9 +14,12 @@ import {
CheckIcon,
ClockIcon,
CopyIcon,
+ ExclamationIcon,
LinkIcon,
PartnerIcon,
ShareIcon,
+ TelegramIcon,
+ UsersIcon,
WalletIcon,
} from '@/components/icons';
@@ -212,19 +215,7 @@ export default function Referral() {
return (
{t('referral.title')}
@@ -273,9 +264,7 @@ export default function Referral() {
{botReferralLink && (
-
-
-
+
{t('referral.botLink')}
@@ -302,19 +291,7 @@ export default function Referral() {
{/* Cabinet link */}
-
-
-
+
{t('referral.cabinetLink')}
@@ -383,19 +360,7 @@ export default function Referral() {
) : (
{t('referral.noReferrals')}
@@ -519,19 +484,7 @@ export default function Referral() {
diff --git a/src/pages/ReferralNetwork/components/CampaignDetailPanel.tsx b/src/pages/ReferralNetwork/components/CampaignDetailPanel.tsx
index 84c1ac6..2661911 100644
--- a/src/pages/ReferralNetwork/components/CampaignDetailPanel.tsx
+++ b/src/pages/ReferralNetwork/components/CampaignDetailPanel.tsx
@@ -1,5 +1,6 @@
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
+import { CloseIcon } from '@/components/icons';
import { referralNetworkApi } from '@/api/referralNetwork';
import { useReferralNetworkStore } from '@/store/referralNetwork';
import { formatKopeksToRubles } from '../utils';
@@ -37,15 +38,7 @@ export function CampaignDetailPanel({ campaignId, className }: CampaignDetailPan
className="rounded-lg p-1 text-dark-500 transition-colors hover:bg-dark-800 hover:text-dark-300"
aria-label={t('common.close')}
>
-
-
-
+
diff --git a/src/pages/ReferralNetwork/components/NetworkControls.tsx b/src/pages/ReferralNetwork/components/NetworkControls.tsx
index fbd4478..2bab30c 100644
--- a/src/pages/ReferralNetwork/components/NetworkControls.tsx
+++ b/src/pages/ReferralNetwork/components/NetworkControls.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
+import { MinusIcon, PlusIcon } from '@/components/icons';
import { getSigmaInstance } from '../sigmaGlobals';
interface NetworkControlsProps {
@@ -62,32 +63,12 @@ export function NetworkControls({ className }: NetworkControlsProps) {
{
label: t('admin.referralNetwork.controls.zoomIn'),
onClick: handleZoomIn,
- icon: (
-
-
-
- ),
+ icon:
,
},
{
label: t('admin.referralNetwork.controls.zoomOut'),
onClick: handleZoomOut,
- icon: (
-
-
-
- ),
+ icon:
,
},
{
label: t('admin.referralNetwork.controls.resetZoom'),
diff --git a/src/pages/ReferralNetwork/components/NetworkFilters.tsx b/src/pages/ReferralNetwork/components/NetworkFilters.tsx
index 94c53d3..5ac1c6f 100644
--- a/src/pages/ReferralNetwork/components/NetworkFilters.tsx
+++ b/src/pages/ReferralNetwork/components/NetworkFilters.tsx
@@ -1,5 +1,6 @@
import { useState, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
+import { CloseIcon, FilterIcon } from '@/components/icons';
import { useReferralNetworkStore } from '@/store/referralNetwork';
import type { NetworkGraphData } from '@/types/referralNetwork';
@@ -120,19 +121,7 @@ export function NetworkFilters({ data, className }: NetworkFiltersProps) {
: 'border-dark-700/50 bg-dark-800/80 text-dark-300 hover:border-dark-600 hover:text-dark-100'
}`}
>
-
-
-
+
{t('admin.referralNetwork.filters.title')}
{hasActiveFilters && (
@@ -152,15 +141,7 @@ export function NetworkFilters({ data, className }: NetworkFiltersProps) {
aria-label={t('common.close')}
className="text-dark-500 transition-colors hover:text-dark-300"
>
-
-
-
+
{panelContent}
@@ -182,15 +163,7 @@ export function NetworkFilters({ data, className }: NetworkFiltersProps) {
aria-label={t('common.close')}
className="rounded-lg p-1 text-dark-500 transition-colors hover:bg-dark-800 hover:text-dark-300"
>
-
-
-
+
{panelContent}
diff --git a/src/pages/ReferralNetwork/components/ScopeSelector.tsx b/src/pages/ReferralNetwork/components/ScopeSelector.tsx
index 00d453f..fd35b6e 100644
--- a/src/pages/ReferralNetwork/components/ScopeSelector.tsx
+++ b/src/pages/ReferralNetwork/components/ScopeSelector.tsx
@@ -2,6 +2,7 @@ import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { referralNetworkApi } from '@/api/referralNetwork';
+import { CheckIcon, CloseIcon, PlusIcon, SearchIcon } from '@/components/icons';
import { MAX_SCOPE_ITEMS } from '@/store/referralNetwork';
import type { ScopeSelection, ScopeType } from '@/types/referralNetwork';
@@ -30,28 +31,6 @@ const AVATAR_LETTERS: Record
= {
user: 'U',
};
-function CheckIcon() {
- return (
-
-
-
- );
-}
-
-function CloseIcon({ className = 'h-3 w-3' }: { className?: string }) {
- return (
-
-
-
- );
-}
-
function Spinner({ size = 'h-5 w-5' }: { size?: string }) {
return (
-
+
))}
@@ -273,15 +252,7 @@ export function ScopeSelector({ value, onAdd, onRemove, onClear, className }: Sc
}`}
disabled={isMaxReached && !isDropdownOpen}
>
-
-
-
+
@@ -323,19 +294,7 @@ export function ScopeSelector({ value, onAdd, onRemove, onClear, className }: Sc
diff --git a/src/pages/ResetPassword.tsx b/src/pages/ResetPassword.tsx
index 97f1a05..9863fef 100644
--- a/src/pages/ResetPassword.tsx
+++ b/src/pages/ResetPassword.tsx
@@ -3,6 +3,7 @@ import { useSearchParams, Link, useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import { authApi } from '../api/auth';
import LanguageSwitcher from '../components/LanguageSwitcher';
+import { CheckIcon } from '@/components/icons';
export default function ResetPassword() {
const { t } = useTranslation();
@@ -97,15 +98,7 @@ export default function ResetPassword() {
{status === 'success' ? (
{t('resetPassword.success', 'Password changed!')}
diff --git a/src/pages/Subscription.tsx b/src/pages/Subscription.tsx
index 6d7a2c1..cc5017c 100644
--- a/src/pages/Subscription.tsx
+++ b/src/pages/Subscription.tsx
@@ -17,7 +17,16 @@ import InsufficientBalancePrompt from '../components/InsufficientBalancePrompt';
import { useCurrency } from '../hooks/useCurrency';
import { useCloseOnSuccessNotification } from '../store/successNotification';
import PurchaseCTAButton from '../components/subscription/PurchaseCTAButton';
-import { CopyIcon, CheckIcon, PauseIcon } from '../components/icons';
+import {
+ CopyIcon,
+ CheckIcon,
+ PauseIcon,
+ CalendarIcon,
+ RefreshIcon,
+ DevicesIcon,
+ DownloadIcon,
+ TrashIcon,
+} from '../components/icons';
import { useHaptic } from '../platform';
import { resolveConnectionUrlForUi } from '../utils/connectionLink';
import {
@@ -97,26 +106,17 @@ const CountdownTimer = memo(function CountdownTimer({
: g.hoverBg,
}}
>
-
-
-
-
+
+
{t('dashboard.remaining')}
@@ -774,20 +774,10 @@ export default function Subscription() {
disabled={refreshTrafficMutation.isPending || trafficRefreshCooldown > 0}
className="flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium text-dark-50/30 transition-colors hover:bg-dark-50/[0.05] hover:text-dark-50/50 disabled:cursor-not-allowed disabled:opacity-50"
>
-
-
-
+
{trafficRefreshCooldown > 0
? `${trafficRefreshCooldown}s`
: t('common.refresh')}
@@ -827,23 +817,9 @@ export default function Subscription() {
>
@@ -1000,21 +976,9 @@ export default function Subscription() {
{purchase.traffic_gb} {t('common.units.gb')}
@@ -1121,23 +1085,9 @@ export default function Subscription() {
>
{t('subscription.noSubscription')}
diff --git a/src/pages/SubscriptionPurchase.tsx b/src/pages/SubscriptionPurchase.tsx
index 28be245..d5e1387 100644
--- a/src/pages/SubscriptionPurchase.tsx
+++ b/src/pages/SubscriptionPurchase.tsx
@@ -12,6 +12,7 @@ import { SwitchTariffSheet } from '../components/subscription/sheets/SwitchTarif
import { TariffPurchaseForm } from '../components/subscription/purchase/TariffPurchaseForm';
import { TariffPickerGrid } from '../components/subscription/purchase/TariffPickerGrid';
import { ClassicPurchaseWizard } from '../components/subscription/purchase/ClassicPurchaseWizard';
+import { ExclamationIcon, SparklesIcon } from '@/components/icons';
export default function SubscriptionPurchase() {
const { t } = useTranslation();
@@ -177,23 +178,12 @@ export default function SubscriptionPurchase() {
void }) {
className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-2xl"
style={{ background: g.innerBg }}
>
-
-
-
+
{t('subscriptions.empty', 'Нет подписок')}
@@ -128,15 +117,7 @@ export default function Subscriptions() {
border: '1px solid rgba(var(--color-accent-400), 0.2)',
}}
>
-
-
-
+
{t('subscriptions.buyAnother', 'Новый тариф')}
)}
diff --git a/src/pages/Support.tsx b/src/pages/Support.tsx
index 4e0c67c..5d44498 100644
--- a/src/pages/Support.tsx
+++ b/src/pages/Support.tsx
@@ -12,7 +12,7 @@ import type { TicketDetail } from '../types';
import { Card } from '@/components/data-display/Card';
import { Button } from '@/components/primitives/Button';
import { staggerContainer, staggerItem } from '@/components/motion/transitions';
-import { CloseIcon, ImageIcon, PlusIcon, SendIcon } from '@/components/icons';
+import { ChatIcon, CloseIcon, ImageIcon, PlusIcon, SendIcon } from '@/components/icons';
import { usePlatform } from '@/platform';
import { linkifyText } from '../utils/linkify';
@@ -266,19 +266,7 @@ export default function Support() {
{supportMessage.title}
{supportMessage.message}
@@ -366,19 +354,7 @@ export default function Support() {
{t('support.contactUs')}
@@ -440,19 +416,7 @@ export default function Support() {
) : (
diff --git a/src/pages/TelegramRedirect.tsx b/src/pages/TelegramRedirect.tsx
index f7583ed..6c05007 100644
--- a/src/pages/TelegramRedirect.tsx
+++ b/src/pages/TelegramRedirect.tsx
@@ -8,6 +8,7 @@ import { brandingApi } from '../api/branding';
import { isInTelegramWebApp, getTelegramInitData } from '../hooks/useTelegramSDK';
import { tokenStorage } from '../utils/token';
import { getSafeRedirectPath } from '../utils/safeRedirect';
+import { CheckIcon, XIcon, ExclamationIcon } from '@/components/icons';
const MAX_RETRY_ATTEMPTS = 3;
const RETRY_COUNT_KEY = 'telegram_redirect_retry_count';
@@ -158,15 +159,7 @@ export default function TelegramRedirect() {
{status === 'success' && (
{t('auth.loginSuccess')}
{t('telegramRedirect.redirecting')}
@@ -177,15 +170,7 @@ export default function TelegramRedirect() {
{status === 'error' && (
{t('auth.loginFailed')}
{errorMessage}
@@ -204,19 +189,7 @@ export default function TelegramRedirect() {
{status === 'not-telegram' && (
{t('telegramRedirect.openInTelegram')}
{t('telegramRedirect.openInTelegramDesc')}
diff --git a/src/pages/TopUpAmount.tsx b/src/pages/TopUpAmount.tsx
index d0ef21e..a4cc3d7 100644
--- a/src/pages/TopUpAmount.tsx
+++ b/src/pages/TopUpAmount.tsx
@@ -20,6 +20,7 @@ import {
CheckIcon,
CopyIcon,
CryptoIcon,
+ ExclamationIcon,
ExternalLinkIcon,
SparklesIcon,
StarIcon,
@@ -520,19 +521,7 @@ export default function TopUpAmount() {
variants={staggerItem}
className="flex items-center gap-2 rounded-xl border border-error-500/20 bg-error-500/10 p-3"
>
-
-
-
+
{error}
)}