diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx
new file mode 100644
index 0000000..23c815b
--- /dev/null
+++ b/src/app/(auth)/layout.tsx
@@ -0,0 +1,13 @@
+export default function AuthLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ )
+}
diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..676ba9d
--- /dev/null
+++ b/src/app/(auth)/login/page.tsx
@@ -0,0 +1,30 @@
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
+import { LoginForm } from '@/components/auth/login-form'
+import { GoogleSignInButton } from '@/components/auth/google-button'
+
+export default function LoginPage() {
+ return (
+
+
+ Accedi a Leopost
+
+ Inserisci le tue credenziali per continuare
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/(auth)/register/page.tsx b/src/app/(auth)/register/page.tsx
new file mode 100644
index 0000000..2e2bc7c
--- /dev/null
+++ b/src/app/(auth)/register/page.tsx
@@ -0,0 +1,30 @@
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
+import { RegisterForm } from '@/components/auth/register-form'
+import { GoogleSignInButton } from '@/components/auth/google-button'
+
+export default function RegisterPage() {
+ return (
+
+
+ Crea il tuo account
+
+ Inizia a usare Leopost gratuitamente
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/auth/login-form.tsx b/src/components/auth/login-form.tsx
new file mode 100644
index 0000000..12bc0ee
--- /dev/null
+++ b/src/components/auth/login-form.tsx
@@ -0,0 +1,103 @@
+'use client'
+
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import Link from 'next/link'
+import { useState } from 'react'
+import { createClient } from '@/lib/supabase/client'
+import { useRouter } from 'next/navigation'
+
+export function LoginForm() {
+ const [email, setEmail] = useState('')
+ const [password, setPassword] = useState('')
+ const [error, setError] = useState(null)
+ const [loading, setLoading] = useState(false)
+ const router = useRouter()
+ const supabase = createClient()
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault()
+ setError(null)
+ setLoading(true)
+
+ const { error: signInError } = await supabase.auth.signInWithPassword({
+ email,
+ password,
+ })
+
+ if (signInError) {
+ // SPECIFIC error messages per user requirement
+ if (signInError.message.includes('Invalid login credentials')) {
+ setError('Email o password errata')
+ } else if (signInError.message.includes('Email not confirmed')) {
+ setError('Devi confermare la tua email prima di accedere')
+ } else {
+ setError(signInError.message)
+ }
+ setLoading(false)
+ return
+ }
+
+ router.push('/dashboard')
+ router.refresh()
+ }
+
+ return (
+
+ )
+}
diff --git a/src/components/auth/register-form.tsx b/src/components/auth/register-form.tsx
new file mode 100644
index 0000000..6ca0018
--- /dev/null
+++ b/src/components/auth/register-form.tsx
@@ -0,0 +1,172 @@
+'use client'
+
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import Link from 'next/link'
+import { useState } from 'react'
+import { createClient } from '@/lib/supabase/client'
+
+export function RegisterForm() {
+ const [email, setEmail] = useState('')
+ const [password, setPassword] = useState('')
+ const [confirmPassword, setConfirmPassword] = useState('')
+ const [error, setError] = useState(null)
+ const [fieldErrors, setFieldErrors] = useState>({})
+ const [loading, setLoading] = useState(false)
+ const [success, setSuccess] = useState(false)
+ const supabase = createClient()
+
+ function validatePassword(pwd: string): string | null {
+ if (pwd.length < 8) {
+ return 'La password deve contenere almeno 8 caratteri'
+ }
+ if (!/[0-9]/.test(pwd)) {
+ return 'La password deve contenere almeno un numero'
+ }
+ if (!/[A-Z]/.test(pwd)) {
+ return 'La password deve contenere almeno una lettera maiuscola'
+ }
+ return null
+ }
+
+ async function handleSubmit(e: React.FormEvent) {
+ e.preventDefault()
+ setError(null)
+ setFieldErrors({})
+ setLoading(true)
+
+ // Validate password
+ const passwordError = validatePassword(password)
+ if (passwordError) {
+ setFieldErrors({ password: passwordError })
+ setLoading(false)
+ return
+ }
+
+ // Validate confirm password
+ if (password !== confirmPassword) {
+ setFieldErrors({ confirmPassword: 'Le password non coincidono' })
+ setLoading(false)
+ return
+ }
+
+ const { error: signUpError } = await supabase.auth.signUp({
+ email,
+ password,
+ options: {
+ emailRedirectTo: `${window.location.origin}/auth/callback`,
+ }
+ })
+
+ if (signUpError) {
+ // SPECIFIC error messages per user requirement
+ if (signUpError.message.includes('already registered')) {
+ setError('Questa email e gia registrata')
+ } else if (signUpError.message.includes('invalid')) {
+ setError('Email non valida')
+ } else {
+ setError(signUpError.message)
+ }
+ setLoading(false)
+ return
+ }
+
+ setSuccess(true)
+ setLoading(false)
+ }
+
+ if (success) {
+ return (
+
+
+
+ Registrazione completata! Controlla la tua email per confermare l'account.
+
+
+
+ Torna al login
+
+
+ )
+ }
+
+ return (
+
+ )
+}
diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx
new file mode 100644
index 0000000..98d0e5f
--- /dev/null
+++ b/src/components/ui/input.tsx
@@ -0,0 +1,28 @@
+import { forwardRef, InputHTMLAttributes } from 'react'
+import { cn } from '@/lib/utils'
+
+export interface InputProps extends InputHTMLAttributes {
+ error?: boolean
+}
+
+const Input = forwardRef(
+ ({ className, error, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Input.displayName = 'Input'
+
+export { Input }