Move dashboard to client components. (#26)

* Move to client components

* Move to client components

* Fix create team
This commit is contained in:
KM Koushik
2024-06-02 11:03:50 +10:00
committed by GitHub
parent f183905c9f
commit 4a37c66865
10 changed files with 297 additions and 178 deletions

View File

@@ -1,7 +1,9 @@
"use client";
import ApiList from "./api-list";
import AddApiKey from "./add-api-key";
export default async function ApiKeysPage() {
export default function ApiKeysPage() {
return (
<div>
<div className="flex justify-between items-center">

View File

@@ -1,7 +1,9 @@
"use client";
import DomainsList from "./domain-list";
import AddDomain from "./add-domain";
export default async function DomainsPage() {
export default function DomainsPage() {
return (
<div>
<div className="flex justify-between items-center">

View File

@@ -1,10 +1,9 @@
import dynamic from "next/dynamic";
"use client";
const EmailList = dynamic(
() => import("./email-list").then((mod) => mod.default),
{ ssr: false }
);
export default async function EmailsPage() {
import dynamic from "next/dynamic";
import EmailList from "./email-list";
export default function EmailsPage() {
return (
<div>
<div className="flex justify-between items-center">

View File

@@ -1,6 +1,7 @@
import Link from "next/link";
import { redirect } from "next/navigation";
import {
BookOpenText,
BookUser,
CircleUser,
Code,
@@ -29,10 +30,12 @@ import {
} from "@unsend/ui/src/dropdown-menu";
import { Sheet, SheetContent, SheetTrigger } from "@unsend/ui/src/sheet";
import { NextAuthProvider } from "~/providers/next-auth";
import { getServerAuthSession } from "~/server/auth";
import { NavButton } from "./nav-button";
import { db } from "~/server/db";
import { SessionProvider } from "next-auth/react";
import { DashboardProvider } from "~/providers/dashboard-provider";
import { NextAuthProvider } from "~/providers/next-auth";
export const metadata = {
title: "Unsend",
@@ -45,33 +48,17 @@ export default async function AuthenticatedDashboardLayout({
}: {
children: React.ReactNode;
}) {
const session = await getServerAuthSession();
if (!session?.user) {
redirect("/");
}
if (!session.user.isBetaUser) {
redirect("/wait-list");
}
const teamUser = await db.teamUser.findFirst({
where: {
userId: session.user.id,
},
});
if (!teamUser) {
redirect("/create-team");
}
return (
<NextAuthProvider session={session}>
<NextAuthProvider>
<DashboardProvider>
<div className="flex min-h-screen w-full h-full">
<div className="hidden bg-muted/20 md:block md:w-[280px]">
<div className="flex h-full max-h-screen flex-col gap-2">
<div className="flex h-14 gap-4 items-center px-4 lg:h-[60px] lg:px-6">
<Link href="/" className="flex items-center gap-2 font-semibold">
<Link
href="/"
className="flex items-center gap-2 font-semibold"
>
<span className=" text-lg">Unsend</span>
</Link>
<span className="text-[10px] text-muted-foreground bg-muted p-0.5 px-2 rounded-full">
@@ -117,7 +104,7 @@ export default async function AuthenticatedDashboardLayout({
target="_blank"
className="flex gap-2 items-center"
>
<ExternalLink className="h-4 w-4" />
<BookOpenText className="h-4 w-4" />
<span className="">Docs</span>
</Link>
</div>
@@ -215,6 +202,7 @@ export default async function AuthenticatedDashboardLayout({
</main>
</div>
</div>
</DashboardProvider>
</NextAuthProvider>
);
}

View File

@@ -0,0 +1,9 @@
import { Logo } from "@unsend/ui/src/logo";
export const FullScreenLoading = () => {
return (
<div className="flex items-center justify-center min-h-screen">
<Logo className="w-10 h-10" />
</div>
);
};

View File

@@ -26,6 +26,7 @@ const FormSchema = z.object({
export default function CreateTeam() {
const createTeam = api.team.createTeam.useMutation();
const utils = api.useUtils();
const router = useRouter();
@@ -39,6 +40,7 @@ export default function CreateTeam() {
function onSubmit(data: z.infer<typeof FormSchema>) {
createTeam.mutate(data, {
onSuccess: () => {
utils.team.invalidate();
router.replace("/dashboard");
},
});

View File

@@ -0,0 +1,23 @@
"use client";
import { FullScreenLoading } from "~/components/FullScreenLoading";
import CreateTeam from "~/components/team/CreateTeam";
import { api } from "~/trpc/react";
export const DashboardProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const { data: teams, status } = api.team.getTeams.useQuery();
if (status === "pending") {
return <FullScreenLoading />;
}
if (!teams || teams.length === 0) {
return <CreateTeam />;
}
return <>{children}</>;
};

View File

@@ -3,10 +3,13 @@
import React from "react";
import type { Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import { SessionProvider, useSession } from "next-auth/react";
import LoginPage from "~/app/login/login-page";
import { Rocket } from "lucide-react";
import { FullScreenLoading } from "~/components/FullScreenLoading";
export type NextAuthProviderProps = {
session?: Session | null;
session?: Session | null | undefined;
children: React.ReactNode;
};
@@ -14,5 +17,37 @@ export const NextAuthProvider = ({
session,
children,
}: NextAuthProviderProps) => {
return <SessionProvider session={session}>{children}</SessionProvider>;
return (
<SessionProvider session={session}>
<AppAuthProvider>{children}</AppAuthProvider>
</SessionProvider>
);
};
const AppAuthProvider = ({ children }: { children: React.ReactNode }) => {
const { data: session, status } = useSession({ required: true });
if (status === "loading") {
return <FullScreenLoading />;
}
if (!session) {
return <LoginPage />;
}
if (!session.user.isBetaUser) {
return (
<div className="flex items-center justify-center min-h-screen ">
<div className="p-8 shadow-lg rounded-lg flex flex-col gap-4">
<Rocket />
<h1 className="text-2xl font-bold">You're on the Waitlist!</h1>
<p className=" text-secondary-muted">
Hang tight, we'll get to you as soon as possible.
</p>
</div>
</div>
);
}
return <>{children}</>;
};

59
packages/ui/src/logo.tsx Normal file
View File

@@ -0,0 +1,59 @@
import React from "react";
export const Logo: React.FC<React.SVGProps<SVGSVGElement>> = ({ ...props }) => {
return (
<svg
width="650"
height="650"
viewBox="0 0 650 650"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<mask
id="mask0_28_12"
style={{ maskType: "alpha" }}
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="650"
height="650"
>
<path
d="M0 100C0 44.7715 44.7715 0 100 0H550C605.228 0 650 44.7715 650 100V550C650 605.228 605.228 650 550 650H100C44.7715 650 0 605.228 0 550V100Z"
fill="black"
/>
</mask>
<g mask="url(#mask0_28_12)">
<path
d="M0 100C0 44.7715 44.7715 0 100 0H550C605.228 0 650 44.7715 650 100V550C650 605.228 605.228 650 550 650H100C44.7715 650 0 605.228 0 550V100Z"
fill="black"
/>
<path
d="M436.647 185.212C437.97 180.27 444.984 180.27 446.307 185.212L491.353 353.463C492.86 359.093 485.152 362.312 482.207 357.282L445.792 295.062C443.861 291.763 439.093 291.763 437.162 295.062L400.746 357.282C397.802 362.312 390.094 359.094 391.601 353.463L436.647 185.212Z"
fill="white"
/>
<path
d="M467.077 364.883C467.077 385.571 463.002 406.057 455.085 425.17C447.168 444.284 435.564 461.651 420.935 476.28C406.306 490.908 388.939 502.513 369.826 510.43C350.712 518.347 330.227 522.422 309.538 522.422C288.85 522.422 268.365 518.347 249.251 510.43C230.138 502.513 212.771 490.908 198.142 476.28C183.513 461.651 171.909 444.284 163.992 425.17C156.075 406.057 152 385.571 152 364.883H202.528C202.528 378.936 205.296 392.851 210.674 405.834C216.052 418.817 223.934 430.614 233.871 440.551C243.808 450.488 255.604 458.37 268.587 463.748C281.571 469.125 295.486 471.893 309.538 471.893C323.591 471.893 337.506 469.125 350.49 463.748C363.473 458.37 375.269 450.488 385.206 440.551C395.143 430.614 403.025 418.817 408.403 405.834C413.781 392.851 416.549 378.936 416.549 364.883H467.077Z"
fill="white"
/>
<path
d="M152 156.145C152 142.224 163.285 130.938 177.206 130.938C191.127 130.938 202.412 142.224 202.412 156.145V366.458C202.412 380.379 191.127 391.665 177.206 391.665C163.285 391.665 152 380.379 152 366.458V156.145Z"
fill="white"
/>
<path
d="M416.665 152.206C416.665 138.285 427.95 127 441.871 127C455.792 127 467.077 138.285 467.077 152.206V362.52C467.077 376.441 455.792 387.726 441.871 387.726C427.95 387.726 416.665 376.441 416.665 362.52V152.206Z"
fill="white"
/>
<path
d="M419.676 139.67C421.559 133.877 427.78 130.708 433.572 132.59C439.365 134.472 442.534 140.693 440.652 146.485L366.899 373.475C365.017 379.267 358.796 382.437 353.003 380.555C347.211 378.673 344.041 372.452 345.923 366.659L419.676 139.67Z"
fill="white"
/>
<path
d="M442.916 147.452C441.034 141.66 444.203 135.439 449.996 133.556C455.788 131.674 462.009 134.844 463.891 140.637L537.645 367.626C539.527 373.418 536.357 379.64 530.565 381.522C524.772 383.404 518.551 380.234 516.669 374.442L442.916 147.452Z"
fill="white"
/>
</g>
</svg>
);
};

View File

@@ -57,7 +57,7 @@
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive: 0 68% 41%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;