OCR-annotation / frontend /src /pages /Synthetic.jsx
Sk4467's picture
Upload 108 files
1e83c8a verified
import React, { useState } from "react";
import { apiUrl } from "../services/api";
const modes = [
{ value: "single", label: "Single" },
{ value: "comprehensive", label: "Comprehensive" },
{ value: "ultra-realistic", label: "Ultra Realistic" },
{ value: "huggingface", label: "HuggingFace/CSV Dataset" },
];
export default function Synthetic() {
const [mode, setMode] = useState("single");
const [text, setText] = useState("କବି ସମ୍ରାଟ ଉପେନ୍ଦ୍ର ଭଞ୍ଜ ...");
const [datasetUrl, setDatasetUrl] = useState("");
const [textColumn, setTextColumn] = useState("text");
const [maxSamples, setMaxSamples] = useState("");
const [jobName, setJobName] = useState("");
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [files, setFiles] = useState([]);
const handleGenerate = async () => {
setError(null);
setResult(null);
setLoading(true);
try {
const body = { mode, output_subdir: jobName || undefined };
if (mode === "huggingface") {
body.dataset_url = datasetUrl || undefined;
body.text_column = textColumn || "text";
body.max_samples = maxSamples ? Number(maxSamples) : undefined;
} else {
body.text = text;
}
const res = await fetch(apiUrl("/api/synthetic/generate"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json();
setResult(data);
if (data.files && Array.isArray(data.files)) {
setFiles(data.files);
} else {
setFiles([]);
}
} catch (e) {
setError(e.message || String(e));
} finally {
setLoading(false);
}
};
return (
<div className="max-w-6xl mx-auto p-4">
<h1 className="text-xl font-semibold mb-4">Synthetic Text Generator</h1>
{error && (
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
{error}
</div>
)}
<div className="border rounded p-4 mb-4 bg-white">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1">Mode</label>
<select
className="w-full border p-2 rounded"
value={mode}
onChange={(e) => setMode(e.target.value)}
>
{modes.map((m) => (
<option key={m.value} value={m.value}>
{m.label}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium mb-1">Job Name (optional)</label>
<input
className="w-full border p-2 rounded"
placeholder="e.g., demo_run_01"
value={jobName}
onChange={(e) => setJobName(e.target.value)}
/>
</div>
{mode !== "huggingface" && (
<div className="md:col-span-2">
<label className="block text-sm font-medium mb-1">Text</label>
<textarea
className="w-full border p-2 rounded h-28"
value={text}
onChange={(e) => setText(e.target.value)}
/>
</div>
)}
{mode === "huggingface" && (
<>
<div className="md:col-span-2">
<label className="block text-sm font-medium mb-1">HuggingFace CSV URL</label>
<input
className="w-full border p-2 rounded"
placeholder="https://huggingface.co/datasets/.../raw/main/data.csv"
value={datasetUrl}
onChange={(e) => setDatasetUrl(e.target.value)}
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">Text Column</label>
<input
className="w-full border p-2 rounded"
value={textColumn}
onChange={(e) => setTextColumn(e.target.value)}
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">Max Samples (optional)</label>
<input
type="number"
className="w-full border p-2 rounded"
value={maxSamples}
onChange={(e) => setMaxSamples(e.target.value)}
/>
</div>
</>
)}
</div>
<div className="mt-4">
<button
onClick={handleGenerate}
disabled={loading}
className={`px-4 py-2 rounded text-white ${loading ? "bg-gray-500" : "bg-blue-700 hover:bg-blue-800"}`}
>
{loading ? "Generating..." : "Generate"}
</button>
</div>
</div>
{result && (
<div className="border rounded p-4 bg-white">
<h2 className="font-semibold mb-2">Result</h2>
{result.output_dir && (
<p className="mb-2">
Output Directory: {" "}
<a href={apiUrl(result.output_dir)} target="_blank" className="text-blue-700 underline" rel="noreferrer">
{apiUrl(result.output_dir)}
</a>
</p>
)}
{result.csv && (
<p className="mb-2">
Dataset CSV: {" "}
<a href={apiUrl(result.csv)} target="_blank" className="text-blue-700 underline" rel="noreferrer">
{apiUrl(result.csv)}
</a>
</p>
)}
{result.images_dir && (
<p>
Images Directory: {" "}
<a href={apiUrl(result.images_dir)} target="_blank" className="text-blue-700 underline" rel="noreferrer">
{apiUrl(result.images_dir)}
</a>
</p>
)}
{files && files.length > 0 && (
<>
<h3 className="font-semibold mt-4 mb-2">Preview</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
{files.slice(0, 24).map((url, idx) => (
<a key={idx} href={apiUrl(url)} target="_blank" rel="noreferrer" className="block">
<img src={apiUrl(url)} alt={`img-${idx}`} className="w-full h-32 object-cover rounded border" />
</a>
))}
</div>
{files.length > 24 && (
<p className="text-sm text-gray-600 mt-2">Showing first 24 of {files.length} images.</p>
)}
</>
)}
</div>
)}
</div>
);
}