diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx index da83b409fe3..d9ba692436a 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx @@ -1,5 +1,5 @@ import { getProjects } from "@/api/projects"; -import { getTeams } from "@/api/team"; +import { getTeamNebulaWaitList, getTeams } from "@/api/team"; import { TabPathLinks } from "@/components/ui/tabs"; import { notFound } from "next/navigation"; import { TeamHeaderLoggedIn } from "../../components/TeamHeader/team-header-logged-in.client"; @@ -22,6 +22,9 @@ export default async function TeamLayout(props: { notFound(); } + const isOnNebulaWaitList = (await getTeamNebulaWaitList(team.slug)) + ?.onWaitlist; + return (
@@ -55,10 +58,14 @@ export default async function TeamLayout(props: { path: `/team/${params.team_slug}/~/ecosystem`, name: "Ecosystems", }, - { - path: `/team/${params.team_slug}/~/nebula`, - name: "Nebula", - }, + ...(isOnNebulaWaitList + ? [ + { + path: `/team/${params.team_slug}/~/nebula`, + name: "Nebula", + }, + ] + : []), { path: `/team/${params.team_slug}/~/usage`, name: "Usage", diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/nebula/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/nebula/page.tsx index 175b8c33ee7..e919b4cd522 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/nebula/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/nebula/page.tsx @@ -1,6 +1,4 @@ -import { getTeamBySlug, getTeamNebulaWaitList } from "@/api/team"; -import { redirect } from "next/navigation"; -import { JoinNebulaWaitlistPage } from "../../../[project_slug]/nebula/components/nebula-waitlist-page.client"; +import { NebulaWaitListPage } from "../../../[project_slug]/nebula/components/nebula-waitlist-page"; export default async function Page(props: { params: Promise<{ @@ -8,31 +6,11 @@ export default async function Page(props: { }>; }) { const params = await props.params; - const team = await getTeamBySlug(params.team_slug); - - if (!team) { - redirect( - `/login?next=${encodeURIComponent(`/team/${params.team_slug}/~/nebula`)}`, - ); - } - - const nebulaWaitList = await getTeamNebulaWaitList(team.slug); - - // this should never happen - if (!nebulaWaitList) { - return ( -
-
- Something went wrong trying to fetch the nebula waitlist -
-
- ); - } return ( - ); } diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/layout.tsx index 7e2545b4dff..f7a25c64eb2 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/layout.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/layout.tsx @@ -1,5 +1,5 @@ import { getProjects } from "@/api/projects"; -import { getTeams } from "@/api/team"; +import { getTeamNebulaWaitList, getTeams } from "@/api/team"; import { TabPathLinks } from "@/components/ui/tabs"; import { notFound, redirect } from "next/navigation"; import { TeamHeaderLoggedIn } from "../../components/TeamHeader/team-header-logged-in.client"; @@ -34,6 +34,9 @@ export default async function TeamLayout(props: { redirect(`/team/${params.team_slug}`); } + const isOnNebulaWaitList = (await getTeamNebulaWaitList(team.slug)) + ?.onWaitlist; + return (
@@ -58,10 +61,14 @@ export default async function TeamLayout(props: { path: `/team/${params.team_slug}/${params.project_slug}/contracts`, name: "Contracts", }, - { - path: `/team/${params.team_slug}/${params.project_slug}/nebula`, - name: "Nebula", - }, + ...(isOnNebulaWaitList + ? [ + { + path: `/team/${params.team_slug}/${params.project_slug}/nebula`, + name: "Nebula", + }, + ] + : []), { path: `/team/${params.team_slug}/${params.project_slug}/settings`, name: "Settings", diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page-ui.client.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page-ui.client.tsx index eb2fe260d70..970c8ae98d4 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page-ui.client.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page-ui.client.tsx @@ -1,21 +1,9 @@ -"use client"; - -import { Spinner } from "@/components/ui/Spinner/Spinner"; import { Button } from "@/components/ui/button"; -import { ToolTipLabel } from "@/components/ui/tooltip"; -import { useDashboardRouter } from "@/lib/DashboardRouter"; -import { useMutation } from "@tanstack/react-query"; -import { ArrowRightIcon, CheckIcon, OrbitIcon, ShareIcon } from "lucide-react"; +import { OrbitIcon } from "lucide-react"; import Link from "next/link"; -import { useState } from "react"; -import { toast } from "sonner"; - -export function JoinNebulaWaitlistPageUI(props: { - onWaitlist: boolean; - joinWaitList: () => Promise; -}) { - const router = useDashboardRouter(); +import { ShareButton } from "./share-button.client"; +export function NebulaWaitListPageUI() { return (
{/* Header */} @@ -31,89 +19,16 @@ export function JoinNebulaWaitlistPageUI(props: {
- {props.onWaitlist ? ( - } - /> - ) : ( - { - router.refresh(); - }} - /> - } - /> - )} + } + />
); } -function ShareButton() { - const [isCopied, setIsCopied] = useState(false); - - return ( - - - - ); -} - -function JoinWaitingListButton(props: { - joinWaitList: () => Promise; - onSuccess: () => void; -}) { - const joinWaitListMutation = useMutation({ - mutationFn: props.joinWaitList, - onSuccess: props.onSuccess, - }); - - return ( - - ); -} - function CenteredCard(props: { footer: React.ReactNode; title: React.ReactNode; diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.client.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.client.tsx deleted file mode 100644 index 559b8bb3fa1..00000000000 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.client.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { joinTeamWaitlist } from "@/actions/joinWaitlist"; -import { JoinNebulaWaitlistPageUI } from "./nebula-waitlist-page-ui.client"; - -export function JoinNebulaWaitlistPage(props: { - onWaitlist: boolean; - teamSlug: string; -}) { - return ( - { - await joinTeamWaitlist({ - scope: "nebula", - teamSlug: props.teamSlug, - }); - }} - /> - ); -} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.tsx new file mode 100644 index 00000000000..b0a93df2de3 --- /dev/null +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist-page.tsx @@ -0,0 +1,60 @@ +import { joinTeamWaitlist } from "@/actions/joinWaitlist"; +import { getTeamBySlug, getTeamNebulaWaitList } from "@/api/team"; +import { Button } from "@/components/ui/button"; +import Link from "next/link"; +import { redirect } from "next/navigation"; +import { NebulaWaitListPageUI } from "./nebula-waitlist-page-ui.client"; + +export async function NebulaWaitListPage(props: { + redirectOnNoTeam: string; + teamSlug: string; +}) { + const team = await getTeamBySlug(props.teamSlug); + + if (!team) { + redirect(props.redirectOnNoTeam); + } + + const nebulaWaitList = await getTeamNebulaWaitList(team.slug); + + // this should never happen + if (!nebulaWaitList) { + return ( + + ); + } + + // if not already on the waitlist, join the waitlist + if (!nebulaWaitList.onWaitlist) { + const joined = await joinTeamWaitlist({ + scope: "nebula", + teamSlug: team.slug, + }).catch(() => null); + + // this should never happen + if (!joined) { + return ( + + ); + } + } + + return ; +} + +function UnexpectedErrorPage(props: { + message: string; +}) { + return ( +
+
+
+ {props.message} + +
+
+
+ ); +} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist.stories.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist.stories.tsx index f01835d307b..a007238a06d 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist.stories.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/nebula-waitlist.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Toaster } from "sonner"; import { mobileViewport } from "stories/utils"; -import { JoinNebulaWaitlistPageUI } from "./nebula-waitlist-page-ui.client"; +import { NebulaWaitListPageUI } from "./nebula-waitlist-page-ui.client"; const meta = { title: "nebula/waitlist", @@ -16,48 +15,19 @@ const meta = { export default meta; type Story = StoryObj; -export const NotInWaitingListDesktop: Story = { +export const Desktop: Story = { args: { inWaitlist: false, }, }; -export const InWaitingListDesktop: Story = { - args: { - inWaitlist: true, - }, -}; - -export const NotInWaitingListMobile: Story = { - args: { - inWaitlist: false, - }, - parameters: { - viewport: mobileViewport("iphone14"), - }, -}; - -export const InWaitingListMobile: Story = { - args: { - inWaitlist: true, - }, +export const Mobile: Story = { + args: {}, parameters: { viewport: mobileViewport("iphone14"), }, }; -function Story(props: { - inWaitlist: boolean; -}) { - return ( - <> - { - await new Promise((resolve) => setTimeout(resolve, 1500)); - }} - /> - - - ); +function Story() { + return ; } diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/share-button.client.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/share-button.client.tsx new file mode 100644 index 00000000000..33001a1c19b --- /dev/null +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/components/share-button.client.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { ToolTipLabel } from "@/components/ui/tooltip"; +import { CheckIcon, ShareIcon } from "lucide-react"; +import { useState } from "react"; + +export function ShareButton() { + const [isCopied, setIsCopied] = useState(false); + + return ( + + + + ); +} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/page.tsx index 1eceea3eec1..1b8d9088423 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/nebula/page.tsx @@ -1,6 +1,4 @@ -import { getTeamBySlug, getTeamNebulaWaitList } from "@/api/team"; -import { redirect } from "next/navigation"; -import { JoinNebulaWaitlistPage } from "./components/nebula-waitlist-page.client"; +import { NebulaWaitListPage } from "./components/nebula-waitlist-page"; export default async function Page(props: { params: Promise<{ @@ -9,31 +7,11 @@ export default async function Page(props: { }>; }) { const params = await props.params; - const team = await getTeamBySlug(params.team_slug); - - if (!team) { - redirect( - `/login?next=${encodeURIComponent(`/team/${params.team_slug}/${params.project_slug}/nebula`)}`, - ); - } - - const nebulaWaitList = await getTeamNebulaWaitList(team.slug); - - // this should never happen - if (!nebulaWaitList) { - return ( -
-
- Something went wrong trying to fetch the nebula waitlist -
-
- ); - } return ( - ); }