diff --git a/src/pages/AdminApps.tsx b/src/pages/AdminApps.tsx index 29cbc3a..8ed24d2 100644 --- a/src/pages/AdminApps.tsx +++ b/src/pages/AdminApps.tsx @@ -1,4 +1,5 @@ import { useState, useRef } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { @@ -12,10 +13,23 @@ import { RemnawaveConfig, importFromRemnawaveFormat as convertRemnawave, } from '../api/adminApps'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const AppsIcon = () => ( navigate('/admin')); + const [selectedPlatform, setSelectedPlatform] = useState('ios'); const [editingApp, setEditingApp] = useState<{ app: AppDefinition; isNew: boolean } | null>(null); const [copyTarget, setCopyTarget] = useState<{ appId: string; platform: string } | null>(null); @@ -805,7 +825,15 @@ export default function AdminApps() {
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.apps.title')}

diff --git a/src/pages/AdminBroadcastCreate.tsx b/src/pages/AdminBroadcastCreate.tsx index e6988c3..0bc4f2d 100644 --- a/src/pages/AdminBroadcastCreate.tsx +++ b/src/pages/AdminBroadcastCreate.tsx @@ -10,6 +10,7 @@ import { CombinedBroadcastCreateRequest, } from '../api/adminBroadcasts'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const BroadcastIcon = () => ( @@ -118,6 +119,8 @@ export default function AdminBroadcastCreate() { const queryClient = useQueryClient(); const fileInputRef = useRef(null); + useBackButton(() => navigate('/admin/broadcasts')); + // Channel selection const [channel, setChannel] = useState('telegram'); diff --git a/src/pages/AdminBroadcastDetail.tsx b/src/pages/AdminBroadcastDetail.tsx index e399b72..244d725 100644 --- a/src/pages/AdminBroadcastDetail.tsx +++ b/src/pages/AdminBroadcastDetail.tsx @@ -3,6 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminBroadcastsApi, type BroadcastChannel } from '../api/adminBroadcasts'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons @@ -158,6 +159,8 @@ export default function AdminBroadcastDetail() { const broadcastId = id ? parseInt(id, 10) : null; + useBackButton(() => navigate('/admin/broadcasts')); + // Fetch broadcast details const { data: broadcast, diff --git a/src/pages/AdminBroadcasts.tsx b/src/pages/AdminBroadcasts.tsx index 1d651b6..f8fd05c 100644 --- a/src/pages/AdminBroadcasts.tsx +++ b/src/pages/AdminBroadcasts.tsx @@ -3,10 +3,23 @@ import { useNavigate } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminBroadcastsApi } from '../api/adminBroadcasts'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const BroadcastIcon = () => ( navigate('/admin')); const [page, setPage] = useState(0); const limit = 20; @@ -136,7 +153,15 @@ export default function AdminBroadcasts() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.broadcasts.title')}

{t('admin.broadcasts.subtitle')}

diff --git a/src/pages/AdminCampaignCreate.tsx b/src/pages/AdminCampaignCreate.tsx index ea0914e..e5d8566 100644 --- a/src/pages/AdminCampaignCreate.tsx +++ b/src/pages/AdminCampaignCreate.tsx @@ -11,6 +11,7 @@ import { } from '../api/campaigns'; import { AdminBackButton } from '../components/admin'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const CampaignIcon = () => ( @@ -155,6 +156,8 @@ export default function AdminCampaignCreate() { const navigate = useNavigate(); const queryClient = useQueryClient(); + useBackButton(() => navigate('/admin/campaigns')); + // Form state const [name, setName] = useState(''); const [startParameter, setStartParameter] = useState(''); diff --git a/src/pages/AdminCampaignEdit.tsx b/src/pages/AdminCampaignEdit.tsx index cb2396e..6c50895 100644 --- a/src/pages/AdminCampaignEdit.tsx +++ b/src/pages/AdminCampaignEdit.tsx @@ -12,6 +12,7 @@ import { import { AdminBackButton } from '../components/admin'; import { CheckIcon, CampaignIcon } from '../components/icons'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Bonus type config const bonusTypeConfig: Record< @@ -132,6 +133,8 @@ export default function AdminCampaignEdit() { const campaignId = parseInt(id || '0'); + useBackButton(() => navigate('/admin/campaigns')); + // Fetch campaign const { data: campaign, diff --git a/src/pages/AdminCampaignStats.tsx b/src/pages/AdminCampaignStats.tsx index 89cae50..1c7403b 100644 --- a/src/pages/AdminCampaignStats.tsx +++ b/src/pages/AdminCampaignStats.tsx @@ -4,6 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { campaignsApi, CampaignBonusType } from '../api/campaigns'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const CopyIcon = () => ( @@ -97,6 +98,8 @@ export default function AdminCampaignStats() { const [copied, setCopied] = useState(false); const [showUsers, setShowUsers] = useState(false); + useBackButton(() => navigate('/admin/campaigns')); + // Fetch stats const { data: stats, diff --git a/src/pages/AdminCampaigns.tsx b/src/pages/AdminCampaigns.tsx index be493c9..7ed0359 100644 --- a/src/pages/AdminCampaigns.tsx +++ b/src/pages/AdminCampaigns.tsx @@ -4,8 +4,9 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { campaignsApi, CampaignListItem, CampaignBonusType } from '../api/campaigns'; -import { AdminBackButton } from '../components/admin'; import { PlusIcon, EditIcon, TrashIcon, CheckIcon, XIcon, ChartIcon } from '../components/icons'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Bonus type labels and colors const bonusTypeConfig: Record< @@ -34,6 +35,19 @@ const bonusTypeConfig: Record< }, }; +// Icons +const BackIcon = () => ( + + + +); + // Locale mapping for formatting const localeMap: Record = { ru: 'ru-RU', en: 'en-US', zh: 'zh-CN', fa: 'fa-IR' }; @@ -51,6 +65,10 @@ export default function AdminCampaigns() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); const [deleteConfirm, setDeleteConfirm] = useState(null); @@ -89,7 +107,15 @@ export default function AdminCampaigns() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.campaigns.title')}

{t('admin.campaigns.subtitle')}

diff --git a/src/pages/AdminDashboard.tsx b/src/pages/AdminDashboard.tsx index 347cf94..6babd35 100644 --- a/src/pages/AdminDashboard.tsx +++ b/src/pages/AdminDashboard.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { statsApi, @@ -9,10 +10,23 @@ import { type RecentPaymentsResponse, } from '../api/admin'; import { useCurrency } from '../hooks/useCurrency'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons - styled like main navigation +const BackIcon = () => ( + + + +); + const ServerIcon = () => ( navigate('/admin')); + const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -450,7 +470,15 @@ export default function AdminDashboard() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('adminDashboard.title')}

{t('adminDashboard.subtitle')}

diff --git a/src/pages/AdminPaymentMethodEdit.tsx b/src/pages/AdminPaymentMethodEdit.tsx index c0dd88d..15927c2 100644 --- a/src/pages/AdminPaymentMethodEdit.tsx +++ b/src/pages/AdminPaymentMethodEdit.tsx @@ -1,9 +1,11 @@ import { useState, useEffect } from 'react'; -import { useParams, useNavigate, Link } from 'react-router-dom'; +import { useParams, useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminPaymentMethodsApi } from '../api/adminPaymentMethods'; import type { PromoGroupSimple } from '../types'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; const BackIcon = () => ( (); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin/payment-methods')); // Fetch payment methods const { data: methods, isLoading } = useQuery({ @@ -174,12 +180,15 @@ export default function AdminPaymentMethodEdit() { return (
- - - + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.paymentMethods.notFound', 'Payment method not found')}

@@ -195,12 +204,15 @@ export default function AdminPaymentMethodEdit() {
{/* Header */}
- - - + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}
{icon}
diff --git a/src/pages/AdminPayments.tsx b/src/pages/AdminPayments.tsx index 1a782c9..c80d6df 100644 --- a/src/pages/AdminPayments.tsx +++ b/src/pages/AdminPayments.tsx @@ -1,15 +1,35 @@ import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminPaymentsApi } from '../api/adminPayments'; import { useCurrency } from '../hooks/useCurrency'; -import { AdminBackButton } from '../components/admin'; import type { PendingPayment, PaginatedResponse } from '../types'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; + +// BackIcon +const BackIcon = () => ( + + + +); export default function AdminPayments() { const { t } = useTranslation(); + const navigate = useNavigate(); const queryClient = useQueryClient(); const { formatAmount, currencySymbol } = useCurrency(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); const [page, setPage] = useState(1); const [methodFilter, setMethodFilter] = useState(''); @@ -68,7 +88,15 @@ export default function AdminPayments() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.payments.title')}

{t('admin.payments.description')}

diff --git a/src/pages/AdminPromoGroupCreate.tsx b/src/pages/AdminPromoGroupCreate.tsx index 66fcb57..436ccdf 100644 --- a/src/pages/AdminPromoGroupCreate.tsx +++ b/src/pages/AdminPromoGroupCreate.tsx @@ -9,6 +9,7 @@ import { PromoGroupUpdateRequest, } from '../api/promocodes'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const PlusIcon = () => ( @@ -55,6 +56,8 @@ export default function AdminPromoGroupCreate() { const queryClient = useQueryClient(); const isEdit = !!id; + useBackButton(() => navigate('/admin/promo-groups')); + // Form state const [name, setName] = useState(''); const [serverDiscount, setServerDiscount] = useState(0); diff --git a/src/pages/AdminPromoGroups.tsx b/src/pages/AdminPromoGroups.tsx index 2124eb1..a4aa870 100644 --- a/src/pages/AdminPromoGroups.tsx +++ b/src/pages/AdminPromoGroups.tsx @@ -3,9 +3,22 @@ import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { promocodesApi, PromoGroup } from '../api/promocodes'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const PlusIcon = () => ( @@ -46,6 +59,10 @@ export default function AdminPromoGroups() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); const [deleteConfirm, setDeleteConfirm] = useState(null); @@ -71,7 +88,15 @@ export default function AdminPromoGroups() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.promoGroups.title')}

{t('admin.promoGroups.subtitle')}

diff --git a/src/pages/AdminPromoOfferSend.tsx b/src/pages/AdminPromoOfferSend.tsx index c37712b..fb68f0d 100644 --- a/src/pages/AdminPromoOfferSend.tsx +++ b/src/pages/AdminPromoOfferSend.tsx @@ -12,6 +12,7 @@ import { } from '../api/promoOffers'; import { adminUsersApi, UserListItem } from '../api/adminUsers'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const SendIcon = () => ( @@ -75,6 +76,8 @@ export default function AdminPromoOfferSend() { const navigate = useNavigate(); const queryClient = useQueryClient(); + useBackButton(() => navigate('/admin/promo-offers')); + const [selectedTemplateId, setSelectedTemplateId] = useState(null); const [sendMode, setSendMode] = useState<'segment' | 'user'>('segment'); const [selectedTarget, setSelectedTarget] = useState('active'); diff --git a/src/pages/AdminPromoOfferTemplateEdit.tsx b/src/pages/AdminPromoOfferTemplateEdit.tsx index 78c984f..40f4ff5 100644 --- a/src/pages/AdminPromoOfferTemplateEdit.tsx +++ b/src/pages/AdminPromoOfferTemplateEdit.tsx @@ -10,6 +10,7 @@ import { } from '../api/promoOffers'; import { AdminBackButton } from '../components/admin'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import { useBackButton } from '../platform/hooks/useBackButton'; const getOfferTypeIcon = (offerType: string): string => { return OFFER_TYPE_CONFIG[offerType as OfferType]?.icon || '🎁'; @@ -21,6 +22,8 @@ export default function AdminPromoOfferTemplateEdit() { const { id } = useParams<{ id: string }>(); const queryClient = useQueryClient(); + useBackButton(() => navigate('/admin/promo-offers')); + // Form state const [name, setName] = useState(''); const [messageText, setMessageText] = useState(''); diff --git a/src/pages/AdminPromoOffers.tsx b/src/pages/AdminPromoOffers.tsx index 103042d..06eaad7 100644 --- a/src/pages/AdminPromoOffers.tsx +++ b/src/pages/AdminPromoOffers.tsx @@ -4,9 +4,22 @@ import { useTranslation } from 'react-i18next'; import { useQuery } from '@tanstack/react-query'; import i18n from '../i18n'; import { promoOffersApi, PromoOfferLog, OFFER_TYPE_CONFIG, OfferType } from '../api/promoOffers'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const EditIcon = () => ( { export default function AdminPromoOffers() { const { t } = useTranslation(); const navigate = useNavigate(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); const [activeTab, setActiveTab] = useState<'templates' | 'logs'>('templates'); @@ -116,7 +133,15 @@ export default function AdminPromoOffers() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.promoOffers.title')}

{t('admin.promoOffers.subtitle')}

diff --git a/src/pages/AdminPromocodeCreate.tsx b/src/pages/AdminPromocodeCreate.tsx index 0f43a1a..8c615e2 100644 --- a/src/pages/AdminPromocodeCreate.tsx +++ b/src/pages/AdminPromocodeCreate.tsx @@ -10,9 +10,22 @@ import { PromoCodeUpdateRequest, PromoGroup, } from '../api/promocodes'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const RefreshIcon = () => ( (); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); const isEdit = !!id; + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin/promocodes')); + // Form state const [code, setCode] = useState(''); const [type, setType] = useState('balance'); @@ -186,7 +203,15 @@ export default function AdminPromocodeCreate() {
{/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{isEdit diff --git a/src/pages/AdminPromocodeStats.tsx b/src/pages/AdminPromocodeStats.tsx index bf0de08..f6f7662 100644 --- a/src/pages/AdminPromocodeStats.tsx +++ b/src/pages/AdminPromocodeStats.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { promocodesApi, PromoCodeType } from '../api/promocodes'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const EditIcon = () => ( @@ -88,6 +89,8 @@ export default function AdminPromocodeStats() { const navigate = useNavigate(); const { id } = useParams<{ id: string }>(); + useBackButton(() => navigate('/admin/promocodes')); + const { data: promocode, isLoading, diff --git a/src/pages/AdminPromocodes.tsx b/src/pages/AdminPromocodes.tsx index 2de68b1..684b2f8 100644 --- a/src/pages/AdminPromocodes.tsx +++ b/src/pages/AdminPromocodes.tsx @@ -4,10 +4,23 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import i18n from '../i18n'; import { promocodesApi, PromoCode, PromoCodeType } from '../api/promocodes'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const PlusIcon = () => ( @@ -98,6 +111,10 @@ export default function AdminPromocodes() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); const [deleteConfirm, setDeleteConfirm] = useState(null); const [copiedCode, setCopiedCode] = useState(null); @@ -130,7 +147,15 @@ export default function AdminPromocodes() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.promocodes.title')}

{t('admin.promocodes.subtitle')}

diff --git a/src/pages/AdminRemnawave.tsx b/src/pages/AdminRemnawave.tsx index 3a9bd36..c95072e 100644 --- a/src/pages/AdminRemnawave.tsx +++ b/src/pages/AdminRemnawave.tsx @@ -9,7 +9,8 @@ import { SystemStatsResponse, AutoSyncStatus, } from '../api/adminRemnawave'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; import { ServerIcon, ChartIcon, @@ -23,6 +24,20 @@ import { RemnawaveIcon, } from '../components/icons'; +// ============ Icons ============ + +const BackIcon = () => ( + + + +); + // ============ Helpers ============ const formatBytes = (bytes: number): string => { @@ -861,6 +876,10 @@ export default function AdminRemnawave() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); // State const [activeTab, setActiveTab] = useState('overview'); @@ -996,7 +1015,15 @@ export default function AdminRemnawave() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}
diff --git a/src/pages/AdminRemnawaveSquadDetail.tsx b/src/pages/AdminRemnawaveSquadDetail.tsx index 0fa9f82..a4383a6 100644 --- a/src/pages/AdminRemnawaveSquadDetail.tsx +++ b/src/pages/AdminRemnawaveSquadDetail.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import { adminRemnawaveApi, SquadWithLocalInfo } from '../api/adminRemnawave'; import { AdminBackButton } from '../components/admin'; import { ServerIcon, UsersIcon, CheckIcon, XIcon } from '../components/icons'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Country flags helper const getCountryFlag = (code: string | null | undefined): string => { @@ -54,6 +55,8 @@ export default function AdminRemnawaveSquadDetail() { const { uuid } = useParams<{ uuid: string }>(); const navigate = useNavigate(); + useBackButton(() => navigate('/admin/remnawave')); + // Fetch all squads and find the one we need const { data: squadsData, diff --git a/src/pages/AdminServerEdit.tsx b/src/pages/AdminServerEdit.tsx index 9dea960..2ad4e04 100644 --- a/src/pages/AdminServerEdit.tsx +++ b/src/pages/AdminServerEdit.tsx @@ -6,6 +6,7 @@ import { serversApi, ServerUpdateRequest } from '../api/servers'; import { AdminBackButton } from '../components/admin'; import { ServerIcon } from '../components/icons'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Country flags (simple emoji mapping) const getCountryFlag = (code: string | null): string => { @@ -48,6 +49,8 @@ export default function AdminServerEdit() { const serverId = parseInt(id || '0'); + useBackButton(() => navigate('/admin/servers')); + const { data: server, isLoading, diff --git a/src/pages/AdminServers.tsx b/src/pages/AdminServers.tsx index 348a2ad..941a49f 100644 --- a/src/pages/AdminServers.tsx +++ b/src/pages/AdminServers.tsx @@ -2,8 +2,22 @@ import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { serversApi, ServerListItem } from '../api/servers'; -import { AdminBackButton } from '../components/admin'; import { SyncIcon, EditIcon, CheckIcon, XIcon, UsersIcon, GiftIcon } from '../components/icons'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; + +// BackIcon +const BackIcon = () => ( + + + +); // Country flags (simple emoji mapping) const getCountryFlag = (code: string | null): string => { @@ -42,6 +56,10 @@ export default function AdminServers() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); // Queries const { data: serversData, isLoading } = useQuery({ @@ -79,7 +97,15 @@ export default function AdminServers() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.servers.title')}

{t('admin.servers.subtitle')}

diff --git a/src/pages/AdminSettings.tsx b/src/pages/AdminSettings.tsx index 1ac3640..8e145ff 100644 --- a/src/pages/AdminSettings.tsx +++ b/src/pages/AdminSettings.tsx @@ -1,10 +1,13 @@ import { useState, useMemo, useEffect, useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminSettingsApi, SettingDefinition } from '../api/adminSettings'; import { themeColorsApi } from '../api/themeColors'; import { useFavoriteSettings } from '../hooks/useFavoriteSettings'; -import { MENU_SECTIONS, MenuItem, formatSettingKey, AdminBackButton } from '../components/admin'; +import { MENU_SECTIONS, MenuItem, formatSettingKey } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; import { AnalyticsTab } from '../components/admin/AnalyticsTab'; import { BrandingTab } from '../components/admin/BrandingTab'; import { ThemeTab } from '../components/admin/ThemeTab'; @@ -17,6 +20,19 @@ import { SettingsSearchResults, } from '../components/admin/SettingsSearch'; +// BackIcon +const BackIcon = () => ( + + + +); + // Find section ID by category key function findSectionByCategory(categoryKey: string): string | null { for (const section of MENU_SECTIONS) { @@ -31,6 +47,11 @@ function findSectionByCategory(categoryKey: string): string | null { export default function AdminSettings() { const { t } = useTranslation(); + const navigate = useNavigate(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); // State const [activeSection, setActiveSection] = useState('branding'); @@ -216,7 +237,15 @@ export default function AdminSettings() {
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.settings.title')}

diff --git a/src/pages/AdminTariffCreate.tsx b/src/pages/AdminTariffCreate.tsx index f026374..af70c84 100644 --- a/src/pages/AdminTariffCreate.tsx +++ b/src/pages/AdminTariffCreate.tsx @@ -12,6 +12,7 @@ import { } from '../api/tariffs'; import { AdminBackButton } from '../components/admin'; import { createNumberInputHandler, toNumber } from '../utils/inputHelpers'; +import { useBackButton } from '../platform/hooks/useBackButton'; // Icons const PlusIcon = () => ( @@ -91,6 +92,8 @@ export default function AdminTariffCreate() { const queryClient = useQueryClient(); const isEdit = !!id; + useBackButton(() => navigate('/admin/tariffs')); + // Step: null = type selection, 'period' or 'daily' = form const [tariffType, setTariffType] = useState(null); diff --git a/src/pages/AdminTariffs.tsx b/src/pages/AdminTariffs.tsx index 5bf44c1..55850c6 100644 --- a/src/pages/AdminTariffs.tsx +++ b/src/pages/AdminTariffs.tsx @@ -2,8 +2,9 @@ import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { tariffsApi, TariffListItem } from '../api/tariffs'; -import { AdminBackButton } from '../components/admin'; import { useDestructiveConfirm, useNotify } from '@/platform'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons const PlusIcon = () => ( @@ -54,12 +55,29 @@ const GiftIcon = () => ( ); +// BackIcon +const BackIcon = () => ( + + + +); + export default function AdminTariffs() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); const confirmDelete = useDestructiveConfirm(); const notify = useNotify(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); // Queries const { data: tariffsData, isLoading } = useQuery({ @@ -117,7 +135,15 @@ export default function AdminTariffs() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.tariffs.title')}

{t('admin.tariffs.subtitle')}

diff --git a/src/pages/AdminTicketSettings.tsx b/src/pages/AdminTicketSettings.tsx index f6e9c9c..72df75e 100644 --- a/src/pages/AdminTicketSettings.tsx +++ b/src/pages/AdminTicketSettings.tsx @@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminApi } from '../api/admin'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; const SettingsIcon = () => ( @@ -21,6 +22,8 @@ export default function AdminTicketSettings() { const navigate = useNavigate(); const queryClient = useQueryClient(); + useBackButton(() => navigate('/admin/tickets')); + const { data: settings, isLoading, diff --git a/src/pages/AdminTickets.tsx b/src/pages/AdminTickets.tsx index 6a8dce6..fc6c7cc 100644 --- a/src/pages/AdminTickets.tsx +++ b/src/pages/AdminTickets.tsx @@ -4,7 +4,8 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { adminApi, AdminTicket, AdminTicketDetail, AdminTicketMessage } from '../api/admin'; import { ticketsApi } from '../api/tickets'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; function AdminMessageMedia({ message, @@ -103,10 +104,28 @@ function AdminMessageMedia({ ); } +// BackIcon +const BackIcon = () => ( + + + +); + export default function AdminTickets() { const { t } = useTranslation(); const navigate = useNavigate(); const queryClient = useQueryClient(); + const { capabilities } = usePlatform(); + + // Use native Telegram back button in Mini App + useBackButton(() => navigate('/admin')); + const [selectedTicketId, setSelectedTicketId] = useState(null); const [statusFilter, setStatusFilter] = useState(''); const [replyText, setReplyText] = useState(''); @@ -209,7 +228,15 @@ export default function AdminTickets() {
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.tickets.title')}

diff --git a/src/pages/AdminUserDetail.tsx b/src/pages/AdminUserDetail.tsx index 0bc29fa..eb1087b 100644 --- a/src/pages/AdminUserDetail.tsx +++ b/src/pages/AdminUserDetail.tsx @@ -11,6 +11,7 @@ import { type UpdateSubscriptionRequest, } from '../api/adminUsers'; import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; // ============ Icons ============ @@ -81,6 +82,8 @@ export default function AdminUserDetail() { const navigate = useNavigate(); const { id } = useParams<{ id: string }>(); + useBackButton(() => navigate('/admin/users')); + const localeMap: Record = { ru: 'ru-RU', en: 'en-US', zh: 'zh-CN', fa: 'fa-IR' }; const locale = localeMap[i18n.language] || 'ru-RU'; diff --git a/src/pages/AdminUsers.tsx b/src/pages/AdminUsers.tsx index 106e0a6..4132af4 100644 --- a/src/pages/AdminUsers.tsx +++ b/src/pages/AdminUsers.tsx @@ -4,10 +4,23 @@ import { useTranslation } from 'react-i18next'; import { useCurrency } from '../hooks/useCurrency'; import { useToast } from '../components/Toast'; import { adminUsersApi, type UserListItem, type UsersStatsResponse } from '../api/adminUsers'; -import { AdminBackButton } from '../components/admin'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // ============ Icons ============ +const BackIcon = () => ( + + + +); + const SearchIcon = () => ( navigate('/admin')); const [users, setUsers] = useState([]); const [stats, setStats] = useState(null); @@ -551,7 +568,15 @@ export default function AdminUsers() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.users.title')}

{t('admin.users.subtitle')}

diff --git a/src/pages/AdminWheel.tsx b/src/pages/AdminWheel.tsx index 61a2493..213e7a0 100644 --- a/src/pages/AdminWheel.tsx +++ b/src/pages/AdminWheel.tsx @@ -1,4 +1,5 @@ import { useState, useCallback, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { @@ -20,12 +21,25 @@ import { } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { adminWheelApi, type WheelPrizeAdmin, type CreateWheelPrizeData } from '../api/wheel'; -import { AdminBackButton } from '../components/admin'; import { useDestructiveConfirm } from '@/platform'; import FortuneWheel from '../components/wheel/FortuneWheel'; +import { useBackButton } from '../platform/hooks/useBackButton'; +import { usePlatform } from '../platform/hooks/usePlatform'; // Icons +const BackIcon = () => ( + + + +); + const CogIcon = () => ( navigate('/admin')); + const [activeTab, setActiveTab] = useState('settings'); const [expandedPrizeId, setExpandedPrizeId] = useState(null); const [isCreating, setIsCreating] = useState(false); @@ -487,7 +507,15 @@ export default function AdminWheel() { {/* Header */}
- + {/* Show back button only on web, not in Telegram Mini App */} + {!capabilities.hasBackButton && ( + + )}

{t('admin.wheel.title')}