mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
refactor(subscription): extract DeleteSubscriptionSheet from god page
Move the delete-subscription expand/confirm block into src/components/subscription/sheets/DeleteSubscriptionSheet.tsx. The sheet itself decides between the Telegram destructive native dialog and the inline web confirm panel, so the parent no longer needs the platform discriminator. It owns deleteLoading and the API call; the parent passes onDeleted (navigate + invalidate) and the textSecondary glass color token used in the warning copy. Subscription.tsx: 1828 → 1750 lines. Drops now-unused imports (usePlatform; deleteLoading state).
This commit is contained in:
@@ -6,7 +6,6 @@ import { subscriptionApi } from '../api/subscription';
|
||||
import { DEVICE_ALIAS_MAX_LENGTH } from '../constants/devices';
|
||||
import { WebBackButton } from '../components/WebBackButton';
|
||||
import { useDestructiveConfirm } from '../platform/hooks/useNativeDialog';
|
||||
import { usePlatform } from '../platform';
|
||||
import TrafficProgressBar from '../components/dashboard/TrafficProgressBar';
|
||||
import { HoverBorderGradient } from '../components/ui/hover-border-gradient';
|
||||
import { useTrafficZone } from '../hooks/useTrafficZone';
|
||||
@@ -31,6 +30,7 @@ import { DeviceTopupSheet } from '../components/subscription/sheets/DeviceTopupS
|
||||
import { DeviceReductionSheet } from '../components/subscription/sheets/DeviceReductionSheet';
|
||||
import { TrafficTopupSheet } from '../components/subscription/sheets/TrafficTopupSheet';
|
||||
import { ServerManagementSheet } from '../components/subscription/sheets/ServerManagementSheet';
|
||||
import { DeleteSubscriptionSheet } from '../components/subscription/sheets/DeleteSubscriptionSheet';
|
||||
|
||||
/** Isolated countdown so 1s interval doesn't re-render the whole page */
|
||||
const CountdownTimer = memo(function CountdownTimer({
|
||||
@@ -195,8 +195,6 @@ export default function Subscription() {
|
||||
const haptic = useHaptic();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [showDeleteSheet, setShowDeleteSheet] = useState(false);
|
||||
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||
const { platform } = usePlatform();
|
||||
const destructiveConfirm = useDestructiveConfirm();
|
||||
|
||||
// Helper to format price from kopeks
|
||||
@@ -1340,93 +1338,17 @@ export default function Subscription() {
|
||||
!subscription.is_trial &&
|
||||
!subscription.is_limited && (
|
||||
<div className="space-y-3">
|
||||
{!showDeleteSheet ? (
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (platform === 'telegram') {
|
||||
const confirmed = await destructiveConfirm(
|
||||
t(
|
||||
'subscription.deleteWarning',
|
||||
'Подписка будет удалена безвозвратно. Все данные, устройства и настройки будут потеряны.',
|
||||
),
|
||||
t('subscription.confirmDelete', 'Да, удалить'),
|
||||
t('subscription.deleteTitle', 'Удалить подписку?'),
|
||||
);
|
||||
if (!confirmed) return;
|
||||
setDeleteLoading(true);
|
||||
try {
|
||||
await subscriptionApi.deleteSubscription(subscription.id);
|
||||
queryClient.invalidateQueries({ queryKey: ['subscriptions-list'] });
|
||||
navigate('/subscriptions', { replace: true });
|
||||
} catch {
|
||||
setDeleteLoading(false);
|
||||
}
|
||||
} else {
|
||||
setShowDeleteSheet(true);
|
||||
}
|
||||
}}
|
||||
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"
|
||||
>
|
||||
<svg
|
||||
className="h-4 w-4"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
{t('subscription.delete', 'Удалить подписку')}
|
||||
</button>
|
||||
) : (
|
||||
<div
|
||||
className="rounded-2xl border border-error-400/20 p-4"
|
||||
style={{ background: 'rgba(255,59,92,0.04)' }}
|
||||
>
|
||||
<div className="mb-3 text-sm font-semibold text-error-400">
|
||||
{t('subscription.deleteTitle', 'Удалить подписку?')}
|
||||
</div>
|
||||
<div className="mb-4 text-xs" style={{ color: g.textSecondary }}>
|
||||
{t(
|
||||
'subscription.deleteWarning',
|
||||
'Подписка будет удалена безвозвратно. Все данные, устройства и настройки будут потеряны. Это действие нельзя отменить.',
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={async () => {
|
||||
setDeleteLoading(true);
|
||||
try {
|
||||
await subscriptionApi.deleteSubscription(subscription.id);
|
||||
queryClient.invalidateQueries({ queryKey: ['subscriptions-list'] });
|
||||
navigate('/subscriptions', { replace: true });
|
||||
} catch {
|
||||
setDeleteLoading(false);
|
||||
setShowDeleteSheet(false);
|
||||
}
|
||||
}}
|
||||
disabled={deleteLoading}
|
||||
className="flex-1 rounded-xl bg-error-500 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-error-600 disabled:opacity-50"
|
||||
>
|
||||
{deleteLoading
|
||||
? t('common.processing', 'Удаление...')
|
||||
: t('subscription.confirmDelete', 'Да, удалить')}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowDeleteSheet(false)}
|
||||
className="flex-1 rounded-xl border border-dark-700 py-2.5 text-sm font-medium transition-colors hover:bg-dark-700"
|
||||
style={{ color: g.textSecondary }}
|
||||
>
|
||||
{t('common.cancel', 'Отмена')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<DeleteSubscriptionSheet
|
||||
subscriptionId={subscription.id}
|
||||
open={showDeleteSheet}
|
||||
onOpen={() => setShowDeleteSheet(true)}
|
||||
onClose={() => setShowDeleteSheet(false)}
|
||||
textSecondary={g.textSecondary}
|
||||
onDeleted={() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['subscriptions-list'] });
|
||||
navigate('/subscriptions', { replace: true });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user