mirror of
https://github.com/ershisan99/www.git
synced 2025-12-17 12:34:17 +00:00
add sign in
This commit is contained in:
@@ -6,6 +6,7 @@ import { Geist } from 'next/font/google'
|
|||||||
import { MainHeader } from '@/components/header'
|
import { MainHeader } from '@/components/header'
|
||||||
import { ThemeProvider } from '@/components/theme-provider'
|
import { ThemeProvider } from '@/components/theme-provider'
|
||||||
import { TRPCReactProvider } from '@/trpc/react'
|
import { TRPCReactProvider } from '@/trpc/react'
|
||||||
|
import { SessionProvider } from 'next-auth/react'
|
||||||
import { NextIntlClientProvider } from 'next-intl'
|
import { NextIntlClientProvider } from 'next-intl'
|
||||||
import { getLocale } from 'next-intl/server'
|
import { getLocale } from 'next-intl/server'
|
||||||
|
|
||||||
@@ -33,15 +34,17 @@ export default async function RootLayout({
|
|||||||
<body>
|
<body>
|
||||||
<TRPCReactProvider>
|
<TRPCReactProvider>
|
||||||
<NextIntlClientProvider>
|
<NextIntlClientProvider>
|
||||||
<ThemeProvider
|
<SessionProvider>
|
||||||
attribute='class'
|
<ThemeProvider
|
||||||
defaultTheme='system'
|
attribute='class'
|
||||||
enableSystem
|
defaultTheme='system'
|
||||||
disableTransitionOnChange
|
enableSystem
|
||||||
>
|
disableTransitionOnChange
|
||||||
<MainHeader />
|
>
|
||||||
{children}
|
<MainHeader />
|
||||||
</ThemeProvider>
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</SessionProvider>
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</TRPCReactProvider>
|
</TRPCReactProvider>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu'
|
} from '@/components/ui/dropdown-menu'
|
||||||
import { LogIn, LogOut, Menu, Moon, Settings, Sun, User, X } from 'lucide-react'
|
import { LogIn, LogOut, Menu, Moon, Settings, Sun, User, X } from 'lucide-react'
|
||||||
|
import { signIn, signOut, useSession } from 'next-auth/react'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
@@ -16,21 +17,8 @@ import { useState } from 'react'
|
|||||||
export function MainHeader() {
|
export function MainHeader() {
|
||||||
const { setTheme, theme } = useTheme()
|
const { setTheme, theme } = useTheme()
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||||
|
const { data: session, status } = useSession()
|
||||||
// Mock authentication state - replace with your actual auth logic
|
const isAuthenticated = status === 'authenticated'
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState(false)
|
|
||||||
|
|
||||||
// Mock user data - replace with your actual user data
|
|
||||||
const userData = {
|
|
||||||
name: 'Player123',
|
|
||||||
avatar: '/placeholder.svg?height=40&width=40',
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toggle authentication for demo purposes
|
|
||||||
const toggleAuth = () => {
|
|
||||||
setIsAuthenticated(!isAuthenticated)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className='sticky top-0 z-40 border-gray-200 border-b bg-white dark:border-zinc-800 dark:bg-zinc-900'>
|
<header className='sticky top-0 z-40 border-gray-200 border-b bg-white dark:border-zinc-800 dark:bg-zinc-900'>
|
||||||
<div className='container mx-auto px-4'>
|
<div className='container mx-auto px-4'>
|
||||||
@@ -97,7 +85,7 @@ export function MainHeader() {
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
{/* Sign In Button or User Menu */}
|
{/* Sign In Button or User Menu */}
|
||||||
{isAuthenticated ? (
|
{isAuthenticated && session?.user && session.user.name ? (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
@@ -105,9 +93,12 @@ export function MainHeader() {
|
|||||||
className='relative h-9 w-9 rounded-full'
|
className='relative h-9 w-9 rounded-full'
|
||||||
>
|
>
|
||||||
<Avatar className='h-9 w-9'>
|
<Avatar className='h-9 w-9'>
|
||||||
<AvatarImage src={userData.avatar} alt={userData.name} />
|
<AvatarImage
|
||||||
|
src={session.user.image ?? ''}
|
||||||
|
alt={session.user.name}
|
||||||
|
/>
|
||||||
<AvatarFallback className='bg-violet-50 text-violet-600 dark:bg-violet-900/50 dark:text-violet-300'>
|
<AvatarFallback className='bg-violet-50 text-violet-600 dark:bg-violet-900/50 dark:text-violet-300'>
|
||||||
{userData.name.slice(0, 2).toUpperCase()}
|
{session.user.name?.slice(0, 2).toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -115,11 +106,14 @@ export function MainHeader() {
|
|||||||
<DropdownMenuContent className='w-56' align='end' forceMount>
|
<DropdownMenuContent className='w-56' align='end' forceMount>
|
||||||
<div className='flex items-center justify-start gap-2 p-2'>
|
<div className='flex items-center justify-start gap-2 p-2'>
|
||||||
<div className='flex flex-col space-y-1 leading-none'>
|
<div className='flex flex-col space-y-1 leading-none'>
|
||||||
<p className='font-medium'>{userData.name}</p>
|
<p className='font-medium'>{session.user.name}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenuItem asChild>
|
<DropdownMenuItem asChild>
|
||||||
<Link href='/profile' className='flex w-full items-center'>
|
<Link
|
||||||
|
href={`/players/${session.user.discord_id}`}
|
||||||
|
className='flex w-full items-center'
|
||||||
|
>
|
||||||
<User className='mr-2 h-4 w-4' />
|
<User className='mr-2 h-4 w-4' />
|
||||||
<span>Profile</span>
|
<span>Profile</span>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -130,7 +124,7 @@ export function MainHeader() {
|
|||||||
<span>Settings</span>
|
<span>Settings</span>
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={toggleAuth}>
|
<DropdownMenuItem onClick={() => signOut()}>
|
||||||
<LogOut className='mr-2 h-4 w-4' />
|
<LogOut className='mr-2 h-4 w-4' />
|
||||||
<span>Log out</span>
|
<span>Log out</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -141,7 +135,7 @@ export function MainHeader() {
|
|||||||
variant='default'
|
variant='default'
|
||||||
size='sm'
|
size='sm'
|
||||||
className='bg-violet-600 hover:bg-violet-700 dark:text-zinc-100'
|
className='bg-violet-600 hover:bg-violet-700 dark:text-zinc-100'
|
||||||
onClick={toggleAuth}
|
onClick={() => signIn('discord')}
|
||||||
>
|
>
|
||||||
<LogIn className='mr-2 h-4 w-4' />
|
<LogIn className='mr-2 h-4 w-4' />
|
||||||
Sign In
|
Sign In
|
||||||
|
|||||||
@@ -20,15 +20,11 @@ declare module 'next-auth' {
|
|||||||
interface Session extends DefaultSession {
|
interface Session extends DefaultSession {
|
||||||
user: {
|
user: {
|
||||||
id: string
|
id: string
|
||||||
|
discord_id: string
|
||||||
// ...other properties
|
// ...other properties
|
||||||
// role: UserRole;
|
// role: UserRole;
|
||||||
} & DefaultSession['user']
|
} & DefaultSession['user']
|
||||||
}
|
}
|
||||||
|
|
||||||
// interface User {
|
|
||||||
// // ...other properties
|
|
||||||
// // role: UserRole;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +34,27 @@ declare module 'next-auth' {
|
|||||||
*/
|
*/
|
||||||
export const authConfig = {
|
export const authConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
DiscordProvider,
|
DiscordProvider({
|
||||||
|
profile(profile) {
|
||||||
|
if (profile.avatar === null) {
|
||||||
|
const defaultAvatarNumber =
|
||||||
|
profile.discriminator === '0'
|
||||||
|
? Number(BigInt(profile.id) >> BigInt(22)) % 6
|
||||||
|
: Number.parseInt(profile.discriminator) % 5
|
||||||
|
profile.image_url = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNumber}.png`
|
||||||
|
} else {
|
||||||
|
const format = profile.avatar.startsWith('a_') ? 'gif' : 'png'
|
||||||
|
profile.image_url = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: profile.id,
|
||||||
|
name: profile.global_name ?? profile.username,
|
||||||
|
email: profile.email,
|
||||||
|
image: profile.image_url,
|
||||||
|
discord_id: profile.id.toString(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
/**
|
/**
|
||||||
* ...add more providers here.
|
* ...add more providers here.
|
||||||
*
|
*
|
||||||
@@ -61,6 +77,7 @@ export const authConfig = {
|
|||||||
user: {
|
user: {
|
||||||
...session.user,
|
...session.user,
|
||||||
id: user.id,
|
id: user.id,
|
||||||
|
discord_id: session.user.discord_id,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ export const users = pgTable('user', (d) => ({
|
|||||||
})
|
})
|
||||||
.default(sql`CURRENT_TIMESTAMP`),
|
.default(sql`CURRENT_TIMESTAMP`),
|
||||||
image: d.varchar({ length: 255 }),
|
image: d.varchar({ length: 255 }),
|
||||||
|
discord_id: d.varchar({ length: 255 }),
|
||||||
|
role: d.varchar({ length: 255 }).notNull().default('user'),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export const usersRelations = relations(users, ({ many }) => ({
|
export const usersRelations = relations(users, ({ many }) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user