All checks were successful
Docker Build and Push / build-and-push (push) Successful in 11s
161 lines
4.5 KiB
JavaScript
161 lines
4.5 KiB
JavaScript
import { useState } from 'react';
|
||
import { Camera, RefreshCw, Languages, Loader2 } from 'lucide-react';
|
||
import { resizeImage } from './utils/imageUtils';
|
||
import { analyzeImage, translateText } from './services/api';
|
||
|
||
function App() {
|
||
const [image, setImage] = useState(null); // { base64, previewUser }
|
||
const [status, setStatus] = useState('idle'); // idle, analyzing, success, translating, translated, error
|
||
const [description, setDescription] = useState('');
|
||
const [translation, setTranslation] = useState('');
|
||
const [error, setError] = useState('');
|
||
|
||
const handleFileChange = async (e) => {
|
||
if (e.target.files && e.target.files[0]) {
|
||
try {
|
||
const file = e.target.files[0];
|
||
const resized = await resizeImage(file);
|
||
setImage(resized);
|
||
setStatus('ready');
|
||
setError('');
|
||
setDescription('');
|
||
setTranslation('');
|
||
} catch (err) {
|
||
console.error(err);
|
||
setError("Görsel işlenirken bir hata oluştu.");
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleAnalyze = async () => {
|
||
if (!image) return;
|
||
|
||
setStatus('analyzing');
|
||
setError('');
|
||
|
||
try {
|
||
const result = await analyzeImage(image.base64);
|
||
setDescription(result);
|
||
setStatus('success');
|
||
} catch (err) {
|
||
setError("Analiz sırasında hata oluştu: " + err.message);
|
||
setStatus('error');
|
||
}
|
||
};
|
||
|
||
const handleTranslate = async () => {
|
||
if (!description) return;
|
||
|
||
setStatus('translating');
|
||
|
||
try {
|
||
const result = await translateText(description);
|
||
setTranslation(result);
|
||
setStatus('translated');
|
||
} catch (err) {
|
||
setError("Çeviri sırasında hata oluştu: " + err.message);
|
||
// Keep status as success to show description still
|
||
setStatus('success');
|
||
}
|
||
};
|
||
|
||
const handleReset = () => {
|
||
setImage(null);
|
||
setStatus('idle');
|
||
setDescription('');
|
||
setTranslation('');
|
||
setError('');
|
||
};
|
||
|
||
return (
|
||
<div className="container">
|
||
<h1>Bu resimde ne var?</h1>
|
||
|
||
<div className="upload-section" onClick={() => document.getElementById('fileInput').click()}>
|
||
<input
|
||
type="file"
|
||
id="fileInput"
|
||
hidden
|
||
accept="image/*"
|
||
onChange={handleFileChange}
|
||
/>
|
||
{image ? (
|
||
<p>{image.previewUser ? "Görsel Seçildi" : "Görsel Yükleniyor..."}</p>
|
||
) : (
|
||
<p style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px' }}>
|
||
<Camera className="icon" /> 📷 Görseli seçmek için buraya tıklayın
|
||
</p>
|
||
)}
|
||
</div>
|
||
|
||
{image && (
|
||
<img
|
||
src={image.previewUser}
|
||
alt="Preview"
|
||
className="preview-image"
|
||
/>
|
||
)}
|
||
|
||
{error && (
|
||
<div style={{ color: '#ff6b6b', marginTop: '10px', textAlign: 'center' }}>
|
||
{error}
|
||
</div>
|
||
)}
|
||
|
||
<button
|
||
onClick={handleAnalyze}
|
||
disabled={!image || status === 'analyzing' || status === 'translating' || (status !== 'ready' && status !== 'error')}
|
||
style={{ display: (status === 'idle' || status === 'ready' || status === 'analyzing' || status === 'error') ? 'flex' : 'none' }}
|
||
>
|
||
{status === 'analyzing' ? (
|
||
<>
|
||
<Loader2 className="loader" /> Düşünüyor...
|
||
</>
|
||
) : (
|
||
"Analiz Et"
|
||
)}
|
||
</button>
|
||
|
||
{(status === 'success' || status === 'translating' || status === 'translated') && (
|
||
<div className="result-box">
|
||
<span className="label">English Description</span>
|
||
<div>{description}</div>
|
||
|
||
{status !== 'translated' && (
|
||
<button
|
||
className="translate-btn"
|
||
onClick={handleTranslate}
|
||
disabled={status === 'translating'}
|
||
>
|
||
{status === 'translating' ? (
|
||
<>
|
||
<Loader2 className="loader" /> Çevriliyor...
|
||
</>
|
||
) : (
|
||
<>
|
||
<Languages className="icon" /> Türkçeye Çevir
|
||
</>
|
||
)}
|
||
</button>
|
||
)}
|
||
</div>
|
||
)}
|
||
|
||
{(status === 'translated' || translation) && (
|
||
<div className="result-box translation">
|
||
<span className="label">Türkçe Çeviri</span>
|
||
<div>{translation}</div>
|
||
</div>
|
||
)}
|
||
|
||
{status !== 'idle' && (
|
||
<button className="reset-btn" onClick={handleReset}>
|
||
<RefreshCw className="icon" /> Yeni Analiz Başlat
|
||
</button>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default App;
|