mirror of
https://github.com/PostHog/posthog.git
synced 2024-11-21 13:39:22 +01:00
feat: add self serve credit override (#26260)
This commit is contained in:
parent
02d74072a4
commit
f34872115c
@ -230,6 +230,7 @@ export const FEATURE_FLAGS = {
|
||||
EDIT_DWH_SOURCE_CONFIG: 'edit_dwh_source_config', // owner: @Gilbert09 #team-data-warehouse
|
||||
AI_SURVEY_RESPONSE_SUMMARY: 'ai-survey-response-summary', // owner: @pauldambra
|
||||
CUSTOM_CHANNEL_TYPE_RULES: 'custom-channel-type-rules', // owner: @robbie-c #team-web-analytics
|
||||
SELF_SERVE_CREDIT_OVERRIDE: 'self-serve-credit-override', // owner: @zach
|
||||
EXPERIMENTS_MIGRATION_DISABLE_UI: 'experiments-migration-disable-ui', // owner: @jurajmajerik #team-experiments
|
||||
} as const
|
||||
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]
|
||||
|
@ -2,19 +2,25 @@ import { IconX } from '@posthog/icons'
|
||||
import { LemonButton, LemonDivider } from '@posthog/lemon-ui'
|
||||
import { useActions, useValues } from 'kea'
|
||||
import { BurningMoneyHog } from 'lib/components/hedgehogs'
|
||||
import { FEATURE_FLAGS } from 'lib/constants'
|
||||
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
|
||||
import useResizeObserver from 'use-resize-observer'
|
||||
|
||||
import { billingLogic } from './billingLogic'
|
||||
import { PurchaseCreditsModal } from './PurchaseCreditsModal'
|
||||
|
||||
export const DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD = 500
|
||||
|
||||
export const CreditCTAHero = (): JSX.Element | null => {
|
||||
const { width, ref: heroRef } = useResizeObserver()
|
||||
const { featureFlags } = useValues(featureFlagLogic)
|
||||
|
||||
const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } =
|
||||
useValues(billingLogic)
|
||||
const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic)
|
||||
|
||||
if (!creditOverview.eligible || creditOverview.status === 'paid') {
|
||||
const isEligible = creditOverview.eligible || featureFlags[FEATURE_FLAGS.SELF_SERVE_CREDIT_OVERRIDE]
|
||||
if (creditOverview.status === 'paid' || !isEligible) {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -37,6 +43,8 @@ export const CreditCTAHero = (): JSX.Element | null => {
|
||||
)
|
||||
}
|
||||
|
||||
const estimatedMonthlyCreditAmountUsd =
|
||||
creditOverview?.estimated_monthly_credit_amount_usd || DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD
|
||||
return (
|
||||
<div
|
||||
className="flex relative justify-between items-start rounded-lg bg-bg-light border mb-2 gap-2"
|
||||
@ -56,7 +64,7 @@ export const CreditCTAHero = (): JSX.Element | null => {
|
||||
</div>
|
||||
)}
|
||||
<div className="p-4 flex-1">
|
||||
{creditOverview.eligible && creditOverview.status === 'pending' && (
|
||||
{isEligible && creditOverview.status === 'pending' && (
|
||||
<>
|
||||
<h1 className="mb-0">We're applying your credits</h1>
|
||||
<p className="mt-2 mb-0 max-w-xl">
|
||||
@ -78,7 +86,7 @@ export const CreditCTAHero = (): JSX.Element | null => {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{creditOverview.eligible && creditOverview.status === 'none' && (
|
||||
{isEligible && (!creditOverview || creditOverview.status === 'none') && (
|
||||
<>
|
||||
<h2 className="mb-0">
|
||||
Stop burning money.{' '}
|
||||
@ -87,20 +95,20 @@ export const CreditCTAHero = (): JSX.Element | null => {
|
||||
</h2>
|
||||
<p className="mt-2 mb-0 max-w-xl">
|
||||
Based on your usage, your monthly bill is forecasted to be an average of{' '}
|
||||
<strong>${creditOverview.estimated_monthly_credit_amount_usd.toFixed(0)}/month</strong> over
|
||||
the next year.
|
||||
<strong>${estimatedMonthlyCreditAmountUsd.toFixed(0)}/month</strong> over the next year.
|
||||
</p>
|
||||
<p className="mt-2 mb-0 max-w-xl">
|
||||
This qualifies you for a <strong>{computedDiscount * 100}% discount</strong> by
|
||||
pre-purchasing usage credits. Which gives you a net savings of{' '}
|
||||
<strong>
|
||||
$
|
||||
{Math.round(
|
||||
creditOverview.estimated_monthly_credit_amount_usd * computedDiscount * 12
|
||||
).toLocaleString('en-US', {
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
{Math.round(estimatedMonthlyCreditAmountUsd * computedDiscount * 12).toLocaleString(
|
||||
'en-US',
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
}
|
||||
)}
|
||||
</strong>{' '}
|
||||
over the next year.
|
||||
</p>
|
||||
|
@ -8,6 +8,7 @@ import { LemonRadio } from 'lib/lemon-ui/LemonRadio'
|
||||
|
||||
import { BillingGauge } from './BillingGauge'
|
||||
import { billingLogic } from './billingLogic'
|
||||
import { DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD } from './CreditCTAHero'
|
||||
import { BillingGaugeItemKind } from './types'
|
||||
|
||||
export const PurchaseCreditsModal = (): JSX.Element | null => {
|
||||
@ -16,6 +17,8 @@ export const PurchaseCreditsModal = (): JSX.Element | null => {
|
||||
const { openSupportForm } = useActions(supportLogic)
|
||||
|
||||
const creditInputValue: number = +creditForm.creditInput || 0
|
||||
const estimatedMonthlyCreditAmountUsd =
|
||||
creditOverview.estimated_monthly_credit_amount_usd || DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD
|
||||
return (
|
||||
<LemonModal
|
||||
onClose={() => showPurchaseCreditsModal(false)}
|
||||
@ -56,7 +59,7 @@ export const PurchaseCreditsModal = (): JSX.Element | null => {
|
||||
Based on your usage, we think you'll use{' '}
|
||||
<b>
|
||||
$
|
||||
{(+creditOverview.estimated_monthly_credit_amount_usd).toLocaleString('en-US', {
|
||||
{(+estimatedMonthlyCreditAmountUsd).toLocaleString('en-US', {
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
@ -64,7 +67,7 @@ export const PurchaseCreditsModal = (): JSX.Element | null => {
|
||||
of credits per month, for a total of{' '}
|
||||
<b>
|
||||
$
|
||||
{(+creditOverview.estimated_monthly_credit_amount_usd * 12).toLocaleString('en-US', {
|
||||
{(+estimatedMonthlyCreditAmountUsd * 12).toLocaleString('en-US', {
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
|
@ -18,6 +18,7 @@ import { userLogic } from 'scenes/userLogic'
|
||||
import { BillingPlanType, BillingProductV2Type, BillingType, ProductKey } from '~/types'
|
||||
|
||||
import type { billingLogicType } from './billingLogicType'
|
||||
import { DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD } from './CreditCTAHero'
|
||||
|
||||
export const ALLOCATION_THRESHOLD_ALERT = 0.85 // Threshold to show warning of event usage near limit
|
||||
export const ALLOCATION_THRESHOLD_BLOCK = 1.2 // Threshold to block usage
|
||||
@ -325,7 +326,7 @@ export const billingLogic = kea<billingLogicType>([
|
||||
creditOverview: [
|
||||
{
|
||||
eligible: false,
|
||||
estimated_monthly_credit_amount_usd: 0,
|
||||
estimated_monthly_credit_amount_usd: DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD,
|
||||
status: 'none',
|
||||
invoice_url: null,
|
||||
collection_method: null,
|
||||
@ -340,7 +341,10 @@ export const billingLogic = kea<billingLogicType>([
|
||||
if (!values.creditForm.creditInput) {
|
||||
actions.setCreditFormValue(
|
||||
'creditInput',
|
||||
Math.round(response.estimated_monthly_credit_amount_usd * 12)
|
||||
Math.round(
|
||||
(response.estimated_monthly_credit_amount_usd ||
|
||||
DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD) * 12
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -352,7 +356,7 @@ export const billingLogic = kea<billingLogicType>([
|
||||
// Return default values if not subscribed
|
||||
return {
|
||||
eligible: false,
|
||||
estimated_monthly_credit_amount_usd: 0,
|
||||
estimated_monthly_credit_amount_usd: DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD,
|
||||
status: 'none',
|
||||
invoice_url: null,
|
||||
collection_method: null,
|
||||
@ -531,7 +535,8 @@ export const billingLogic = kea<billingLogicType>([
|
||||
posthog.capture('credits cta shown', {
|
||||
eligible: creditOverview.eligible,
|
||||
status: creditOverview.status,
|
||||
estimated_monthly_credit_amount_usd: creditOverview.estimated_monthly_credit_amount_usd,
|
||||
estimated_monthly_credit_amount_usd:
|
||||
creditOverview.estimated_monthly_credit_amount_usd || DEFAULT_ESTIMATED_MONTHLY_CREDIT_AMOUNT_USD,
|
||||
})
|
||||
},
|
||||
toggleCreditCTAHeroDismissed: ({ isDismissed }) => {
|
||||
|
Loading…
Reference in New Issue
Block a user