Skip to content

Commit

Permalink
feat: adds initial support for restricting reports by user roles (#451)
Browse files Browse the repository at this point in the history
Closes #395
  • Loading branch information
brandonroberts committed Sep 28, 2022
1 parent c032234 commit 15a7643
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 27 deletions.
4 changes: 2 additions & 2 deletions components/molecules/AuthSection/auth-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
30 changes: 30 additions & 0 deletions components/molecules/WaitlistButton/waitlist-button.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLButtonElement>) => void;
}

const WaitlistButton = ({ submitting, waitlisted, handleJoinClick }: WaitlistButtonProps) => {
return (
<>
{waitlisted === true ? (
<Text className="!font-medium">You&apos;re on the waitlist to gain access to generate custom reports!</Text>
) : (
<div>
<Text className="!font-medium">Join the waitlist to gain access to generate custom reports!</Text>

<p className="flex justify-center py-4 px-2">
<Button type="primary" onClick={handleJoinClick} disabled={submitting} className="w-52 h-[38px]">
Join Waitlist
</Button>
</p>
</div>
)}
</>
);
};

export default WaitlistButton;
83 changes: 67 additions & 16 deletions components/organisms/Reports/reports.tsx
Original file line number Diff line number Diff line change
@@ -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";

Expand All @@ -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<Report[]>(initialState);
const [reports, setReports] = useState<Report[]>(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(" ", "-")
Expand All @@ -31,38 +42,78 @@ 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<HTMLButtonElement>) => {
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 (
<section className="flex flex-col w-full py-4 px-2 md:px-4 justify-center items-center">
<div className="max-w-4xl">
<Title className="!font-medium relative" level={3}>
Contribution Insights
</Title>
<hr className="border-light-slate-6 my-4" />
<SelectReportsFilter
filterList={filterList}
callback={handleFilterClick}
/>

{ reports.length > 0 &&
{hasReports ? (
<>
<Title className="!font-medium relative mt-16" level={3}>
Download History
</Title>
<hr className="border-light-slate-6 my-4" />
<ReportsHistory reportList={reports}/>
<SelectReportsFilter filterList={filterList} callback={handleFilterClick} />

{reports.length > 0 && (
<>
<Title className="!font-medium relative mt-16" level={3}>
Download History
</Title>
<hr className="border-light-slate-6 my-4" />
<ReportsHistory reportList={reports} />
</>
)}
</>
}
) : hasReports === undefined ? (
<div>
{user ? (
<div>Loading...</div>
) : (
<div className="flex justify-center py-4">
<Button type="primary" onClick={async () => await signIn({ provider: "github" })}>
Connect with GitHub <Icon IconImage={GitHubIcon} className="ml-2" />
</Button>
</div>
)}
</div>
) : (
<WaitlistButton waitlisted={waitlisted} submitting={submitting} handleJoinClick={handleJoinClick} />
)}
</div>
</section>
);
Expand Down
1 change: 1 addition & 0 deletions interfaces/global-state-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { User } from "@supabase/gotrue-js/src/lib/types";
export interface GlobalStateInterface {
user?: User | null;
onboarded?: boolean;
waitlisted?: boolean;
}
18 changes: 11 additions & 7 deletions lib/hooks/useOnboarded.ts → lib/hooks/useSession.ts
Original file line number Diff line number Diff line change
@@ -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<boolean | undefined>(undefined);

async function loadData() {
async function loadSession() {
try {
const resp = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/auth/session`, {
method: "GET",
Expand All @@ -19,20 +20,23 @@ 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
}
}

useEffect(() => {
if (sessionToken) {
loadData();
loadSession();
}
}, [sessionToken]);

return { onboarded: appState?.onboarded };
return { onboarded: appState?.onboarded, waitlisted: appState?.waitlisted, hasReports };
};

export default useOnboarded;
export default useSession;
4 changes: 2 additions & 2 deletions pages/start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -38,7 +38,7 @@ const LoginStep1: React.FC<LoginStep1Props> = ({ handleLoginStep, user }) => {
captureAnayltics("User Onboarding", "onboardingStep1", "visited");

const router = useRouter();
const { onboarded } = useOnboarded();
const { onboarded } = useSession();

useEffect(() => {
if (onboarded) {
Expand Down
29 changes: 29 additions & 0 deletions stories/molecules/wailtlist-button.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof WaitlistButton> = (args) => <WaitlistButton {...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,
}

0 comments on commit 15a7643

Please sign in to comment.