Files
weeding/src/components/ui/captcha.tsx

91 lines
2.9 KiB
TypeScript

'use client'
import { useState, useEffect, forwardRef, useImperativeHandle, useCallback } from 'react'
import { getNewCaptcha, CaptchaResponse } from '@/app/actions/captcha'
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Loader2, RefreshCw } from "lucide-react"
interface CaptchaProps {
onVerify: (hash: string, value: string) => void
}
export interface CaptchaRef {
reset: () => void
}
export const Captcha = forwardRef<CaptchaRef, CaptchaProps>(({ onVerify }, ref) => {
const [captcha, setCaptcha] = useState<CaptchaResponse | null>(null)
const [input, setInput] = useState("")
const [loading, setLoading] = useState(true)
const fetchCaptcha = useCallback(async () => {
setLoading(true)
try {
const data = await getNewCaptcha()
setCaptcha(data)
setInput("")
onVerify(data.hash, "") // Reset parent state
} catch (error) {
console.error("Captcha fetch failed", error)
} finally {
setLoading(false)
}
}, [onVerify])
useEffect(() => {
fetchCaptcha()
}, [fetchCaptcha])
useImperativeHandle(ref, () => ({
reset: fetchCaptcha
}))
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
setInput(value)
if (captcha) {
onVerify(captcha.hash, value)
}
}
return (
<div className="space-y-2">
<Label>Güvenlik Kodu</Label>
<div className="flex gap-2 items-start">
<div className="relative w-[200px] h-[80px]">
<div
className="border rounded-md overflow-hidden bg-gray-100 w-full h-full flex items-center justify-center select-none"
dangerouslySetInnerHTML={{ __html: captcha?.image || '' }}
/>
{loading && (
<div className="absolute inset-0 flex items-center justify-center bg-gray-100/50">
<Loader2 className="animate-spin text-gray-400" />
</div>
)}
</div>
<Button
type="button"
variant="outline"
size="icon"
onClick={fetchCaptcha}
title="Kodu Yenile"
disabled={loading}
>
<RefreshCw className={`h-4 w-4 ${loading ? 'animate-spin' : ''}`} />
</Button>
</div>
<Input
placeholder="Resimdeki kodu giriniz"
value={input}
onChange={handleChange}
maxLength={5}
required
/>
</div>
)
})
Captcha.displayName = "Captcha"