Skip to content

Commit

Permalink
Billing notifications (#1861)
Browse files Browse the repository at this point in the history
* initial changes

* wire up wallet

* add circular progress bar label

* add currency icons

* add copy buttons

* lingui extract

* lint and padding

* Apply suggestions from code review

Co-authored-by: Thibaut Sardan <[email protected]>
Co-authored-by: Tanmoy Basak Anjan <[email protected]>

* implement fixes

* lingui extract

* Update packages/files-ui/src/Components/Modules/Settings/SubscriptionTab/ChangePlan/CryptoPayment.tsx

Co-authored-by: Thibaut Sardan <[email protected]>

* fixes from comments

* remove unnecessary prop

* temp daily duration for testing - revert before merge

* fix dark mode icon colors

* update api client to latest

* Apply suggestions from code review

Co-authored-by: Thibaut Sardan <[email protected]>

* revert conflict marker

* remove max-content width

* fix mobile width issues

* Revert "fix mobile width issues"

This reverts commit 74ddf46.

* ensure that text doesnt overflow

* fix width

* add notifications for account restricted, unpaid

* update notification text

* update translations

* add credit card expiring notification

* fix lint

Co-authored-by: GitHub Actions <[email protected]>
Co-authored-by: Thibaut Sardan <[email protected]>
Co-authored-by: Tanmoy Basak Anjan <[email protected]>
  • Loading branch information
4 people authored Jan 21, 2022
1 parent 035788c commit 7625ce3
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 31 deletions.
20 changes: 10 additions & 10 deletions packages/files-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,21 @@ const App = () => {
enableLogging={directAuthNetwork !== "mainnet"}
network={directAuthNetwork}
>
<NotificationsProvider>
<UserProvider>
<FilesProvider>
<BillingProvider>
<Router>
<Router>
<NotificationsProvider>
<UserProvider>
<FilesProvider>
<BillingProvider>
<PosthogProvider>
<AppWrapper>
<FilesRoutes />
</AppWrapper>
</PosthogProvider>
</Router>
</BillingProvider>
</FilesProvider>
</UserProvider>
</NotificationsProvider>
</BillingProvider>
</FilesProvider>
</UserProvider>
</NotificationsProvider>
</Router>
</ThresholdKeyProvider>
</FilesApiProvider>
</Web3Provider>
Expand Down
21 changes: 14 additions & 7 deletions packages/files-ui/src/Components/Elements/InvoiceLines.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useMemo } from "react"
import { makeStyles, createStyles } from "@chainsafe/common-theme"
import { CSFTheme } from "../../Themes/types"
import { Typography, Loading } from "@chainsafe/common-components"
import { Typography, Loading, Button } from "@chainsafe/common-components"
import { Trans } from "@lingui/macro"
import dayjs from "dayjs"
import { useBilling } from "../../Contexts/BillingContext"
Expand Down Expand Up @@ -60,7 +60,7 @@ interface IInvoiceProps {

const InvoiceLines = ({ lineNumber }: IInvoiceProps) => {
const classes = useStyles()
const { invoices } = useBilling()
const { invoices, downloadInvoice } = useBilling()
const invoicesToShow = useMemo(() => {
if (!invoices) return

Expand Down Expand Up @@ -92,7 +92,7 @@ const InvoiceLines = ({ lineNumber }: IInvoiceProps) => {
</div>
)}
{!!invoicesToShow?.length && (
invoicesToShow.map(({ paid_on, amount, currency, uuid }) =>
invoicesToShow.map(({ amount, currency, uuid, period_start, status }) =>
<section
className={classes.setOption}
key={uuid}
Expand All @@ -108,11 +108,18 @@ const InvoiceLines = ({ lineNumber }: IInvoiceProps) => {
variant="body2"
className="receiptDate"
>
{dayjs(paid_on).format("MMM D, YYYY")}
</Typography>
<Typography>
{uuid}
{dayjs.unix(period_start).format("MMM D, YYYY")}
</Typography>
{(status === "paid") && (
<Button onClick={() => downloadInvoice(uuid)}>
<Trans>Download</Trans>
</Button>
)}
{(status === "open") && (
<Button onClick={() => console.log("Not implemented")}>
<Trans>Pay invoice</Trans>
</Button>
)}
</div>
</section>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const NotificationList = ({ notifications }: INotificationListProps) => {
className={classes.notificationTime}
component="p"
>
{dayjs(n.createdAt).fromNow()}
{dayjs.unix(n.createdAt).fromNow()}
</Typography>
</div>
))}
Expand Down
97 changes: 84 additions & 13 deletions packages/files-ui/src/Contexts/BillingContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { useCallback } from "react"
import { t } from "@lingui/macro"
import { PaymentMethod as StripePaymentMethod } from "@stripe/stripe-js"
import { useFiles } from "./FilesContext"
import { useNotifications } from "./NotificationsContext"
import dayjs from "dayjs"
import { useHistory } from "@chainsafe/common-components"
import { ROUTE_LINKS } from "../Components/FilesRoutes"

export type PaymentMethod = "crypto" | "creditCard"

Expand All @@ -24,6 +28,7 @@ interface IBillingContext {
updateDefaultCard: (id: StripePaymentMethod["id"]) => Promise<void>
invoices?: InvoiceResponse[]
cancelCurrentSubscription: () => Promise<void>
downloadInvoice: (invoiceId: string) => Promise<void>
}

const ProductMapping: {[key: string]: {
Expand All @@ -49,32 +54,86 @@ const BillingContext = React.createContext<IBillingContext | undefined>(
)

const BillingProvider = ({ children }: BillingContextProps) => {
const { filesApiClient, isLoggedIn } = useFilesApi()
const { filesApiClient, isLoggedIn, accountRestricted } = useFilesApi()
const { redirect } = useHistory()
const { addNotification, removeNotification } = useNotifications()
const { refreshBuckets } = useFiles()
const [currentSubscription, setCurrentSubscription] = useState<CurrentSubscription | undefined>()
const [defaultCard, setDefaultCard] = useState<Card | undefined>(undefined)
const [invoices, setInvoices] = useState<InvoiceResponse[] | undefined>()
const [restrictedNotification, setRestrictedNotification] = useState<string | undefined>()
const [unpaidInvoiceNotification, setUnpaidInvoiceNotification] = useState<string | undefined>()
const [cardExpiringNotification, setCardExpiringNotification] = useState<string | undefined>()

useEffect(() => {
if (!currentSubscription) return

filesApiClient.getAllInvoices(currentSubscription.id)
.then(({ invoices }) => {
setInvoices(invoices)
})
.catch((e: any) => {
setInvoices(invoices
.filter(i => i.status !== "void")
.sort((a, b) => b.period_start - a.period_start))
}).catch((e: any) => {
console.error(e)
setInvoices([])
})
}, [currentSubscription, filesApiClient])

useEffect(() => {
if (accountRestricted && !restrictedNotification) {
const notif = addNotification({
createdAt: dayjs().unix(),
title: t`Account is restricted`,
onClick: () => redirect(ROUTE_LINKS.SettingsPath("plan"))
})
setRestrictedNotification(notif)
} else if (accountRestricted === false && restrictedNotification) {
removeNotification(restrictedNotification)
setRestrictedNotification(undefined)
}
}, [accountRestricted, addNotification, redirect, removeNotification, restrictedNotification])

useEffect(() => {
const outstandingInvoice = invoices?.find(i => i.status === "open")
if (outstandingInvoice && !unpaidInvoiceNotification) {
const notif = addNotification({
createdAt: outstandingInvoice.period_start,
title: t`Invoice outstanding`,
onClick: () => redirect(ROUTE_LINKS.SettingsPath("plan"))
})
setUnpaidInvoiceNotification(notif)
} else if (!outstandingInvoice && unpaidInvoiceNotification) {
removeNotification(unpaidInvoiceNotification)
setUnpaidInvoiceNotification(undefined)
}
}, [addNotification, invoices, redirect, removeNotification, unpaidInvoiceNotification])

useEffect(() => {
if (defaultCard && currentSubscription) {
if (!cardExpiringNotification && currentSubscription.expiry_date >
dayjs(`${defaultCard.exp_year}-${defaultCard.exp_month}-01`, "YYYY-MM-DD").endOf("month").unix()) {
const notif = addNotification({
createdAt: dayjs().unix(),
title: t`Credit Card is expiring soon`,
onClick: () => redirect(ROUTE_LINKS.SettingsPath("plan"))
})
setCardExpiringNotification(notif)
} else if (cardExpiringNotification && currentSubscription?.expiry_date <=
dayjs(`${defaultCard?.exp_year}-${defaultCard?.exp_month}-01`, "YYYY-MM-DD").endOf("month").unix()) {
removeNotification(cardExpiringNotification)
setCardExpiringNotification(undefined)
}
}
}, [addNotification, cardExpiringNotification, currentSubscription, defaultCard, redirect, removeNotification])

const refreshDefaultCard = useCallback(() => {
filesApiClient.getDefaultCard().then((card) => {
setDefaultCard(card)
}).catch((err) => {
console.error(err)
setDefaultCard(undefined)
})
filesApiClient.getDefaultCard()
.then((card) => {
setDefaultCard(card)
}).catch((err) => {
console.error(err)
setDefaultCard(undefined)
})
}, [filesApiClient])

const deleteCard = useCallback((card: Card) =>
Expand Down Expand Up @@ -155,8 +214,19 @@ const BillingProvider = ({ children }: BillingContextProps) => {
console.error(error)
return Promise.reject()
})
}, [currentSubscription, fetchCurrentSubscription, filesApiClient, refreshBuckets]
)
}, [currentSubscription, fetchCurrentSubscription, filesApiClient, refreshBuckets])

const downloadInvoice = useCallback(async (invoiceId: string) => {
try {
const result = await filesApiClient.downloadInvoice(invoiceId)
const link = document.createElement("a")
link.href = URL.createObjectURL(result.data)
link.download = "Chainsafe Files Invoice"
link.click()
} catch (error) {
console.error(error)
}
}, [filesApiClient])

return (
<BillingContext.Provider
Expand All @@ -170,7 +240,8 @@ const BillingProvider = ({ children }: BillingContextProps) => {
deleteCard,
updateDefaultCard,
invoices,
cancelCurrentSubscription
cancelCurrentSubscription,
downloadInvoice
}}
>
{children}
Expand Down
12 changes: 12 additions & 0 deletions packages/files-ui/src/locales/de/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ msgstr ""
msgid "Account"
msgstr "Konto"

msgid "Account is restricted"
msgstr ""

msgid "Active links"
msgstr ""

Expand Down Expand Up @@ -250,6 +253,9 @@ msgstr ""
msgid "Create your public username in <0>Settings</0>!"
msgstr ""

msgid "Credit Card is expiring soon"
msgstr ""

msgid "Credit card saved"
msgstr ""

Expand Down Expand Up @@ -472,6 +478,9 @@ msgstr "Infos"
msgid "Insufficient balance"
msgstr ""

msgid "Invoice outstanding"
msgstr ""

msgid "I’m done saving my backup secret phrase"
msgstr "Ich bin fertig mit dem Speichern meines Sixherungsgeheimsatzes"

Expand Down Expand Up @@ -637,6 +646,9 @@ msgstr "Passwort:"
msgid "Passwords must match"
msgstr "Passwörter müssen übereinstimmen"

msgid "Pay invoice"
msgstr ""

msgid "Pay with Crypto"
msgstr ""

Expand Down
12 changes: 12 additions & 0 deletions packages/files-ui/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ msgstr "Access your billing history in settings or view your"
msgid "Account"
msgstr "Account"

msgid "Account is restricted"
msgstr "Account is restricted"

msgid "Active links"
msgstr "Active links"

Expand Down Expand Up @@ -250,6 +253,9 @@ msgstr "Create link"
msgid "Create your public username in <0>Settings</0>!"
msgstr "Create your public username in <0>Settings</0>!"

msgid "Credit Card is expiring soon"
msgstr "Credit Card is expiring soon"

msgid "Credit card saved"
msgstr "Credit card saved"

Expand Down Expand Up @@ -475,6 +481,9 @@ msgstr "Info"
msgid "Insufficient balance"
msgstr "Insufficient balance"

msgid "Invoice outstanding"
msgstr "Invoice outstanding"

msgid "I’m done saving my backup secret phrase"
msgstr "I’m done saving my backup secret phrase"

Expand Down Expand Up @@ -640,6 +649,9 @@ msgstr "Password:"
msgid "Passwords must match"
msgstr "Passwords must match"

msgid "Pay invoice"
msgstr "Pay invoice"

msgid "Pay with Crypto"
msgstr "Pay with Crypto"

Expand Down
12 changes: 12 additions & 0 deletions packages/files-ui/src/locales/es/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ msgstr ""
msgid "Account"
msgstr "Cuenta"

msgid "Account is restricted"
msgstr ""

msgid "Active links"
msgstr ""

Expand Down Expand Up @@ -251,6 +254,9 @@ msgstr ""
msgid "Create your public username in <0>Settings</0>!"
msgstr ""

msgid "Credit Card is expiring soon"
msgstr ""

msgid "Credit card saved"
msgstr ""

Expand Down Expand Up @@ -476,6 +482,9 @@ msgstr "Info"
msgid "Insufficient balance"
msgstr ""

msgid "Invoice outstanding"
msgstr ""

msgid "I’m done saving my backup secret phrase"
msgstr ""

Expand Down Expand Up @@ -641,6 +650,9 @@ msgstr "Contraseña:"
msgid "Passwords must match"
msgstr "Las contraseñas deben coincidir"

msgid "Pay invoice"
msgstr ""

msgid "Pay with Crypto"
msgstr ""

Expand Down
12 changes: 12 additions & 0 deletions packages/files-ui/src/locales/fr/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ msgstr "Accédez à l'historique de votre facturation dans les paramètres ou vi
msgid "Account"
msgstr "Compte"

msgid "Account is restricted"
msgstr ""

msgid "Active links"
msgstr "Liens actifs"

Expand Down Expand Up @@ -251,6 +254,9 @@ msgstr "Créer un lien"
msgid "Create your public username in <0>Settings</0>!"
msgstr "Créez votre nom d'utilisateur public dans <0>Paramètres</0> !"

msgid "Credit Card is expiring soon"
msgstr ""

msgid "Credit card saved"
msgstr "Carte de crédit enregistrée"

Expand Down Expand Up @@ -476,6 +482,9 @@ msgstr "Infos"
msgid "Insufficient balance"
msgstr ""

msgid "Invoice outstanding"
msgstr ""

msgid "I’m done saving my backup secret phrase"
msgstr "Phrase de sauvegarde secrète enregistrée"

Expand Down Expand Up @@ -641,6 +650,9 @@ msgstr "Mot de passe :"
msgid "Passwords must match"
msgstr "Les mots de passes de correspondent pas"

msgid "Pay invoice"
msgstr ""

msgid "Pay with Crypto"
msgstr ""

Expand Down
Loading

0 comments on commit 7625ce3

Please sign in to comment.