mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +02:00
Check if saas before blocking credit insufficiencies (#5929)
fixes #5926
This commit is contained in:
+1
-1
@@ -78,7 +78,7 @@ springBoot {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = 'stirling.software'
|
group = 'stirling.software'
|
||||||
version = '2.7.1'
|
version = '2.7.2'
|
||||||
|
|
||||||
configurations.configureEach {
|
configurations.configureEach {
|
||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
||||||
|
import { useSaaSMode } from '@app/hooks/useSaaSMode';
|
||||||
import { BILLING_CONFIG } from '@app/config/billing';
|
import { BILLING_CONFIG } from '@app/config/billing';
|
||||||
import { CreditExhaustedModal } from '@app/components/shared/modals/CreditExhaustedModal';
|
import { CreditExhaustedModal } from '@app/components/shared/modals/CreditExhaustedModal';
|
||||||
import { InsufficientCreditsModal } from '@app/components/shared/modals/InsufficientCreditsModal';
|
import { InsufficientCreditsModal } from '@app/components/shared/modals/InsufficientCreditsModal';
|
||||||
@@ -19,16 +20,17 @@ export function CreditModalBootstrap() {
|
|||||||
requiredCredits?: number;
|
requiredCredits?: number;
|
||||||
}>({});
|
}>({});
|
||||||
|
|
||||||
|
const isSaaSMode = useSaaSMode();
|
||||||
const { creditBalance, isManagedTeamMember, lastFetchTime, plansLastFetchTime, refreshPlans } = useSaaSBilling();
|
const { creditBalance, isManagedTeamMember, lastFetchTime, plansLastFetchTime, refreshPlans } = useSaaSBilling();
|
||||||
|
|
||||||
// Preload plan pricing when billing confirms credits are low.
|
// Preload plan pricing when billing confirms credits are low.
|
||||||
// Fires once: only when billing has loaded (lastFetchTime set) and plans haven't been
|
// Fires once: only when in SaaS mode, billing has loaded (lastFetchTime set) and plans haven't been
|
||||||
// fetched yet (plansLastFetchTime null). This way the modal shows real prices instantly.
|
// fetched yet (plansLastFetchTime null). This way the modal shows real prices instantly.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lastFetchTime !== null && plansLastFetchTime === null && creditBalance < BILLING_CONFIG.PLAN_PRICING_PRELOAD_THRESHOLD && !isManagedTeamMember) {
|
if (isSaaSMode && lastFetchTime !== null && plansLastFetchTime === null && creditBalance < BILLING_CONFIG.PLAN_PRICING_PRELOAD_THRESHOLD && !isManagedTeamMember) {
|
||||||
refreshPlans();
|
refreshPlans();
|
||||||
}
|
}
|
||||||
}, [lastFetchTime, plansLastFetchTime, creditBalance, isManagedTeamMember, refreshPlans]);
|
}, [isSaaSMode, lastFetchTime, plansLastFetchTime, creditBalance, isManagedTeamMember, refreshPlans]);
|
||||||
|
|
||||||
// Monitor credit balance and dispatch events
|
// Monitor credit balance and dispatch events
|
||||||
useCreditEvents();
|
useCreditEvents();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
||||||
|
import { useSaaSMode } from '@app/hooks/useSaaSMode';
|
||||||
import { getToolCreditCost } from '@app/utils/creditCosts';
|
import { getToolCreditCost } from '@app/utils/creditCosts';
|
||||||
import { CREDIT_EVENTS } from '@app/constants/creditEvents';
|
import { CREDIT_EVENTS } from '@app/constants/creditEvents';
|
||||||
import type { ToolId } from '@app/types/toolId';
|
import type { ToolId } from '@app/types/toolId';
|
||||||
@@ -16,9 +17,11 @@ import type { ToolId } from '@app/types/toolId';
|
|||||||
*/
|
*/
|
||||||
export function useCreditCheck(operationType?: string) {
|
export function useCreditCheck(operationType?: string) {
|
||||||
const billing = useSaaSBilling();
|
const billing = useSaaSBilling();
|
||||||
|
const isSaaSMode = useSaaSMode();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const checkCredits = useCallback(async (): Promise<string | null> => {
|
const checkCredits = useCallback(async (): Promise<string | null> => {
|
||||||
|
if (!isSaaSMode) return null; // Credits only apply in SaaS mode, not self-hosted
|
||||||
if (!billing) return null;
|
if (!billing) return null;
|
||||||
|
|
||||||
const { creditBalance, loading } = billing;
|
const { creditBalance, loading } = billing;
|
||||||
@@ -41,7 +44,7 @@ export function useCreditCheck(operationType?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}, [billing, operationType, t]);
|
}, [billing, isSaaSMode, operationType, t]);
|
||||||
|
|
||||||
return { checkCredits };
|
return { checkCredits };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
import { useSaaSBilling } from '@app/contexts/SaasBillingContext';
|
||||||
|
import { useSaaSMode } from '@app/hooks/useSaaSMode';
|
||||||
import { CREDIT_EVENTS } from '@app/constants/creditEvents';
|
import { CREDIT_EVENTS } from '@app/constants/creditEvents';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Desktop hook that monitors credit balance and dispatches events
|
* Desktop hook that monitors credit balance and dispatches events
|
||||||
* when credits are exhausted or low
|
* when credits are exhausted or low.
|
||||||
|
* Only active in SaaS mode — self-hosted users have no credit balance.
|
||||||
*/
|
*/
|
||||||
export function useCreditEvents() {
|
export function useCreditEvents() {
|
||||||
|
const isSaaSMode = useSaaSMode();
|
||||||
const { creditBalance } = useSaaSBilling();
|
const { creditBalance } = useSaaSBilling();
|
||||||
const prevBalanceRef = useRef(creditBalance);
|
const prevBalanceRef = useRef(creditBalance);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prevBalance = prevBalanceRef.current;
|
const prevBalance = prevBalanceRef.current;
|
||||||
|
|
||||||
// Dispatch exhausted event when credits reach 0 from positive balance
|
// Dispatch exhausted event when credits reach 0 from positive balance.
|
||||||
if (creditBalance <= 0 && prevBalance > 0) {
|
// Skip entirely in self-hosted mode — creditBalance defaults to 0 there.
|
||||||
|
if (isSaaSMode && creditBalance <= 0 && prevBalance > 0) {
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent(CREDIT_EVENTS.EXHAUSTED, {
|
new CustomEvent(CREDIT_EVENTS.EXHAUSTED, {
|
||||||
detail: { previousBalance: prevBalance, currentBalance: creditBalance },
|
detail: { previousBalance: prevBalance, currentBalance: creditBalance },
|
||||||
@@ -24,5 +28,5 @@ export function useCreditEvents() {
|
|||||||
|
|
||||||
// Update ref for next comparison
|
// Update ref for next comparison
|
||||||
prevBalanceRef.current = creditBalance;
|
prevBalanceRef.current = creditBalance;
|
||||||
}, [creditBalance]);
|
}, [isSaaSMode, creditBalance]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user