-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApp.js
More file actions
233 lines (207 loc) · 7.73 KB
/
App.js
File metadata and controls
233 lines (207 loc) · 7.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
import React, { useState } from "react";
// Imports the core React library and the 'useState' Hook, which lets you store
// and manage data that changes over time in your component.
import axios from "axios";
// Imports 'axios', a popular JavaScript library used to easily send HTTP requests
// (like the POST request) to the backend server.
import "./App.css";
function App() {
const [mode, setMode] = useState("form"); // "form" | "json"
// State for tracking whether the user is using the multiple-text 'form' input or the raw 'json' input.
const [texts, setTexts] = useState([{ id: 1, value: "" }]); // Dynamic array of statements
// State that holds the array of individual text inputs when in 'form' mode. It starts with one empty box.
const [jsonInput, setJsonInput] = useState("");
// State to store the raw text entered by the user in the 'JSON Input' box.
const [isJsonValid, setIsJsonValid] = useState(true);
// State to track if the text in the 'JSON Input' box is properly formatted JSON.
const [targetLanguage, setTargetLanguage] = useState("hindi");
// State to store the language the user wants to translate the text into (e.g., "hindi").
const [translatedText, setTranslatedText] = useState({});
// State to store the translated result (an object) received back from the backend API.
const [loading, setLoading] = useState(false);
// State to track if a translation request is currently being processed, used to show "Translating..." and disable the button.
// Update value for a specific statement
const handleChange = (id, newValue) => {
setTexts(texts.map(t => (t.id === id ? { ...t, value: newValue } : t)));
};
// Finds a text box by its ID and updates its content (value) in the 'texts' state.
// Add a new statement
const handleAdd = () => {
setTexts([...texts, { id: texts.length + 1, value: "" }]);
};
// Adds a new, empty text box to the list for the user to type in.
// Remove a statement and renumber IDs
const handleRemove = (id) => {
const updated = texts.filter(t => t.id !== id);
const renumbered = updated.map((t, index) => ({ ...t, id: index + 1 }));
setTexts(renumbered);
};
// Removes a text box and then re-assigns simple sequential IDs (1, 2, 3...) to the remaining boxes.
// JSON Mode Function
const handleJsonChange = (e) => {
const value = e.target.value;
setJsonInput(value);
// Stores the raw text from the JSON textarea into the 'jsonInput' state.
try {
// Validates the JSON → sets isJsonValid to false if invalid.
JSON.parse(value);
setIsJsonValid(true);
} catch {
// Ensures React disables the translate button when JSON is malformed.
setIsJsonValid(false);
}
};
// Translate Function
// Triggered when the Translate button is clicked.
const handleTranslate = async () => {
setLoading(true);
// Sets loading state to true to show the user a process is running.
try {
let payloadText = {};
// Initializes an empty object that will hold the text data to be sent to the backend.
if (mode === "form") {
// Convert array to object: key1, key2, ...
texts.forEach((t, index) => {
payloadText[`key${index + 1}`] = t.value;
});
// If in 'form' mode, it converts the array of texts into an object
// where the keys are 'key1', 'key2', etc. (as required by the FastAPI/Pydantic model).
} else {
// Parses JSON mode input if selected.
try {
payloadText = JSON.parse(jsonInput);
} catch (err) {
alert("Invalid JSON format. Please correct it.");
setLoading(false);
return;
}
}
// Sends POST request to FastAPI backend /translate
const response = await axios.post("http://127.0.0.1:8000/translate", {
text: payloadText,
target_language: targetLanguage,
user: {
name: "rohit",
email: "rohit@example.com"
}
});
// Stores the translated text returned from backend in translatedText.
setTranslatedText(response.data.translated_text);
}
// Handles API errors with an alert.
catch (error) {
console.error("Translation error:", error);
alert("Translation failed. Check console for details.");
}
setLoading(false);
// Sets loading state back to false to enable the button again.
};
// UI Rendering (return)
// The return block is what actually draws the elements on the web page:
return (
<div className="App" style={{ padding: "4rem", fontFamily: "Arial" }}>
<h1>FastAPI Translator</h1>
{/* Mode Toggle */}
{/* Displays the two radio buttons to switch between "Form Input" and "JSON Input" modes. */}
<div style={{ marginBottom: "1rem" }}>
<label>
<input
type="radio"
value="form"
checked={mode === "form"}
onChange={() => setMode("form")}
/>
Form Input
</label>
<label>
<input
type="radio"
value="json"
checked={mode === "json"}
onChange={() => setMode("json")}
/>
JSON Input
</label>
</div>
{/* Form Mode */}
{mode === "form" &&
texts.map((t) => (
<div key={t.id} style={{ marginBottom: "1rem" }}>
<label>Text {t.id}:</label>
<textarea
id="txtarea" placeholder = "Enter your text..."
value={t.value}
onChange={(e) => handleChange(t.id, e.target.value)}
rows="5"
cols="60"
/>
{texts.length > 1 && (
<button
type="button"
style={{ marginLeft: "1rem" }}
onClick={() => handleRemove(t.id)}
>
Remove
</button>
)}
</div>
))}
{mode === "form" && (
<button type="button" onClick={handleAdd}>
Add Statement
</button>
)}
{/* JSON Mode */}
{mode === "json" && (
<div style={{ marginBottom: "1rem" }}>
<label>Enter JSON Object:</label>
<textarea
id="txtarea"
className={isJsonValid ? "valid-json" : "invalid-json"}
value={jsonInput}
onChange={handleJsonChange}
rows="10"
cols="60"
placeholder='{"key1":"Hello","key2":"World"}'
/>
{!isJsonValid && (
<p style={{ color: "red" }}>⚠ Invalid JSON format</p>
)}
</div>
)}
{/* Target Language */}
<div style={{ marginTop: "1rem" }}>
<label>Target Language:</label>
<select
id="select"
value={targetLanguage}
onChange={(e) => setTargetLanguage(e.target.value)}
>
<option value="hindi">Hindi</option>
<option value="english">English</option>
<option value="marathi">Marathi</option>
</select>
</div>
{/* Translate Button */}
<button
id="btn"
onClick={handleTranslate}
disabled={loading || (mode === "json" && !isJsonValid)}
>
{loading ? "Translating..." : "Translate"}
</button>
{/* Translated Output */}
{Object.keys(translatedText).length > 0 && (
<div style={{ marginTop: "2rem", textAlign: "left" }}>
<h2>Translated Text:</h2>
{/* ✅ Use JSON.stringify to render nested objects safely */}
<pre style={{ background: "#f4f4f4", padding: "1rem", borderRadius: "8px", whiteSpace: "pre-wrap" }}>
{JSON.stringify(translatedText, null, 2)}
</pre>
</div>
)}
</div>
);
}
export default App;