Import source: app/src/lib/TeknavCAP
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,124 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
const TeknavCAP = ({ onChange, style = {} }) => {
|
||||||
|
const [captchaId, setCaptchaId] = useState('');
|
||||||
|
const [captchaSvg, setCaptchaSvg] = useState('');
|
||||||
|
const [userSolution, setUserSolution] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const loadCaptcha = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
setError('');
|
||||||
|
setUserSolution('');
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/v1/teknav-cap/generate', {
|
||||||
|
credentials: 'include',
|
||||||
|
});
|
||||||
|
if (!response.ok) throw new Error('Failed to load captcha');
|
||||||
|
const data = await response.json();
|
||||||
|
setCaptchaId(data.id);
|
||||||
|
setCaptchaSvg(data.data);
|
||||||
|
if (onChange) onChange({ captchaId: data.id, userSolution: '' });
|
||||||
|
} catch (err) {
|
||||||
|
setError('خطا در بارگذاری کپچا');
|
||||||
|
console.error('TeknavCAP load error:', err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadCaptcha();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleInputChange = (e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setUserSolution(value);
|
||||||
|
if (onChange) onChange({ captchaId, userSolution: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ direction: 'rtl', ...style }}>
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 12,
|
||||||
|
marginBottom: 8,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
onClick={loadCaptcha}
|
||||||
|
style={{
|
||||||
|
border: '2px solid #E4DDD2',
|
||||||
|
borderRadius: 8,
|
||||||
|
padding: 8,
|
||||||
|
background: '#fff',
|
||||||
|
cursor: 'pointer',
|
||||||
|
minWidth: 200,
|
||||||
|
minHeight: 80,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
position: 'relative',
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
}}
|
||||||
|
title="برای تازهسازی کلیک کنید"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<div style={{ fontSize: 13, color: '#5F6B6D' }}>در حال بارگذاری...</div>
|
||||||
|
) : error ? (
|
||||||
|
<div style={{ fontSize: 12, color: '#C94C4C' }}>{error}</div>
|
||||||
|
) : (
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: captchaSvg }} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={loadCaptcha}
|
||||||
|
disabled={loading}
|
||||||
|
style={{
|
||||||
|
padding: '10px 16px',
|
||||||
|
background: '#0F6B73',
|
||||||
|
color: '#fff',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: 8,
|
||||||
|
cursor: loading ? 'not-allowed' : 'pointer',
|
||||||
|
fontSize: 13,
|
||||||
|
fontFamily: 'Vazirmatn, sans-serif',
|
||||||
|
fontWeight: 600,
|
||||||
|
opacity: loading ? 0.6 : 1,
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
↻ تازهسازی
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={userSolution}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
placeholder="کد امنیتی را وارد کنید"
|
||||||
|
maxLength={10}
|
||||||
|
autoComplete="off"
|
||||||
|
dir="ltr"
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '10px 14px',
|
||||||
|
border: '1px solid #E4DDD2',
|
||||||
|
borderRadius: 8,
|
||||||
|
fontSize: 14,
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
letterSpacing: '0.1em',
|
||||||
|
textAlign: 'center',
|
||||||
|
background: '#fff',
|
||||||
|
transition: 'border-color 0.2s',
|
||||||
|
}}
|
||||||
|
onFocus={(e) => e.target.style.borderColor = '#0F6B73'}
|
||||||
|
onBlur={(e) => e.target.style.borderColor = '#E4DDD2'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TeknavCAP;
|
||||||
Reference in New Issue
Block a user