sourcebot/packages/web/src/app/[domain]/settings/page.tsx
Michael Sukkarieh 7c187121c8
Add stripe billing logic (#190)
* add side bar nav in settings page

* improve styling of members page

* wip adding stripe checkout button

* wip onboarding flow

* add stripe subscription id to org

* save stripe session id and add manage subscription button in settings

* properly block access to pages if user isn't in an org

* wip add paywall

* Domain support

* add back paywall and also add support for incrememnting seat count on invite redemption

* prevent self invite

* action button styling in settings and toast on copy

* add ability to remove member from org

* move stripe product id to env var

* add await for blocking loop in backend

* add subscription info to billing page

* handle trial case in billing info page

* add trial duration indicator to nav bar

* check if domain starts or ends with dash

* remove unused no org component

* remove package lock file and fix prisma dep version

* revert dep version updates

* fix yarn.lock

* add auth and membership check to fetchSubscription

* properly handle invite redeem with no valid subscription case

* change back fetch subscription to not require org membership

* add back subscription check in invite redeem page

---------

Co-authored-by: bkellam <bshizzle1234@gmail.com>
2025-02-13 15:52:33 -08:00

105 lines
2.7 KiB
TypeScript

import { auth } from "@/auth"
import { getUser } from "@/data/user"
import { prisma } from "@/prisma"
import { MemberTable } from "./components/memberTable"
import { MemberInviteForm } from "./components/memberInviteForm"
import { InviteTable } from "./components/inviteTable"
import { Separator } from "@/components/ui/separator"
interface SettingsPageProps {
params: {
domain: string
}
}
export default async function SettingsPage({ params: { domain } }: SettingsPageProps) {
const fetchData = async () => {
const session = await auth()
if (!session) {
return null
}
const user = await getUser(session.user.id)
if (!user) {
return null
}
const activeOrg = await prisma.org.findUnique({
where: {
domain,
},
})
if (!activeOrg) {
return null
}
const members = await prisma.user.findMany({
where: {
orgs: {
some: {
orgId: activeOrg.id,
},
},
},
include: {
orgs: {
where: {
orgId: activeOrg.id,
},
select: {
role: true,
},
},
},
})
const invites = await prisma.invite.findMany({
where: {
orgId: activeOrg.id,
},
})
const memberInfo = members.map((member) => ({
id: member.id,
name: member.name!,
email: member.email!,
role: member.orgs[0].role,
}))
const inviteInfo = invites.map((invite) => ({
id: invite.id,
email: invite.recipientEmail,
createdAt: invite.createdAt,
}))
return {
user,
memberInfo,
inviteInfo,
activeOrg,
}
}
const data = await fetchData()
if (!data) {
return <div>Error: Unable to fetch data</div>
}
const { user, memberInfo, inviteInfo } = data
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-medium">Members</h3>
<p className="text-sm text-muted-foreground">Invite and manage members of your organization.</p>
</div>
<Separator />
<div className="space-y-6">
<MemberTable currentUserId={user.id} initialMembers={memberInfo} />
<MemberInviteForm userId={user.id} />
<InviteTable initialInvites={inviteInfo} />
</div>
</div>
)
}