diff --git a/packages/common-components/src/Breadcrumb/Breadcrumb.tsx b/packages/common-components/src/Breadcrumb/Breadcrumb.tsx index 4a4eeb4ead..5bcf51c909 100644 --- a/packages/common-components/src/Breadcrumb/Breadcrumb.tsx +++ b/packages/common-components/src/Breadcrumb/Breadcrumb.tsx @@ -13,6 +13,7 @@ export type Crumb = { export type BreadcrumbProps = { crumbs?: Crumb[] homeOnClick?: () => void + hideHome?: boolean className?: string showDropDown?: boolean } @@ -60,7 +61,7 @@ const useStyles = makeStyles( "&.clickable": { cursor: "pointer" }, - maxWidth: 100, + maxWidth: 120, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", @@ -94,6 +95,7 @@ const useStyles = makeStyles( const Breadcrumb: React.FC = ({ crumbs = [], homeOnClick, + hideHome, className, showDropDown }: BreadcrumbProps) => { @@ -102,7 +104,6 @@ const Breadcrumb: React.FC = ({ const generateFullCrumbs = (crumbs: Crumb[]) => { return crumbs.map((item: Crumb, index: number) => ( -
(item.onClick ? item.onClick() : null)} @@ -112,6 +113,7 @@ const Breadcrumb: React.FC = ({ {item.text}
+ {index < (crumbs.length - 1) &&
} )) } @@ -120,7 +122,7 @@ const Breadcrumb: React.FC = ({ return ( = ({ if (crumbs.length < 3 || !showDropDown) { return generateFullCrumbs(crumbs) } else { - const dropdownCrumbs = crumbs.slice(0, length - 1) + const dropdownCrumbs = crumbs.slice(0, crumbs.length - 1) const lastCrumb = crumbs[crumbs.length - 1] return ( <> -
{generateDropdownCrumb(dropdownCrumbs)}
@@ -169,10 +170,14 @@ const Breadcrumb: React.FC = ({ return (
- (homeOnClick ? homeOnClick() : null)} - /> + {!hideHome && <> + (homeOnClick ? homeOnClick() : null)} + /> +
+ + } {generateCrumbs()}
) diff --git a/packages/common-components/src/RadioInput/RadioInput.tsx b/packages/common-components/src/RadioInput/RadioInput.tsx index 69a00e5c39..e413c9c6d7 100644 --- a/packages/common-components/src/RadioInput/RadioInput.tsx +++ b/packages/common-components/src/RadioInput/RadioInput.tsx @@ -13,7 +13,6 @@ const useStyles = makeStyles( cursor: "pointer", paddingLeft: constants.generalUnit * 3, paddingRight: constants.generalUnit * 3, - margin: `${constants.generalUnit}px 0`, ...overrides?.RadioInput?.radioContainer }, radioInput: { @@ -27,7 +26,7 @@ const useStyles = makeStyles( width: constants.generalUnit * 2, height: constants.generalUnit * 2, left: 0, - top: 0, + top: "auto", borderRadius: "50%", transition: `all ${animation.transform}ms ease`, ...overrides?.RadioInput?.radio?.root, @@ -83,6 +82,7 @@ const useStyles = makeStyles( export interface IRadioInputProps extends React.HTMLProps { className?: string + labelClassName?: string value: string label?: string name?: string @@ -94,6 +94,7 @@ export interface IRadioInputProps extends React.HTMLProps { const RadioInput: React.FC = ({ className, + labelClassName, value, name, label, @@ -130,7 +131,7 @@ const RadioInput: React.FC = ({ })} /> {label && ( - {label} + {label} )} {error &&
{error}
} diff --git a/packages/common-components/src/stories/Breadcrumb.stories.tsx b/packages/common-components/src/stories/Breadcrumb.stories.tsx index 8a4f3bd32e..ba9be0c287 100644 --- a/packages/common-components/src/stories/Breadcrumb.stories.tsx +++ b/packages/common-components/src/stories/Breadcrumb.stories.tsx @@ -38,6 +38,7 @@ export const BreadcrumbStory = (): React.ReactNode => { homeOnClick={() => actionsData.homeClicked()} showDropDown={boolean("show dropdown", true)} crumbs={crumbs} + hideHome={boolean("hide home", false)} /> )} diff --git a/packages/files-ui/package.json b/packages/files-ui/package.json index 0cd6d2460b..c0e4f9b470 100644 --- a/packages/files-ui/package.json +++ b/packages/files-ui/package.json @@ -6,7 +6,7 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.20", + "@chainsafe/files-api-client": "^1.18.22", "@chainsafe/web3-context": "1.1.4", "@emeraldpay/hashicon-react": "^0.5.1", "@lingui/core": "^3.7.2", diff --git a/packages/files-ui/src/Components/FilesRoutes.tsx b/packages/files-ui/src/Components/FilesRoutes.tsx index 34e79afadb..80a55e6ce0 100644 --- a/packages/files-ui/src/Components/FilesRoutes.tsx +++ b/packages/files-ui/src/Components/FilesRoutes.tsx @@ -15,12 +15,14 @@ import LinkSharingLanding from "./Pages/LinkSharingLanding" export const SETTINGS_BASE = "/settings" export const LINK_SHARING_BASE = "/link-sharing" +const CHAINSAFE_LANDING = "https://chainsafe.io/" export const ROUTE_LINKS = { Landing: "/", PrivacyPolicy: "https://files.chainsafe.io/privacy-policy", Terms: "https://files.chainsafe.io/terms-of-service", - ChainSafe: "https://chainsafe.io/", + ChainSafe: CHAINSAFE_LANDING, + ProductPlans: `${CHAINSAFE_LANDING}`, Drive: (rawCurrentPath: string) => `/drive${rawCurrentPath}`, Bin: (rawBinPath: string) => `/bin${rawBinPath}`, Search: (rawSearchTerm: string) => `/search/${rawSearchTerm}`, diff --git a/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductModal.tsx b/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductModal.tsx deleted file mode 100644 index 3e9d5ab105..0000000000 --- a/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductModal.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React, { useEffect, useState } from "react" -import { makeStyles, createStyles } from "@chainsafe/common-theme" -import { CSFTheme } from "../../../../Themes/types" -import clsx from "clsx" -import { Modal } from "@chainsafe/common-components" -import SelectPlan from "./ChangeProductViews/SelectPlan" -import { useBilling } from "../../../../Contexts/BillingContext" - -const useStyles = makeStyles(({ constants }: CSFTheme) => - createStyles({ - root: { - }, - inner: { - borderRadius: `${constants.generalUnit / 2}px` - }, - slide: { - borderRadius: constants.generalUnit / 2, - padding: `0 ${constants.generalUnit * 3}px` - } - }) -) - -interface IChangeProductModal { - className?: string - close: () => void -} - -const ChangeProductModal = ({ className, close }: IChangeProductModal) => { - const classes = useStyles() - const { changeSubscription } = useBilling() - const [slide, setSlide] = useState<"select" | "confirm">("select") - - useEffect(() => { - if (slide !== "select") { - setSlide("select") - } - }, [slide]) - - return ( - - { - slide === "select" && { - // setSlide("confirm") - changeSubscription(newpriceId) - .then(() => close()) - .catch(console.error) - }} - /> - } - - ) -} - -export default ChangeProductModal \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductViews/SelectPlan.tsx b/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductViews/SelectPlan.tsx deleted file mode 100644 index 86842560f3..0000000000 --- a/packages/files-ui/src/Components/Modules/Settings/Products/ChangeProductViews/SelectPlan.tsx +++ /dev/null @@ -1,270 +0,0 @@ -import React, { useEffect, useMemo, useState } from "react" -import { makeStyles, createStyles } from "@chainsafe/common-theme" -import clsx from "clsx" -import { Button, ExternalSvg, Loading, ToggleSwitch, Typography } from "@chainsafe/common-components" -import { t, Trans } from "@lingui/macro" -import { CSFTheme } from "../../../../../Themes/types" -import { useBilling } from "../../../../../Contexts/BillingContext" -import { Product, ProductPriceRecurringInterval } from "@chainsafe/files-api-client" - -const useStyles = makeStyles(({ breakpoints, constants, palette, typography }: CSFTheme) => - createStyles({ - root: { - margin: `${constants.generalUnit * 2}px 0px` - }, - header: { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "space-between" - }, - label: { - ...typography.h5 - }, - panels: { - display: "flex", - flexDirection: "row", - flexWrap: "wrap", - justifyContent: "space-between", - margin: `${constants.generalUnit * 3.5}px 0` - }, - panel: { - display: "flex", - flexDirection: "column", - padding: `${constants.generalUnit}px ${constants.generalUnit * 3}px`, - width: `calc(33.3333% - ${constants.generalUnit * 2}px)`, - minHeight: 200, - cursor: "pointer", - border: `3px solid ${palette.additional.gray[4]}`, - borderRadius: constants.generalUnit, - marginBottom: constants.generalUnit, - "&.active": { - opacity: "1 !important", - backgroundColor: constants.changeProduct.currentBackground, - borderColor: constants.changeProduct.selectedColor - }, - [breakpoints.down("sm")]: { - width: `calc(50% - ${constants.generalUnit}px)` - } - }, - loader: { - margin: "0 auto" - }, - panelTop: { - height: "60%", - "& > header": { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center", - marginBottom: constants.generalUnit - } - }, - tag: { - display: "block", - padding: `0 ${constants.generalUnit}px`, - borderRadius: `${constants.generalUnit * 2}px`, - height: 20, - "&.current": { - backgroundColor: palette.primary.main, - color: constants.changeProduct.currentTag.text - }, - "&.popular": { - backgroundColor: palette.additional.gold[5] - } - }, - panelBottom: { - height: "40%" - }, - link: { - display: "flex", - justifyContent: "flex-start", - alignItems: "center", - "& svg": { - marginLeft: constants.generalUnit, - stroke: palette.additional.gray[10], - width: constants.generalUnit * 2, - height: constants.generalUnit * 2 - } - }, - buttons: { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "flex-end", - "& > *": { - marginLeft: constants.generalUnit - } - }, - bottomSection: { - display: "flex", - flexDirection: "row", - justifyContent: "space-between", - alignItems: "center" - } - }) -) - -interface ISelectPlan { - className?: string - close: () => void - next: (newPriceId: string) => void -} - -const SelectPlan = ({ close, className, next }: ISelectPlan) => { - const classes = useStyles() - const { getAvailablePlans, currentSubscription } = useBilling() - const [selectedPlan, setSelectedPlan] = useState(currentSubscription?.product.id) - const [plans, setPlans] = useState() - const [interval, setInterval] = useState("month") - - useEffect(() => { - if(!plans) { - getAvailablePlans() - .then((plans) => setPlans(plans)) - .catch(console.error) - } - }) - - const selectedPrice = useMemo(() => { - return plans?.find(plan => plan.id === selectedPlan)?.prices.find(price => price.recurring.interval === interval)?.id - }, [selectedPlan, plans, interval]) - - const translatedPrice = useMemo(() => { - switch (interval) { - case "day": - return t`per day` - case "week": - return t`per week` - case "month": - return t`per month` - case "year": - return t`per year` - } - }, [interval]) - - return ( -
-
- - - Switch Plans - - -
- setInterval(value)} - size="medium" - /> -
-
-
- {!plans && } - {plans && plans.map((plan) => ( -
setSelectedPlan(plan.id) } - key={`plan-${plan.id}`} - > -
-
- - {plan.name} - - {plan.id === currentSubscription?.product.id && ( - - - Current - - - )} -
- - { - plan.description - } - -
-
- {plan.prices - .filter(price => price.recurring.interval === interval) - .map(price => ( - - {price.unit_amount === 0 ? t`Free` : `${price.unit_amount} ${price.currency} ${translatedPrice}`} - - ))} -
-
- )) - } -
-
- - - - Not sure what to pick? Learn more about our plans - - - - -
- - -
-
-
- ) -} - -export default SelectPlan \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/Products/ProductInfo.tsx b/packages/files-ui/src/Components/Modules/Settings/Products/ProductInfo.tsx deleted file mode 100644 index 109cbadbb0..0000000000 --- a/packages/files-ui/src/Components/Modules/Settings/Products/ProductInfo.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from "react" -import { Divider, Typography } from "@chainsafe/common-components" -import { makeStyles, createStyles } from "@chainsafe/common-theme" -import { CSFTheme } from "../../../../Themes/types" -import clsx from "clsx" -import { Trans } from "@lingui/macro" -import { Product } from "@chainsafe/files-api-client" - -const useStyles = makeStyles(({ constants, palette, typography }: CSFTheme) => - createStyles({ - container: { - border: "1px solid", - borderColor: palette.additional["gray"][3], - color: "inherit", - padding: `${constants.generalUnit * 4}px ${constants.generalUnit * 4}px ${constants.generalUnit * 5}px` - }, - planFor: { - fontSize: 18, - color: "inherit" - }, - title: { - fontSize: 30, - margin: `${constants.generalUnit * 2}px 0px ${constants.generalUnit * 4}px` - }, - feature: { - margin: `${constants.generalUnit * 0.5}px 0px` - }, - price: { - fontWeight: "bold", - margin: `${constants.generalUnit * 3}px 0px ${constants.generalUnit * 6}px` - }, - buttonLink: { - outline: "none", - textDecoration: "underline", - cursor: "pointer", - textAlign: "left", - ...typography.body1, - fontWeight: "bold" - }, - divider: { - margin: `${constants.generalUnit * 3}px 0px` - } - }) -) - -interface ProductInfoProps { - product: Product - className: string -} - -const ProductInfo = ({ product, className }: ProductInfoProps) => { - const classes = useStyles() - const { description, name } = product - // const { tax_behavior, recurring, type, currency, unit_amount } = prices - return ( -
- - - - - {/* not adding translations to titles */} - {name} - - - {description} - - {/* - {t`$${billingPeriod === "monthly" ? monthly : yearly} USD/${billingPeriod === "monthly" ? "month" : "year"}`} - */} -
- Try for 7 days -
- -
- Purchase with card -
-
- ) -} - -export default ProductInfo \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/Products/Products.tsx b/packages/files-ui/src/Components/Modules/Settings/Products/Products.tsx deleted file mode 100644 index c569f8844d..0000000000 --- a/packages/files-ui/src/Components/Modules/Settings/Products/Products.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React, { useState } from "react" -import { makeStyles, createStyles } from "@chainsafe/common-theme" -import { CSFTheme } from "../../../../Themes/types" -import ProductInfo from "./ProductInfo" -import { ArrowLeftIcon, Link, RadioInput, Typography } from "@chainsafe/common-components" -import { t, Trans } from "@lingui/macro" -import { ROUTE_LINKS } from "../../../FilesRoutes" -import { useFilesApi } from "../../../../Contexts/FilesApiContext" -import { Product } from "@chainsafe/files-api-client" -import { useEffect } from "react" - -const useStyles = makeStyles(({ constants, palette, breakpoints }: CSFTheme) => - createStyles({ - root: { - [breakpoints.down("md")]: { - padding: `${constants.generalUnit * 4}px ${constants.generalUnit * 2}px` - } - }, - container: { - display: "grid", - gridColumnGap: constants.generalUnit * 2, - gridTemplateColumns: "1fr 1fr 1fr", - [breakpoints.down("md")]: { - gridTemplateColumns: "1fr 1fr", - gridRowGap: constants.generalUnit * 2 - }, - [breakpoints.down("sm")]: { - gridTemplateColumns: "1fr", - gridRowGap: constants.generalUnit * 2 - } - }, - heading: { - marginBottom: constants.generalUnit * 4, - [breakpoints.down("md")]: { - marginBottom: constants.generalUnit * 2 - } - }, - backIcon: { - fontSize: 10, - marginRight: constants.generalUnit - }, - planSettings: { - display: "flex", - justifyContent: "space-between", - margin: `${constants.generalUnit * 2}px 0px ${constants.generalUnit * 5}px`, - alignItems: "center", - [breakpoints.down("sm")]: { - flexDirection: "column", - alignItems: "flex-start", - margin: `${constants.generalUnit * 2}px 0px ${constants.generalUnit * 2}px` - } - }, - planRadios: { - display: "flex", - alignItems: "center" - }, - plan1: { - backgroundColor: palette.additional["gray"][3], - color: palette.additional["gray"][9] - }, - plan2: { - backgroundColor: palette.additional["blue"][7], - color: palette.additional["gray"][1] - }, - plan3: { - backgroundColor: palette.additional["gray"][9], - color: palette.additional["gray"][1] - } - }) -) - -const Products = () => { - const classes = useStyles() - const [billingPeriod, setBillingPeriod] = useState<"monthly" | "yearly">("monthly") - const { filesApiClient } = useFilesApi() - const [products] = useState([]) - - useEffect(() => { - filesApiClient.getAllProducts().then(prods => { - console.log(prods) - // setProducts(prods) - }).catch(console.error) - }, [filesApiClient]) - - return ( -
- - Upgrade your plan - -
- - - Back to plan settings - -
- setBillingPeriod("monthly")} - checked={billingPeriod === "monthly"} - /> - setBillingPeriod("yearly")} - checked={billingPeriod === "yearly"} - /> -
-
-
- {products.map(p => )} -
-
- - ) -} - -export default Products \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCardModal.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCard.tsx similarity index 50% rename from packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCardModal.tsx rename to packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCard.tsx index 52c215ceb9..a95e180708 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCardModal.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCard.tsx @@ -1,38 +1,25 @@ import React, { FormEvent, useMemo, useState } from "react" import { Button, Grid, Typography, useToasts } from "@chainsafe/common-components" import { createStyles, makeStyles, useTheme } from "@chainsafe/common-theme" -import { CSFTheme } from "../../../../Themes/types" -import CustomModal from "../../../Elements/CustomModal" -import CustomButton from "../../../Elements/CustomButton" +import { CSFTheme } from "../../../../../Themes/types" +import CustomButton from "../../../../Elements/CustomButton" import { t, Trans } from "@lingui/macro" -import { useStripe, useElements, CardNumberElement, CardExpiryElement, CardCvcElement } from "@stripe/react-stripe-js" -import { useFilesApi } from "../../../../Contexts/FilesApiContext" -import { useBilling } from "../../../../Contexts/BillingContext" +import { useStripe, + useElements, + CardNumberElement, + CardExpiryElement, + CardCvcElement +} from "@stripe/react-stripe-js" +import { useFilesApi } from "../../../../../Contexts/FilesApiContext" +import { useBilling } from "../../../../../Contexts/BillingContext" import clsx from "clsx" -import { Card } from "@chainsafe/files-api-client" const useStyles = makeStyles( - ({ breakpoints, constants, typography, zIndex, palette, animation }: CSFTheme) => { + ({ breakpoints, constants, palette, animation }: CSFTheme) => { return createStyles({ root: { - padding: constants.generalUnit * 4, flexDirection: "column" }, - modalRoot: { - zIndex: zIndex?.blocker, - [breakpoints.down("md")]: {} - }, - modalInner: { - backgroundColor: constants.createFolder.backgroundColor, - color: constants.createFolder.color, - [breakpoints.down("md")]: { - bottom: - Number(constants?.mobileButtonHeight) + constants.generalUnit, - borderTopLeftRadius: `${constants.generalUnit * 1.5}px`, - borderTopRightRadius: `${constants.generalUnit * 1.5}px`, - maxWidth: `${breakpoints.width("md")}px !important` - } - }, okButton: { marginLeft: constants.generalUnit }, @@ -49,15 +36,6 @@ const useStyles = makeStyles( fontSize: 14, lineHeight: "22px" }, - heading: { - color: constants.createFolder.color, - fontWeight: typography.fontWeight.semibold, - textAlign: "left", - marginBottom: constants.generalUnit * 2 - }, - footer: { - marginTop: constants.generalUnit * 4 - }, cardNumberInputs: { marginBottom: constants.generalUnit * 2, [breakpoints.down("md")]: { @@ -91,24 +69,36 @@ const useStyles = makeStyles( error: { marginTop: constants.generalUnit * 2, color: palette.error.main + }, + backButton: { + flex: 1, + display: "flex", + alignItems: "center" + }, + linkButton: { + textDecoration: "underline", + cursor: "pointer" } }) } ) -interface IAddCardModalProps { - isModalOpen: boolean - onClose: () => void - defaultCard?: Card +interface IAddCardProps { + submitText: string + onCardAdd?: () => void + onClose?: () => void + goBack?: () => void + footerClassName?: string } -const AddCardModal = ({ isModalOpen, onClose, defaultCard }: IAddCardModalProps) => { + +const AddCard = ({ onClose, onCardAdd, footerClassName, submitText, goBack }: IAddCardProps) => { const classes = useStyles() const stripe = useStripe() const elements = useElements() const { addToast } = useToasts() const { filesApiClient } = useFilesApi() - const { refreshDefaultCard, deleteCard, updateDefaultCard } = useBilling() + const { refreshDefaultCard, deleteCard, updateDefaultCard, defaultCard } = useBilling() const [focusElement, setFocusElement] = useState<"number" | "expiry" | "cvc" | undefined>(undefined) const [cardAddError, setCardAddError] = useState(undefined) const theme: CSFTheme = useTheme() @@ -151,7 +141,7 @@ const AddCardModal = ({ isModalOpen, onClose, defaultCard }: IAddCardModalProps) isUpdate && defaultCard && await deleteCard(defaultCard) await updateDefaultCard(paymentMethod.id) refreshDefaultCard() - onClose() + onCardAdd && onCardAdd() setLoadingPaymentMethodAdd(false) addToast({ title: isUpdate ? t`Card updated` : t`Card added`, type: "success" }) } catch (error) { @@ -162,97 +152,82 @@ const AddCardModal = ({ isModalOpen, onClose, defaultCard }: IAddCardModalProps) } return ( - -
-
- - - { - isUpdate - ? Update your credit card - : Add a credit card - } - - - +
+ setFocusElement("number")} + onBlur={() => setFocusElement(undefined)} + onChange={() => setCardAddError(undefined)} + /> +
+ setFocusElement("expiry")} + onBlur={() => setFocusElement(undefined)} + onChange={() => setCardAddError(undefined)} + options={{ style: { base: { color: theme.constants.addCard.color } } }} - onFocus={() => setFocusElement("number")} + /> + setFocusElement("cvc")} onBlur={() => setFocusElement(undefined)} onChange={() => setCardAddError(undefined)} + options={{ style: { + base: { + color: theme.constants.addCard.color + } + } }} /> -
- setFocusElement("expiry")} - onBlur={() => setFocusElement(undefined)} - onChange={() => setCardAddError(undefined)} - options={{ style: { - base: { - color: theme.constants.addCard.color - } - } }} - /> - setFocusElement("cvc")} - onBlur={() => setFocusElement(undefined)} - onChange={() => setCardAddError(undefined)} - options={{ style: { - base: { - color: theme.constants.addCard.color - } - } }} - /> +
+ {cardAddError && + {cardAddError} + + } + +
+ {goBack && + + Go back + + }
- {cardAddError && - - {cardAddError} - - } - + {onClose && Cancel - - -
- - + } + + +
+ ) } -export default AddCardModal +export default AddCard diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCardModal.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCardModal.tsx new file mode 100644 index 0000000000..7c34316924 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/AddCard/AddCardModal.tsx @@ -0,0 +1,86 @@ +import React, { useMemo } from "react" +import { createStyles, makeStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import CustomModal from "../../../../Elements/CustomModal" +import { t, Trans } from "@lingui/macro" +import AddCard from "./AddCard" +import { Typography } from "@chainsafe/common-components" +import { useBilling } from "../../../../../Contexts/BillingContext" + +const useStyles = makeStyles( + ({ breakpoints, constants, zIndex, typography }: CSFTheme) => { + return createStyles({ + root: { + padding: constants.generalUnit * 4 + }, + modalRoot: { + zIndex: zIndex?.blocker, + [breakpoints.down("md")]: {} + }, + modalInner: { + backgroundColor: constants.createFolder.backgroundColor, + color: constants.createFolder.color, + [breakpoints.down("md")]: { + bottom: + Number(constants?.mobileButtonHeight) + constants.generalUnit, + borderTopLeftRadius: `${constants.generalUnit * 1.5}px`, + borderTopRightRadius: `${constants.generalUnit * 1.5}px`, + maxWidth: `${breakpoints.width("md")}px !important` + } + }, + heading: { + color: constants.createFolder.color, + fontWeight: typography.fontWeight.semibold, + textAlign: "left", + marginBottom: constants.generalUnit * 3 + }, + footer: { + marginTop: constants.generalUnit * 4 + } + }) + } +) + +interface IAddCardModalProps { + isModalOpen: boolean + onClose: () => void +} + +const AddCardModal = ({ isModalOpen, onClose }: IAddCardModalProps) => { + const classes = useStyles() + const { defaultCard } = useBilling() + const isUpdate = useMemo(() => !!defaultCard, [defaultCard]) + + return ( + +
+ + {isUpdate + ? Update your credit card + : Add a credit card + } + + +
+
+ ) +} + +export default AddCardModal diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ChangePlanModal.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ChangePlanModal.tsx new file mode 100644 index 0000000000..e0817d328a --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ChangePlanModal.tsx @@ -0,0 +1,148 @@ +import React, { useEffect, useState } from "react" +import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Modal } from "@chainsafe/common-components" +import SelectPlan from "./SelectPlan" +import PlanDetails from "./PlanDetails" +import PaymentMethod from "./PaymentMethod" +import ConfirmPlan from "./ConfirmPlan" +import { useBilling } from "../../../../../Contexts/BillingContext" +import { Product, ProductPrice } from "@chainsafe/files-api-client" +import PlanSuccess from "./PlanSuccess" + +const useStyles = makeStyles(({ constants, breakpoints }: CSFTheme) => + createStyles({ + root: { + "&:before": { + backgroundColor: constants.modalDefault.fadeBackground + } + }, + inner: { + borderRadius: `${constants.generalUnit / 2}px`, + [breakpoints.up("sm")]: { + minWidth: 480 + }, + [breakpoints.down("sm")]: { + width: "100%" + } + } + }) +) + +type ChangeModalSlides = "select" | +"planDetails" | +"paymentMethod" | +"confirmPlan" | +"planSuccess" + +interface IChangeProductModal { + onClose: () => void +} + +const ChangeProductModal = ({ onClose }: IChangeProductModal) => { + const classes = useStyles() + const { getAvailablePlans, changeSubscription } = useBilling() + const [selectedPlan, setSelectedPlan] = useState() + const [selectedPrice, setSelectedPrice] = useState() + const [slide, setSlide] = useState("select") + const [plans, setPlans] = useState() + const [isLoadingChangeSubscription, setIsLoadingChangeSubscription] = useState(false) + const [isSubscriptionError, setIsSubscriptionError] = useState(false) + + useEffect(() => { + if(!plans) { + getAvailablePlans() + .then((plans) => setPlans(plans)) + .catch(console.error) + } + }) + + const handleChangeSubscription = () => { + if (selectedPrice) { + setIsLoadingChangeSubscription(true) + changeSubscription(selectedPrice.id) + .then(() => { + setSlide("planSuccess") + }) + .catch(() => { + setIsSubscriptionError(true) + }) + .finally(() => setIsLoadingChangeSubscription(false)) + } + } + + return ( + + { + slide === "select" && { + setSelectedPlan(plan) + setSlide("planDetails") + }} + plans={plans} + /> + } + {slide === "planDetails" && selectedPlan && { + setSlide("select") + }} + onSelectPlanPrice={(planPrice: ProductPrice) => { + setSelectedPrice(planPrice) + setSlide("paymentMethod") + }} + /> + } + {slide === "paymentMethod" && { + setSlide("select") + }} + goToPlanDetails={() => { + setSlide("planDetails") + }} + onSelectPaymentMethod={() => { + setSlide("confirmPlan") + }} + /> + } + {slide === "confirmPlan" && selectedPlan && selectedPrice && { + setSlide("select") + }} + goToPlanDetails={() => { + setSlide("planDetails") + }} + goToPaymentMethod={() => { + setSlide("paymentMethod") + }} + loadingChangeSubscription={isLoadingChangeSubscription} + onChangeSubscription={handleChangeSubscription} + isSubscriptionError={isSubscriptionError} + /> + } + {slide === "planSuccess" && selectedPlan && selectedPrice && + } + + ) +} + +export default ChangeProductModal \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx new file mode 100644 index 0000000000..a076d478a3 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/ConfirmPlan.tsx @@ -0,0 +1,285 @@ +import React from "react" +import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Product, ProductPrice } from "@chainsafe/files-api-client" +import { Breadcrumb, Button, CreditCardIcon, Divider, formatBytes, Typography } from "@chainsafe/common-components" +import { t, Trans } from "@lingui/macro" +import dayjs from "dayjs" +import { useBilling } from "../../../../../Contexts/BillingContext" +import clsx from "clsx" + +const useStyles = makeStyles(({ constants, palette }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + }, + heading: { + marginTop: constants.generalUnit * 3, + marginBottom: constants.generalUnit * 2 + }, + subheading: { + marginBottom: constants.generalUnit * 3 + }, + boldText: { + fontWeight: "bold" + }, + normalWeightText: { + fontWeight: "normal" + }, + rowBox: { + display: "flex", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + middleRowBox: { + display: "flex", + alignItems: "center", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + pushRightBox: { + display: "flex", + flexDirection: "column", + alignItems: "flex-end", + flex: 1 + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + margin: `${constants.generalUnit * 3}px 0px` + }, + divider: { + margin: `${constants.generalUnit}px 0` + }, + textButton: { + color: palette.primary.background, + cursor: "pointer", + textDecoration: "underline" + }, + creditCardIcon: { + marginRight: constants.generalUnit, + fill: palette.additional["gray"][9] + }, + featuresBox: { + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit * 2 + }, + creditCardRow: { + display: "flex", + alignItems: "center", + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit + }, + featureSeparator: { + marginBottom: constants.generalUnit + }, + error: { + marginTop: constants.generalUnit, + color: palette.error.main + } + }) +) + +interface IConfirmPlan { + plan: Product + planPrice: ProductPrice + onClose: () => void + goToSelectPlan: () => void + goToPlanDetails: () => void + goToPaymentMethod: () => void + onChangeSubscription: () => void + loadingChangeSubscription: boolean + isSubscriptionError: boolean +} + +const ConfirmPlan = ({ + plan, + onClose, + planPrice, + goToSelectPlan, + goToPlanDetails, + goToPaymentMethod, + onChangeSubscription, + loadingChangeSubscription, + isSubscriptionError +}: IConfirmPlan) => { + const classes = useStyles() + const { defaultCard } = useBilling() + const currentPlanStorage = formatBytes(Number(planPrice?.metadata?.storage_size_bytes), 2) + + return ( +
+ + + Confirm plan change + + +
+ + {plan.name} + +
+ + Edit plan + +
+
+
+ + Features + +
+ + {planPrice?.metadata?.storage_size_bytes + ? {currentPlanStorage} of storage + : plan.description + } + + + {plan.description} + +
+
+ +
+ + Payment method + +
+ + Edit payment method + +
+
+ {defaultCard && +
+ + + •••• •••• •••• {defaultCard.last_four_digit} + +
+ } +
+ + Billing start time + +
+ + {dayjs().format("DD MMM YYYY")} + +
+
+ +
+ + Total + +
+ + {planPrice.unit_amount ? planPrice.currency : ""} {planPrice.unit_amount} + + {planPrice.recurring.interval === "month" ? t`/month` : t`/year`} + + +
+
+ {isSubscriptionError && + + Failed to change subscription + + } +
+
+ + +
+
+
+ ) +} + +export default ConfirmPlan \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PaymentMethod.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PaymentMethod.tsx new file mode 100644 index 0000000000..0271261699 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PaymentMethod.tsx @@ -0,0 +1,190 @@ +import React, { useEffect, useState } from "react" +import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Breadcrumb, Button, Divider, RadioInput, Typography } from "@chainsafe/common-components" +import { t, Trans } from "@lingui/macro" +import AddCard from "../AddCard/AddCard" +import { useBilling } from "../../../../../Contexts/BillingContext" + +const useStyles = makeStyles(({ constants, palette }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + }, + heading: { + marginTop: constants.generalUnit * 3, + marginBottom: constants.generalUnit * 2 + }, + subHeading: { + marginBottom: constants.generalUnit * 2, + color: palette.additional["gray"][8] + }, + boldText: { + fontWeight: "bold" + }, + normalWeightText: { + fontWeight: "normal" + }, + rowBox: { + display: "flex", + justifyContent: "space-between" + }, + pushRightBox: { + display: "flex", + flexDirection: "column", + alignItems: "flex-end", + flex: 1 + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + marginTop: constants.generalUnit * 4, + marginBottom: constants.generalUnit * 3 + }, + divider: { + margin: `${constants.generalUnit}px 0` + }, + radioLabel: { + fontSize: 14 + }, + textButton: { + color: palette.primary.background, + cursor: "pointer" + }, + linkButton: { + textDecoration: "underline", + cursor: "pointer" + }, + addCardWrapper: { + padding: `${constants.generalUnit * 2}px 0px` + }, + footer: { + marginTop: constants.generalUnit * 2 + } + }) +) + +interface IPaymentMethodProps { + onClose: () => void + goToSelectPlan: () => void + goToPlanDetails: () => void + onSelectPaymentMethod: () => void +} + +const PlanDetails = ({ onClose, goToSelectPlan, goToPlanDetails, onSelectPaymentMethod }: IPaymentMethodProps) => { + const classes = useStyles() + const [paymentMethod, setPaymentMethod] = useState<"creditCard" | "crypto" | undefined>() + const [view, setView] = useState<"selectPaymentMethod" | "addCard">("selectPaymentMethod") + const { defaultCard } = useBilling() + + useEffect(() => { + if (defaultCard) { + setPaymentMethod("creditCard") + } + }, [defaultCard]) + + return ( +
+ + + Select payment method + + + {view === "addCard" && This card will become your default payment method} + + + {view === "selectPaymentMethod" && <> +
+ setPaymentMethod("creditCard")} + checked={paymentMethod === "creditCard"} + labelClassName={classes.radioLabel} + disabled={!defaultCard} + /> + setView("addCard")} + > + {defaultCard + ? Update credit card + : Add credit card + } + +
+ + setPaymentMethod("crypto")} + checked={paymentMethod === "crypto"} + labelClassName={classes.radioLabel} + disabled={true} + /> + + } + {view === "addCard" &&
+ setView("selectPaymentMethod")} + goBack={() => setView("selectPaymentMethod")} + /> +
+ } + +
+
+ + +
+
+
+ ) +} + +export default PlanDetails \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx new file mode 100644 index 0000000000..f764ff5137 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanDetails.tsx @@ -0,0 +1,226 @@ +import React, { useState } from "react" +import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Product, ProductPrice } from "@chainsafe/files-api-client" +import { Breadcrumb, Button, Divider, formatBytes, ToggleSwitch, Typography } from "@chainsafe/common-components" +import { t, Trans } from "@lingui/macro" +import dayjs from "dayjs" + +const useStyles = makeStyles(({ constants }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + }, + heading: { + marginTop: constants.generalUnit * 3, + marginBottom: constants.generalUnit + }, + subheading: { + marginBottom: constants.generalUnit * 3 + }, + boldText: { + fontWeight: "bold" + }, + normalWeightText: { + fontWeight: "normal" + }, + featureSeparator: { + marginBottom: constants.generalUnit + }, + rowBox: { + display: "flex", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + middleRowBox: { + display: "flex", + alignItems: "center", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + pushRightBox: { + display: "flex", + flexDirection: "column", + alignItems: "flex-end", + flex: 1 + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + margin: `${constants.generalUnit * 3}px 0px` + }, + divider: { + margin: `${constants.generalUnit}px 0` + } + }) +) + +interface IPlanDetails { + plan: Product + onClose: () => void + goToSelectPlan: () => void + onSelectPlanPrice: (planPrice: ProductPrice) => void +} + +const PlanDetails = ({ plan, onClose, goToSelectPlan, onSelectPlanPrice }: IPlanDetails) => { + const classes = useStyles() + const monthlyPrice = plan.prices.find((price) => price.recurring.interval === "month") + const yearlyPrice = plan.prices.find((price) => price.recurring.interval === "year") + const currentPlanStorage = formatBytes(Number(monthlyPrice?.metadata?.storage_size_bytes), 2) + + const [billingPeriod, setBillingPeriod] = useState<"monthly" | "yearly">(monthlyPrice ? "monthly" : "yearly") + + const handleSelectPlan = () => { + if(billingPeriod === "monthly" && monthlyPrice) { + onSelectPlanPrice(monthlyPrice) + } else if (yearlyPrice) { + onSelectPlanPrice(yearlyPrice) + } + } + + return ( +
+ + + {plan.name} + + + You get access to these features right now. + + +
+ + Features + +
+ + {monthlyPrice?.metadata?.storage_size_bytes + ? {currentPlanStorage} of storage + : plan.description + } + + + {plan.description} + +
+
+ +
+ + Billing start time + +
+ + {dayjs().format("DD MMM YYYY")} + +
+
+ + {monthlyPrice && yearlyPrice && + <> +
+ + {billingPeriod === "monthly" + ? Monthly billing + : Yearly billing + } + +
+ setBillingPeriod(billingPeriod === "monthly" ? "yearly" : "monthly")} + /> +
+
+ + + } +
+ + Total + +
+ + {billingPeriod === "monthly" + ? `${monthlyPrice?.unit_amount ? monthlyPrice?.currency : ""} ${monthlyPrice?.unit_amount}` + : `${yearlyPrice?.unit_amount ? yearlyPrice?.currency : ""} ${yearlyPrice?.unit_amount}` + }{billingPeriod ? t`/month` : t`/year`} + +
+
+
+
+ + +
+
+
+ ) +} + +export default PlanDetails \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanSuccess.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanSuccess.tsx new file mode 100644 index 0000000000..b55c30d97f --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/PlanSuccess.tsx @@ -0,0 +1,174 @@ +import React from "react" +import { makeStyles, createStyles } from "@chainsafe/common-theme" +import { CSFTheme } from "../../../../../Themes/types" +import { Product, ProductPrice } from "@chainsafe/files-api-client" +import { Button, CheckCircleIcon, CheckIcon, Divider, formatBytes, Link, Typography } from "@chainsafe/common-components" +import { Trans } from "@lingui/macro" +import { ROUTE_LINKS } from "../../../../FilesRoutes" +import clsx from "clsx" + +const useStyles = makeStyles(({ constants, palette }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + }, + headingBadge: { + color: palette.additional["gray"][7], + marginTop: constants.generalUnit * 3 + }, + headingBox: { + marginTop: constants.generalUnit * 2, + marginBottom: constants.generalUnit * 2 + }, + rowBox: { + display: "flex", + padding: `${constants.generalUnit * 0.5}px 0px` + }, + middleRowBox: { + display: "flex", + alignItems: "center" + }, + featuresTitle: { + marginTop: constants.generalUnit * 2, + marginBottom: constants.generalUnit * 2 + }, + pushRightBox: { + display: "flex", + flexDirection: "column", + alignItems: "flex-start", + marginLeft: constants.generalUnit * 4 + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "flex-end", + alignItems: "center", + margin: `${constants.generalUnit * 3}px 0px` + }, + divider: { + margin: `${constants.generalUnit}px 0` + }, + featuresBox: { + marginTop: constants.generalUnit, + marginBottom: constants.generalUnit * 2 + }, + featureTickBox: { + marginBottom: constants.generalUnit + }, + textLink: { + color: palette.primary.background + }, + checkCircleIcon: { + fill: palette.additional["gray"][7], + marginLeft: constants.generalUnit + }, + tickIcon: { + fill: palette.success.main + }, + invoiceText: { + marginTop: constants.generalUnit * 3, + marginBottom: constants.generalUnit + } + }) +) + +interface IPlanSuccess { + plan: Product + planPrice: ProductPrice + onClose: () => void +} + +const PlanSuccess = ({ plan, onClose, planPrice }: IPlanSuccess) => { + const classes = useStyles() + const newPlanCapacity = formatBytes(Number(planPrice?.metadata?.storage_size_bytes), 2) + + return ( +
+ + Confirmation + +
+ + Plan changed successfully + + +
+ +
+ + You now have: + +
+
+ + + {planPrice?.metadata?.storage_size_bytes + ? {newPlanCapacity} of storage + : plan.description + } + +
+
+ + + {plan.description} + +
+
+
+
+ + Access your billing history in settings or view your   + + invoices here + + +
+
+
+ +
+
+
+ ) +} + +export default PlanSuccess \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/SelectPlan.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/SelectPlan.tsx new file mode 100644 index 0000000000..30229862f1 --- /dev/null +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/SelectPlan.tsx @@ -0,0 +1,315 @@ +import React, { useState } from "react" +import { makeStyles, createStyles, useThemeSwitcher } from "@chainsafe/common-theme" +import clsx from "clsx" +import { Button, ExternalSvg, formatBytes, Loading, Typography } from "@chainsafe/common-components" +import { t, Trans } from "@lingui/macro" +import { CSFTheme } from "../../../../../Themes/types" +import { useBilling } from "../../../../../Contexts/BillingContext" +import { Product } from "@chainsafe/files-api-client" +import { ROUTE_LINKS } from "../../../../FilesRoutes" + +const useStyles = makeStyles(({ breakpoints, constants, palette, typography }: CSFTheme) => + createStyles({ + root: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 3}px`, + [breakpoints.down("md")]: { + margin: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px` + } + }, + header: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + marginTop: constants.generalUnit * 2 + }, + loadingContainer: { + margin: `${constants.generalUnit * 4}px 0`, + display: "flex", + justifyContent: "center" + }, + panels: { + display: "grid", + gridColumnGap: constants.generalUnit * 1.5, + gridRowGap: constants.generalUnit * 1.5, + gridTemplateColumns: "1fr 1fr 1fr", + marginTop: constants.generalUnit * 2, + marginBottom: constants.generalUnit * 4, + [breakpoints.down("md")]: { + gridTemplateColumns: "1fr", + marginTop: constants.generalUnit * 3 + } + }, + planBox: { + border: `2px solid ${palette.additional["gray"][5]}`, + padding: `${constants.generalUnit * 3}px ${constants.generalUnit * 4}px `, + display: "flex", + flexDirection: "column", + alignItems: "center", + borderRadius: 5, + [breakpoints.down("md")]: { + flexDirection: "row", + padding: `${constants.generalUnit * 2}px ${constants.generalUnit * 2}px `, + justifyContent: "space-between" + }, + "&.active": { + borderColor: palette.primary.background + } + }, + priceSpace: { + height: 22 + }, + link: { + display: "flex", + justifyContent: "flex-start", + alignItems: "center", + "& svg": { + marginLeft: constants.generalUnit, + stroke: palette.additional.gray[10], + width: constants.generalUnit * 2, + height: constants.generalUnit * 2 + } + }, + buttons: { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end", + "& > *": { + marginLeft: constants.generalUnit + }, + [breakpoints.down("md")]: { + flex: 1 + } + }, + bottomSection: { + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center" + }, + planTitle: { + fontWeight: "bold", + marginBottom: constants.generalUnit + }, + priceSubtitle: { + ...typography.body2, + color: palette.additional["gray"][9] + }, + description: { + margin: `${constants.generalUnit * 3}px 0`, + [breakpoints.down("md")]: { + margin: 0 + } + }, + priceYearlyTitle: { + fontWeight: "bold", + [breakpoints.down("md")]: { + fontWeight: "normal", + marginTop: constants.generalUnit + } + }, + mobilePriceBox: { + display: "flex", + flexDirection: "column", + alignItems: "end", + height: "100%" + }, + selectButton: { + marginLeft: constants.generalUnit + } + }) +) + +interface ISelectPlan { + className?: string + plans?: Product[] + onClose: () => void + onSelectPlan: (plan: Product) => void +} + +const SelectPlan = ({ onClose, className, onSelectPlan, plans }: ISelectPlan) => { + const classes = useStyles() + const { currentSubscription } = useBilling() + const { desktop } = useThemeSwitcher() + const [tempSelectedPlan, setTempSelectedPlan] = useState() + + return ( +
+
+ + Switch Plans + +
+ {!plans && ( +
+ +
+ )} +
+ {plans && plans.map((plan) => { + const monthly = plan.prices.find((price) => price.recurring.interval === "month") + const yearly = plan.prices.find((price) => price.recurring.interval === "year") + const isPlanSelectable = plan.id !== currentSubscription?.product.id && + (monthly?.is_update_allowed || yearly?.is_update_allowed) + const currentStorage = formatBytes(Number(monthly?.metadata?.storage_size_bytes), 2) + + + return desktop ? ( +
+ + {plan.name} + + {monthly && ( + + {monthly.unit_amount + ? <> + {monthly.currency.toUpperCase()} {monthly.unit_amount} + + /month + + + : t`Free`} + + )} + {monthly && yearly + ? ( + + {yearly.currency.toUpperCase()} {yearly.unit_amount} + + /year + + + ) + :
+ } + + { + monthly?.metadata?.storage_size_bytes + ? {currentStorage} of storage + : plan.description + } + + +
+ ) + : ( +
isPlanSelectable && setTempSelectedPlan(plan)} + key={`plan-${plan.id}`} + > +
+ + {plan.name} + + + { + monthly?.metadata?.storage_size_bytes + ? {currentStorage} of storage + : plan.description + } + +
+
+ {monthly && ( + + {monthly.unit_amount + ? <> + {monthly.currency.toUpperCase()} {monthly.unit_amount} + /month + + : t`Free`} + + )} + {monthly && yearly + ? ( + + {yearly.currency.toUpperCase()} {yearly.unit_amount} + /year + + ) + :
+ } +
+
+ )})} +
+
+ {desktop && ( + + + Not sure what to pick? Learn more about our plans + + + + )} +
+ + {!desktop && ( + + )} +
+
+
+ ) +} + +export default SelectPlan \ No newline at end of file diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentCard.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentCard.tsx index 43d795947c..be2b392f97 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentCard.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentCard.tsx @@ -3,7 +3,7 @@ import { Typography, CreditCardIcon, Button } from "@chainsafe/common-components import { makeStyles, ITheme, createStyles } from "@chainsafe/common-theme" import { Trans } from "@lingui/macro" import { useBilling } from "../../../../Contexts/BillingContext" -import AddCardModal from "./AddCardModal" +import AddCardModal from "./AddCard/AddCardModal" const useStyles = makeStyles(({ constants, palette }: ITheme) => createStyles({ @@ -66,7 +66,6 @@ const CurrentCard: React.FC = () => { setIsAddCardModalOpen(false)} - defaultCard={defaultCard} /> ) diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentProduct.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentPlan.tsx similarity index 93% rename from packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentProduct.tsx rename to packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentPlan.tsx index 9529631d5f..3f12d30d9c 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentProduct.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/CurrentPlan.tsx @@ -11,7 +11,7 @@ import { useFiles } from "../../../../Contexts/FilesContext" import { t, Trans } from "@lingui/macro" import clsx from "clsx" import { useBilling } from "../../../../Contexts/BillingContext" -import ChangeProductModal from "../Products/ChangeProductModal" +import ChangeProductModal from "./ChangePlan/ChangePlanModal" const useStyles = makeStyles(({ breakpoints, constants }: ITheme) => createStyles({ @@ -78,7 +78,10 @@ const CurrentProduct = ({ className }: ICurrentProduct) => { > {currentSubscription?.product.name} - : + : } {storageSummary && <> @@ -108,7 +111,7 @@ const CurrentProduct = ({ className }: ICurrentProduct) => {
{ isChangeProductModalVisible && ( setChangeProductModalVisible(false)} + onClose={() => setChangeProductModalVisible(false)} />) } diff --git a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/index.tsx b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/index.tsx index 6597ec5cc3..8e314af8a6 100644 --- a/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/index.tsx +++ b/packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/index.tsx @@ -6,7 +6,7 @@ import { Trans } from "@lingui/macro" import BillingHistory from "./BillingHistory" import { Elements } from "@stripe/react-stripe-js" import { loadStripe } from "@stripe/stripe-js" -import CurrentProduct from "./CurrentProduct" +import CurrentProduct from "./CurrentPlan" const useStyles = makeStyles(({ breakpoints, constants }: ITheme) => createStyles({ diff --git a/packages/files-ui/src/Contexts/BillingContext.tsx b/packages/files-ui/src/Contexts/BillingContext.tsx index 9dc2ef27a3..bd2908f68e 100644 --- a/packages/files-ui/src/Contexts/BillingContext.tsx +++ b/packages/files-ui/src/Contexts/BillingContext.tsx @@ -5,6 +5,7 @@ import { Card, CurrentSubscription, Product } from "@chainsafe/files-api-client" import { useCallback } from "react" import { t } from "@lingui/macro" import { PaymentMethod } from "@stripe/stripe-js" +import { useFiles } from "./FilesContext" type BillingContextProps = { children: ReactNode | ReactNode[] @@ -14,7 +15,7 @@ interface IBillingContext { defaultCard: Card | undefined refreshDefaultCard: () => void currentSubscription: CurrentSubscription | undefined - changeSubscription: (newPriceId: string) => Promise + changeSubscription: (newPriceId: string) => Promise fetchCurrentSubscription: () => void getAvailablePlans: () => Promise deleteCard: (card: Card) => Promise @@ -45,6 +46,7 @@ const BillingContext = React.createContext( const BillingProvider = ({ children }: BillingContextProps) => { const { filesApiClient, isLoggedIn } = useFilesApi() + const { refreshBuckets } = useFiles() const [currentSubscription, setCurrentSubscription] = useState() const [defaultCard, setDefaultCard] = useState(undefined) @@ -109,11 +111,18 @@ const BillingProvider = ({ children }: BillingContextProps) => { const changeSubscription = useCallback((newPriceId: string) => { if (!currentSubscription?.id) return Promise.resolve() return filesApiClient.updateSubscription(currentSubscription.id, { - price_id: newPriceId + price_id: newPriceId, + payment_method: "stripe" }) - .then(() => true) - .catch(console.error) - }, [filesApiClient, currentSubscription]) + .then(() => { + fetchCurrentSubscription() + refreshBuckets() + }) + .catch((error) => { + console.error(error) + return Promise.reject() + }) + }, [filesApiClient, currentSubscription, fetchCurrentSubscription, refreshBuckets]) return ( ({ palette: { primary: { main: "var(--gray3)", - hover: "var(--gray10)" + hover: "var(--gray10)", + background: "var(--csf-primary)" }, secondary: { main: "var(--gray10)", diff --git a/packages/files-ui/src/Themes/LightTheme.ts b/packages/files-ui/src/Themes/LightTheme.ts index 8d8e88f9be..95b20987c7 100644 --- a/packages/files-ui/src/Themes/LightTheme.ts +++ b/packages/files-ui/src/Themes/LightTheme.ts @@ -10,7 +10,8 @@ export const lightTheme = createTheme({ themeConfig: { palette: { primary: { - main: "var(--csf-primary)" + main: "var(--csf-primary)", + background: "var(--csf-primary)" }, secondary: { } diff --git a/packages/files-ui/src/locales/de/messages.po b/packages/files-ui/src/locales/de/messages.po index 5b17fe427a..bc292d0229 100644 --- a/packages/files-ui/src/locales/de/messages.po +++ b/packages/files-ui/src/locales/de/messages.po @@ -28,6 +28,9 @@ msgstr "Es existiert bereits eine Datei mit demselben Namen" msgid "Accept" msgstr "Akzeptieren" +msgid "Access your billing history in settings or view your" +msgstr "" + msgid "Account" msgstr "Konto" @@ -70,18 +73,21 @@ msgstr "Sicherungsgeheimsatz" msgid "Backup secret phrase does not match user account, please double-check and try again." msgstr "Der Sicherungsgeheimsatz stimmt nicht mit dem Benutzerkonto überein, bitte überprüfen Sie dies und versuchen Sie es erneut." -msgid "Billed Annually" -msgstr "" +#~ msgid "Billed Annually" +#~ msgstr "" -msgid "Billed Monthly" -msgstr "" +#~ msgid "Billed Monthly" +#~ msgstr "" -msgid "Billed Yearly" -msgstr "" +#~ msgid "Billed Yearly" +#~ msgstr "" msgid "Billing history" msgstr "" +msgid "Billing start time" +msgstr "" + msgid "Bin" msgstr "Papierkorb" @@ -124,6 +130,9 @@ msgstr "" msgid "Change password" msgstr "Passwort ändern" +msgid "Change plan" +msgstr "" + msgid "Check your inbox! We've sent another email." msgstr "Prüfen Sie Ihren Posteingang! Wir haben eine weitere E-Mail verschickt." @@ -139,6 +148,15 @@ msgstr "Bestätigen" msgid "Confirm Password:" msgstr "Passwort bestätigen:" +msgid "Confirm plan" +msgstr "" + +msgid "Confirm plan change" +msgstr "" + +msgid "Confirmation" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Wallet mit Dateien verbinden" @@ -271,6 +289,12 @@ msgstr "" msgid "Drop to upload files" msgstr "Zum Hochladen von Dateien ablegen" +msgid "Edit payment method" +msgstr "" + +msgid "Edit plan" +msgstr "" + msgid "Email is required" msgstr "E-Mail ist erforderlich" @@ -289,6 +313,9 @@ msgstr "Geben Sie den Verifizierungscode ein:" msgid "Failed to add payment method" msgstr "" +msgid "Failed to change subscription" +msgstr "" + msgid "Failed to get signature" msgstr "Signatur kann nicht abgerufen werden" @@ -301,6 +328,9 @@ msgid "" "sure you have activated your wallet." msgstr "" +msgid "Features" +msgstr "" + msgid "File Info" msgstr "Dateiinfos" @@ -337,8 +367,8 @@ msgstr "Aus Sicherheitsgründen werden wir Sie bei jeder Anmeldung nach einer de msgid "Forget this browser" msgstr "Diesen Browser vergessen" -msgid "Free" -msgstr "" +#~ msgid "Free" +#~ msgstr "" msgid "Free plan" msgstr "" @@ -364,6 +394,9 @@ msgstr "" msgid "Give view-only permission to:" msgstr "" +msgid "Go back" +msgstr "" + msgid "Go back" msgstr "Zurück" @@ -553,6 +586,15 @@ msgstr "Passwörter müssen übereinstimmen" msgid "Payment and Subscriptions" msgstr "" +msgid "Payment method" +msgstr "" + +msgid "Plan changed successfully" +msgstr "" + +msgid "Plan details" +msgstr "" + msgid "Please enter a file name" msgstr "Bitte geben Sie einen Dateinamen ein" @@ -589,8 +631,8 @@ msgstr "Profileinstellungen" msgid "Profile updated" msgstr "Profil aktualisiert" -msgid "Purchase with card" -msgstr "" +#~ msgid "Purchase with card" +#~ msgstr "" msgid "Receipt" msgstr "" @@ -844,14 +886,17 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" +msgid "Total" +msgstr "" + msgid "Try again" msgstr "Erneut versuchen" msgid "Try another method" msgstr "Eine andere Methode versuchen" -msgid "Try for 7 days" -msgstr "" +#~ msgid "Try for 7 days" +#~ msgstr "" msgid "Unable to upload" msgstr "" @@ -865,14 +910,12 @@ msgstr "" msgid "Update Shared Folder" msgstr "" -msgid "Update card" -msgstr "" -msgid "Update your credit card" +msgid "Update credit card" msgstr "" -msgid "Upgrade your plan" -msgstr "" +#~ msgid "Upgrade your plan" +#~ msgstr "" msgid "Upload" msgstr "Hochladen" @@ -886,6 +929,9 @@ msgstr "Eine andere Anmeldemethode verwenden" msgid "Use a saved browser" msgstr "Einen gespeicherten Browser verwenden" +msgid "Use this card" +msgstr "" + msgid "User {0} is both a reader and writer" msgstr "" @@ -946,6 +992,9 @@ msgstr "Was für ein schöner Tag." msgid "What a fine night it is." msgstr "Was für eine schöne Nacht." +msgid "Yearly billing" +msgstr "" + msgid "Yes, save it" msgstr "Ja, es speichern" @@ -958,12 +1007,15 @@ msgstr "Sie können nun geteilte Ordner erstellen, um eine Datei zu teilen." msgid "You can't move folders to this path" msgstr "Sie können keine Ordner in diesen Pfad verschieben" -msgid "You do not have access to this shared folder." +msgid "You get access to these features right now." msgstr "" msgid "You haven't set a username yet." msgstr "Sie haben noch keinen Benutzernamen festgelegt." +msgid "You now have:" +msgstr "" + msgid "You were added to the shared folder ({0}): {1}" msgstr "" @@ -976,9 +1028,15 @@ msgstr "" msgid "can-edit" msgstr "" +msgid "invoices here" +msgstr "" + msgid "me" msgstr "ich" +msgid "of storage" +msgstr "" + msgid "on" msgstr "am" diff --git a/packages/files-ui/src/locales/en/messages.po b/packages/files-ui/src/locales/en/messages.po index 4cb0929c75..55bdde76ab 100644 --- a/packages/files-ui/src/locales/en/messages.po +++ b/packages/files-ui/src/locales/en/messages.po @@ -28,6 +28,9 @@ msgstr "A file with the same name already exists" msgid "Accept" msgstr "Accept" +msgid "Access your billing history in settings or view your" +msgstr "Access your billing history in settings or view your" + msgid "Account" msgstr "Account" @@ -46,6 +49,9 @@ msgstr "Add by sharing address, username or wallet address" msgid "Add card" msgstr "Add card" +msgid "Add credit card" +msgstr "Add credit card" + msgid "Add more files" msgstr "Add more files" @@ -73,18 +79,21 @@ msgstr "Backup secret phrase" msgid "Backup secret phrase does not match user account, please double-check and try again." msgstr "Backup secret phrase does not match user account, please double-check and try again." -msgid "Billed Annually" -msgstr "Billed Annually" +#~ msgid "Billed Annually" +#~ msgstr "Billed Annually" -msgid "Billed Monthly" -msgstr "Billed Monthly" +#~ msgid "Billed Monthly" +#~ msgstr "Billed Monthly" -msgid "Billed Yearly" -msgstr "Billed Yearly" +#~ msgid "Billed Yearly" +#~ msgstr "Billed Yearly" msgid "Billing history" msgstr "Billing history" +msgid "Billing start time" +msgstr "Billing start time" + msgid "Bin" msgstr "Bin" @@ -127,6 +136,9 @@ msgstr "Change Plan" msgid "Change password" msgstr "Change password" +msgid "Change plan" +msgstr "Change plan" + msgid "Check your inbox! We've sent another email." msgstr "Check your inbox! We've sent another email." @@ -142,6 +154,15 @@ msgstr "Confirm" msgid "Confirm Password:" msgstr "Confirm Password:" +msgid "Confirm plan" +msgstr "Confirm plan" + +msgid "Confirm plan change" +msgstr "Confirm plan change" + +msgid "Confirmation" +msgstr "Confirmation" + msgid "Connect Wallet to Files" msgstr "Connect Wallet to Files" @@ -274,6 +295,12 @@ msgstr "Downloads failed" msgid "Drop to upload files" msgstr "Drop to upload files" +msgid "Edit payment method" +msgstr "Edit payment method" + +msgid "Edit plan" +msgstr "Edit plan" + msgid "Email is required" msgstr "Email is required" @@ -292,6 +319,9 @@ msgstr "Enter the verification code:" msgid "Failed to add payment method" msgstr "Failed to add payment method" +msgid "Failed to change subscription" +msgstr "Failed to change subscription" + msgid "Failed to get signature" msgstr "Failed to get signature" @@ -307,6 +337,9 @@ msgstr "" "If you are using a contract wallet, please make \n" "sure you have activated your wallet." +msgid "Features" +msgstr "Features" + msgid "File Info" msgstr "File Info" @@ -343,8 +376,8 @@ msgstr "For security reasons, each time you sign in we’ll ask you for one of t msgid "Forget this browser" msgstr "Forget this browser" -msgid "Free" -msgstr "Free" +#~ msgid "Free" +#~ msgstr "Free" msgid "Free plan" msgstr "Free plan" @@ -370,6 +403,9 @@ msgstr "Give edit permission to:" msgid "Give view-only permission to:" msgstr "Give view-only permission to:" +msgid "Go back" +msgstr "Go back" + msgid "Go back" msgstr "Go back" @@ -559,6 +595,15 @@ msgstr "Passwords must match" msgid "Payment and Subscriptions" msgstr "Payment and Subscriptions" +msgid "Payment method" +msgstr "Payment method" + +msgid "Plan changed successfully" +msgstr "Plan changed successfully" + +msgid "Plan details" +msgstr "Plan details" + msgid "Please enter a file name" msgstr "Please enter a file name" @@ -595,8 +640,8 @@ msgstr "Profile settings" msgid "Profile updated" msgstr "Profile updated" -msgid "Purchase with card" -msgstr "Purchase with card" +#~ msgid "Purchase with card" +#~ msgstr "Purchase with card" msgid "Receipt" msgstr "Receipt" @@ -850,14 +895,17 @@ msgstr "This website uses cookies" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" +msgid "Total" +msgstr "Total" + msgid "Try again" msgstr "Try again" msgid "Try another method" msgstr "Try another method" -msgid "Try for 7 days" -msgstr "Try for 7 days" +#~ msgid "Try for 7 days" +#~ msgstr "Try for 7 days" msgid "Unable to upload" msgstr "Unable to upload" @@ -871,14 +919,12 @@ msgstr "Update Card" msgid "Update Shared Folder" msgstr "Update Shared Folder" -msgid "Update card" -msgstr "Update card" +msgid "Update credit card" +msgstr "Update credit card" -msgid "Update your credit card" -msgstr "Update your credit card" +#~ msgid "Upgrade your plan" +#~ msgstr "Upgrade your plan" -msgid "Upgrade your plan" -msgstr "Upgrade your plan" msgid "Upload" msgstr "Upload" @@ -892,6 +938,9 @@ msgstr "Use a different login method" msgid "Use a saved browser" msgstr "Use a saved browser" +msgid "Use this card" +msgstr "Use this card" + msgid "User {0} is both a reader and writer" msgstr "User {0} is both a reader and writer" @@ -952,6 +1001,9 @@ msgstr "What a fine day it is." msgid "What a fine night it is." msgstr "What a fine night it is." +msgid "Yearly billing" +msgstr "Yearly billing" + msgid "Yes, save it" msgstr "Yes, save it" @@ -964,12 +1016,16 @@ msgstr "You can now create shared folders to share a file." msgid "You can't move folders to this path" msgstr "You can't move folders to this path" -msgid "You do not have access to this shared folder." -msgstr "You do not have access to this shared folder." +msgid "You get access to these features right now." +msgstr "You get access to these features right now." + msgid "You haven't set a username yet." msgstr "You haven't set a username yet." +msgid "You now have:" +msgstr "You now have:" + msgid "You were added to the shared folder ({0}): {1}" msgstr "You were added to the shared folder ({0}): {1}" @@ -982,9 +1038,15 @@ msgstr "You've got a payment due. Until you've settled up, we've placed your acc msgid "can-edit" msgstr "can-edit" +msgid "invoices here" +msgstr "invoices here" + msgid "me" msgstr "me" +msgid "of storage" +msgstr "of storage" + msgid "on" msgstr "on" diff --git a/packages/files-ui/src/locales/es/messages.po b/packages/files-ui/src/locales/es/messages.po index 3fbb309c6d..0c4248ad39 100644 --- a/packages/files-ui/src/locales/es/messages.po +++ b/packages/files-ui/src/locales/es/messages.po @@ -29,6 +29,9 @@ msgstr "Ya existe un archivo con el mismo nombre" msgid "Accept" msgstr "" +msgid "Access your billing history in settings or view your" +msgstr "" + msgid "Account" msgstr "Cuenta" @@ -47,6 +50,9 @@ msgstr "" msgid "Add card" msgstr "" +msgid "Add credit card" +msgstr "" + msgid "Add more files" msgstr "Agrega mas archivos" @@ -74,18 +80,21 @@ msgstr "" msgid "Backup secret phrase does not match user account, please double-check and try again." msgstr "" -msgid "Billed Annually" -msgstr "" +#~ msgid "Billed Annually" +#~ msgstr "" -msgid "Billed Monthly" -msgstr "" +#~ msgid "Billed Monthly" +#~ msgstr "" -msgid "Billed Yearly" -msgstr "" +#~ msgid "Billed Yearly" +#~ msgstr "" msgid "Billing history" msgstr "" +msgid "Billing start time" +msgstr "" + msgid "Bin" msgstr "Papelera" @@ -128,6 +137,9 @@ msgstr "" msgid "Change password" msgstr "Cambiar la contraseña" +msgid "Change plan" +msgstr "" + msgid "Check your inbox! We've sent another email." msgstr "" @@ -143,6 +155,15 @@ msgstr "Confirmar" msgid "Confirm Password:" msgstr "Confirmar Contraseña:" +msgid "Confirm plan" +msgstr "" + +msgid "Confirm plan change" +msgstr "" + +msgid "Confirmation" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Conectar monedero a archivos" @@ -275,6 +296,12 @@ msgstr "" msgid "Drop to upload files" msgstr "Suelta para subir archivos" +msgid "Edit payment method" +msgstr "" + +msgid "Edit plan" +msgstr "" + msgid "Email is required" msgstr "" @@ -293,6 +320,9 @@ msgstr "" msgid "Failed to add payment method" msgstr "" +msgid "Failed to change subscription" +msgstr "" + msgid "Failed to get signature" msgstr "No se pudo obtener la firma" @@ -308,6 +338,9 @@ msgstr "" "Si está utilizando una billetera de contrato, haga\n" "seguro que has activado tu billetera." +msgid "Features" +msgstr "" + msgid "File Info" msgstr "Información del archivo" @@ -344,8 +377,8 @@ msgstr "Por motivos de seguridad, cada vez que inicie sesión le pediremos uno d msgid "Forget this browser" msgstr "Olvida este navegador" -msgid "Free" -msgstr "" +#~ msgid "Free" +#~ msgstr "" msgid "Free plan" msgstr "" @@ -371,6 +404,9 @@ msgstr "" msgid "Give view-only permission to:" msgstr "" +msgid "Go back" +msgstr "" + msgid "Go back" msgstr "Regresar" @@ -560,6 +596,15 @@ msgstr "Las contraseñas deben coincidir" msgid "Payment and Subscriptions" msgstr "" +msgid "Payment method" +msgstr "" + +msgid "Plan changed successfully" +msgstr "" + +msgid "Plan details" +msgstr "" + msgid "Please enter a file name" msgstr "Ingrese un nombre de archivo" @@ -596,8 +641,8 @@ msgstr "" msgid "Profile updated" msgstr "Perfil actualizado" -msgid "Purchase with card" -msgstr "" +#~ msgid "Purchase with card" +#~ msgstr "" msgid "Receipt" msgstr "" @@ -851,14 +896,17 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" +msgid "Total" +msgstr "" + msgid "Try again" msgstr "Intentar otra vez" msgid "Try another method" msgstr "Prueba con otro método" -msgid "Try for 7 days" -msgstr "" +#~ msgid "Try for 7 days" +#~ msgstr "" msgid "Unable to upload" msgstr "" @@ -872,14 +920,11 @@ msgstr "" msgid "Update Shared Folder" msgstr "" -msgid "Update card" +msgid "Update credit card" msgstr "" -msgid "Update your credit card" -msgstr "" - -msgid "Upgrade your plan" -msgstr "" +#~ msgid "Upgrade your plan" +#~ msgstr "" msgid "Upload" msgstr "Subir" @@ -893,6 +938,9 @@ msgstr "Utilice un método de inicio de sesión diferente" msgid "Use a saved browser" msgstr "Utilice un navegador guardado" +msgid "Use this card" +msgstr "" + msgid "User {0} is both a reader and writer" msgstr "" @@ -953,6 +1001,9 @@ msgstr "Qué buen día es." msgid "What a fine night it is." msgstr "Qué hermosa noche es." +msgid "Yearly billing" +msgstr "" + msgid "Yes, save it" msgstr "Si guárdalo" @@ -965,12 +1016,15 @@ msgstr "" msgid "You can't move folders to this path" msgstr "" -msgid "You do not have access to this shared folder." +msgid "You get access to these features right now." msgstr "" msgid "You haven't set a username yet." msgstr "" +msgid "You now have:" +msgstr "" + msgid "You were added to the shared folder ({0}): {1}" msgstr "" @@ -983,9 +1037,15 @@ msgstr "" msgid "can-edit" msgstr "" +msgid "invoices here" +msgstr "" + msgid "me" msgstr "" +msgid "of storage" +msgstr "" + msgid "on" msgstr "en" diff --git a/packages/files-ui/src/locales/fr/messages.po b/packages/files-ui/src/locales/fr/messages.po index 866ed3ba85..a86b6968f7 100644 --- a/packages/files-ui/src/locales/fr/messages.po +++ b/packages/files-ui/src/locales/fr/messages.po @@ -29,6 +29,9 @@ msgstr "Un fichier avec ce nom existe déjà" msgid "Accept" msgstr "Accepter" +msgid "Access your billing history in settings or view your" +msgstr "" + msgid "Account" msgstr "Compte" @@ -47,6 +50,9 @@ msgstr "Ajouter par adresse de partage, nom d'utilisateur ou adresse de portefeu msgid "Add card" msgstr "" +msgid "Add credit card" +msgstr "" + msgid "Add more files" msgstr "Ajouter d’autres fichiers" @@ -74,18 +80,21 @@ msgstr "Phrase secrète de sauvegarde" msgid "Backup secret phrase does not match user account, please double-check and try again." msgstr "La phrase secrète de sauvegarde est incorrecte, merci de vérifier et réessayer." -msgid "Billed Annually" -msgstr "" +#~ msgid "Billed Annually" +#~ msgstr "" -msgid "Billed Monthly" -msgstr "" +#~ msgid "Billed Monthly" +#~ msgstr "" -msgid "Billed Yearly" -msgstr "" +#~ msgid "Billed Yearly" +#~ msgstr "" msgid "Billing history" msgstr "" +msgid "Billing start time" +msgstr "" + msgid "Bin" msgstr "Corbeille" @@ -128,6 +137,9 @@ msgstr "" msgid "Change password" msgstr "Changer le mot de passe" +msgid "Change plan" +msgstr "" + msgid "Check your inbox! We've sent another email." msgstr "Vérifiez votre boîte de réception ! Nous avons envoyé un autre courriel." @@ -143,6 +155,15 @@ msgstr "Confirmer" msgid "Confirm Password:" msgstr "Confirmer le mot de passe :" +msgid "Confirm plan" +msgstr "" + +msgid "Confirm plan change" +msgstr "" + +msgid "Confirmation" +msgstr "" + msgid "Connect Wallet to Files" msgstr "Connecter un wallet à Files" @@ -275,6 +296,12 @@ msgstr "Les téléchargements ont échoué" msgid "Drop to upload files" msgstr "Faire glisser pour téléverser un fichier" +msgid "Edit payment method" +msgstr "" + +msgid "Edit plan" +msgstr "" + msgid "Email is required" msgstr "Un courriel est requis" @@ -293,6 +320,9 @@ msgstr "Entrez le code de vérification :" msgid "Failed to add payment method" msgstr "" +msgid "Failed to change subscription" +msgstr "" + msgid "Failed to get signature" msgstr "Échec de l’obtention de la signature" @@ -308,6 +338,9 @@ msgstr "" "Si vous utilisez un contract wallet, veuillez\n" "vérifier que vous avez activé votre wallet." +msgid "Features" +msgstr "" + msgid "File Info" msgstr "Infos du fichier" @@ -344,8 +377,8 @@ msgstr "Pour des raisons de sécurité, chaque fois que vous vous connectez, nou msgid "Forget this browser" msgstr "Oublier ce navigateur" -msgid "Free" -msgstr "" +#~ msgid "Free" +#~ msgstr "" msgid "Free plan" msgstr "" @@ -371,6 +404,9 @@ msgstr "Donner l’autorisation de modifier à :" msgid "Give view-only permission to:" msgstr "Donner l’accès en lecture seule à :" +msgid "Go back" +msgstr "" + msgid "Go back" msgstr "Retour" @@ -566,6 +602,15 @@ msgstr "Les mots de passes de correspondent pas" msgid "Payment and Subscriptions" msgstr "" +msgid "Payment method" +msgstr "" + +msgid "Plan changed successfully" +msgstr "" + +msgid "Plan details" +msgstr "" + msgid "Please enter a file name" msgstr "Veuillez entrer un nom de fichier" @@ -602,8 +647,8 @@ msgstr "Paramètres du profil" msgid "Profile updated" msgstr "Profile mis à jour" -msgid "Purchase with card" -msgstr "" +#~ msgid "Purchase with card" +#~ msgstr "" msgid "Receipt" msgstr "" @@ -857,14 +902,17 @@ msgstr "Ce site web utilise des cookies" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "Ce site web utilise des cookies qui l'aident à fonctionner et à suivre les interactions à des fins d'analyse. Vous avez le droit de refuser notre utilisation des cookies. Pour que nous puissions vous offrir une expérience utilisateur personnalisable, veuillez cliquer sur le bouton Accepter ci-dessous.<0>En savoir plus" +msgid "Total" +msgstr "" + msgid "Try again" msgstr "Essayer de nouveau" msgid "Try another method" msgstr "Essayer une autre méthode" -msgid "Try for 7 days" -msgstr "" +#~ msgid "Try for 7 days" +#~ msgstr "" msgid "Unable to upload" msgstr "" @@ -878,14 +926,11 @@ msgstr "" msgid "Update Shared Folder" msgstr "Mettre à jour le dossier partagé" -msgid "Update card" -msgstr "" - -msgid "Update your credit card" +msgid "Update credit card" msgstr "" -msgid "Upgrade your plan" -msgstr "" +#~ msgid "Upgrade your plan" +#~ msgstr "" msgid "Upload" msgstr "Téléverser" @@ -899,6 +944,9 @@ msgstr "Utilisez une méthode de connexion différente" msgid "Use a saved browser" msgstr "Utiliser un navigateur enregistré" +msgid "Use this card" +msgstr "" + msgid "User {0} is both a reader and writer" msgstr "L'utilisateur {0} est dans les auteurs et lecteurs" @@ -959,6 +1007,9 @@ msgstr "Quelle belle journée." msgid "What a fine night it is." msgstr "Quelle belle nuit." +msgid "Yearly billing" +msgstr "" + msgid "Yes, save it" msgstr "Oui, l’enregistrer" @@ -971,12 +1022,15 @@ msgstr "Vous pouvez maintenant créer des dossiers partagés pour partager un fi msgid "You can't move folders to this path" msgstr "Vous ne pouvez pas déplacer les dossiers vers ce chemin" -msgid "You do not have access to this shared folder." -msgstr "Vous n'avez pas accès à ce dossier partagé." +msgid "You get access to these features right now." +msgstr "" msgid "You haven't set a username yet." msgstr "Vous n’avez pas encore défini de nom d’utilisateur." +msgid "You now have:" +msgstr "" + msgid "You were added to the shared folder ({0}): {1}" msgstr "Vous avez été ajouté(e) au dossier partagé ({0}) : {1}" @@ -989,9 +1043,15 @@ msgstr "" msgid "can-edit" msgstr "peut-modifier" +msgid "invoices here" +msgstr "" + msgid "me" msgstr "moi" +msgid "of storage" +msgstr "" + msgid "on" msgstr "le" diff --git a/packages/files-ui/src/locales/no/messages.po b/packages/files-ui/src/locales/no/messages.po index 307bd38a4b..ece689f4ac 100644 --- a/packages/files-ui/src/locales/no/messages.po +++ b/packages/files-ui/src/locales/no/messages.po @@ -28,6 +28,9 @@ msgstr "" msgid "Accept" msgstr "" +msgid "Access your billing history in settings or view your" +msgstr "" + msgid "Account" msgstr "Konto" @@ -46,6 +49,9 @@ msgstr "" msgid "Add card" msgstr "" +msgid "Add credit card" +msgstr "" + msgid "Add more files" msgstr "Legg til flere filer" @@ -67,24 +73,33 @@ msgstr "" msgid "Approve" msgstr "Godkjenn" +<<<<<<< HEAD +#~ msgid "Back to plan settings" +#~ msgstr "" + +======= +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgid "Backup secret phrase" msgstr "" msgid "Backup secret phrase does not match user account, please double-check and try again." msgstr "" -msgid "Billed Annually" -msgstr "" +#~ msgid "Billed Annually" +#~ msgstr "" -msgid "Billed Monthly" -msgstr "" +#~ msgid "Billed Monthly" +#~ msgstr "" -msgid "Billed Yearly" -msgstr "" +#~ msgid "Billed Yearly" +#~ msgstr "" msgid "Billing history" msgstr "" +msgid "Billing start time" +msgstr "" + msgid "Bin" msgstr "" @@ -127,6 +142,9 @@ msgstr "" msgid "Change password" msgstr "Endre passord" +msgid "Change plan" +msgstr "" + msgid "Check your inbox! We've sent another email." msgstr "" @@ -142,6 +160,15 @@ msgstr "Bekreft" msgid "Confirm Password:" msgstr "Bekreft passord:" +msgid "Confirm plan" +msgstr "" + +msgid "Confirm plan change" +msgstr "" + +msgid "Confirmation" +msgstr "" + msgid "Connect Wallet to Files" msgstr "" @@ -205,6 +232,15 @@ msgstr "" msgid "Create your public username in <0>Settings!" msgstr "" +<<<<<<< HEAD +msgid "Credit card saved" +msgstr "" + +#~ msgid "Current" +#~ msgstr "" + +======= +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgid "Dark Theme" msgstr "Mørk drakt" @@ -274,6 +310,12 @@ msgstr "" msgid "Drop to upload files" msgstr "Dra for å laste opp filer" +msgid "Edit payment method" +msgstr "" + +msgid "Edit plan" +msgstr "" + msgid "Email is required" msgstr "E-post kreves" @@ -292,6 +334,9 @@ msgstr "Skriv inn bekreftelseskoden:" msgid "Failed to add payment method" msgstr "" +msgid "Failed to change subscription" +msgstr "" + msgid "Failed to get signature" msgstr "" @@ -304,6 +349,9 @@ msgid "" "sure you have activated your wallet." msgstr "" +msgid "Features" +msgstr "" + msgid "File Info" msgstr "Filinfo" @@ -340,8 +388,8 @@ msgstr "" msgid "Forget this browser" msgstr "" -msgid "Free" -msgstr "" +#~ msgid "Free" +#~ msgstr "" msgid "Free plan" msgstr "" @@ -367,6 +415,9 @@ msgstr "" msgid "Give view-only permission to:" msgstr "" +msgid "Go back" +msgstr "" + msgid "Go back" msgstr "Tilbake" @@ -442,7 +493,11 @@ msgstr "" msgid "Method" msgstr "" +<<<<<<< HEAD +msgid "Monthly billing" +======= msgid "Manage Shared Folder" +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgstr "" msgid "Move" @@ -562,6 +617,15 @@ msgstr "Passordene må samsvare" msgid "Payment and Subscriptions" msgstr "" +msgid "Payment method" +msgstr "" + +msgid "Plan changed successfully" +msgstr "" + +msgid "Plan details" +msgstr "" + msgid "Please enter a file name" msgstr "Skriv inn et filnavn" @@ -598,8 +662,8 @@ msgstr "Profilinnstillinger" msgid "Profile updated" msgstr "Profil oppdatert" -msgid "Purchase with card" -msgstr "" +#~ msgid "Purchase with card" +#~ msgstr "" msgid "Receipt" msgstr "" @@ -688,6 +752,18 @@ msgstr "" msgid "Select an existing shared folder or your home" msgstr "" +<<<<<<< HEAD +msgid "Select payment method" +msgstr "" + +msgid "Select plan" +msgstr "" + +msgid "Select this plan" +msgstr "" + +======= +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgid "Send another email" msgstr "Send en ny e-post" @@ -841,6 +917,15 @@ msgstr "" msgid "There was an error when setting username." msgstr "" +<<<<<<< HEAD +msgid "This card will become your default payment method" +msgstr "" + +msgid "This is the free product." +msgstr "" + +======= +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgid "This link is marlformed. Please verify that you copy/pasted it correctly." msgstr "" @@ -856,14 +941,17 @@ msgstr "" msgid "This website uses cookies that help the website function and track interactions for analytics purposes. You have the right to decline our use of cookies. For us to provide a customizable user experience to you, please click on the Accept button below.<0>Learn more" msgstr "" +msgid "Total" +msgstr "" + msgid "Try again" msgstr "Prøv igjen" msgid "Try another method" msgstr "Prøv annen metode" -msgid "Try for 7 days" -msgstr "" +#~ msgid "Try for 7 days" +#~ msgstr "" msgid "Unable to upload" msgstr "" @@ -877,14 +965,11 @@ msgstr "" msgid "Update Shared Folder" msgstr "" -msgid "Update card" -msgstr "" - -msgid "Update your credit card" +msgid "Update credit card" msgstr "" -msgid "Upgrade your plan" -msgstr "" +#~ msgid "Upgrade your plan" +#~ msgstr "" msgid "Upload" msgstr "Last opp" @@ -898,6 +983,9 @@ msgstr "Bruk en annen innloggingsmetode" msgid "Use a saved browser" msgstr "" +msgid "Use this card" +msgstr "" + msgid "User {0} is both a reader and writer" msgstr "" @@ -958,6 +1046,9 @@ msgstr "" msgid "What a fine night it is." msgstr "" +msgid "Yearly billing" +msgstr "" + msgid "Yes, save it" msgstr "Ja, lagre" @@ -970,12 +1061,15 @@ msgstr "" msgid "You can't move folders to this path" msgstr "" -msgid "You do not have access to this shared folder." +msgid "You get access to these features right now." msgstr "" msgid "You haven't set a username yet." msgstr "Du har ikke satt noe brukernavn enda." +msgid "You now have:" +msgstr "" + msgid "You were added to the shared folder ({0}): {1}" msgstr "" @@ -988,12 +1082,33 @@ msgstr "" msgid "can-edit" msgstr "" +msgid "invoices here" +msgstr "" + msgid "me" msgstr "" +<<<<<<< HEAD +msgid "of storage" +msgstr "" + msgid "on" msgstr "" +#~ msgid "per day" +#~ msgstr "" + +#~ msgid "per month" +#~ msgstr "" + +#~ msgid "per week" +#~ msgstr "" + +#~ msgid "per year" +#~ msgstr "" + +======= +>>>>>>> ecce826c708fb0146bff649f12f0896b4d9ca89e msgid "unknown" msgstr "" diff --git a/packages/storage-ui/package.json b/packages/storage-ui/package.json index 44a80fe987..11e8c3294c 100644 --- a/packages/storage-ui/package.json +++ b/packages/storage-ui/package.json @@ -6,7 +6,7 @@ "@babel/core": "^7.12.10", "@babel/runtime": "^7.0.0", "@chainsafe/browser-storage-hooks": "^1.0.1", - "@chainsafe/files-api-client": "^1.18.20", + "@chainsafe/files-api-client": "^1.18.22", "@chainsafe/web3-context": "1.1.4", "@lingui/core": "^3.7.2", "@lingui/react": "^3.7.2", diff --git a/yarn.lock b/yarn.lock index c33e0bc23e..0e4ea986d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1925,10 +1925,10 @@ resolved "https://registry.yarnpkg.com/@chainsafe/browser-storage-hooks/-/browser-storage-hooks-1.0.1.tgz#26d32cde1999914db755a631e2643823c54959f7" integrity sha512-Q4b5gQAZnsRXKeADspd5isqfwwhhXjDk70y++YadufA6EZ3tf340oW0OVszp74KaGEw+CAYFGQR4X7bzpZ3x9Q== -"@chainsafe/files-api-client@^1.18.20": - version "1.18.20" - resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.20.tgz#5b184946acfa4026b21c95faa2f0c1c9d9999481" - integrity sha512-OQN4V2bUe0981RsBirjNA2YrkaMzAV/7oWSzBwN27ejhAbM6fRbxDEYTZfLRVuick91/JfM2/TbKc3vHYQRDdg== +"@chainsafe/files-api-client@^1.18.22": + version "1.18.22" + resolved "https://registry.yarnpkg.com/@chainsafe/files-api-client/-/files-api-client-1.18.22.tgz#7e66a43f5c8b4234a53745a2be8172c32a6f0b9d" + integrity sha512-m3RfBMcWKOITyH0goMl7jxg8NY//3N2cglzKS64ksrWhULKeaCARZxe5Auo8NXEfIlTkQCKmazHoozl146UR/g== dependencies: "@redocly/openapi-cli" "^1.0.0-beta.58" "@redocly/openapi-core" "^1.0.0-beta.58"