From 062976180cea0708918b234e9d767c3a5861693a Mon Sep 17 00:00:00 2001 From: Fringg Date: Tue, 17 Feb 2026 10:28:32 +0300 Subject: [PATCH] refactor: convert partner/withdrawal modals to separate pages Replace 7 modal dialogs with 8 dedicated page routes for better mobile/Telegram WebApp UX. Add campaign management (assign/create with auto-assign) to partner detail page. New pages: AdminApplicationReview, AdminPartnerCommission, AdminPartnerRevoke, AdminWithdrawalReject, AdminPartnerCampaignAssign, AdminPartnerCampaignCreate, ReferralPartnerApply, ReferralWithdrawalRequest. ~610 lines removed from parent pages, ~425 lines removed net. --- src/App.tsx | 88 +++++++ src/locales/en.json | 15 +- src/locales/fa.json | 15 +- src/locales/ru.json | 15 +- src/locales/zh.json | 15 +- src/pages/AdminApplicationReview.tsx | 228 ++++++++++++++++++ src/pages/AdminPartnerCampaignAssign.tsx | 107 +++++++++ src/pages/AdminPartnerCampaignCreate.tsx | 185 +++++++++++++++ src/pages/AdminPartnerCommission.tsx | 107 +++++++++ src/pages/AdminPartnerDetail.tsx | 189 +++++---------- src/pages/AdminPartnerRevoke.tsx | 64 +++++ src/pages/AdminPartners.tsx | 157 +----------- src/pages/AdminWithdrawalDetail.tsx | 66 +----- src/pages/AdminWithdrawalReject.tsx | 100 ++++++++ src/pages/Referral.tsx | 290 ++--------------------- src/pages/ReferralPartnerApply.tsx | 157 ++++++++++++ src/pages/ReferralWithdrawalRequest.tsx | 136 +++++++++++ 17 files changed, 1320 insertions(+), 614 deletions(-) create mode 100644 src/pages/AdminApplicationReview.tsx create mode 100644 src/pages/AdminPartnerCampaignAssign.tsx create mode 100644 src/pages/AdminPartnerCampaignCreate.tsx create mode 100644 src/pages/AdminPartnerCommission.tsx create mode 100644 src/pages/AdminPartnerRevoke.tsx create mode 100644 src/pages/AdminWithdrawalReject.tsx create mode 100644 src/pages/ReferralPartnerApply.tsx create mode 100644 src/pages/ReferralWithdrawalRequest.tsx diff --git a/src/App.tsx b/src/App.tsx index bfd25ff..f98b65d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -61,8 +61,16 @@ const AdminCampaignStats = lazy(() => import('./pages/AdminCampaignStats')); const AdminCampaignEdit = lazy(() => import('./pages/AdminCampaignEdit')); const AdminPartners = lazy(() => import('./pages/AdminPartners')); const AdminPartnerDetail = lazy(() => import('./pages/AdminPartnerDetail')); +const AdminApplicationReview = lazy(() => import('./pages/AdminApplicationReview')); +const AdminPartnerCommission = lazy(() => import('./pages/AdminPartnerCommission')); +const AdminPartnerRevoke = lazy(() => import('./pages/AdminPartnerRevoke')); +const AdminPartnerCampaignAssign = lazy(() => import('./pages/AdminPartnerCampaignAssign')); +const AdminPartnerCampaignCreate = lazy(() => import('./pages/AdminPartnerCampaignCreate')); const AdminWithdrawals = lazy(() => import('./pages/AdminWithdrawals')); const AdminWithdrawalDetail = lazy(() => import('./pages/AdminWithdrawalDetail')); +const AdminWithdrawalReject = lazy(() => import('./pages/AdminWithdrawalReject')); +const ReferralPartnerApply = lazy(() => import('./pages/ReferralPartnerApply')); +const ReferralWithdrawalRequest = lazy(() => import('./pages/ReferralWithdrawalRequest')); const AdminUsers = lazy(() => import('./pages/AdminUsers')); const AdminPayments = lazy(() => import('./pages/AdminPayments')); const AdminPaymentMethods = lazy(() => import('./pages/AdminPaymentMethods')); @@ -221,6 +229,26 @@ function App() { } /> + + + + + + } + /> + + + + + + } + /> } /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> } /> + + + + + + } + /> (); + const navigate = useNavigate(); + const location = useLocation(); + const queryClient = useQueryClient(); + + const [commission, setCommission] = useState('10'); + const [rejectComment, setRejectComment] = useState(''); + + // Try to get application from navigate state, fallback to fetching + const passedApp = (location.state as { application?: AdminPartnerApplicationItem } | null) + ?.application; + + const { data: fetchedApps } = useQuery({ + queryKey: ['admin-partner-applications'], + queryFn: () => partnerApi.getApplications({ status: 'pending' }), + enabled: !passedApp && !!id, + }); + + const app = passedApp ?? fetchedApps?.items.find((a) => a.id === Number(id)); + + const approveMutation = useMutation({ + mutationFn: ({ appId, commissionPercent }: { appId: number; commissionPercent: number }) => + partnerApi.approveApplication(appId, { commission_percent: commissionPercent }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-partner-applications'] }); + queryClient.invalidateQueries({ queryKey: ['admin-partners'] }); + queryClient.invalidateQueries({ queryKey: ['admin-partner-stats'] }); + navigate('/admin/partners'); + }, + }); + + const rejectMutation = useMutation({ + mutationFn: ({ appId, comment }: { appId: number; comment?: string }) => + partnerApi.rejectApplication(appId, { comment }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['admin-partner-applications'] }); + queryClient.invalidateQueries({ queryKey: ['admin-partner-stats'] }); + navigate('/admin/partners'); + }, + }); + + if (!app) { + return ( +
+
+ +

+ {t('admin.partners.approveDialog.title')} +

+
+
+
+
+
+ ); + } + + const displayName = app.first_name || app.username || `#${app.user_id}`; + + return ( +
+ {/* Header */} +
+ +
+

+ {t('admin.partners.actions.review')} +

+

{displayName}

+
+
+ +
+ {/* Application Details */} +
+

+ {t('admin.partners.tabs.applications')} +

+
+
+
+
+ {displayName} + {app.username && @{app.username}} +
+
+
+ +
+ {app.company_name && ( +
+ + {t('admin.partners.applicationFields.companyName')}: + {' '} + {app.company_name} +
+ )} + {app.website_url && ( +
+ + {t('admin.partners.applicationFields.website')}: + {' '} + {app.website_url} +
+ )} + {app.telegram_channel && ( +
+ + {t('admin.partners.applicationFields.channel')}: + {' '} + {app.telegram_channel} +
+ )} + {app.description && ( +
+ + {t('admin.partners.applicationFields.description')}: + {' '} + {app.description} +
+ )} + {app.expected_monthly_referrals != null && ( +
+ + {t('admin.partners.applicationFields.expectedReferrals')}: + {' '} + {app.expected_monthly_referrals} +
+ )} +
+
+
+ + {/* Approve Section */} +
+

+ {t('admin.partners.approveDialog.title')} +

+

+ {t('admin.partners.approveDialog.description', { name: displayName })} +

+ + setCommission(e.target.value)} + className="mb-4 w-full rounded-lg border border-dark-600 bg-dark-700 px-3 py-2 text-dark-100 outline-none focus:border-accent-500" + placeholder="10" + /> + +
+ + {approveMutation.isError && ( +
+ {t('common.error')} +
+ )} + + {/* Reject Section */} +
+

+ {t('admin.partners.rejectDialog.title')} +

+

+ {t('admin.partners.rejectDialog.description', { name: displayName })} +

+ +