Skip to content

FE: display purchase summary in sidebar#168

Open
rkumarsingh-sonata-crypto wants to merge 23 commits intomainfrom
feat/ENT-11420-display-purchase-summary-sidebar
Open

FE: display purchase summary in sidebar#168
rkumarsingh-sonata-crypto wants to merge 23 commits intomainfrom
feat/ENT-11420-display-purchase-summary-sidebar

Conversation

@rkumarsingh-sonata-crypto
Copy link
Copy Markdown
Contributor

@rkumarsingh-sonata-crypto rkumarsingh-sonata-crypto commented Apr 3, 2026

@rkumarsingh-sonata-crypto rkumarsingh-sonata-crypto force-pushed the feat/ENT-11420-display-purchase-summary-sidebar branch 2 times, most recently from c5198db to d88a2bc Compare April 6, 2026 05:10
Copilot AI review requested due to automatic review settings April 7, 2026 04:53
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 7, 2026

Codecov Report

❌ Patch coverage is 92.74194% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.11%. Comparing base (6359b0e) to head (3064169).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...omponents/PurchaseSummary/TeamsPurchaseSummary.tsx 74.28% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #168      +/-   ##
==========================================
+ Coverage   88.08%   88.11%   +0.03%     
==========================================
  Files         155      160       +5     
  Lines        2920     3013      +93     
  Branches      576      608      +32     
==========================================
+ Hits         2572     2655      +83     
- Misses        348      358      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Purchase Summary sidebar UI to support an “Essentials” flow variant, changing header/subtitle behavior, pricing/total calculations, and the footer CTA.

Changes:

  • Add Essentials-specific Purchase Summary rendering (different header/subtitle, hard-coded per-user price, conditional testimonial display, and an extra “Compare plans” card).
  • Introduce an “Upgrade to Teams” footer CTA and update PurchaseSummaryCardButton to support an isEssentials override.
  • Adjust several tests to align with updated Purchase Summary rendering and to relax some mutation hook assertions.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/utils/test/common.test.ts Adjusts Jest system time setup to use a numeric timestamp.
src/components/StatefulButton/tests/StatefulProvisioningButton.test.tsx Simplifies window mocking (removes location override).
src/components/PurchaseSummary/UpgradeToTeamsButton.tsx Adds a new “Upgrade to Teams” button component.
src/components/PurchaseSummary/TotalAfterTrialRow.tsx Changes the “Total after trial” right-side display when quantity is missing/0.
src/components/PurchaseSummary/tests/TotalAfterTrialRow.test.tsx Updates assertions for the “Total after trial” row display.
src/components/PurchaseSummary/tests/PurchaseSummaryHeader.test.tsx Updates header tests and adds i18n wrapper.
src/components/PurchaseSummary/tests/PurchaseSummary.test.tsx Updates PurchaseSummary header expectation to match new subtitle format.
src/components/PurchaseSummary/PurchaseSummaryHeader.tsx Adds isEssentials prop and changes subtitle/title rendering.
src/components/PurchaseSummary/PurchaseSummaryCardButton.tsx Adds isEssentials prop and new upgrade button type mapping.
src/components/PurchaseSummary/PurchaseSummary.tsx Implements Essentials-specific pricing/total logic and conditional UI.
src/components/PurchaseSummary/PricePerUserRow.tsx Adds Essentials-specific label text.
src/components/PurchaseSummary/DueTodayRow.tsx Adjusts bold styling by wrapping label/right contents.
src/components/app/data/hooks/tests/useRegisterMutation.test.tsx Loosens onMutate assertion to objectContaining.
src/components/app/data/hooks/tests/useLoginMutation.test.tsx Loosens onMutate assertion to objectContaining.
src/components/app/data/hooks/tests/useCreateCheckoutIntentMutation.test.tsx Loosens onMutate assertion to objectContaining.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/PurchaseSummary/UpgradeToTeamsButton.tsx
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx Outdated
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx Outdated
Comment thread src/components/PurchaseSummary/TotalAfterTrialRow.tsx
Comment thread src/components/PurchaseSummary/tests/TotalAfterTrialRow.test.tsx
Comment thread src/components/app/data/hooks/tests/useRegisterMutation.test.tsx Outdated
Comment thread src/components/app/data/hooks/tests/useLoginMutation.test.tsx Outdated
Comment thread src/components/app/data/hooks/tests/useCreateCheckoutIntentMutation.test.tsx Outdated
Comment thread src/components/PurchaseSummary/PurchaseSummaryCardButton.tsx Outdated
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx Outdated
Copilot AI review requested due to automatic review settings April 9, 2026 09:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 4 to 8
import { usePurchaseSummaryPricing } from '@/components/app/data';
import useTestimonials from '@/components/app/data/hooks/useTestimonials';
import { isEssentialsFlow } from '@/components/app/routes/loaders/utils';
import { DataStoreKey } from '@/constants/checkout';
import { useCheckoutFormStore } from '@/hooks/index';
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isEssentialsFlow is imported from components/app/routes/loaders/utils, which pulls in heavy loader-only dependencies (e.g., zod resolvers/Stripe types). Importing that module into a render component can unnecessarily bloat the client bundle; consider moving isEssentialsFlow into a small, client-safe utility module (or duplicating the tiny sessionStorage check locally) and importing from there instead.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 2fcb92b. isEssentialsFlow has been moved to src/utils/common.ts (alongside the similarly structured isFeatureEnabled function). loaders/utils.ts now re-exports it from there for backward compatibility with loader files, and all UI components (PurchaseSummary, StatefulSubscribeButton, BillingDetailsPage, AccountDetailsPage) now import from @/utils/common directly.

Comment on lines +34 to +38
// For Essentials, hardcode price to $149
const pricePerUser = isEssentials ? 149 : yearlyCostPerSubscriptionPerUser;
const totalPerYear = normalizedQuantity && normalizedQuantity > 0 && pricePerUser
? normalizedQuantity * pricePerUser
: null;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pricePerUser/totalPerYear uses truthiness checks (pricePerUser in particular), which will incorrectly treat a valid value of 0 as absent and produce null totals. Also, hardcoding 149 here makes pricing easy to drift from backend/config and harder to change. Prefer explicit null/undefined checks (e.g., pricePerUser != null) and source the Essentials price from a constant/config or the pricing context so the UI stays in sync.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +37 to +41
<DisplayPrice value={totalPerYear ?? 0} /> USD
</span>
)
: ('-')}/yr
: '-'
}/yr
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When quantity is missing/0 this currently renders just "/yr" (empty string before it). That makes the value column ambiguous and also contradicts the test name that says "shows dash". Consider rendering a clear placeholder such as - (resulting in -/yr) to match the pattern used in other rows (e.g., PricePerUserRow and LicensesRow) and update the test expectation accordingly.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +9 to +16
const PurchaseSummaryHeaderComponent: React.FC<PurchaseSummaryHeaderProps> = ({ companyName, isEssentials }) => {
let subtitle: string | undefined;
if (isEssentials) {
subtitle = companyName || undefined;
} else {
subtitle = companyName
? `${companyName} • Team subscription, price per user, paid yearly.`
: 'Team subscription, price per user, paid yearly.';
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plan-description text is duplicated here as a hardcoded English string and is slightly inconsistent with the label in PricePerUserRow (capitalization/punctuation). To avoid UI drift and ease localization, consider sourcing this from a shared i18n message/constant and composing the subtitle using that single source of truth.

Suggested change
const PurchaseSummaryHeaderComponent: React.FC<PurchaseSummaryHeaderProps> = ({ companyName, isEssentials }) => {
let subtitle: string | undefined;
if (isEssentials) {
subtitle = companyName || undefined;
} else {
subtitle = companyName
? `${companyName} • Team subscription, price per user, paid yearly.`
: 'Team subscription, price per user, paid yearly.';
const TEAM_SUBSCRIPTION_PLAN_DESCRIPTION = 'Team subscription, price per user, paid yearly.';
const PurchaseSummaryHeaderComponent: React.FC<PurchaseSummaryHeaderProps> = ({ companyName, isEssentials }) => {
let subtitle: string | undefined;
if (isEssentials) {
subtitle = companyName || undefined;
} else {
subtitle = companyName
? `${companyName}${TEAM_SUBSCRIPTION_PLAN_DESCRIPTION}`
: TEAM_SUBSCRIPTION_PLAN_DESCRIPTION;

Copilot uses AI. Check for mistakes.
Comment on lines 42 to +46
const buttonType = useMemo(
(): ButtonType => ROUTE_BUTTON_MAP[location.pathname] ?? BUTTON_TYPES.NONE,
[location.pathname],
(): ButtonType => {
if (isEssentials) {
return BUTTON_TYPES.UPGRADE;
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new isEssentials branch introduces a new button type (UPGRADE) that isn't exercised by the existing PurchaseSummaryCardButton tests. Add a test that renders with isEssentials={true} and asserts the upgrade button is shown (and that route changes don’t affect it) to prevent regressions.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copilot AI review requested due to automatic review settings April 9, 2026 13:02
@rkumarsingh-sonata-crypto rkumarsingh-sonata-crypto review requested due to automatic review settings April 9, 2026 13:02
Copilot AI review requested due to automatic review settings April 9, 2026 13:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +24
// If we don't have the prerequisites for Stripe, render the page shell without Stripe Elements.
if (!checkoutSessionClientSecret || !PUBLISHABLE_STRIPE_API_KEY || !stripePromise) {
return children;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StripeProvider returns children when Stripe prerequisites (client secret / publishable key / stripePromise) are missing. In this app the only current usage wraps BillingDetailsPage, which renders Stripe components (AddressElement/PaymentElement) that require the Stripe context—rendering them without CheckoutProvider will likely throw at runtime if the key is misconfigured. Prefer keeping the previous return null (or rendering an explicit non-Stripe fallback UI) unless children are guaranteed not to use Stripe context.

Suggested change
// If we don't have the prerequisites for Stripe, render the page shell without Stripe Elements.
if (!checkoutSessionClientSecret || !PUBLISHABLE_STRIPE_API_KEY || !stripePromise) {
return children;
// If we don't have the prerequisites for Stripe, avoid rendering Stripe-dependent children
// outside of CheckoutProvider.
if (!checkoutSessionClientSecret || !PUBLISHABLE_STRIPE_API_KEY || !stripePromise) {
return null;

Copilot uses AI. Check for mistakes.
renderWithI18n(<TotalAfterTrialRow quantity={quantity} totalPerYear={totalPerYear} />);
validateText(`Total after ${SUBSCRIPTION_TRIAL_LENGTH_DAYS}-day free trial`);
validateText('-/yr');
validateText('/yr');
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test now asserts an exact text node of "/yr", but TotalAfterTrialRow renders a dash placeholder and then appends /yr, producing "-/yr" as the combined text content. Update the expectation to match the rendered output (e.g., assert "-/yr", or use a non-exact match if you only care about the suffix).

Suggested change
validateText('/yr');
validateText('-/yr');

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 9, 2026 13:59
@rkumarsingh-sonata-crypto rkumarsingh-sonata-crypto force-pushed the feat/ENT-11420-display-purchase-summary-sidebar branch from ea897f7 to 13d6f52 Compare April 9, 2026 13:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx Outdated
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx Outdated
Comment thread src/components/PurchaseSummary/PurchaseSummaryHeader.tsx Outdated
Comment thread src/setupTest.ts
Copilot AI added a commit that referenced this pull request Apr 10, 2026
Agent-Logs-Url: https://github.com/edx/frontend-app-enterprise-checkout/sessions/cdf8568e-5024-4fd3-afd2-39b3c160ff72

Co-authored-by: rkumarsingh-sonata-crypto <265776069+rkumarsingh-sonata-crypto@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 10, 2026 09:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 39 to 50
const PurchaseSummaryCardButton: React.FC<PurchaseSummaryCardButtonProps> = ({ isEssentials }) => {
const location = useLocation();

const buttonType = useMemo(
(): ButtonType => ROUTE_BUTTON_MAP[location.pathname] ?? BUTTON_TYPES.NONE,
[location.pathname],
(): ButtonType => {
if (isEssentials) {
return BUTTON_TYPES.UPGRADE;
}
return ROUTE_BUTTON_MAP[location.pathname] ?? BUTTON_TYPES.NONE;
},
[location.pathname, isEssentials],
);
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx
Comment thread src/components/PurchaseSummary/PurchaseSummary.tsx
Copilot AI review requested due to automatic review settings April 13, 2026 09:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 35 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/common.ts
Comment on lines +136 to +141
/**
* Returns true when the current session is operating in the Essentials flow.
* Reads from sessionStorage so it is safe to call from any client-side module.
*/
const isEssentialsFlow = (): boolean => sessionStorage.getItem('isEssentials') === 'true';

Comment on lines 7 to 18
interface PricePerUserRowProps {
pricePerUser?: number | null;
label?: string;
}

const PricePerUserRowComponent: React.FC<PricePerUserRowProps> = ({ pricePerUser }) => (
const PricePerUserRowComponent: React.FC<PricePerUserRowProps> = ({
pricePerUser,
label = 'Price per user, paid yearly',
}) => (
<SummaryRow
label={(
<FormattedMessage
id="checkout.purchaseSummary.yearlyPricePerUser.text"
defaultMessage="Team Subscription, price per user, paid yearly"
description="Label for the team plan per user per year"
/>
)}
label={label}
right={pricePerUser == null ? '-' : <span><DisplayPrice value={pricePerUser} /> USD</span>}
Comment on lines +8 to +12
import PurchaseSummaryCardButton from './PurchaseSummaryCardButton';

const ESSENTIALS_PRICE_PER_USER = 149;

type AcademySelectionData = {
Comment thread src/setupTest.ts
Comment on lines 26 to 34
const CONSOLE_FILTERS = {
warn: [
'PubSub already loaded',
],
error: [
'Support for defaultProps will be removed from function components',
'Warning: An update to',
],
};
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +17
import { Card } from '@openedx/paragon';

const COMPARE_PLANS_URL = 'https://business.edx.org/course-library-compare-plans/';

const ComparePlansBox = () => (
<Card className="bg-light border">
<Card.Body className="text-center">
<p className="mb-0 text-dark">
<strong>
Not sure which plan is right for you?{' '}
<a
href={COMPARE_PLANS_URL}
target="_blank"
rel="noopener noreferrer"
>
Compare plans
</a>
Comment on lines +23 to +25
const normalizedQuantity = parseInt(quantity, 10) === 0 ? null : quantity;

const totalPerYear = normalizedQuantity && normalizedQuantity > 0 && yearlyCostPerSubscriptionPerUser
Comment on lines +21 to +26
const { yearlyCostPerSubscriptionPerUser } = usePurchaseSummaryPricing();

const normalizedQuantity = parseInt(quantity, 10) === 0 ? null : quantity;

const totalPerYear = normalizedQuantity && normalizedQuantity > 0 && yearlyCostPerSubscriptionPerUser
? normalizedQuantity * yearlyCostPerSubscriptionPerUser
Comment on lines +6 to +20
const UpgradeToTeamsButton: React.FC = () => (
<Button
variant="outline-danger"
className="w-100 text-danger"
data-testid="upgrade-to-teams-button"
>
<Icon src={Lock} className="me-2" style={{ color: '#dc3545' }} />
<FormattedMessage
id="components.PurchaseSummary.UpgradeToTeamsButton.upgradeToTeams"
defaultMessage="Upgrade to Teams"
description="Button text to upgrade to Teams plan"
/>
</Button>
);

Comment on lines +18 to +26
subtitle = headerName
? `${headerName} • Team subscription, price per user, paid yearly.`
: 'Team subscription, price per user, paid yearly.';
}

return (
<Card.Header
title={<span className="font-weight-bold">Purchase summary</span>}
subtitle={subtitle}
import PurchaseSummaryBase from './PurchaseSummaryBase';
import PurchaseSummaryCardButton from './PurchaseSummaryCardButton';

const ESSENTIALS_PRICE_PER_USER = 149;
Comment on lines +52 to +56
<PurchaseSummaryBase
headerName={academyName}
isEssentials
pricePerUser={ESSENTIALS_PRICE_PER_USER}
priceLabel="Essentials subscription, price per user, paid yearly."
@brobro10000 brobro10000 self-assigned this Apr 23, 2026
rkumarsingh-sonata-crypto and others added 23 commits April 24, 2026 17:23
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Agent-Logs-Url: https://github.com/edx/frontend-app-enterprise-checkout/sessions/524d8165-8753-4d83-b292-a9aeb878c937

Co-authored-by: rkumarsingh-sonata-crypto <265776069+rkumarsingh-sonata-crypto@users.noreply.github.com>
Co-authored-by: rkumarsingh-sonata-crypto <265776069+rkumarsingh-sonata-crypto@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 11:53
@rkumarsingh-sonata-crypto rkumarsingh-sonata-crypto force-pushed the feat/ENT-11420-display-purchase-summary-sidebar branch from ed32b1d to 3064169 Compare April 24, 2026 11:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/common.ts
Comment on lines +141 to +146
/**
* Returns true when the current session is operating in the Essentials flow.
* Reads from sessionStorage so it is safe to call from any client-side module.
*/
const isEssentialsFlow = (): boolean => sessionStorage.getItem('isEssentials') === 'true';

Comment on lines +40 to +43
const academyName = academySelectionData?.academyName
?? planDetailsData?.academyName
?? accountDetailsData?.companyName
?? null;
Comment on lines +18 to +26
subtitle = headerName
? `${headerName} • Team subscription, price per user, paid yearly.`
: 'Team subscription, price per user, paid yearly.';
}

return (
<Card.Header
title={<span className="font-weight-bold">Purchase summary</span>}
subtitle={subtitle && <span className="purchase-summary-header-name">{subtitle}</span>}
Comment on lines +8 to +19
<p className="mb-0 compare-plans-text">
<strong>
Not sure which plan is right for you?{' '}
<a
href={COMPARE_PLANS_URL}
target="_blank"
rel="noopener noreferrer"
className="compare-plans-link"
>
Compare plans.
</a>
</strong>
Comment on lines +10 to +11
const ESSENTIALS_PRICE_PER_USER = 149;

Comment on lines +6 to +12
const UpgradeToTeamsButton: React.FC = () => (
<Button
variant="outline-danger"
className="w-100 text-danger upgrade-to-teams-btn"
data-testid="upgrade-to-teams-button"
>
<Icon src={Lock} className="me-2" style={{ color: '#dc3545' }} />
Comment thread src/setupTest.ts
Comment on lines 26 to 34
const CONSOLE_FILTERS = {
warn: [
'PubSub already loaded',
],
error: [
'Support for defaultProps will be removed from function components',
'Warning: An update to',
],
};
Comment on lines +23 to +25
const normalizedQuantity = parseInt(quantity, 10) === 0 ? null : quantity;

const totalPerYear = normalizedQuantity && normalizedQuantity > 0 && yearlyCostPerSubscriptionPerUser
Comment on lines +33 to +37
useEffect(() => {
if (!testimonials.length) { return; }

let available = testimonials.filter(
(t) => t.uuid && !shownTestimonialsRef.current.includes(t.uuid),
Comment on lines +54 to +57
isEssentials
pricePerUser={ESSENTIALS_PRICE_PER_USER}
priceLabel="Essentials subscription, price per user, paid yearly."
quantity={normalizedQuantity}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants