From 05d13b6f166eae5c2de8fe6f6038819b1b6ba1a0 Mon Sep 17 00:00:00 2001
From: polwex <polwex@sortug.com>
Date: Thu, 15 May 2025 15:50:51 +0700
Subject: m

---
 src/components/Main.tsx | 128 ++++++++++++++++++++++--------------------------
 1 file changed, 58 insertions(+), 70 deletions(-)

(limited to 'src/components/Main.tsx')

diff --git a/src/components/Main.tsx b/src/components/Main.tsx
index fc587e2..2157a91 100644
--- a/src/components/Main.tsx
+++ b/src/components/Main.tsx
@@ -24,10 +24,8 @@ const SorlangPage: React.FC = () => {
   const [textValue, setTextValue] = useState<string>("");
   const [pastedImageUrl, setPastedImageUrl] = useState<string | null>(null);
   const [pastedImageFile, setPastedImageFile] = useState<File | null>(null); // Store the file for extraction
+  const [isAnalyzing, setIsAnalyzing] = useState<boolean>(false);
   const [isExtracting, setIsExtracting] = useState<boolean>(false);
-  const [extractedTextResult, setExtractedTextResult] = useState<string | null>(
-    null,
-  );
 
   const textareaRef = useRef<HTMLTextAreaElement>(null);
 
@@ -41,15 +39,13 @@ const SorlangPage: React.FC = () => {
   }, [pastedImageUrl]);
 
   const handlePaste = useCallback(
-    (event: React.ClipboardEvent<HTMLTextAreaElement>) => {
+    (event: ClipboardEvent) => {
       const items = event.clipboardData?.items;
       console.log({ items });
       if (!items) return;
 
       let imageFound = false;
-      for (let i = 0; i < items.length; i++) {
-        const item = items[i];
-        if (!item) return;
+      for (const item of items) {
         if (item.kind === "file" && item.type.startsWith("image/")) {
           event.preventDefault(); // Prevent pasting image data as text
           const file = item.getAsFile();
@@ -60,90 +56,85 @@ const SorlangPage: React.FC = () => {
             const newImageUrl = URL.createObjectURL(file);
             setPastedImageUrl(newImageUrl);
             setPastedImageFile(file);
-            setTextValue(""); // Clear textarea when image is pasted, or decide on desired behavior
-            setExtractedTextResult(null); // Clear previous extraction results
             imageFound = true;
           }
           break; // Handle first image found
         }
       }
 
-      // If no image was found, let the default text paste happen
-      // Or, if you want to explicitly handle text paste:
-      if (!imageFound) {
-        // Let the default textarea paste handle it, or:
-        // event.preventDefault();
-        // const text = event.clipboardData.getData('text/plain');
-        // setTextValue(prev => prev + text); // Or replace, depending on desired behavior
-        // setPastedImageUrl(null); // Clear image if text is pasted
-        // setPastedImageFile(null);
-      }
+      // // If no image was found, let the default text paste happen
+      // // Or, if you want to explicitly handle text paste:
+      // if (!imageFound) {
+      //   // Let the default textarea paste handle it, or:
+      //   // event.preventDefault();
+      //   // const text = event.clipboardData.getData('text/plain');
+      //   // setTextValue(prev => prev + text); // Or replace, depending on desired behavior
+      //   // setPastedImageUrl(null); // Clear image if text is pasted
+      //   // setPastedImageFile(null);
+      // }
     },
     [pastedImageUrl],
   );
+  useEffect(() => {
+    window.addEventListener("paste", handlePaste);
+    return () => {
+      window.removeEventListener("paste", handlePaste);
+    };
+  }, [handlePaste]);
 
-  const handleProcessText = () => {
-    if (!textValue.trim()) {
+  const handleProcessText = async () => {
+    setIsAnalyzing(true);
+    const text = textValue.trim();
+    if (!text) {
       alert("Text area is empty!");
       return;
     }
-    console.log("Processing text:", textValue);
-    // Add your text processing logic here
-    alert(
-      `Text submitted: "${textValue.substring(0, 50)}${textValue.length > 50 ? "..." : ""}"`,
-    );
+    const opts = {
+      method: "POST",
+      headers: { "Content-type": "application/json" },
+      body: JSON.stringify({ text, app: "spacy" }),
+    };
+    const res = await fetch("/api/nlp", opts);
+    const j = await res.json();
+    console.log("j", j);
+    if ("ok" in j) {
+      console.log("good");
+    }
+    setIsAnalyzing(false);
   };
 
-  const [isPending, startTransition] = useTransition();
-  const onClick = () => {
-    startTransition(async () => {
-      const lol = "lmao";
-    });
-  };
+  // const [isPending, startTransition] = useTransition();
   const handleExtractTextFromImage = async () => {
     if (!pastedImageFile) {
       alert("No image to extract text from!");
       return;
     }
     setIsExtracting(true);
-    setExtractedTextResult(null);
+    const formData = new FormData();
+    formData.append("file", pastedImageFile, pastedImageFile.name);
     console.log("Extracting text from image:", pastedImageFile.name);
-
-    // --- SIMULATE OCR API CALL ---
-    // In a real app, you would send `pastedImageFile` to a backend
-    // or use a client-side OCR library like Tesseract.js
-    await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate network delay
-
-    // Example: Simulate successful extraction
-    const mockExtractedText = `This is simulated extracted text from "${pastedImageFile.name}".\nIt could be multiple lines.`;
-
-    // Example: Simulate an error
-    // const mockExtractedText = null;
-    // alert("Failed to extract text (simulated).");
-
-    if (mockExtractedText) {
-      setTextValue(mockExtractedText); // Put extracted text into the textarea
-      setExtractedTextResult(
-        `Successfully extracted text and placed it in the textarea.`,
-      );
-    } else {
-      setExtractedTextResult("Failed to extract text (simulated).");
+    const res = await fetch("/api/formdata/ocr", {
+      method: "POST",
+      body: formData,
+    });
+    const j = await res.json();
+    console.log("ocr res", j);
+    if ("ok" in j) {
+      setTextValue((t) => t + j.ok.join("\n"));
     }
-    // --- END SIMULATION ---
-
     setIsExtracting(false);
-    // Optionally clear the image after attempting extraction
-    // setPastedImageUrl(null);
-    // setPastedImageFile(null);
+    // handleClearImage();
   };
 
+  // setPastedImageUrl(null);
+  // setPastedImageFile(null);
+
   const handleClearImage = () => {
     if (pastedImageUrl) {
       URL.revokeObjectURL(pastedImageUrl);
     }
     setPastedImageUrl(null);
     setPastedImageFile(null);
-    setExtractedTextResult(null);
   };
 
   return (
@@ -159,9 +150,8 @@ const SorlangPage: React.FC = () => {
             ref={textareaRef}
             value={textValue}
             onChange={(e) => setTextValue(e.target.value)}
-            onPaste={handlePaste}
             placeholder="Paste text here, or paste an image..."
-            className="min-h-[200px] text-base"
+            className="min-h-[200px] w-full text-base"
             aria-label="Input text area"
           />
 
@@ -185,14 +175,6 @@ const SorlangPage: React.FC = () => {
               />
             </div>
           )}
-
-          {extractedTextResult && (
-            <p
-              className={`mt-2 text-sm ${extractedTextResult.startsWith("Failed") ? "text-destructive" : "text-green-600"}`}
-            >
-              {extractedTextResult}
-            </p>
-          )}
         </CardContent>
         <CardFooter className="flex flex-col sm:flex-row justify-center gap-4">
           {pastedImageUrl ? (
@@ -212,7 +194,13 @@ const SorlangPage: React.FC = () => {
             </Button>
           ) : (
             <Button onClick={handleProcessText} className="w-full sm:w-auto">
-              Process Text
+              {isAnalyzing ? (
+                <>
+                  <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Analyzing...
+                </>
+              ) : (
+                "Process Text"
+              )}
             </Button>
           )}
         </CardFooter>
-- 
cgit v1.2.3

