diff --git a/components/molecules/AuthSection/auth-section.tsx b/components/molecules/AuthSection/auth-section.tsx index d7e9fd62d5..b50241c5a4 100644 --- a/components/molecules/AuthSection/auth-section.tsx +++ b/components/molecules/AuthSection/auth-section.tsx @@ -12,11 +12,11 @@ import useSupabaseAuth from "../../../lib/hooks/useSupabaseAuth"; import {FiLogOut} from "react-icons/fi"; import GitHubIcon from "public/icons/github-icon.svg"; import Icon from "components/atoms/Icon/icon"; -import useOnboarded from "lib/hooks/useOnboarded"; +import useSession from "lib/hooks/useSession"; const AuthSection: React.FC = ({ }) => { const { signIn, signOut, user } = useSupabaseAuth(); - const { onboarded } = useOnboarded(); + const { onboarded } = useSession(); const authMenu = { authed: [ diff --git a/components/molecules/WaitlistButton/waitlist-button.tsx b/components/molecules/WaitlistButton/waitlist-button.tsx new file mode 100644 index 0000000000..6b488d6b0b --- /dev/null +++ b/components/molecules/WaitlistButton/waitlist-button.tsx @@ -0,0 +1,30 @@ +import Text from "components/atoms/Typography/text"; +import Button from "components/atoms/Button/button"; + +interface WaitlistButtonProps { + waitlisted: boolean | undefined; + submitting: boolean; + handleJoinClick: (e: React.MouseEvent) => void; +} + +const WaitlistButton = ({ submitting, waitlisted, handleJoinClick }: WaitlistButtonProps) => { + return ( + <> + {waitlisted === true ? ( + You're on the waitlist to gain access to generate custom reports! + ) : ( +
+ Join the waitlist to gain access to generate custom reports! + +

+ +

+
+ )} + + ); +}; + +export default WaitlistButton; diff --git a/components/organisms/Reports/reports.tsx b/components/organisms/Reports/reports.tsx index d677c1d8e5..0b70347450 100644 --- a/components/organisms/Reports/reports.tsx +++ b/components/organisms/Reports/reports.tsx @@ -1,9 +1,16 @@ +import Button from "components/atoms/Button/button"; +import Icon from "components/atoms/Icon/icon"; import Title from "components/atoms/Typography/title"; +import GitHubIcon from "public/icons/github-icon.svg"; import ReportsHistory from "components/molecules/ReportsHistory/reports-history"; import SelectReportsFilter from "components/molecules/SelectReportsFilter/select-reports-filter"; +import WaitlistButton from "components/molecules/WaitlistButton/waitlist-button"; +import { useGlobalStateContext } from "context/global-state"; import { Report } from "interfaces/report-type"; import useFilterOptions from "lib/hooks/useFilterOptions"; import { useRepositoriesList } from "lib/hooks/useRepositoriesList"; +import useSession from "lib/hooks/useSession"; +import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import getCurrentDate from "lib/utils/get-current-date"; import { useState } from "react"; @@ -13,10 +20,14 @@ const Reports = (): JSX.Element => { const userDeviceState = localStorage.getItem(USERDEVICESTORAGENAME); const initialState = userDeviceState ? JSON.parse(userDeviceState as string) : []; const { data, isLoading, isError } = useRepositoriesList(); - const [ reports, setReports ] = useState(initialState); + const [reports, setReports] = useState(initialState); + const { sessionToken, user, signIn } = useSupabaseAuth(); + const { setAppState } = useGlobalStateContext(); + const { hasReports, waitlisted } = useSession(); + const [submitting, setSubmitting] = useState(false); const filterOptions = useFilterOptions(); - const filterList = filterOptions.map(filter => { + const filterList = filterOptions.map((filter) => { return { filterName: filter, filterValue: filter.toLowerCase().replaceAll(" ", "-") @@ -31,17 +42,41 @@ const Reports = (): JSX.Element => { reportDate: getCurrentDate(), reportFormat: "CSV", isGenerated: dataReady, - data : dataReady ? data : [] + data: dataReady ? data : [] }; - setReports(prevState => { - const newState = [ ...prevState, constructedReport ]; + setReports((prevState) => { + const newState = [...prevState, constructedReport]; localStorage.setItem(USERDEVICESTORAGENAME, JSON.stringify(newState)); return newState; }); }; + const handleJoinClick = async (e: React.MouseEvent) => { + e.preventDefault(); + + setSubmitting(true); + + try { + await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/waitlist`, { + method: "POST", + headers: { + Authorization: `Bearer ${sessionToken}` + } + }); + + setAppState((state) => ({ + ...state, + waitlisted: true + })); + } catch (e) { + // handle error + } finally { + setSubmitting(false); + } + }; + return (
@@ -49,20 +84,36 @@ const Reports = (): JSX.Element => { Contribution Insights
- - { reports.length > 0 && + {hasReports ? ( <> - - Download History - -
- + + + {reports.length > 0 && ( + <> + + Download History + +
+ + + )} - } + ) : hasReports === undefined ? ( +
+ {user ? ( +
Loading...
+ ) : ( +
+ +
+ )} +
+ ) : ( + + )}
); diff --git a/interfaces/global-state-types.ts b/interfaces/global-state-types.ts index 645c79b27b..0fcb0b8dbb 100644 --- a/interfaces/global-state-types.ts +++ b/interfaces/global-state-types.ts @@ -3,4 +3,5 @@ import { User } from "@supabase/gotrue-js/src/lib/types"; export interface GlobalStateInterface { user?: User | null; onboarded?: boolean; + waitlisted?: boolean; } \ No newline at end of file diff --git a/lib/hooks/useOnboarded.ts b/lib/hooks/useSession.ts similarity index 59% rename from lib/hooks/useOnboarded.ts rename to lib/hooks/useSession.ts index b7d0bf294e..1c3487beb6 100644 --- a/lib/hooks/useOnboarded.ts +++ b/lib/hooks/useSession.ts @@ -1,12 +1,13 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useGlobalStateContext } from "context/global-state"; import useSupabaseAuth from "./useSupabaseAuth"; -const useOnboarded = () => { +const useSession = () => { const { sessionToken } = useSupabaseAuth(); const { appState, setAppState } = useGlobalStateContext(); + const [ hasReports, setHasReports ] = useState(undefined); - async function loadData() { + async function loadSession() { try { const resp = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/session`, { method: "GET", @@ -19,8 +20,11 @@ const useOnboarded = () => { setAppState((state) => ({ ...state, - onboarded: data.is_onboarded + onboarded: data.is_onboarded, + waitlisted: data.is_waitlisted })); + + setHasReports(data.insights_role >= 50); } catch (e) { // show an alert } @@ -28,11 +32,11 @@ const useOnboarded = () => { useEffect(() => { if (sessionToken) { - loadData(); + loadSession(); } }, [sessionToken]); - return { onboarded: appState?.onboarded }; + return { onboarded: appState?.onboarded, waitlisted: appState?.waitlisted, hasReports }; }; -export default useOnboarded; +export default useSession; diff --git a/pages/start.tsx b/pages/start.tsx index 1d016e29fb..e44434f673 100644 --- a/pages/start.tsx +++ b/pages/start.tsx @@ -25,7 +25,7 @@ import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import { User } from "@supabase/supabase-js"; import { useGlobalStateContext } from "context/global-state"; import { getAvatarLink } from "lib/utils/github"; -import useOnboarded from "lib/hooks/useOnboarded"; +import useSession from "lib/hooks/useSession"; type handleLoginStep = () => void; @@ -38,7 +38,7 @@ const LoginStep1: React.FC = ({ handleLoginStep, user }) => { captureAnayltics("User Onboarding", "onboardingStep1", "visited"); const router = useRouter(); - const { onboarded } = useOnboarded(); + const { onboarded } = useSession(); useEffect(() => { if (onboarded) { diff --git a/stories/molecules/wailtlist-button.stories.tsx b/stories/molecules/wailtlist-button.stories.tsx new file mode 100644 index 0000000000..3fe63dd31c --- /dev/null +++ b/stories/molecules/wailtlist-button.stories.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { ComponentStory } from "@storybook/react"; +import WaitlistButton from "../../components/molecules/WaitlistButton/waitlist-button"; + +const StoryConfig = { + title: "Design System/Molecules/Waitlist Button" +}; + +export default StoryConfig; + + +const WaitlistButtonTemplate: ComponentStory = (args) => ; + +export const Default = WaitlistButtonTemplate.bind({}); +export const Submitting = WaitlistButtonTemplate.bind({}); +export const Waitlisted = WaitlistButtonTemplate.bind({}); + +Default.args = { + waitlisted: false +}; + +Submitting.args = { + waitlisted: false, + submitting: true +}; + +Waitlisted.args = { + waitlisted: true, +}