Compare commits

...

1 Commits

Author SHA1 Message Date
Florian Rival
59c48d52f7 Change how bundle price is calculated to avoid API calls 2025-08-01 12:45:40 +02:00
7 changed files with 36 additions and 46 deletions

View File

@@ -255,13 +255,9 @@ const getColumnsFromWindowSize = (windowSize: WindowSizeType) => {
type Props = {|
onDisplayBundle: (bundleListingData: BundleListingData) => void,
getSubscriptionPlansWithPricingSystems: () => Array<SubscriptionPlanWithPricingSystems> | null,
|};
const BundlePreviewBanner = ({
onDisplayBundle,
getSubscriptionPlansWithPricingSystems,
}: Props) => {
const BundlePreviewBanner = ({ onDisplayBundle }: Props) => {
const { isMobile, isLandscape, windowSize } = useResponsiveWindowSize();
const numberOfTilesToDisplay = getColumnsFromWindowSize(windowSize) - 1; // Reserve one tile for the bundle preview.
const { privateGameTemplateListingDatas } = React.useContext(
@@ -339,8 +335,6 @@ const BundlePreviewBanner = ({
]
);
const subscriptionPlansWithPricingSystems = getSubscriptionPlansWithPricingSystems();
const redemptionCodesIncludedInBundle = React.useMemo(
() =>
bundleListingData
@@ -496,7 +490,6 @@ const BundlePreviewBanner = ({
bundleListingData,
productListingDatasIncludedInBundle,
redemptionCodesIncludedInBundle,
subscriptionPlansWithPricingSystems,
})}
</span>
</Text>

View File

@@ -8,14 +8,12 @@ import {
type CreditsPackageListingData,
type IncludedRedemptionCode,
} from '../../Utils/GDevelopServices/Shop';
import { type SubscriptionPlanWithPricingSystems } from '../../Utils/GDevelopServices/Usage';
export const renderEstimatedTotalPriceFormatted = ({
i18n,
bundleListingData,
productListingDatasIncludedInBundle,
redemptionCodesIncludedInBundle,
subscriptionPlansWithPricingSystems,
}: {
i18n: I18nType,
bundleListingData: ?BundleListingData,
@@ -27,14 +25,12 @@ export const renderEstimatedTotalPriceFormatted = ({
| CreditsPackageListingData
>,
redemptionCodesIncludedInBundle: ?Array<IncludedRedemptionCode>,
subscriptionPlansWithPricingSystems: ?Array<SubscriptionPlanWithPricingSystems>,
}): ?string => {
let totalPrice = 0;
if (
!bundleListingData ||
!productListingDatasIncludedInBundle ||
!redemptionCodesIncludedInBundle ||
!subscriptionPlansWithPricingSystems
!redemptionCodesIncludedInBundle
)
return null;
@@ -106,19 +102,33 @@ export const renderEstimatedTotalPriceFormatted = ({
for (const redemptionCode of redemptionCodesIncludedInBundle) {
const planId = redemptionCode.givenSubscriptionPlanId;
if (planId) {
const subscriptionPlanWithPricingSystems = subscriptionPlansWithPricingSystems.find(
plan => plan.id === planId
);
if (subscriptionPlanWithPricingSystems) {
const monthlyPricingSystem = subscriptionPlanWithPricingSystems.pricingSystems.find(
pricingSystem => pricingSystem.period === 'month'
let estimatedAmountInCents = null;
if (redemptionCode.estimatedPrices) {
const estimatedPrice = redemptionCode.estimatedPrices.find(
price => price.currency === currencyCode
);
if (monthlyPricingSystem) {
totalPrice +=
monthlyPricingSystem.amountInCents *
Math.round(redemptionCode.durationInDays / 30);
if (estimatedPrice) {
estimatedAmountInCents = estimatedPrice.value;
}
}
// If no estimated price is provided, guess a mostly correct value
// for backward compatibility.
if (estimatedAmountInCents === null) {
const monthlyEstimatedAmountInCents =
planId === 'gdevelop_silver'
? 599
: planId === 'gdevelop_gold'
? 1099
: planId === 'gdevelop_startup'
? 3499
: 0;
estimatedAmountInCents =
monthlyEstimatedAmountInCents *
Math.max(1, Math.round(redemptionCode.durationInDays / 30));
}
totalPrice += estimatedAmountInCents || 0;
}
}
}

View File

@@ -8,7 +8,6 @@ import {
type CourseChapter,
} from '../../../../Utils/GDevelopServices/Asset';
import type { BundleListingData } from '../../../../Utils/GDevelopServices/Shop';
import { type SubscriptionPlanWithPricingSystems } from '../../../../Utils/GDevelopServices/Usage';
import CoursePreviewBanner from '../../../../Course/CoursePreviewBanner';
import type { CourseCompletion, CourseChapterCompletion } from '../UseCourses';
import { Line } from '../../../../UI/Grid';
@@ -46,7 +45,6 @@ type Props = {|
courseId: string,
chapterId: string
) => CourseChapterCompletion | null,
getSubscriptionPlansWithPricingSystems: () => Array<SubscriptionPlanWithPricingSystems> | null,
|};
const CoursesPage = ({
@@ -58,7 +56,6 @@ const CoursesPage = ({
getCourseChapters,
getCourseChapterCompletion,
getCourseCompletion,
getSubscriptionPlansWithPricingSystems,
}: Props) => {
const { listedCourses } = React.useContext(CourseStoreContext);
const { windowSize, isLandscape } = useResponsiveWindowSize();
@@ -132,12 +129,7 @@ const CoursesPage = ({
</SectionRow>
{!hidePremiumProducts && (
<SectionRow>
<BundlePreviewBanner
onDisplayBundle={onSelectBundle}
getSubscriptionPlansWithPricingSystems={
getSubscriptionPlansWithPricingSystems
}
/>
<BundlePreviewBanner onDisplayBundle={onSelectBundle} />
</SectionRow>
)}
{courses && listedCourses && courses.length > numberOfItemsOnOneRow && (

View File

@@ -80,7 +80,6 @@ type Props = {|
privateGameTemplateListingData: PrivateGameTemplateListingData
) => void,
onSelectExampleShortHeader: (exampleShortHeader: ExampleShortHeader) => void,
getSubscriptionPlansWithPricingSystems: () => Array<SubscriptionPlanWithPricingSystems> | null,
|};
const MainPage = ({
@@ -95,7 +94,6 @@ const MainPage = ({
onOpenNewProjectSetupDialog,
onSelectPrivateGameTemplateListingData,
onSelectExampleShortHeader,
getSubscriptionPlansWithPricingSystems,
}: Props) => {
const { limits } = React.useContext(AuthenticatedUserContext);
const {
@@ -243,12 +241,7 @@ const MainPage = ({
</SectionRow>
{!hidePremiumProducts && (
<SectionRow>
<BundlePreviewBanner
onDisplayBundle={onSelectBundle}
getSubscriptionPlansWithPricingSystems={
getSubscriptionPlansWithPricingSystems
}
/>
<BundlePreviewBanner onDisplayBundle={onSelectBundle} />
</SectionRow>
)}
<SectionRow>

View File

@@ -235,9 +235,6 @@ const LearnSection = ({
onSelectPrivateGameTemplateListingData
}
onSelectExampleShortHeader={onSelectExampleShortHeader}
getSubscriptionPlansWithPricingSystems={
getSubscriptionPlansWithPricingSystems
}
/>
) : selectedCategory === 'all-tutorials' ? (
<TutorialsPage onSelectCategory={onSelectCategory} />
@@ -256,9 +253,6 @@ const LearnSection = ({
getCourseChapters={getCourseChapters}
getCourseCompletion={getCourseCompletion}
getCourseChapterCompletion={getCourseChapterCompletion}
getSubscriptionPlansWithPricingSystems={
getSubscriptionPlansWithPricingSystems
}
/>
) : (
<TutorialsCategoryPage

View File

@@ -147,6 +147,10 @@ export type IncludedProduct = {|
export type IncludedRedemptionCode = {|
givenSubscriptionPlanId: string,
durationInDays: number,
estimatedPrices?: Array<{
value: number,
currency: 'USD' | 'EUR',
}>,
|};
export type Bundle = {|

View File

@@ -48,6 +48,10 @@ export type IncludedListableProduct = {|
export type IncludedRedemptionCode = {|
givenSubscriptionPlanId: string,
durationInDays: number,
estimatedPrices?: Array<{
value: number,
currency: 'USD' | 'EUR',
}>,
|};
export type ProductListingData = {|