From e948cdc8d2cb8893a269c099d07b395d6a3b36cb Mon Sep 17 00:00:00 2001 From: c0mrade Date: Wed, 4 Feb 2026 05:03:06 +0300 Subject: [PATCH] Complete back button logic for all admin pages in Telegram Mini App Main sections navigate to /admin (15 pages) Detail/edit pages navigate to parent lists (16 pages) All pages use useBackButton hook with proper navigation paths Native Telegram back button in Mini App, UI button on web Email template pages keep UI-only back buttons as required --- src/pages/AdminApps.tsx | 32 +++++++++++++++++-- src/pages/AdminBroadcastCreate.tsx | 3 ++ src/pages/AdminBroadcastDetail.tsx | 3 ++ src/pages/AdminBroadcasts.tsx | 29 +++++++++++++++-- src/pages/AdminCampaignCreate.tsx | 3 ++ src/pages/AdminCampaignEdit.tsx | 3 ++ src/pages/AdminCampaignStats.tsx | 3 ++ src/pages/AdminCampaigns.tsx | 30 ++++++++++++++++-- src/pages/AdminDashboard.tsx | 32 +++++++++++++++++-- src/pages/AdminPaymentMethodEdit.tsx | 38 +++++++++++++++-------- src/pages/AdminPayments.tsx | 32 +++++++++++++++++-- src/pages/AdminPromoGroupCreate.tsx | 3 ++ src/pages/AdminPromoGroups.tsx | 29 +++++++++++++++-- src/pages/AdminPromoOfferSend.tsx | 3 ++ src/pages/AdminPromoOfferTemplateEdit.tsx | 3 ++ src/pages/AdminPromoOffers.tsx | 29 +++++++++++++++-- src/pages/AdminPromocodeCreate.tsx | 29 +++++++++++++++-- src/pages/AdminPromocodeStats.tsx | 3 ++ src/pages/AdminPromocodes.tsx | 29 +++++++++++++++-- src/pages/AdminRemnawave.tsx | 31 ++++++++++++++++-- src/pages/AdminRemnawaveSquadDetail.tsx | 3 ++ src/pages/AdminServerEdit.tsx | 3 ++ src/pages/AdminServers.tsx | 30 ++++++++++++++++-- src/pages/AdminSettings.tsx | 33 ++++++++++++++++++-- src/pages/AdminTariffCreate.tsx | 3 ++ src/pages/AdminTariffs.tsx | 30 ++++++++++++++++-- src/pages/AdminTicketSettings.tsx | 3 ++ src/pages/AdminTickets.tsx | 31 ++++++++++++++++-- src/pages/AdminUserDetail.tsx | 3 ++ src/pages/AdminUsers.tsx | 29 +++++++++++++++-- src/pages/AdminWheel.tsx | 32 +++++++++++++++++-- 31 files changed, 522 insertions(+), 45 deletions(-) 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')}