Add create team page

This commit is contained in:
KMKoushik
2024-04-30 21:31:54 +10:00
parent b352210185
commit 7996a8e373
6 changed files with 215 additions and 27 deletions

View File

@@ -31,6 +31,7 @@ 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";
export const metadata = {
title: "Unsend",
@@ -53,6 +54,16 @@ export default async function AuthenticatedDashboardLayout({
redirect("/wait-list");
}
const teamUser = await db.teamUser.findFirst({
where: {
userId: session.user.id,
},
});
if (!teamUser) {
redirect("/create-team");
}
return (
<NextAuthProvider session={session}>
<div className="flex min-h-screen w-full h-full">

View File

@@ -0,0 +1,92 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@unsend/ui/src/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormMessage,
} from "@unsend/ui/src/form";
import { Input } from "@unsend/ui/src/input";
import { Spinner } from "@unsend/ui/src/spinner";
import { api } from "~/trpc/react";
import { useRouter } from "next/navigation";
const FormSchema = z.object({
name: z.string().min(2, {
message: "Team name must be at least 2 characters.",
}),
});
export default function CreateTeam() {
const createTeam = api.team.createTeam.useMutation();
const router = useRouter();
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
name: "",
},
});
function onSubmit(data: z.infer<typeof FormSchema>) {
createTeam.mutate(data, {
onSuccess: () => {
router.replace("/dashboard");
},
});
}
return (
<div className="flex items-center justify-center min-h-screen ">
<div className=" w-[300px] flex flex-col gap-8">
<div>
<h1 className="text-2xl font-semibold text-center">Create Team</h1>
</div>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className=" flex flex-col gap-8 w-full"
>
<FormField
control={form.control}
name="name"
render={({ field, formState }) => (
<FormItem>
<FormControl>
<Input
placeholder="Team name"
className="w-full"
{...field}
/>
</FormControl>
{formState.errors.name ? (
<FormMessage />
) : (
<FormDescription>
Request admin to join existing team
</FormDescription>
)}
</FormItem>
)}
/>
<Button type="submit" disabled={createTeam.isPending}>
{createTeam.isPending ? (
<Spinner className="w-5 h-5" />
) : (
"Create"
)}
</Button>
</form>
</Form>
</div>
</div>
);
}

View File

@@ -1,33 +1,16 @@
import Link from "next/link";
import { getServerAuthSession } from "~/server/auth";
import { Button } from "@unsend/ui/src/button";
import { SendHorizonal } from "lucide-react";
import { redirect } from "next/navigation";
export default async function Home() {
const session = await getServerAuthSession();
return (
<main className="h-screen">
<h1 className="text-center text-4xl mt-20 flex gap-4 justify-center items-center">
<SendHorizonal />
Send emails in minutes. Completely open source
</h1>
<div className="flex justify-center mt-10">
{session?.user ? (
<Button className="mx-auto">
<Link href="/dashboard" className="mx-auto">
Send email
</Link>
</Button>
) : (
<Button className="mx-auto">
<Link href="api/auth/signin" className="mx-auto">
Signin
</Link>
</Button>
)}
</div>
</main>
);
if (!session?.user) {
redirect("/login");
}
if (!session.user.isBetaUser) {
redirect("/wait-list");
} else {
redirect("/dashboard");
}
}

View File

@@ -2,6 +2,7 @@ import { domainRouter } from "~/server/api/routers/domain";
import { createCallerFactory, createTRPCRouter } from "~/server/api/trpc";
import { apiRouter } from "./routers/api";
import { emailRouter } from "./routers/email";
import { teamRouter } from "./routers/team";
/**
* This is the primary router for your server.
@@ -12,6 +13,7 @@ export const appRouter = createTRPCRouter({
domain: domainRouter,
apiKey: apiRouter,
email: emailRouter,
team: teamRouter,
});
// export type definition of API

View File

@@ -0,0 +1,50 @@
import { z } from "zod";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
export const teamRouter = createTRPCRouter({
createTeam: protectedProcedure
.input(z.object({ name: z.string() }))
.mutation(async ({ ctx, input }) => {
const teams = await ctx.db.team.findMany({
where: {
teamUsers: {
some: {
userId: ctx.session.user.id,
},
},
},
});
if (teams) {
console.log("User already has a team");
return;
}
return ctx.db.team.create({
data: {
name: input.name,
teamUsers: {
create: {
userId: ctx.session.user.id,
role: "ADMIN",
},
},
},
});
}),
getTeams: protectedProcedure.query(async ({ ctx }) => {
const teams = await ctx.db.team.findMany({
where: {
teamUsers: {
some: {
userId: ctx.session.user.id,
},
},
},
});
return teams;
}),
});