Skip to content

Commit a834906

Browse files
authored
Merge pull request #6792 from layer5io/plans
add currency switcher in pricing page
2 parents 750efa8 + 589c782 commit a834906

4 files changed

Lines changed: 121 additions & 68 deletions

File tree

src/components/Pricing/PlanCard/index.js

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import Button from "../../../reusecore/Button";
33
import { Col, Row, Container } from "../../../reusecore/Layout";
44
import PlanCardWrapper from "./planCard.style";
55
import FeatureDetails from "./collapsible-details";
6+
import { Currencies, formatAndConvertPrice } from "../../../utils/currencies";
67

78

8-
const PlanCard = ({ planData , isYearly }) => {
9+
const PlanCard = ({ planData , isYearly ,currency }) => {
910

1011

1112
if (!planData || !Array.isArray(planData) || planData.length === 0) {
@@ -18,6 +19,10 @@ const PlanCard = ({ planData , isYearly }) => {
1819
"Enterprise": "https://cloud.layer5.io/account/plans/upgrade?plan=ad68ce59-8c5a-42b0-955c-9b2b2f7c98e3"
1920
};
2021

22+
const formatPrice = (price) => {
23+
return formatAndConvertPrice(price, currency)
24+
};
25+
2126
return (
2227
<PlanCardWrapper>
2328
<Container>
@@ -41,39 +46,17 @@ const PlanCard = ({ planData , isYearly }) => {
4146
<h5 className="byline">{x.byline}</h5>
4247

4348
<div className="price-container">
44-
{isYearly ? (
45-
x.yearlyprice !== undefined ? (
49+
4650
<div className="price">
47-
<span className="price-amount"><sup>$</sup>
48-
{x.yearlyprice === 0
49-
? "0"
50-
: x.yearlyprice.toFixed(0)}
51+
<span className="price-amount">
52+
{isYearly
53+
? formatPrice(x.yearlyPrice)
54+
: formatPrice(x.monthlyPrice)}
5155
</span>
52-
<span className="currency">USD</span>
56+
<span className="currency">{Currencies[currency]?.name ?? "USD" } </span>
5357
<span className="price-per">per user/year</span>
5458
</div>
55-
) : (
56-
<div className="pricing_coming_soon">
57-
{x.pricing_coming_soon}
58-
</div>
59-
)
60-
) : (
61-
x.monthlyprice !== undefined ? (
62-
<div className="price">
63-
<span className="price-amount"><sup>$</sup>
64-
{x.monthlyprice === 0
65-
? "0"
66-
: x.monthlyprice.toFixed(0)}
67-
</span>
68-
<span className="currency">USD</span>
69-
<span className="price-per">per user/month</span>
70-
</div>
71-
) : (
72-
<div className="pricing_coming_soon">
73-
{x.pricing_coming_soon}
74-
</div>
75-
)
76-
)}
59+
7760
</div>
7861

7962

src/components/Pricing/PricingAddons/index.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ import {
4141
getSliderStyle
4242
} from "./styles";
4343

44-
export const PricingAddons = ({ isYearly = false, setIsYearly, enterprisePlan }) => {
44+
import { formatAndConvertPrice } from "../../../utils/currencies";
45+
46+
export const PricingAddons = ({ isYearly = false, setIsYearly ,currency }) => {
47+
4548
const [selectedAddon, setSelectedAddon] = useState(null);
4649
// const [quantity, setQuantity] = useState(1);
4750
const quantity = 1;
@@ -74,6 +77,10 @@ export const PricingAddons = ({ isYearly = false, setIsYearly, enterprisePlan })
7477
}
7578
};
7679

80+
const formatPrice = (price) => {
81+
return formatAndConvertPrice(price, currency)
82+
}
83+
7784
useEffect(() => {
7885
if (selectedAddon) {
7986
let baseTotal = 0;
@@ -139,14 +146,6 @@ export const PricingAddons = ({ isYearly = false, setIsYearly, enterprisePlan })
139146
}));
140147
};
141148

142-
const formatPrice = (price) => {
143-
return new Intl.NumberFormat("en-US", {
144-
style: "currency",
145-
currency: "USD",
146-
minimumFractionDigits: 0,
147-
maximumFractionDigits: 0,
148-
}).format(price);
149-
};
150149

151150
const getPlanLinkForAcademy = () => {
152151
if (!selectedAddon || selectedAddon.id !== "academy") {
@@ -566,4 +565,4 @@ export const PricingAddons = ({ isYearly = false, setIsYearly, enterprisePlan })
566565
</CssBaseline>
567566
</SistentThemeProvider>
568567
);
569-
};
568+
};

src/sections/Pricing/index.js

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,71 @@ import PlanCard from "../../components/Pricing/PlanCard";
88
import OpenSourceBanner from "./openSource";
99
import { PricingAddons } from "../../components/Pricing/PricingAddons";
1010
import SubscriptionToggle from "./SubscriptionToggle";
11+
import { Box, FormControl, InputLabel, MenuItem, Select, Typography } from "@sistent/sistent";
12+
import { Currencies } from "../../utils/currencies";
13+
14+
export const CurrencySelect = ({ currency, setCurrency }) => {
15+
return (
16+
<FormControl variant="outlined" size="small" sx={{ minWidth: 150 }}>
17+
<InputLabel>Currency</InputLabel>
18+
<Select
19+
value={currency}
20+
sx={{}}
21+
onChange={(e) => setCurrency(e.target.value)}
22+
label="Currency"
23+
renderValue={(value) => (
24+
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
25+
<Typography variant="body1">{Currencies[value].symbol}</Typography>
26+
<Typography variant="body2" color="text.secondary">
27+
{Currencies[value].name}
28+
</Typography>
29+
</Box>
30+
)}
31+
>
32+
{Object.entries(Currencies).map(([code, { symbol, name }]) => (
33+
<MenuItem key={code} value={code}>
34+
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
35+
<Typography variant="body1">{symbol}</Typography>
36+
<Typography variant="body2" color="text.secondary">
37+
{name}
38+
</Typography>
39+
</Box>
40+
</MenuItem>
41+
))}
42+
</Select>
43+
</FormControl>
44+
);
45+
}
1146

1247
const Pricing = () => {
13-
// const [monthly, setMonthly] = useState(false);
14-
const [isYearly, setIsYearly] = useState(false);
15-
16-
return (
17-
<PricingWrapper>
18-
<div className="headers">
19-
<h1 className="header-heading">Plans For Every Team Size</h1>
20-
21-
<SubscriptionToggle isYearly={isYearly} setIsYearly={setIsYearly} />
22-
23-
{/* <svg className="header-svg" aria-hidden="true" role="presentation" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="none">
24-
<polygon fill="white" points="0,100 100,0 100,100"/>
25-
<polygon fill="rgba(0,179,159,0.2)" points="50,50 100,0 100,100"/>
26-
</svg> */}
27-
</div>
28-
29-
<div className="wrapper">
30-
<PlanCard planData={options} isYearly={isYearly}/>
31-
</div>
32-
<div style={{ marginTop: "7rem", marginBottom: "3rem" }}>
33-
<PricingAddons isYearly={isYearly} setIsYearly={setIsYearly} enterprisePlan={options.filter(opt => opt.tier == "Enterprise")[0]} />
34-
</div>
35-
<Comparison />
36-
<Reviews />
37-
<OpenSourceBanner />
38-
<FAQ category={["Pricing", "Billing"]} />
39-
</PricingWrapper>
40-
);
48+
// const [monthly, setMonthly] = useState(false);
49+
const [isYearly, setIsYearly] = useState(false);
50+
const [currency, setCurrency] = useState("USD");
51+
52+
return (
53+
<PricingWrapper>
54+
<div className="headers">
55+
<h1 className="header-heading">Plans For Every Team Size</h1>
56+
57+
<CurrencySelect currency={currency} setCurrency={setCurrency} />
58+
59+
<SubscriptionToggle isYearly={isYearly} setIsYearly={setIsYearly} />
60+
61+
</div>
62+
63+
<div className="wrapper">
64+
<PlanCard planData={options} isYearly={isYearly} currency={currency} />
65+
</div>
66+
<div style={{ marginTop: "7rem", marginBottom: "3rem" }}>
67+
<PricingAddons isYearly={isYearly} setIsYearly={setIsYearly} currency={currency} />
68+
</div>
69+
<Comparison />
70+
<Reviews />
71+
<OpenSourceBanner />
72+
<FAQ category={["Pricing", "Billing"]} />
73+
</PricingWrapper>
74+
);
75+
4176
};
4277

4378

src/utils/currencies.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
export const Currencies = {
3+
USD: {
4+
name: "USD",
5+
symbol: "$",
6+
rate: 1,
7+
formatPrice: (price) =>
8+
new Intl.NumberFormat("en-US", {
9+
style: "currency",
10+
currency: "USD",
11+
minimumFractionDigits: 0,
12+
maximumFractionDigits: 2,
13+
}).format(price),
14+
},
15+
EUR: {
16+
name: "EUR",
17+
symbol: "€",
18+
rate: 0.86,
19+
formatPrice: (price) =>
20+
new Intl.NumberFormat("en-US", {
21+
style: "currency",
22+
currency: "EUR",
23+
minimumFractionDigits: 0,
24+
maximumFractionDigits: 2,
25+
}).format(price * 0.86),
26+
},
27+
};
28+
29+
30+
// the price is in USD
31+
export const formatAndConvertPrice = (price, currency) => {
32+
if (Currencies[currency]) {
33+
return Currencies[currency].formatPrice(price);
34+
}
35+
return price;
36+
}

0 commit comments

Comments
 (0)