Skip to content

Commit 52e9d23

Browse files
authored
Merge pull request #6794 from layer5io/currency-switcher
Add currency switcher
2 parents 0550aec + 8c0a18c commit 52e9d23

7 files changed

Lines changed: 658 additions & 664 deletions

File tree

package-lock.json

Lines changed: 534 additions & 608 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"scripts": {
1313
"build": "gatsby build",
1414
"clean": "gatsby clean && rimraf node_modules",
15-
"develop": "env-cmd -f .env.development gatsby develop",
15+
"develop": "GATSBY_CPU_COUNT=12 NODE_OPTIONS=--max-old-space-size=10096 gatsby develop",
1616
"dev": "npm run develop",
1717
"start": "npm run develop",
1818
"serve": "gatsby serve",
@@ -55,7 +55,7 @@
5555
"dedent": "^1.3.0",
5656
"deepmerge": "^4.3.0",
5757
"formik": "^2.2.9",
58-
"gatsby": "^5.14.0",
58+
"gatsby": "^5.14.6",
5959
"gatsby-awesome-pagination": "^0.3.8",
6060
"gatsby-background-image": "^1.6.0",
6161
"gatsby-cli": "^5.13.3",

src/components/Pricing/PlanCard/index.js

Lines changed: 18 additions & 34 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,11 @@ 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+
console.log("price",price,planData);
24+
return formatAndConvertPrice(price, currency);
25+
};
26+
2127
return (
2228
<PlanCardWrapper>
2329
<Container>
@@ -41,39 +47,17 @@ const PlanCard = ({ planData , isYearly }) => {
4147
<h5 className="byline">{x.byline}</h5>
4248

4349
<div className="price-container">
44-
{isYearly ? (
45-
x.yearlyprice !== undefined ? (
46-
<div className="price">
47-
<span className="price-amount"><sup>$</sup>
48-
{x.yearlyprice === 0
49-
? "0"
50-
: x.yearlyprice.toFixed(0)}
51-
</span>
52-
<span className="currency">USD</span>
53-
<span className="price-per">per user/year</span>
54-
</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-
)}
50+
51+
<div className="price">
52+
<span className="price-amount">
53+
{isYearly
54+
? formatPrice(x.yearlyprice)
55+
: formatPrice(x.monthlyprice)}
56+
</span>
57+
<span className="currency">{Currencies[currency]?.name ?? "USD" } </span>
58+
<span className="price-per">per user/year</span>
59+
</div>
60+
7761
</div>
7862

7963

src/components/Pricing/PricingAddons/index.js

Lines changed: 10 additions & 11 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,enterprisePlan }) => {
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") {
@@ -390,7 +389,7 @@ export const PricingAddons = ({ isYearly = false, setIsYearly, enterprisePlan })
390389
<Box sx={{ textAlign: "center", fontSize: "1.25rem", fontWeight: "bold" }}>
391390
<Box>{option.learners === "2500+" ? "2,500+" : option.learners}</Box>
392391
<Box sx={{ color: "text.secondary", mb: 1.5, fontSize: ".9rem" }}>
393-
{option.currency}{isYearly ? option.yearlyPerUser : option.monthlyPerUser}<br />{targetSubAddon.unitLabelSingular}/{isYearly ? "year" : "month"}
392+
{formatPrice(isYearly ? option.yearlyPerUser : option.monthlyPerUser)}<br />{targetSubAddon.unitLabelSingular}/{isYearly ? "year" : "month"}
394393
</Box>
395394
</Box>
396395
),
@@ -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: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,85 @@ 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={{
17+
minWidth: 150,
18+
"& .MuiInputLabel-root": { color: "white" }, // label
19+
"& .MuiOutlinedInput-notchedOutline": { borderColor: "white" }, // outline
20+
"& .MuiSelect-icon": { color: "white" }, // dropdown arrow
21+
"& .MuiSelect-select": { color: "white" }, // selected text
22+
"&:hover .MuiOutlinedInput-notchedOutline": { borderColor: "white" },
23+
"&.Mui-focused .MuiOutlinedInput-notchedOutline": { borderColor: "white" },
24+
25+
}}>
26+
<InputLabel>Currency</InputLabel>
27+
<Select
28+
value={currency}
29+
sx={{
30+
31+
32+
}}
33+
onChange={(e) => setCurrency(e.target.value)}
34+
label="Currency"
35+
renderValue={(value) => (
36+
<Box sx={{ display: "flex", alignItems: "center", gap: 1, color: "#fff" }}>
37+
<Typography variant="body1">{Currencies[value].symbol}</Typography>
38+
<Typography variant="body2" >
39+
{Currencies[value].name}
40+
</Typography>
41+
</Box>
42+
)}
43+
>
44+
{Object.entries(Currencies).map(([code, { symbol, name }]) => (
45+
<MenuItem key={code} value={code}>
46+
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
47+
<Typography variant="body1">{symbol}</Typography>
48+
<Typography variant="body2" >
49+
{name}
50+
</Typography>
51+
</Box>
52+
</MenuItem>
53+
))}
54+
</Select>
55+
</FormControl>
56+
);
57+
};
1158

1259
const Pricing = () => {
1360
// const [monthly, setMonthly] = useState(false);
1461
const [isYearly, setIsYearly] = useState(false);
62+
const [currency, setCurrency] = useState("USD");
1563

1664
return (
1765
<PricingWrapper>
1866
<div className="headers">
1967
<h1 className="header-heading">Plans For Every Team Size</h1>
2068

21-
<SubscriptionToggle isYearly={isYearly} setIsYearly={setIsYearly} />
69+
<div style={{ display: "flex", "gap": "1rem", alignItems: "center", "justifyContent": "flex-end", width: "85%" }} >
70+
<CurrencySelect currency={currency} setCurrency={setCurrency} />
71+
72+
<SubscriptionToggle isYearly={isYearly} setIsYearly={setIsYearly} />
73+
</div>
2274

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> */}
2775
</div>
2876

2977
<div className="wrapper">
30-
<PlanCard planData={options} isYearly={isYearly}/>
78+
<PlanCard planData={options} isYearly={isYearly} currency={currency} />
3179
</div>
3280
<div style={{ marginTop: "7rem", marginBottom: "3rem" }}>
33-
<PricingAddons isYearly={isYearly} setIsYearly={setIsYearly} enterprisePlan={options.filter(opt => opt.tier == "Enterprise")[0]} />
81+
<PricingAddons isYearly={isYearly} setIsYearly={setIsYearly} currency={currency} enterprisePlan={options.filter(opt => opt.tier == "Enterprise")[0]} />
3482
</div>
3583
<Comparison />
3684
<Reviews />
3785
<OpenSourceBanner />
3886
<FAQ category={["Pricing", "Billing"]} />
3987
</PricingWrapper>
4088
);
89+
4190
};
4291

4392

src/sections/Pricing/pricing.style.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ const PricingWrapper = styled.section`
4444
margin: 2rem 0;
4545
font-size: .9rem;
4646
gap: 10px;
47-
width: 85%;
47+
width: auto;
4848
}
4949
5050
.toggle {
5151
border: 2px solid ${props => props.theme.shadowLightColor};
52-
padding: .4rem;
52+
padding: .6rem;
5353
border-radius: .5rem;
5454
}
5555

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)