Letschat / src /components /dashboard /TransferCodeForm.tsx
HonzaH's picture
Upload 171 files
9853b20 verified
Raw
History Blame Contribute Delete
4.62 kB
'use client'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { Button } from 'components/ui/button'
import { codeWithPinSchema, type CodeWithPinForm } from 'lib/validations/code'
interface TransferCodeFormProps {
onSuccess: () => void
onCancel: () => void
}
export function TransferCodeForm({ onSuccess, onCancel }: TransferCodeFormProps) {
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [needsPin, setNeedsPin] = useState(false)
const {
register,
handleSubmit,
formState: { errors },
watch
} = useForm<CodeWithPinForm>({
resolver: zodResolver(codeWithPinSchema)
})
const codeValue = watch('code')
const onSubmit = async (data: CodeWithPinForm) => {
try {
setLoading(true)
setError(null)
const response = await fetch('/api/users/transfer-code', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code: data.code.toUpperCase(),
pin: data.pin || undefined
})
})
const result = await response.json()
if (!response.ok) {
if (response.status === 400 && result.needsPin) {
setNeedsPin(true)
return
} else if (response.status === 401) {
setError('Neplatný kód nebo PIN')
} else if (response.status === 409) {
setError('Kód již máte ve svém profilu')
} else {
setError(result.error || 'Nastala chyba při převodu kódu')
}
return
}
onSuccess()
} catch {
setError('Došlo k neočekávané chybě')
} finally {
setLoading(false)
}
}
return (
<div className="bg-white p-6 rounded-lg shadow-md">
<h3 className="text-lg font-semibold text-gray-900 mb-4">
Převést anonymní kód
</h3>
<p className="text-sm text-gray-600 mb-6">
Zadejte kód a PIN (pokud je nastaven) pro převedení anonymní místnosti pod váš profil.
</p>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<div>
<label htmlFor="code" className="block text-sm font-medium text-gray-700 mb-1">
Kód místnosti
</label>
<input
{...register('code')}
type="text"
id="code"
maxLength={5}
placeholder="A1B2C"
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500 uppercase text-center font-mono"
style={{ textTransform: 'uppercase' }}
/>
{errors.code && (
<p className="mt-1 text-sm text-red-600">{errors.code.message}</p>
)}
</div>
{(needsPin || codeValue?.length === 5) && (
<div>
<label htmlFor="pin" className="block text-sm font-medium text-gray-700 mb-1">
PIN (pokud je nastaven)
</label>
<input
{...register('pin')}
type="password"
id="pin"
maxLength={5}
placeholder="12345"
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-500 text-center font-mono"
/>
{errors.pin && (
<p className="mt-1 text-sm text-red-600">{errors.pin.message}</p>
)}
<p className="mt-1 text-xs text-gray-500">
Nechte prázdné, pokud místnost není chráněna PIN
</p>
</div>
)}
{error && (
<div className="p-3 text-sm text-red-600 bg-red-50 rounded-md">
{error}
</div>
)}
<div className="flex gap-3">
<button
type="submit"
className="flex-1 bg-gray-800 text-white hover:bg-gray-900 px-4 py-2 rounded-md"
disabled={loading}
>
{loading ? 'Převádím...' : 'Převést kód'}
</button>
<button
type="button"
className="flex-none px-4 py-2 text-sm text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md"
onClick={onCancel}
>
Zrušit
</button>
</div>
</form>
</div>
)
}