feat: add authentication support and user model

- Updated `env.example` to include NextAuth configuration for authentication.
- Added `next-auth` dependency to manage user sessions.
- Introduced `User` model in Prisma schema with fields for user details and password hashing.
- Integrated `AuthProvider` in layout for session management across the app.
- Enhanced `Header` component with `AuthButton` for user authentication controls.
This commit is contained in:
Julien Froidefond
2025-09-30 21:49:52 +02:00
parent 43c141d3cd
commit 17b86b6087
20 changed files with 1418 additions and 13 deletions

View File

@@ -0,0 +1,56 @@
'use client'
import { useSession, signOut } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import { Button } from '@/components/ui/Button'
export function AuthButton() {
const { data: session, status } = useSession()
const router = useRouter()
if (status === 'loading') {
return (
<div className="text-[var(--muted-foreground)] text-sm">
Chargement...
</div>
)
}
if (!session) {
return (
<Button
onClick={() => router.push('/login')}
size="sm"
>
Se connecter
</Button>
)
}
return (
<div className="flex items-center gap-1">
<Button
onClick={() => router.push('/profile')}
variant="ghost"
size="sm"
className="p-1 h-auto"
title={`Profil - ${session.user?.email}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</Button>
<Button
onClick={() => signOut({ callbackUrl: '/login' })}
variant="ghost"
size="sm"
className="p-1 h-auto"
title="Déconnexion"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
</Button>
</div>
)
}

View File

@@ -0,0 +1,7 @@
'use client'
import { SessionProvider } from "next-auth/react"
export function AuthProvider({ children }: { children: React.ReactNode }) {
return <SessionProvider>{children}</SessionProvider>
}

View File

@@ -0,0 +1,11 @@
export function TowerBackground() {
return (
<div className="absolute inset-0 bg-gradient-to-br from-[var(--primary)]/20 via-[var(--background)] to-[var(--accent)]/20">
{/* Effet de profondeur */}
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent"></div>
{/* Effet de lumière */}
<div className="absolute inset-0 bg-gradient-to-br from-transparent via-[var(--primary)]/5 to-transparent"></div>
</div>
)
}

View File

@@ -0,0 +1,37 @@
interface TowerLogoProps {
size?: 'sm' | 'md' | 'lg'
showText?: boolean
className?: string
}
export function TowerLogo({ size = 'md', showText = true, className = '' }: TowerLogoProps) {
const sizeClasses = {
sm: 'w-12 h-12',
md: 'w-20 h-20',
lg: 'w-32 h-32'
}
const textSizes = {
sm: 'text-2xl',
md: 'text-4xl',
lg: 'text-6xl'
}
return (
<div className={`text-center ${className}`}>
<div className={`inline-flex items-center justify-center ${sizeClasses[size]} rounded-2xl mb-4 text-6xl`}>
🗼
</div>
{showText && (
<>
<h1 className={`${textSizes[size]} font-mono font-bold text-[var(--foreground)] mb-2`}>
TowerControl
</h1>
<p className="text-[var(--muted-foreground)] text-lg">
Tour de contrôle de vos projets
</p>
</>
)}
</div>
)
}

View File

@@ -8,6 +8,7 @@ import { useState } from 'react';
import { Theme } from '@/lib/theme-config';
import { THEME_CONFIG, getThemeMetadata } from '@/lib/theme-config';
import { useKeyboardShortcutsModal } from '@/contexts/KeyboardShortcutsContext';
import { AuthButton } from '@/components/AuthButton';
interface HeaderProps {
title?: string;
@@ -173,6 +174,12 @@ export function Header({ title = "TowerControl", subtitle = "Task Management", s
)}
</button>
</div>
</div>
{/* Auth controls à droite mobile */}
<div className="flex items-center gap-1">
<AuthButton />
</div>
</div>
@@ -264,9 +271,15 @@ export function Header({ title = "TowerControl", subtitle = "Task Management", s
</>
)}
</div>
</nav>
</div>
{/* Contrôles à droite */}
<div className="flex items-center gap-2">
<AuthButton />
</div>
</div>
</div>