fix: create stripe customer when inviting new team member

This commit is contained in:
Henry
2025-01-30 22:20:13 +00:00
parent d27b6e6184
commit 0f26e7615b
4 changed files with 28 additions and 26 deletions

View File

@@ -1,8 +1,9 @@
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { HiXMark } from "react-icons/hi2"; import { HiXMark } from "react-icons/hi2";
import { type InviteMemberInput } from "@kan/api/types"; import type { InviteMemberInput } from "@kan/api/types";
import Button from "~/components/Button";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
@@ -15,7 +16,7 @@ export function InviteMemberForm() {
const { register, handleSubmit } = useForm<InviteMemberInput>({ const { register, handleSubmit } = useForm<InviteMemberInput>({
defaultValues: { defaultValues: {
email: "", email: "",
workspacePublicId: workspace?.publicId || "", workspacePublicId: workspace.publicId || "",
}, },
}); });
@@ -58,12 +59,13 @@ export function InviteMemberForm() {
<div className="mt-12 flex items-center justify-end border-t border-light-600 px-5 pb-5 pt-5 dark:border-dark-600"> <div className="mt-12 flex items-center justify-end border-t border-light-600 px-5 pb-5 pt-5 dark:border-dark-600">
<div> <div>
<button <Button
type="submit" type="submit"
isLoading={createBoard.isPending}
className="inline-flex w-full justify-center rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none dark:bg-dark-1000 dark:text-dark-50" className="inline-flex w-full justify-center rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none dark:bg-dark-1000 dark:text-dark-50"
> >
Invite member Invite member
</button> </Button>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -23,25 +23,6 @@ export default function MembersPage() {
// { enabled: workspace?.publicId ? true : false }, // { enabled: workspace?.publicId ? true : false },
); );
const handleUpgrade = async () => {
try {
const response = await fetch("/api/stripe/create_checkout_session", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const { url } = (await response.json()) as { url: string };
if (url) {
window.location.href = url;
}
} catch (error) {
console.error("Error creating checkout session:", error);
}
};
const TableRow = ({ const TableRow = ({
memberPublicId, memberPublicId,
memberName, memberName,
@@ -168,7 +149,7 @@ export default function MembersPage() {
<button <button
type="button" type="button"
className="flex items-center gap-x-1.5 rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:bg-dark-1000 dark:text-dark-50" className="flex items-center gap-x-1.5 rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:bg-dark-1000 dark:text-dark-50"
onClick={() => handleUpgrade()} onClick={() => openModal("INVITE_MEMBER")}
> >
<div className="h-5 w-5 items-center"> <div className="h-5 w-5 items-center">
<HiOutlinePlusSmall <HiOutlinePlusSmall

View File

@@ -1,4 +1,5 @@
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { Stripe } from "stripe";
import { z } from "zod"; import { z } from "zod";
import * as memberRepo from "@kan/db/repository/member.repo"; import * as memberRepo from "@kan/db/repository/member.repo";
@@ -8,6 +9,16 @@ import { sendEmail } from "@kan/email";
import { createTRPCRouter, protectedProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure } from "../trpc";
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
if (!stripeSecretKey) {
throw new Error("STRIPE_SECRET_KEY is not defined");
}
const stripe = new Stripe(stripeSecretKey, {
apiVersion: "2024-12-18.acacia",
});
export const memberRouter = createTRPCRouter({ export const memberRouter = createTRPCRouter({
invite: protectedProcedure invite: protectedProcedure
.meta({ .meta({
@@ -93,10 +104,17 @@ export const memberRouter = createTRPCRouter({
const invitedUserEmail = invite.data.user?.email; const invitedUserEmail = invite.data.user?.email;
if (invitedUserAuthId && invitedUserEmail) { if (invitedUserAuthId && invitedUserEmail) {
const stripeCustomer = await stripe.customers.create({
email: invitedUserEmail,
metadata: {
userId: invitedUserAuthId,
},
});
const newUser = await userRepo.create(ctx.adminDb, { const newUser = await userRepo.create(ctx.adminDb, {
email: invitedUserEmail, email: invitedUserEmail,
id: invitedUserAuthId, id: invitedUserAuthId,
stripeCustomerId: "", stripeCustomerId: stripeCustomer.id,
}); });
invitedUserId = newUser?.id; invitedUserId = newUser?.id;

View File

@@ -55,6 +55,7 @@
"NEXT_PUBLIC_SUPABASE_ANON_KEY", "NEXT_PUBLIC_SUPABASE_ANON_KEY",
"NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME", "NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME",
"SUPABASE_SERVICE_API_KEY", "SUPABASE_SERVICE_API_KEY",
"STRIPE_SECRET_KEY",
"PORT" "PORT"
], ],
"globalPassThroughEnv": [ "globalPassThroughEnv": [
@@ -65,4 +66,4 @@
"VERCEL_URL", "VERCEL_URL",
"npm_lifecycle_event" "npm_lifecycle_event"
] ]
} }