Skip to content

Commit

Permalink
stripe stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
joschan21 committed Sep 25, 2023
1 parent cec40f7 commit 531061c
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 23 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@mantine/hooks": "^7.0.1",
"@pinecone-database/pinecone": "^1.0.1",
"@prisma/client": "^5.3.1",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-progress": "^1.0.3",
Expand Down
27 changes: 27 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 52 additions & 23 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import { buttonVariants } from './ui/button'
import {
LoginLink,
RegisterLink,
getKindeServerSession,
} from '@kinde-oss/kinde-auth-nextjs/server'
import { ArrowRight } from 'lucide-react'
import UserAccountNav from './UserAccountNav'

const Navbar = () => {
const { getUser } = getKindeServerSession()
const user = getUser()

return (
<nav className='sticky h-14 inset-x-0 top-0 z-30 w-full border-b border-gray-200 bg-white/75 backdrop-blur-lg transition-all'>
<MaxWidthWrapper>
Expand All @@ -21,29 +26,53 @@ const Navbar = () => {
{/* todo: add mobile navbar */}

<div className='hidden items-center space-x-4 sm:flex'>
<>
<Link
href='/pricing'
className={buttonVariants({
variant: 'ghost',
size: 'sm',
})}>
Pricing
</Link>
<LoginLink
className={buttonVariants({
variant: 'ghost',
size: 'sm',
})}>
Sign in
</LoginLink>
<RegisterLink
className={buttonVariants({
size: 'sm',
})}>
Get started <ArrowRight className='ml-1.5 h-5 w-5' />
</RegisterLink>
</>
{!user ? (
<>
<Link
href='/pricing'
className={buttonVariants({
variant: 'ghost',
size: 'sm',
})}>
Pricing
</Link>
<LoginLink
className={buttonVariants({
variant: 'ghost',
size: 'sm',
})}>
Sign in
</LoginLink>
<RegisterLink
className={buttonVariants({
size: 'sm',
})}>
Get started{' '}
<ArrowRight className='ml-1.5 h-5 w-5' />
</RegisterLink>
</>
) : (
<>
<Link
href='/dashboard'
className={buttonVariants({
variant: 'ghost',
size: 'sm',
})}>
Dashboard
</Link>

<UserAccountNav
name={
!user.given_name || !user.family_name
? 'Your Account'
: `${user.given_name} ${user.family_name}`
}
email={user.email ?? ''}
imageUrl={user.picture ?? ''}
/>
</>
)}
</div>
</div>
</MaxWidthWrapper>
Expand Down
101 changes: 101 additions & 0 deletions src/components/UserAccountNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { getUserSubscriptionPlan } from '@/lib/stripe'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from './ui/dropdown-menu'
import { Button } from './ui/button'
import { Avatar, AvatarFallback } from './ui/avatar'
import Image from 'next/image'
import { Icons } from './Icons'
import Link from 'next/link'
import { Gem } from 'lucide-react'
import { LogoutLink } from '@kinde-oss/kinde-auth-nextjs/server'

interface UserAccountNavProps {
email: string | undefined
name: string
imageUrl: string
}

const UserAccountNav = async ({
email,
imageUrl,
name,
}: UserAccountNavProps) => {
const subscriptionPlan = await getUserSubscriptionPlan()

return (
<DropdownMenu>
<DropdownMenuTrigger
asChild
className='overflow-visible'>
<Button className='rounded-full h-8 w-8 aspect-square bg-slate-400'>
<Avatar className='relative w-8 h-8'>
{imageUrl ? (
<div className='relative aspect-square h-full w-full'>
<Image
fill
src={imageUrl}
alt='profile picture'
referrerPolicy='no-referrer'
/>
</div>
) : (
<AvatarFallback>
<span className='sr-only'>{name}</span>
<Icons.user className='h-4 w-4 text-zinc-900' />
</AvatarFallback>
)}
</Avatar>
</Button>
</DropdownMenuTrigger>

<DropdownMenuContent className='bg-white' align='end'>
<div className='flex items-center justify-start gap-2 p-2'>
<div className='flex flex-col space-y-0.5 leading-none'>
{name && (
<p className='font-medium text-sm text-black'>
{name}
</p>
)}
{email && (
<p className='w-[200px] truncate text-xs text-zinc-700'>
{email}
</p>
)}
</div>
</div>

<DropdownMenuSeparator />

<DropdownMenuItem asChild>
<Link href='/dashboard'>Dashboard</Link>
</DropdownMenuItem>

<DropdownMenuItem asChild>
{subscriptionPlan?.isSubscribed ? (
<Link href='/dashboard/billing'>
Manage Subscription
</Link>
) : (
<Link href='/pricing'>
Upgrade{' '}
<Gem className='text-blue-600 h-4 w-4 ml-1.5' />
</Link>
)}
</DropdownMenuItem>

<DropdownMenuSeparator />

<DropdownMenuItem className='cursor-pointer'>
<LogoutLink>Log out</LogoutLink>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}

export default UserAccountNav
50 changes: 50 additions & 0 deletions src/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client"

import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"

import { cn } from "@/lib/utils"

const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName

const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName

const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
)}
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName

export { Avatar, AvatarImage, AvatarFallback }
7 changes: 7 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { authMiddleware } from '@kinde-oss/kinde-auth-nextjs/server'

export const config = {
matcher: ['/dashboard/:path*', '/auth-callback'],
}

export default authMiddleware

0 comments on commit 531061c

Please sign in to comment.