| 'use client' |
|
|
| import { useState } from 'react' |
| import { useForm } from 'react-hook-form' |
| import { zodResolver } from '@hookform/resolvers/zod' |
| import { useRouter } from 'next/navigation' |
| import { loginSchema, type LoginForm } from 'lib/validations/auth' |
| import { emitAuthChanged } from 'hooks/useAuth' |
| import { getSupabaseBrowserConfig, isSupabaseBrowserConfigured } from 'lib/supabase/publicEnv' |
|
|
| export function LoginForm() { |
| const [loading, setLoading] = useState(false) |
| const [error, setError] = useState<string | null>(null) |
| const supabaseReady = isSupabaseBrowserConfigured() |
| const supabaseEnv = getSupabaseBrowserConfig() |
| const router = useRouter() |
|
|
| const { |
| register, |
| handleSubmit, |
| formState: { errors } |
| } = useForm<LoginForm>({ |
| resolver: zodResolver(loginSchema) |
| }) |
|
|
| const onSubmit = async (data: LoginForm) => { |
| console.info('[login] submit', { supabaseReady, email: data.email, supabaseUrl: supabaseEnv.url }) |
| try { |
| setLoading(true) |
| setError(null) |
|
|
| const res = await fetch('/api/auth/login', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify(data), |
| credentials: 'include' |
| }) |
| const json = await res.json().catch(() => ({})) |
| if (!res.ok) { |
| setError(json?.error || 'Neplatné přihlašovací údaje') |
| return |
| } |
|
|
| |
| try { |
| if (typeof window !== 'undefined') { |
| const match = document.cookie.split(';').map(s => s.trim()).find(c => c.startsWith('letschat_session_pub=')) |
| if (match) { |
| const token = match.split('=')[1] |
| window.localStorage.setItem('letschat_session', token) |
| } |
| } |
| } catch (e) { |
| |
| } |
|
|
| emitAuthChanged() |
| router.push('/dashboard') |
| } catch (e: any) { |
| console.error('Login error:', e) |
| setError(e?.message || 'Došlo k neočekávané chybě při přihlášení') |
| } finally { |
| setLoading(false) |
| } |
| } |
|
|
| return ( |
| <form id="form-login" action="#" method="post" className="form" onSubmit={handleSubmit(onSubmit)}> |
| <div className="input"> |
| <div className="text">E-mail</div> |
| <div className="insert"> |
| <input |
| {...register('email')} |
| type="email" |
| maxLength={255} |
| placeholder="E-mailová adresa" |
| autoComplete="email" |
| /> |
| <div className="error">{errors.email?.message}</div> |
| </div> |
| </div> |
| |
| <div className="input"> |
| <div className="text">Heslo</div> |
| <div className="insert"> |
| <input |
| {...register('password')} |
| type="password" |
| maxLength={255} |
| placeholder="Heslo k přihlášení" |
| autoComplete="current-password" |
| /> |
| <div className="error">{errors.password?.message}</div> |
| <div className="visible" data-input="password"></div> |
| </div> |
| </div> |
| |
| <div className="input"> |
| <div className="text"></div> |
| <div className="insert"> |
| {error ? ( |
| <div |
| className="error" |
| style={{ |
| marginBottom: 12, |
| padding: '10px 12px', |
| background: '#FEE2E2', |
| color: '#991B1B', |
| borderRadius: 8, |
| fontWeight: 600 |
| }} |
| > |
| {error} |
| </div> |
| ) : null} |
| |
| <input |
| type="submit" |
| value={loading ? 'Přihlašuji…' : 'Přihlásit'} |
| disabled={loading} |
| onClick={() => console.info('[login] button click', { supabaseReady, supabaseUrl: supabaseEnv.url })} |
| /> |
| {!supabaseReady ? ( |
| <div className="error" style={{ marginTop: 8 }}> |
| Přidejte Supabase klíče do prostředí Space (NEXT_PUBLIC_SUPABASE_URL a NEXT_PUBLIC_SUPABASE_ANON_KEY) a znovu |
| spusťte build. |
| </div> |
| ) : null} |
| </div> |
| </div> |
| </form> |
| ) |
| } |
|
|
|
|