mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +02:00
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:
+25
-4
@@ -13,9 +13,12 @@ import { InfoBanner } from '@app/components/shared/InfoBanner';
|
|||||||
import { useLicenseAlert } from '@app/hooks/useLicenseAlert';
|
import { useLicenseAlert } from '@app/hooks/useLicenseAlert';
|
||||||
import { isSupabaseConfigured } from '@app/services/supabaseClient';
|
import { isSupabaseConfigured } from '@app/services/supabaseClient';
|
||||||
import { getPreferredCurrency, setCachedCurrency } from '@app/utils/currencyDetection';
|
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 AdminPlanSection: React.FC = () => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
const { loginEnabled, validateLoginEnabled } = useLoginRequired();
|
||||||
const { openCheckout } = useCheckout();
|
const { openCheckout } = useCheckout();
|
||||||
const { licenseInfo, refetchLicense } = useLicense();
|
const { licenseInfo, refetchLicense } = useLicense();
|
||||||
const [currency, setCurrency] = useState<string>(() => {
|
const [currency, setCurrency] = useState<string>(() => {
|
||||||
@@ -39,6 +42,11 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
const handleSaveLicense = async () => {
|
const handleSaveLicense = async () => {
|
||||||
|
// Block save if login is disabled
|
||||||
|
if (!validateLoginEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setSavingLicense(true);
|
setSavingLicense(true);
|
||||||
// Allow empty string to clear/remove license
|
// Allow empty string to clear/remove license
|
||||||
@@ -86,6 +94,11 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const handleManageClick = useCallback(async () => {
|
const handleManageClick = useCallback(async () => {
|
||||||
|
// Block access if login is disabled
|
||||||
|
if (!validateLoginEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Only allow PRO or ENTERPRISE licenses to access billing portal
|
// Only allow PRO or ENTERPRISE licenses to access billing portal
|
||||||
if (!licenseInfo?.licenseType || licenseInfo.licenseType === 'NORMAL') {
|
if (!licenseInfo?.licenseType || licenseInfo.licenseType === 'NORMAL') {
|
||||||
@@ -112,7 +125,7 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
body: error.message || 'Please try again or contact support.',
|
body: error.message || 'Please try again or contact support.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [licenseInfo, t]);
|
}, [licenseInfo, t, validateLoginEnabled]);
|
||||||
|
|
||||||
const handleCurrencyChange = useCallback((newCurrency: string) => {
|
const handleCurrencyChange = useCallback((newCurrency: string) => {
|
||||||
setCurrency(newCurrency);
|
setCurrency(newCurrency);
|
||||||
@@ -122,6 +135,11 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
|
|
||||||
const handleUpgradeClick = useCallback(
|
const handleUpgradeClick = useCallback(
|
||||||
(planGroup: PlanTierGroup) => {
|
(planGroup: PlanTierGroup) => {
|
||||||
|
// Block access if login is disabled
|
||||||
|
if (!validateLoginEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Only allow upgrades for server and enterprise tiers
|
// Only allow upgrades for server and enterprise tiers
|
||||||
if (planGroup.tier === 'free') {
|
if (planGroup.tier === 'free') {
|
||||||
return;
|
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';
|
const shouldShowLicenseWarning = licenseAlert.active && licenseAlert.audience === 'admin';
|
||||||
@@ -200,6 +218,8 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
||||||
|
<LoginRequiredBanner show={!loginEnabled} />
|
||||||
|
|
||||||
{shouldShowLicenseWarning && (
|
{shouldShowLicenseWarning && (
|
||||||
<InfoBanner
|
<InfoBanner
|
||||||
icon="warning-rounded"
|
icon="warning-rounded"
|
||||||
@@ -231,6 +251,7 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
currency={currency}
|
currency={currency}
|
||||||
onCurrencyChange={handleCurrencyChange}
|
onCurrencyChange={handleCurrencyChange}
|
||||||
currencyOptions={currencyOptions}
|
currencyOptions={currencyOptions}
|
||||||
|
loginEnabled={loginEnabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -288,11 +309,11 @@ const AdminPlanSection: React.FC = () => {
|
|||||||
onChange={(e) => setLicenseKeyInput(e.target.value)}
|
onChange={(e) => setLicenseKeyInput(e.target.value)}
|
||||||
placeholder={licenseInfo?.licenseKey || '00000000-0000-0000-0000-000000000000'}
|
placeholder={licenseInfo?.licenseKey || '00000000-0000-0000-0000-000000000000'}
|
||||||
type="password"
|
type="password"
|
||||||
disabled={savingLicense}
|
disabled={!loginEnabled || savingLicense}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Group justify="flex-end">
|
<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')}
|
{t('admin.settings.save', 'Save Changes')}
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
+4
@@ -15,6 +15,7 @@ interface AvailablePlansSectionProps {
|
|||||||
currency?: string;
|
currency?: string;
|
||||||
onCurrencyChange?: (currency: string) => void;
|
onCurrencyChange?: (currency: string) => void;
|
||||||
currencyOptions?: { value: string; label: string }[];
|
currencyOptions?: { value: string; label: string }[];
|
||||||
|
loginEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
|
const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
|
||||||
@@ -25,6 +26,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
|
|||||||
currency,
|
currency,
|
||||||
onCurrencyChange,
|
onCurrencyChange,
|
||||||
currencyOptions,
|
currencyOptions,
|
||||||
|
loginEnabled = true,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showComparison, setShowComparison] = useState(false);
|
const [showComparison, setShowComparison] = useState(false);
|
||||||
@@ -91,6 +93,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
|
|||||||
clearable={false}
|
clearable={false}
|
||||||
w={300}
|
w={300}
|
||||||
comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }}
|
comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }}
|
||||||
|
disabled={!loginEnabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
@@ -113,6 +116,7 @@ const AvailablePlansSection: React.FC<AvailablePlansSectionProps> = ({
|
|||||||
currentTier={currentTier}
|
currentTier={currentTier}
|
||||||
onUpgradeClick={onUpgradeClick}
|
onUpgradeClick={onUpgradeClick}
|
||||||
onManageClick={onManageClick}
|
onManageClick={onManageClick}
|
||||||
|
loginEnabled={loginEnabled}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ interface PlanCardProps {
|
|||||||
currentTier?: 'free' | 'server' | 'enterprise' | null;
|
currentTier?: 'free' | 'server' | 'enterprise' | null;
|
||||||
onUpgradeClick: (planGroup: PlanTierGroup) => void;
|
onUpgradeClick: (planGroup: PlanTierGroup) => void;
|
||||||
onManageClick?: () => 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();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// Render Free plan
|
// Render Free plan
|
||||||
@@ -174,7 +175,7 @@ const PlanCard: React.FC<PlanCardProps> = ({ planGroup, isCurrentTier, isDowngra
|
|||||||
variant={isCurrentTier ? 'filled' : isDowngrade ? 'filled' : isEnterpriseBlockedForFree ? 'light' : 'filled'}
|
variant={isCurrentTier ? 'filled' : isDowngrade ? 'filled' : isEnterpriseBlockedForFree ? 'light' : 'filled'}
|
||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => isCurrentTier && onManageClick ? onManageClick() : onUpgradeClick(planGroup)}
|
onClick={() => isCurrentTier && onManageClick ? onManageClick() : onUpgradeClick(planGroup)}
|
||||||
disabled={isDowngrade || isEnterpriseBlockedForFree}
|
disabled={!loginEnabled || isDowngrade || isEnterpriseBlockedForFree}
|
||||||
>
|
>
|
||||||
{isCurrentTier
|
{isCurrentTier
|
||||||
? t('plan.manage', 'Manage')
|
? t('plan.manage', 'Manage')
|
||||||
|
|||||||
Reference in New Issue
Block a user