Disable admin plan section when no login (#5039)

Admin plan section matches other admin sections

<img width="1013" height="629" alt="image"
src="https://github.com/user-attachments/assets/39e9fad7-461c-491d-99cb-4b140292f2f4"
/>
<img width="730" height="595" alt="image"
src="https://github.com/user-attachments/assets/b26354d2-5401-40b3-8ca7-3b48b26b644e"
/>
This commit is contained in:
ConnorYoh 2025-11-27 13:57:04 +00:00 committed by GitHub
parent f63df148ad
commit 04c4aec0d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 7 deletions

View File

@ -13,9 +13,12 @@ import { InfoBanner } from '@app/components/shared/InfoBanner';
import { useLicenseAlert } from '@app/hooks/useLicenseAlert';
import { isSupabaseConfigured } from '@app/services/supabaseClient';
import { getPreferredCurrency, setCachedCurrency } from '@app/utils/currencyDetection';
import { useLoginRequired } from '@app/hooks/useLoginRequired';
import LoginRequiredBanner from '@core/components/shared/config/LoginRequiredBanner';
const AdminPlanSection: React.FC = () => {
const { t, i18n } = useTranslation();
const { loginEnabled, validateLoginEnabled } = useLoginRequired();
const { openCheckout } = useCheckout();
const { licenseInfo, refetchLicense } = useLicense();
const [currency, setCurrency] = useState<string>(() => {
@ -39,6 +42,11 @@ const AdminPlanSection: React.FC = () => {
}, [error]);
const handleSaveLicense = async () => {
// Block save if login is disabled
if (!validateLoginEnabled()) {
return;
}
try {
setSavingLicense(true);
// Allow empty string to clear/remove license
@ -86,6 +94,11 @@ const AdminPlanSection: React.FC = () => {
];
const handleManageClick = useCallback(async () => {
// Block access if login is disabled
if (!validateLoginEnabled()) {
return;
}
try {
// Only allow PRO or ENTERPRISE licenses to access billing portal
if (!licenseInfo?.licenseType || licenseInfo.licenseType === 'NORMAL') {
@ -112,7 +125,7 @@ const AdminPlanSection: React.FC = () => {
body: error.message || 'Please try again or contact support.',
});
}
}, [licenseInfo, t]);
}, [licenseInfo, t, validateLoginEnabled]);
const handleCurrencyChange = useCallback((newCurrency: string) => {
setCurrency(newCurrency);
@ -122,6 +135,11 @@ const AdminPlanSection: React.FC = () => {
const handleUpgradeClick = useCallback(
(planGroup: PlanTierGroup) => {
// Block access if login is disabled
if (!validateLoginEnabled()) {
return;
}
// Only allow upgrades for server and enterprise tiers
if (planGroup.tier === 'free') {
return;
@ -151,7 +169,7 @@ const AdminPlanSection: React.FC = () => {
},
});
},
[openCheckout, currency, refetch, licenseInfo, t]
[openCheckout, currency, refetch, licenseInfo, t, validateLoginEnabled]
);
const shouldShowLicenseWarning = licenseAlert.active && licenseAlert.audience === 'admin';
@ -200,7 +218,9 @@ const AdminPlanSection: React.FC = () => {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
{shouldShowLicenseWarning && (
<LoginRequiredBanner show={!loginEnabled} />
{shouldShowLicenseWarning && (
<InfoBanner
icon="warning-rounded"
tone="warning"
@ -231,6 +251,7 @@ const AdminPlanSection: React.FC = () => {
currency={currency}
onCurrencyChange={handleCurrencyChange}
currencyOptions={currencyOptions}
loginEnabled={loginEnabled}
/>
<Divider />
@ -288,11 +309,11 @@ const AdminPlanSection: React.FC = () => {
onChange={(e) => setLicenseKeyInput(e.target.value)}
placeholder={licenseInfo?.licenseKey || '00000000-0000-0000-0000-000000000000'}
type="password"
disabled={savingLicense}
disabled={!loginEnabled || savingLicense}
/>
<Group justify="flex-end">
<Button onClick={handleSaveLicense} loading={savingLicense} size="sm">
<Button onClick={handleSaveLicense} loading={savingLicense} size="sm" disabled={!loginEnabled}>
{t('admin.settings.save', 'Save Changes')}
</Button>
</Group>

View File

@ -15,6 +15,7 @@ interface AvailablePlansSectionProps {
currency?: string;
onCurrencyChange?: (currency: string) => void;
currencyOptions?: { value: string; label: string }[];
loginEnabled?: boolean;
}
const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
@ -25,6 +26,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
currency,
onCurrencyChange,
currencyOptions,
loginEnabled = true,
}) => {
const { t } = useTranslation();
const [showComparison, setShowComparison] = useState(false);
@ -91,6 +93,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
clearable={false}
w={300}
comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }}
disabled={!loginEnabled}
/>
)}
</Group>
@ -113,6 +116,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
currentTier={currentTier}
onUpgradeClick={onUpgradeClick}
onManageClick={onManageClick}
loginEnabled={loginEnabled}
/>
))}
</div>

View File

@ -15,9 +15,10 @@ interface PlanCardProps {
currentTier?: 'free' | 'server' | 'enterprise' | null;
onUpgradeClick: (planGroup: PlanTierGroup) => void;
onManageClick?: () => void;
loginEnabled?: boolean;
}
const PlanCard: React.FC<PlanCardProps> = ({ planGroup, isCurrentTier, isDowngrade, currentLicenseInfo, currentTier, onUpgradeClick, onManageClick }) => {
const PlanCard: React.FC<PlanCardProps> = ({ planGroup, isCurrentTier, isDowngrade, currentLicenseInfo, currentTier, onUpgradeClick, onManageClick, loginEnabled = true }) => {
const { t } = useTranslation();
// Render Free plan
@ -174,7 +175,7 @@ const PlanCard: React.FC<PlanCardProps> = ({ planGroup, isCurrentTier, isDowngra
variant={isCurrentTier ? 'filled' : isDowngrade ? 'filled' : isEnterpriseBlockedForFree ? 'light' : 'filled'}
fullWidth
onClick={() => isCurrentTier && onManageClick ? onManageClick() : onUpgradeClick(planGroup)}
disabled={isDowngrade || isEnterpriseBlockedForFree}
disabled={!loginEnabled || isDowngrade || isEnterpriseBlockedForFree}
>
{isCurrentTier
? t('plan.manage', 'Manage')