Skip to content

Commit

Permalink
🪟 🎉 Display "Credits" in sidebar and add info when user is running ou…
Browse files Browse the repository at this point in the history
…t of credits (#20595)

* 🪟 🎉 Display "Credits" in sidebar and add info when user is running out
of credits

Demo: https://www.loom.com/share/ca43d6b72dcc42208add0bd91e1b1efc
  • Loading branch information
letiescanciano authored Jan 3, 2023
1 parent 8a42960 commit 74be2f8
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 22 deletions.
16 changes: 11 additions & 5 deletions airbyte-webapp/src/components/ui/InfoBox/InfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import styled from "styled-components";
interface Props {
className?: string;
icon?: IconDefinition;
variant?: "default" | "error";
}

const Box = styled.div`
background: ${({ theme }) => theme.yellow100};
const Box = styled.div<{ variant: "default" | "error" }>`
background: ${({ theme, variant }) => (variant === "error" ? theme.red50 : theme.yellow100)};
border-radius: 8px;
padding: 18px 25px 22px;
font-size: 14px;
Expand All @@ -17,11 +18,16 @@ const Box = styled.div`
align-items: center;
`;

export const InfoBox: React.FC<React.PropsWithChildren<Props>> = ({ children, className, icon }) => {
export const InfoBox: React.FC<React.PropsWithChildren<Props>> = ({
children,
className,
icon,
variant = "default",
}) => {
return (
<Box className={className}>
<Box className={className} variant={variant}>
{icon && <FontAwesomeIcon size="lg" icon={icon} />}
<div>{children}</div>
{children}
</Box>
);
};
6 changes: 5 additions & 1 deletion airbyte-webapp/src/packages/cloud/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@
"credits.emailVerificationRequired": "You need to verify your email address before you can buy credits.",
"credits.emailVerification.resendConfirmation": "We send you a new verification link.",
"credits.emailVerification.resend": "Send verification link again",
"credits.lowBalance": "Your credit balance is low. You need to add more credits to prevent your syncs from being stopped.",
"credits.zeroBalance": "All your syncs have been stopped because your credit balance is 0. Add more credits to enable your syncs again.",

"firebase.auth.error.invalidPassword": "Incorrect password",
"firebase.auth.error.networkRequestFailed": "There appears to be a network issue. Please try again later.",
Expand All @@ -174,5 +176,7 @@
"webapp.cannotReachServer": "Cannot reach server.",

"inviteUsersHint.message": "Need help from a teammate to set up the {connector}?",
"inviteUsersHint.cta": "Invite users"
"inviteUsersHint.cta": "Invite users",

"sidebar.credits": "Credits"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@use "scss/colors";

.container {
width: 100%;
}

.wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { faCreditCard, faWarning } from "@fortawesome/free-solid-svg-icons";
import { FormattedMessage } from "react-intl";

import { InfoBox } from "components/ui/InfoBox";

import { useGetCloudWorkspace } from "packages/cloud/services/workspaces/CloudWorkspacesService";
import { useCurrentWorkspace } from "services/workspaces/WorkspacesService";

import styles from "./LowCreditBalanceHint.module.scss";

export const LOW_BALANCE_CREDIT_TRESHOLD = 20;

export const LowCreditBalanceHint: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
const workspace = useCurrentWorkspace();
const cloudWorkspace = useGetCloudWorkspace(workspace.workspaceId);

if (cloudWorkspace.remainingCredits > LOW_BALANCE_CREDIT_TRESHOLD) {
return null;
}

const status = cloudWorkspace.remainingCredits <= 0 ? "zeroBalance" : "lowBalance";
const variant = status === "zeroBalance" ? "error" : "default";

const ICONS = {
lowBalance: faCreditCard,
zeroBalance: faWarning,
};
return (
<InfoBox className={styles.container} icon={ICONS[status]} variant={variant}>
<div className={styles.wrapper}>
<FormattedMessage id={`credits.${status}`} />
{children}
</div>
</InfoBox>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { LowCreditBalanceHint } from "./LowCreditBalanceHint";
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
} from "packages/cloud/services/workspaces/CloudWorkspacesService";
import { links } from "utils/links";

import { LowCreditBalanceHint } from "./LowCreditBalanceHint";

interface Props {
selfServiceCheckoutEnabled: boolean;
}
Expand Down Expand Up @@ -116,29 +118,44 @@ const RemainingCredits: React.FC<Props> = ({ selfServiceCheckoutEnabled }) => {
};

return (
<Block>
<CreditView>
<FormattedMessage id="credits.remainingCredits" />
<Count>
<FormattedNumber value={cloudWorkspace.remainingCredits} />
</Count>
</CreditView>
<Actions>
<>
<LowCreditBalanceHint>
<Button
disabled={!selfServiceCheckoutEnabled}
type="button"
size="xs"
variant="dark"
onClick={startStripeCheckout}
isLoading={isLoading || isWaitingForCredits}
icon={<FontAwesomeIcon icon={faPlus} />}
>
<FormattedMessage id="credits.buyCredits" />
</Button>
<Button size="xs" onClick={() => window.open(links.contactSales, "_blank")}>
<FormattedMessage id="credits.talkToSales" />
</Button>
</Actions>
</Block>
</LowCreditBalanceHint>
<Block>
<CreditView>
<FormattedMessage id="credits.remainingCredits" />
<Count>
<FormattedNumber value={cloudWorkspace.remainingCredits} />
</Count>
</CreditView>
<Actions>
<Button
disabled={!selfServiceCheckoutEnabled}
type="button"
size="xs"
onClick={startStripeCheckout}
isLoading={isLoading || isWaitingForCredits}
icon={<FontAwesomeIcon icon={faPlus} />}
>
<FormattedMessage id="credits.buyCredits" />
</Button>
<Button size="xs" onClick={() => window.open(links.contactSales, "_blank")}>
<FormattedMessage id="credits.talkToSales" />
</Button>
</Actions>
</Block>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ $sidebar-workspace-font-weight: 400;
outline: 1px solid colors.$white;
}
}

.creditsButton {
position: relative;

.lowBalanceIndicator {
position: absolute;
top: 10px;
right: 24px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { faDesktop } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import classNames from "classnames";
import React from "react";
import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
import { FormattedMessage, useIntl } from "react-intl";
import { NavLink } from "react-router-dom";

import { Link } from "components";
import { CreditsIcon } from "components/icons/CreditsIcon";
import { DocsIcon } from "components/icons/DocsIcon";
import { Indicator } from "components/Indicator/Indicator";
import { DropdownMenu, DropdownMenuOptionType } from "components/ui/DropdownMenu";
import { Text } from "components/ui/Text";

Expand All @@ -31,6 +32,7 @@ import { NotificationIndicator } from "views/layout/SideBar/NotificationIndicato
import { useCalculateSidebarStyles } from "views/layout/SideBar/SideBar";

import { RoutePaths } from "../../../../../pages/routePaths";
import { LOW_BALANCE_CREDIT_TRESHOLD } from "../../credits/CreditsPage/components/LowCreditBalanceHint/LowCreditBalanceHint";
import styles from "./SideBar.module.scss";

const SideBar: React.FC = () => {
Expand Down Expand Up @@ -82,11 +84,14 @@ const SideBar: React.FC = () => {
</ul>
</div>
<ul className={styles.menu}>
<li>
<li className={styles.creditsButton}>
<NavLink className={navLinkClassName} to={CloudRoutes.Credits}>
{cloudWorkspace.remainingCredits <= LOW_BALANCE_CREDIT_TRESHOLD && (
<Indicator className={styles.lowBalanceIndicator} />
)}
<CreditsIcon />
<Text className={styles.text} size="sm">
<FormattedNumber value={cloudWorkspace.remainingCredits} />
<FormattedMessage id="sidebar.credits" />
</Text>
</NavLink>
</li>
Expand Down

0 comments on commit 74be2f8

Please sign in to comment.