GopalKrushnaMahapatra commited on
Commit
fd3f4a7
·
verified ·
1 Parent(s): 430a407

Update grammar.html

Browse files
Files changed (1) hide show
  1. grammar.html +259 -85
grammar.html CHANGED
@@ -5,7 +5,7 @@
5
  <title>Grammar Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
- <!-- jsPDF (kept for backward compatibility but server PDF will be used) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-indigo-950 text-white min-h-screen flex flex-col">
@@ -177,7 +177,180 @@
177
  </div>
178
 
179
  <!-- ========= Info sections from file 1 ========= -->
180
- <!-- ... content unchanged ... -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  </main>
182
 
183
  <!-- Footer -->
@@ -196,7 +369,7 @@
196
  window.location.href = "login.html";
197
  }
198
 
199
- // jsPDF helper (kept but server PDF used for final)
200
  function getJsPDF() {
201
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
202
  if (window.jsPDF) return window.jsPDF;
@@ -261,7 +434,7 @@
261
  }
262
  }
263
 
264
- // Word counting & 1000-word indicator
265
  function countWords(text) {
266
  if (!text || !text.trim()) return 0;
267
  return text.trim().split(/\s+/).length;
@@ -279,7 +452,7 @@
279
 
280
  textarea.addEventListener("input", updateWordCount);
281
 
282
- // Simple local heuristic rules
283
  function applyLocalGrammarRules(rawText) {
284
  let corrections = 0;
285
  let text = rawText || "";
@@ -304,7 +477,7 @@
304
  return { corrected: text, corrections };
305
  }
306
 
307
- // Drag & drop
308
  ["dragenter", "dragover"].forEach(evt => {
309
  dropZone.addEventListener(evt, e => {
310
  e.preventDefault();
@@ -376,7 +549,7 @@
376
  }
377
  };
378
 
379
- // API calls
380
  async function callGrammarText(text) {
381
  const res = await fetch(`${BACKEND_URL}/api/grammar-check`, {
382
  method: "POST",
@@ -404,7 +577,7 @@
404
  return data;
405
  }
406
 
407
- // Main check
408
  checkBtn.onclick = async () => {
409
  const text = textarea.value.trim();
410
  const file = fileInput.files[0];
@@ -466,7 +639,7 @@
466
  statusTiny.textContent = "Done";
467
  } catch (err) {
468
  console.error(err);
469
- // Fallback to local heuristic result
470
  const words = localWords;
471
  const corrections = localRes.corrections;
472
  const corrected = localRes.corrected;
@@ -499,80 +672,56 @@
499
  }
500
  };
501
 
502
- // Helper to download blob
503
- function downloadBlob(blob, filename) {
504
- const url = URL.createObjectURL(blob);
505
- const a = document.createElement("a");
506
- a.href = url;
507
- a.download = filename || "report.pdf";
508
- document.body.appendChild(a);
509
- a.click();
510
- a.remove();
511
- setTimeout(() => URL.revokeObjectURL(url), 30000);
512
- }
513
-
514
- // Generic fetch PDF routine
515
- async function fetchReportPdf({ endpointGet, endpointFile, text, file, defaultFilename }) {
516
- if (file) {
517
- const form = new FormData();
518
- form.append("file", file, file.name);
519
- const res = await fetch(`${BACKEND_URL}${endpointFile}`, {
520
- method: "POST",
521
- headers: { "Authorization": `Bearer ${token}` },
522
- body: form
523
- });
524
- if (!res.ok) {
525
- const txt = await res.text();
526
- throw new Error(txt || `Server responded ${res.status}`);
527
- }
528
- const blob = await res.blob();
529
- const cd = res.headers.get("content-disposition") || "";
530
- const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
531
- const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
532
- downloadBlob(blob, fname);
533
- return;
534
- } else {
535
- const q = encodeURIComponent(text || "");
536
- const url = `${BACKEND_URL}${endpointGet}?text=${q}`;
537
- const res = await fetch(url, {
538
- method: "GET",
539
- headers: { "Authorization": `Bearer ${token}` }
540
- });
541
- if (!res.ok) {
542
- const txt = await res.text();
543
- throw new Error(txt || `Server responded ${res.status}`);
544
- }
545
- const blob = await res.blob();
546
- const cd = res.headers.get("content-disposition") || "";
547
- const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
548
- const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
549
- downloadBlob(blob, fname);
550
- }
551
- }
552
-
553
- // PDF download: call backend report endpoints (server-generated PDF)
554
- downloadBtn.onclick = async () => {
555
  if (!lastResult) {
556
  alert("Run at least one grammar check before downloading a report.");
557
  return;
558
  }
559
 
560
- try {
561
- setLoading(true);
562
- const file = fileInput.files[0] && !(fileInput.files[0].type === "text/plain" || fileInput.files[0].name.toLowerCase().endsWith(".txt")) ? fileInput.files[0] : null;
563
- await fetchReportPdf({
564
- endpointGet: "/report/grammar",
565
- endpointFile: "/report/grammar-file",
566
- text: textarea.value,
567
- file,
568
- defaultFilename: "TrueWrite_GrammarReport.pdf"
569
- });
570
- } catch (err) {
571
- console.error(err);
572
- alert("Failed to download report: " + (err.message || err));
573
- } finally {
574
- setLoading(false);
 
 
 
 
 
 
 
 
575
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576
  };
577
 
578
  function escapeHtml(str) {
@@ -582,13 +731,38 @@
582
  }[s]));
583
  }
584
 
585
- // Reviews slider (unchanged)
586
  const reviews = [
587
- { name: "Aarav S.", role: "Final-year B.Tech student", text: "I use this grammar page before every assignment submission. It quickly cleans up the most obvious mistakes.", stars: 5 },
588
- { name: "Priya K.", role: "M.Tech researcher", text: "The corrected text + PDF report help me keep a record of changes when I work on my thesis chapters.", stars: 5 },
589
- { name: "Rahul M.", role: "Content creator", text: "Simple, fast, no distractions. Perfect when I just want to sanity-check captions and short posts.", stars: 4 },
590
- { name: "Sneha R.", role: "English learner", text: "Seeing how my sentences are automatically fixed is helping me understand grammar rules better.", stars: 5 },
591
- { name: "Vikram J.", role: "Developer", text: "Nice example of a purely front-end grammar tool. The UI feels inspired by popular tools like QuillBot.", stars: 4 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
592
  ];
593
 
594
  let currentReview = 0;
@@ -636,7 +810,7 @@
636
  document.getElementById("prevReview").addEventListener("click", () => {
637
  clearInterval(reviewTimer);
638
  prevReview();
639
- reviewTimer = setInterval(prevReview, 6000);
640
  });
641
 
642
  let reviewTimer = setInterval(nextReview, 6000);
@@ -646,4 +820,4 @@
646
  updateWordCount();
647
  </script>
648
  </body>
649
- </html>
 
5
  <title>Grammar Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <!-- jsPDF (no integrity, to avoid SRI issues locally) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-indigo-950 text-white min-h-screen flex flex-col">
 
177
  </div>
178
 
179
  <!-- ========= Info sections from file 1 ========= -->
180
+
181
+ <section class="mt-10 space-y-4">
182
+ <h2 class="text-xl md:text-2xl font-semibold">Why choose this tool?</h2>
183
+ <p class="text-sm text-slate-300">
184
+ Inspired by tools like QuillBot, this page gives you a simple, focused space to check
185
+ short pieces of writing quickly before you submit or share them.
186
+ </p>
187
+
188
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
189
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
190
+ <div class="flex items-center gap-3 mb-2">
191
+ <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
192
+ <span class="text-lg">⚡</span>
193
+ </div>
194
+ <p class="font-semibold text-sm">Fast one-click review</p>
195
+ </div>
196
+ <p class="text-xs text-slate-300">
197
+ Paste, click, and instantly get a cleaner version of your text without any sign-up
198
+ or complicated options.
199
+ </p>
200
+ </div>
201
+
202
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
203
+ <div class="flex items-center gap-3 mb-2">
204
+ <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
205
+ <span class="text-lg">🎯</span>
206
+ </div>
207
+ <p class="font-semibold text-sm">Focus on basics that matter</p>
208
+ </div>
209
+ <p class="text-xs text-slate-300">
210
+ Targets the most common issues students face: extra spaces, lowercase “i”,
211
+ sentence starts, and missing punctuation.
212
+ </p>
213
+ </div>
214
+
215
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
216
+ <div class="flex items-center gap-3 mb-2">
217
+ <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
218
+ <span class="text-lg">📄</span>
219
+ </div>
220
+ <p class="font-semibold text-sm">Instant PDF summaries</p>
221
+ </div>
222
+ <p class="text-xs text-slate-300">
223
+ Export a quick PDF report for your records or to attach with your assignment
224
+ submissions.
225
+ </p>
226
+ </div>
227
+ </div>
228
+ </section>
229
+
230
+ <section class="mt-10 space-y-4">
231
+ <h2 class="text-xl md:text-2xl font-semibold">Who can use this tool?</h2>
232
+ <p class="text-sm text-slate-300">
233
+ This grammar checker is designed as a lightweight helper for anyone who wants a final
234
+ polish before sending or submitting text.
235
+ </p>
236
+
237
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
238
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
239
+ <div class="flex items-center gap-3 mb-2">
240
+ <div class="w-9 h-9 rounded-full bg-sky-500/20 flex items-center justify-center">
241
+ <span class="text-lg">👨‍🎓</span>
242
+ </div>
243
+ <p class="font-semibold text-sm">Students</p>
244
+ </div>
245
+ <p class="text-xs text-slate-300">
246
+ Quickly check lab reports, assignments, mini-projects, and emails to faculty or
247
+ supervisors.
248
+ </p>
249
+ </div>
250
+
251
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
252
+ <div class="flex items-center gap-3 mb-2">
253
+ <div class="w-9 h-9 rounded-full bg-amber-500/20 flex items-center justify-center">
254
+ <span class="text-lg">👩‍🏫</span>
255
+ </div>
256
+ <p class="font-semibold text-sm">Teachers & mentors</p>
257
+ </div>
258
+ <p class="text-xs text-slate-300">
259
+ Use it as a quick demo in class to show students how common grammar issues can be
260
+ auto-detected.
261
+ </p>
262
+ </div>
263
+
264
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
265
+ <div class="flex items-center gap-3 mb-2">
266
+ <div class="w-9 h-9 rounded-full bg-rose-500/20 flex items-center justify-center">
267
+ <span class="text-lg">💼</span>
268
+ </div>
269
+ <p class="font-semibold text-sm">Professionals & creators</p>
270
+ </div>
271
+ <p class="text-xs text-slate-300">
272
+ Clean up short posts, descriptions, and emails before sharing them with clients,
273
+ teams, or on social media.
274
+ </p>
275
+ </div>
276
+ </div>
277
+ </section>
278
+
279
+ <!-- How it works (frontend-focused) from file 1 -->
280
+ <section class="mt-10 space-y-4">
281
+ <h2 class="text-xl md:text-2xl font-semibold">How does this work?</h2>
282
+ <p class="text-sm text-slate-300">
283
+ Behind the scenes, prefers a neural model (GECToR), then falls back to LanguageTool, and finally to a
284
+ lightweight heuristic that do the necessary corrections.
285
+ </p>
286
+
287
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
288
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
289
+ <div class="flex items-center gap-3 mb-2">
290
+ <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
291
+ <span class="text-lg">1️⃣</span>
292
+ </div>
293
+ <p class="font-semibold text-sm">Paste & analyse</p>
294
+ </div>
295
+ <p class="text-xs text-slate-300">
296
+ You paste your text (up to ~1000 words). The tool counts words and prepares it for
297
+ analysis.
298
+ </p>
299
+ </div>
300
+
301
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
302
+ <div class="flex items-center gap-3 mb-2">
303
+ <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
304
+ <span class="text-lg">2️⃣</span>
305
+ </div>
306
+ <p class="font-semibold text-sm">Apply smart rules and models</p>
307
+ </div>
308
+ <p class="text-xs text-slate-300">
309
+ GECToR model rewrites sentences word-by-word, focusing on grammar, agreement, and spelling.
310
+ JavaScript rules can fix double spaces, lowercase “i”, sentence capitalization, and
311
+ end punctuation. Then the text is sent to a neural grammar model on the server for deeper fixes.
312
+ </p>
313
+ </div>
314
+
315
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
316
+ <div class="flex items-center gap-3 mb-2">
317
+ <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
318
+ <span class="text-lg">3️⃣</span>
319
+ </div>
320
+ <p class="font-semibold text-sm">Review & export</p>
321
+ </div>
322
+ <p class="text-xs text-slate-300">
323
+ You compare the original and corrected text, then optionally export a PDF summary
324
+ for future reference.
325
+ </p>
326
+ </div>
327
+ </div>
328
+ </section>
329
+
330
+ <!-- Reviews slider from file 1 -->
331
+ <section class="mt-12">
332
+ <h2 class="text-xl md:text-2xl font-semibold mb-3">What users say about this grammar tool</h2>
333
+ <div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 md:p-6 relative overflow-hidden">
334
+ <div id="reviewCard" class="transition-all duration-500">
335
+ <!-- filled by JS -->
336
+ </div>
337
+
338
+ <div class="flex items-center justify-between mt-4">
339
+ <div id="reviewDots" class="flex gap-1.5"></div>
340
+ <div class="flex gap-2">
341
+ <button id="prevReview"
342
+ class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">
343
+
344
+ </button>
345
+ <button id="nextReview"
346
+ class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">
347
+
348
+ </button>
349
+ </div>
350
+ </div>
351
+ </div>
352
+ </section>
353
+
354
  </main>
355
 
356
  <!-- Footer -->
 
369
  window.location.href = "login.html";
370
  }
371
 
372
+ // jsPDF helper (from file 2)
373
  function getJsPDF() {
374
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
375
  if (window.jsPDF) return window.jsPDF;
 
434
  }
435
  }
436
 
437
+ // Word counting & 1000-word indicator (from file 1)
438
  function countWords(text) {
439
  if (!text || !text.trim()) return 0;
440
  return text.trim().split(/\s+/).length;
 
452
 
453
  textarea.addEventListener("input", updateWordCount);
454
 
455
+ // Simple local heuristic rules (from file 1)
456
  function applyLocalGrammarRules(rawText) {
457
  let corrections = 0;
458
  let text = rawText || "";
 
477
  return { corrected: text, corrections };
478
  }
479
 
480
+ // Drag & drop (from file 2)
481
  ["dragenter", "dragover"].forEach(evt => {
482
  dropZone.addEventListener(evt, e => {
483
  e.preventDefault();
 
549
  }
550
  };
551
 
552
+ // API calls (from file 2)
553
  async function callGrammarText(text) {
554
  const res = await fetch(`${BACKEND_URL}/api/grammar-check`, {
555
  method: "POST",
 
577
  return data;
578
  }
579
 
580
+ // Main check: file 2 logic + file 1 fallback
581
  checkBtn.onclick = async () => {
582
  const text = textarea.value.trim();
583
  const file = fileInput.files[0];
 
639
  statusTiny.textContent = "Done";
640
  } catch (err) {
641
  console.error(err);
642
+ // Fallback to local heuristic result from file 1
643
  const words = localWords;
644
  const corrections = localRes.corrections;
645
  const corrected = localRes.corrected;
 
672
  }
673
  };
674
 
675
+ // PDF download: logic from file 2
676
+ downloadBtn.onclick = () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  if (!lastResult) {
678
  alert("Run at least one grammar check before downloading a report.");
679
  return;
680
  }
681
 
682
+ const jsPDF = getJsPDF();
683
+ if (!jsPDF) return;
684
+
685
+ const doc = new jsPDF({ unit: "pt", format: "a4" });
686
+ let y = 40;
687
+
688
+ doc.setFontSize(16);
689
+ doc.text("TrueWrite Scan — Grammar Report", 40, y); y += 22;
690
+
691
+ doc.setFontSize(11);
692
+ doc.text("Generated: " + new Date().toLocaleString(), 40, y); y += 18;
693
+ doc.text("User: " + (user || "N/A"), 40, y); y += 18;
694
+
695
+ doc.setFontSize(12);
696
+ doc.text(`Words analysed: ${lastResult.words}`, 40, y); y += 16;
697
+ doc.text(`Corrections: ${lastResult.corrections}`, 40, y); y += 20;
698
+
699
+ if (lastResult.summary) {
700
+ doc.text("Summary:", 40, y); y += 16;
701
+ doc.setFontSize(10);
702
+ let lines = doc.splitTextToSize(lastResult.summary, 520);
703
+ doc.text(lines, 40, y);
704
+ y += lines.length * 12 + 10;
705
  }
706
+
707
+ doc.setFontSize(11);
708
+ doc.text("--- Original text (truncated) ---", 40, y); y += 16;
709
+ doc.setFontSize(9);
710
+ const original = lastResult.original || "";
711
+ const originalTrunc = original.length > 2500 ? original.slice(0, 2500) + "\n\n[TRUNCATED]" : original;
712
+ let lines = doc.splitTextToSize(originalTrunc, 520);
713
+ doc.text(lines, 40, y);
714
+ y += lines.length * 10 + 12;
715
+
716
+ doc.setFontSize(11);
717
+ doc.text("--- Corrected text (truncated) ---", 40, y); y += 16;
718
+ doc.setFontSize(9);
719
+ const corrected = lastResult.corrected || "";
720
+ const correctedTrunc = corrected.length > 2500 ? corrected.slice(0, 2500) + "\n\n[TRUNCATED]" : corrected;
721
+ lines = doc.splitTextToSize(correctedTrunc, 520);
722
+ doc.text(lines, 40, y);
723
+
724
+ doc.save("truewrite-grammar-report.pdf");
725
  };
726
 
727
  function escapeHtml(str) {
 
731
  }[s]));
732
  }
733
 
734
+ // ===== Reviews slider (from file 1) =====
735
  const reviews = [
736
+ {
737
+ name: "Aarav S.",
738
+ role: "Final-year B.Tech student",
739
+ text: "I use this grammar page before every assignment submission. It quickly cleans up the most obvious mistakes.",
740
+ stars: 5
741
+ },
742
+ {
743
+ name: "Priya K.",
744
+ role: "M.Tech researcher",
745
+ text: "The corrected text + PDF report help me keep a record of changes when I work on my thesis chapters.",
746
+ stars: 5
747
+ },
748
+ {
749
+ name: "Rahul M.",
750
+ role: "Content creator",
751
+ text: "Simple, fast, no distractions. Perfect when I just want to sanity-check captions and short posts.",
752
+ stars: 4
753
+ },
754
+ {
755
+ name: "Sneha R.",
756
+ role: "English learner",
757
+ text: "Seeing how my sentences are automatically fixed is helping me understand grammar rules better.",
758
+ stars: 5
759
+ },
760
+ {
761
+ name: "Vikram J.",
762
+ role: "Developer",
763
+ text: "Nice example of a purely front-end grammar tool. The UI feels inspired by popular tools like QuillBot.",
764
+ stars: 4
765
+ }
766
  ];
767
 
768
  let currentReview = 0;
 
810
  document.getElementById("prevReview").addEventListener("click", () => {
811
  clearInterval(reviewTimer);
812
  prevReview();
813
+ reviewTimer = setInterval(nextReview, 6000);
814
  });
815
 
816
  let reviewTimer = setInterval(nextReview, 6000);
 
820
  updateWordCount();
821
  </script>
822
  </body>
823
+ </html>