-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: closeable credits banner (#25151)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
0a3e220
commit 2d0ade4
Showing
16 changed files
with
126 additions
and
137 deletions.
There are no files selected for viewing
Binary file modified
BIN
+440 Bytes
(100%)
...nd/__snapshots__/scenes-other-billing--billing-purchase-credits-modal--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+659 Bytes
(100%)
...d/__snapshots__/scenes-other-billing--billing-purchase-credits-modal--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+20.1 KB
(110%)
frontend/__snapshots__/scenes-other-billing--billing-with-credit-cta--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+18.8 KB
(110%)
frontend/__snapshots__/scenes-other-billing--billing-with-credit-cta--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
-32.8 KB
(71%)
frontend/__snapshots__/scenes-other-billing--billing-with-discount--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
-33.4 KB
(71%)
frontend/__snapshots__/scenes-other-billing--billing-with-discount--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
-32.9 KB
(71%)
...s__/scenes-other-billing--billing-with-limit-and-100-percent-discount--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
-33.5 KB
(70%)
...__/scenes-other-billing--billing-with-limit-and-100-percent-discount--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,7 +68,7 @@ export const BillingWithCreditCTA = (): JSX.Element => { | |
'/api/billing/credits/overview': { | ||
status: 'none', | ||
eligible: true, | ||
estimated_monthly_credit_amount_usd: '1200', | ||
estimated_monthly_credit_amount_usd: 1200, | ||
email: '[email protected]', | ||
cc_last_four: '1234', | ||
cc_brand: 'Visa', | ||
|
@@ -100,7 +100,7 @@ export const BillingPurchaseCreditsModal = (): JSX.Element => { | |
'/api/billing/credits/overview': { | ||
status: 'none', | ||
eligible: true, | ||
estimated_monthly_credit_amount_usd: '1200', | ||
estimated_monthly_credit_amount_usd: 1200, | ||
email: '[email protected]', | ||
cc_last_four: '1234', | ||
cc_brand: 'Visa', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,10 @@ | ||
import './Billing.scss' | ||
|
||
import { IconCheckCircle } from '@posthog/icons' | ||
import { LemonButton, LemonDivider, LemonInput, Link } from '@posthog/lemon-ui' | ||
import clsx from 'clsx' | ||
import { useActions, useValues } from 'kea' | ||
import { Field, Form } from 'kea-forms' | ||
import { router } from 'kea-router' | ||
import { SurprisedHog } from 'lib/components/hedgehogs' | ||
import { supportLogic } from 'lib/components/Support/supportLogic' | ||
import { dayjs } from 'lib/dayjs' | ||
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver' | ||
|
@@ -32,16 +30,8 @@ export const scene: SceneExport = { | |
} | ||
|
||
export function Billing(): JSX.Element { | ||
const { | ||
billing, | ||
billingLoading, | ||
isOnboarding, | ||
showLicenseDirectInput, | ||
isActivateLicenseSubmitting, | ||
over20kAnnual, | ||
isAnnualPlan, | ||
billingError, | ||
} = useValues(billingLogic) | ||
const { billing, billingLoading, isOnboarding, showLicenseDirectInput, isActivateLicenseSubmitting, billingError } = | ||
useValues(billingLogic) | ||
const { reportBillingShown } = useActions(billingLogic) | ||
const { preflight, isCloudOrDev } = useValues(preflightLogic) | ||
const { openSupportForm } = useActions(supportLogic) | ||
|
@@ -225,53 +215,6 @@ export function Billing(): JSX.Element { | |
</div> | ||
)} | ||
</div> | ||
{!isOnboarding && !isAnnualPlan && over20kAnnual && ( | ||
<div className="bg-[var(--glass-bg-3000)] flex flex-row gap-2 relative pl-6 p-4 border rounded min-w-120 w-fit"> | ||
<div className="flex flex-col pl-2 "> | ||
<h3>You've unlocked enterprise-grade perks:</h3> | ||
<ul className="pl-4"> | ||
<li className="flex gap-2 items-center"> | ||
<IconCheckCircle className="text-success shrink-0" /> | ||
<span> | ||
<strong>Save 20%</strong> by switching to up-front annual billing | ||
</span> | ||
</li> | ||
<li className="flex gap-2 items-center"> | ||
<IconCheckCircle className="text-success shrink-0" /> | ||
<span> | ||
Get <strong>discounts on bundled subscriptions</strong> to multiple products | ||
</span> | ||
</li> | ||
<li className="flex gap-2 items-center"> | ||
<IconCheckCircle className="text-success shrink-0" /> | ||
<span> | ||
Get <strong>customized training</strong> for you and your team | ||
</span> | ||
</li> | ||
<li className="flex gap-2 items-center"> | ||
<IconCheckCircle className="text-success shrink-0" /> | ||
<span> | ||
Get dedicated support via <strong>private Slack channel</strong> | ||
</span> | ||
</li> | ||
<li className="flex gap-2 items-center"> | ||
<IconCheckCircle className="text-success shrink-0" /> | ||
<span> | ||
We'll even send you <strong>awesome free merch</strong> | ||
</span> | ||
</li> | ||
</ul> | ||
<div className="pt-1 self-start flex flex-row gap-1 mt-2"> | ||
<LemonButton type="secondary" to="mailto:[email protected]"> | ||
Let's chat | ||
</LemonButton> | ||
</div> | ||
</div> | ||
<div className="h-24 self-end -scale-x-100 -ml-20 -mb-2"> | ||
<SurprisedHog className="max-h-full w-auto object-contain" /> | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
|
||
<LemonDivider className="mt-6 mb-8" /> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { LemonButton } from '@posthog/lemon-ui' | ||
import { IconX } from '@posthog/icons' | ||
import { LemonButton, LemonDivider } from '@posthog/lemon-ui' | ||
import { useActions, useValues } from 'kea' | ||
import { BlushingHog } from 'lib/components/hedgehogs' | ||
import { BurningMoneyHog } from 'lib/components/hedgehogs' | ||
import { FEATURE_FLAGS } from 'lib/constants' | ||
import { featureFlagLogic } from 'lib/logic/featureFlagLogic' | ||
import useResizeObserver from 'use-resize-observer' | ||
|
@@ -11,8 +12,9 @@ import { PurchaseCreditsModal } from './PurchaseCreditsModal' | |
export const CreditCTAHero = (): JSX.Element | null => { | ||
const { width, ref: heroRef } = useResizeObserver() | ||
|
||
const { creditOverview, isPurchaseCreditsModalOpen } = useValues(billingLogic) | ||
const { showPurchaseCreditsModal } = useActions(billingLogic) | ||
const { creditOverview, isPurchaseCreditsModalOpen, isCreditCTAHeroDismissed, computedDiscount } = | ||
useValues(billingLogic) | ||
const { showPurchaseCreditsModal, toggleCreditCTAHeroDismissed } = useActions(billingLogic) | ||
const { featureFlags } = useValues(featureFlagLogic) | ||
|
||
if (!creditOverview.eligible || creditOverview.status === 'paid') { | ||
|
@@ -22,9 +24,44 @@ export const CreditCTAHero = (): JSX.Element | null => { | |
return null | ||
} | ||
|
||
if (isCreditCTAHeroDismissed) { | ||
return ( | ||
<div className="absolute top-0 right-0 z-10"> | ||
<div | ||
className="cursor-pointer bg-mark rounded-lg pr-3 pl-2 py-1 hover:bg-mark-light transition-colors group" | ||
onClick={() => toggleCreditCTAHeroDismissed(false)} | ||
> | ||
<span className="flex items-center gap-1.5"> | ||
<BurningMoneyHog | ||
className="w-8 h-8 group-hover:animate-bounce" | ||
style={{ animationDuration: '0.75s' }} | ||
/> | ||
<span>Get {computedDiscount * 100}% off</span> | ||
</span> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
return ( | ||
<div className="flex relative justify-between items-center rounded-lg bg-mark mb-6" ref={heroRef}> | ||
<div className="p-4"> | ||
<div | ||
className="flex relative justify-between items-start rounded-lg bg-bg-light border mb-2 gap-2" | ||
ref={heroRef} | ||
> | ||
<div className="absolute top-2 right-2 z-10"> | ||
<LemonButton | ||
icon={<IconX className="w-4 h-4" />} | ||
size="small" | ||
onClick={() => toggleCreditCTAHeroDismissed(true)} | ||
aria-label="Close" | ||
/> | ||
</div> | ||
{width && width > 500 && ( | ||
<div className="shrink-0 relative pt-4 overflow-hidden"> | ||
<BurningMoneyHog className="w-40 h-40" /> | ||
</div> | ||
)} | ||
<div className="p-4 flex-1"> | ||
{creditOverview.eligible && creditOverview.status === 'pending' && ( | ||
<> | ||
<h1 className="mb-0">We're applying your credits</h1> | ||
|
@@ -49,22 +86,59 @@ export const CreditCTAHero = (): JSX.Element | null => { | |
)} | ||
{creditOverview.eligible && creditOverview.status === 'none' && ( | ||
<> | ||
<h1 className="mb-0">Get a discount of up to 30%</h1> | ||
<h2 className="mb-0"> | ||
Stop burning money.{' '} | ||
<span className="text-success-light">Prepay and save {computedDiscount * 100}%</span> over | ||
the next 12 months. | ||
</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. | ||
</p> | ||
<p className="mt-2 mb-0 max-w-xl"> | ||
Buy credits in advance, at a discount of up to 30%. It helps you make costs more | ||
predictable! | ||
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, | ||
})} | ||
</strong>{' '} | ||
over the next year. | ||
</p> | ||
<LemonButton type="primary" onClick={() => showPurchaseCreditsModal(true)} className="mt-4"> | ||
<LemonButton | ||
type="primary" | ||
status="alt" | ||
onClick={() => showPurchaseCreditsModal(true)} | ||
className="mt-4" | ||
> | ||
Buy credits | ||
</LemonButton> | ||
{creditOverview.estimated_monthly_credit_amount_usd > 1 && ( | ||
<> | ||
<LemonDivider className="my-4" /> | ||
<div className="mt-2 flex justify-between items-center gap-2 w-full"> | ||
<p className="mb-2 flex-1"> | ||
<strong>Also available:</strong> Our Enterprise tier offers dedicated support in | ||
a private Slack channel, personalized training, and most importantly, free | ||
merch. | ||
</p> | ||
<LemonButton | ||
type="primary" | ||
to="mailto:[email protected]?subject=Let's talk enterprise!" | ||
> | ||
Talk to sales | ||
</LemonButton> | ||
</div> | ||
</> | ||
)} | ||
</> | ||
)} | ||
</div> | ||
{width && width > 500 && ( | ||
<div className="shrink-0 relative w-50 pt-4 overflow-hidden"> | ||
<BlushingHog className="w-50 h-50 -my-5" /> | ||
</div> | ||
)} | ||
{isPurchaseCreditsModalOpen && <PurchaseCreditsModal />} | ||
</div> | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.