Skip to content

Commit

Permalink
🪟🧪 [Experiment] Incentivize speedy first connection (aka activation) (#…
Browse files Browse the repository at this point in the history
…17593)

* 🪟🧪 [Experiment] Incentivize speedy first connection (aka activation)
  • Loading branch information
letiescanciano authored Oct 20, 2022
1 parent a71b7ca commit 5466a68
Show file tree
Hide file tree
Showing 18 changed files with 410 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export interface Experiments {
"authPage.oauth.github": boolean;
"authPage.oauth.google.signUpPage": boolean;
"authPage.oauth.github.signUpPage": boolean;
"onboarding.speedyConnection": boolean;
}
5 changes: 4 additions & 1 deletion airbyte-webapp/src/packages/cloud/cloudRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { FeatureItem, FeatureSet, useFeatureService } from "hooks/services/Featu
import { useApiHealthPoll } from "hooks/services/Health";
import { OnboardingServiceProvider } from "hooks/services/Onboarding";
import { useQuery } from "hooks/useQuery";
import { useExperimentSpeedyConnection } from "packages/cloud/components/experiments/SpeedyConnection/hooks/useExperimentSpeedyConnection";
import { useAuthService } from "packages/cloud/services/auth/AuthService";
import { useIntercom } from "packages/cloud/services/thirdParty/intercom/useIntercom";
import { Auth } from "packages/cloud/views/auth";
Expand Down Expand Up @@ -86,6 +87,8 @@ const MainRoutes: React.FC = () => {
const mainNavigate =
workspace.displaySetupWizard && !hideOnboardingExperiment ? RoutePaths.Onboarding : RoutePaths.Connections;

// exp-speedy-connection
const { isExperimentVariant } = useExperimentSpeedyConnection();
return (
<ApiErrorBoundary>
<Routes>
Expand All @@ -95,7 +98,7 @@ const MainRoutes: React.FC = () => {
<Route path={`${RoutePaths.Settings}/*`} element={<CloudSettingsPage />} />
<Route path={CloudRoutes.Credits} element={<CreditsPage />} />

{workspace.displaySetupWizard && !hideOnboardingExperiment && (
{(workspace.displaySetupWizard || isExperimentVariant) && !hideOnboardingExperiment && (
<Route
path={RoutePaths.Onboarding}
element={
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@use "../../../../../../../src/scss/variables";
@use "../../../../../../../src/scss/colors";

.countDownTimerContainer {
display: flex;
gap: variables.$spacing-md;
}

.countDownTimerItem {
color: colors.$orange;
font-size: 16px;
line-height: 28px;
font-weight: 700;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Text } from "components/ui/Text";

import styles from "./CountDownTimer.module.scss";
import { useCountdown } from "./useCountdown";
export const CountDownTimer: React.FC<{ expiredOfferDate: string }> = ({ expiredOfferDate }) => {
const [hours, minutes, seconds] = useCountdown(expiredOfferDate);

return (
<div className={styles.countDownTimerContainer}>
<Text className={styles.countDownTimerItem}>{hours.toString().padStart(2, "0")}h</Text>
<Text className={styles.countDownTimerItem}>{minutes.toString().padStart(2, "0")}m</Text>
<Text className={styles.countDownTimerItem}>{seconds.toString().padStart(2, "0")}s</Text>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./CountDownTimer";
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect, useState } from "react";

export const useCountdown = (targetDate: string) => {
const countDownDate = new Date(targetDate).getTime();

const [countDown, setCountDown] = useState(countDownDate - new Date().getTime());

useEffect(() => {
const interval = setInterval(() => {
setCountDown(countDownDate - new Date().getTime());
}, 1000);

return () => clearInterval(interval);
}, [countDownDate]);

return getReturnValues(countDown);
};

const getReturnValues = (countDown: number): number[] => {
// calculate time left
const hours = Math.floor((countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((countDown % (1000 * 60)) / 1000);

return [hours, minutes, seconds];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@use "../../../../../../../src/scss/variables";
@use "../../../../../../../src/scss/colors";

.container {
height: 43px;
width: 100%;
position: fixed;
top: 0;
z-index: 3;
font-size: 12px;
line-height: 15px;
color: colors.$black;
padding: 8px;
display: flex;
align-items: center;
background-color: colors.$beige-100;

@media (min-width: 1280px) {
height: 50px;
}
}

.innerContainer {
display: flex;
width: 80%;
flex-direction: row;
gap: variables.$spacing-md;
justify-content: center;
align-items: center;
margin: auto;
}

.linkCta {
color: colors.$dark-blue;
}

.textDecorationNone {
text-decoration: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import classnames from "classnames";
import classNames from "classnames";
import { FormattedMessage } from "react-intl";
import { Link, useLocation } from "react-router-dom";

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

import { useExperiment } from "hooks/services/Experiment";
import { CountDownTimer } from "packages/cloud/components/experiments/SpeedyConnection/CountDownTimer";
import { StepType } from "pages/OnboardingPage/types";
import { RoutePaths } from "pages/routePaths";

import { useExperimentSpeedyConnection } from "../hooks/useExperimentSpeedyConnection";
import credits from "./credits.svg";
import styles from "./SpeedyConnectionBanner.module.scss";

export const SpeedyConnectionBanner = () => {
const { expiredOfferDate } = useExperimentSpeedyConnection();
const location = useLocation();
const hideOnboardingExperiment = useExperiment("onboarding.hideOnboarding", false);

return (
<div className={classnames(styles.container)}>
<div className={styles.innerContainer}>
<img src={credits} alt="" />

<FormattedMessage
id="experiment.speedyConnection"
defaultMessage="<link>Set up your first connection</link> in the next <timer></timer> and get <b>100 additonal credits</b> for your trial"
values={{
link: (link: React.ReactNode[]) => (
<Link
className={classNames(styles.linkCta, {
[styles.textDecorationNone]: location.pathname.includes("onboarding"),
})}
to={hideOnboardingExperiment ? RoutePaths.Connections : RoutePaths.Onboarding}
state={{
step: StepType.CREATE_SOURCE,
}}
>
<Text bold>{link}</Text>
</Link>
),
timer: () => <CountDownTimer expiredOfferDate={expiredOfferDate} />,
}}
/>
<img src={credits} alt="" />
</div>
</div>
);
};
Loading

0 comments on commit 5466a68

Please sign in to comment.