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:
arsam
2026-09-18 23:24:46 +03:30
parent 9a6da5fa31
commit 329cb0de75
+124
View File
@@ -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;