195 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
"use client";
 | 
						|
import React, { useRef, useState, useEffect } from "react";
 | 
						|
import "./Register.css"; // Import CSS for styling
 | 
						|
import { toast } from "@/hooks/use-toast";
 | 
						|
import { Button } from "../ui/button";
 | 
						|
 | 
						|
const Register: React.FC = () => {
 | 
						|
  const videoRef = useRef<HTMLVideoElement>(null);
 | 
						|
  const canvasRef = useRef<HTMLCanvasElement>(null);
 | 
						|
  const [name, setName] = useState<string>("");
 | 
						|
  const [error, setError] = useState<string>(""); // State for error message
 | 
						|
  const [selectedFile, setSelectedFile] = useState<File | null>(null); // State for uploaded image
 | 
						|
 | 
						|
  // Automatically open the camera when the component mounts
 | 
						|
  useEffect(() => {
 | 
						|
    const openCamera = async () => {
 | 
						|
      try {
 | 
						|
        const stream = await navigator.mediaDevices.getUserMedia({
 | 
						|
          video: true,
 | 
						|
        });
 | 
						|
        if (videoRef.current) {
 | 
						|
          videoRef.current.srcObject = stream;
 | 
						|
        }
 | 
						|
      } catch (err) {
 | 
						|
        console.error("Error accessing the camera", err);
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    openCamera();
 | 
						|
  }, []);
 | 
						|
 | 
						|
  // Capture image from video stream
 | 
						|
  const captureImage = () => {
 | 
						|
    if (!name.trim()) {
 | 
						|
      setError("Name is required"); // Set error message if name is empty
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    const video = videoRef.current;
 | 
						|
    const canvas = canvasRef.current;
 | 
						|
 | 
						|
    if (video && canvas) {
 | 
						|
      const context = canvas.getContext("2d");
 | 
						|
      if (context) {
 | 
						|
        // Draw the current frame from the video on the canvas
 | 
						|
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
 | 
						|
        canvas.toBlob((blob) => {
 | 
						|
          if (blob) {
 | 
						|
            const file = new File([blob], "captured-image.png", {
 | 
						|
              type: "image/png",
 | 
						|
            });
 | 
						|
            callApi(name, file);
 | 
						|
          }
 | 
						|
        }, "image/png");
 | 
						|
      }
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // Handle file upload
 | 
						|
  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
 | 
						|
    const file = event.target.files?.[0] || null;
 | 
						|
    setSelectedFile(file);
 | 
						|
  };
 | 
						|
 | 
						|
  // Submit uploaded file
 | 
						|
  const submitUploadedFile = () => {
 | 
						|
    if (!name.trim()) {
 | 
						|
      setError("Name is required");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!selectedFile) {
 | 
						|
      setError("Please upload an image file.");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    callApi(name, selectedFile);
 | 
						|
  };
 | 
						|
 | 
						|
  // Call API with name and image file
 | 
						|
  const callApi = async (name: string, file: File) => {
 | 
						|
    const formData = new FormData();
 | 
						|
    formData.append("name", name);
 | 
						|
    formData.append("image", file);
 | 
						|
 | 
						|
    try {
 | 
						|
      const startTime = performance.now();
 | 
						|
      const response = await fetch(
 | 
						|
        `${process.env.NEXT_PUBLIC_BASE_URL}/register`,
 | 
						|
        {
 | 
						|
          method: "POST",
 | 
						|
          body: formData,
 | 
						|
        }
 | 
						|
      );
 | 
						|
 | 
						|
      // End measuring time
 | 
						|
      const endTime = performance.now();
 | 
						|
      const totalTime = (endTime - startTime) / 1000; // Convert milliseconds to seconds
 | 
						|
 | 
						|
      if (response.ok) {
 | 
						|
        const data = await response.json();
 | 
						|
        console.log("API call successful", totalTime);
 | 
						|
        toast({
 | 
						|
          title: data.message,
 | 
						|
          description: `Name: ${data?.name} `,
 | 
						|
        });
 | 
						|
        setError("");
 | 
						|
      } else {
 | 
						|
        console.error("API call failed");
 | 
						|
        setError("Failed to register. Please try again.");
 | 
						|
      }
 | 
						|
    } catch (error) {
 | 
						|
      console.error("Error calling API", error);
 | 
						|
      setError("An error occurred. Please try again.");
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  return (
 | 
						|
    <div className="container">
 | 
						|
      <h1 className="title">Face Capture & Upload Form</h1>
 | 
						|
      <form className="form">
 | 
						|
        <div className="form-group">
 | 
						|
          <label htmlFor="name" className="label">
 | 
						|
            Name:
 | 
						|
          </label>
 | 
						|
          <input
 | 
						|
            id="name"
 | 
						|
            type="text"
 | 
						|
            value={name}
 | 
						|
            onChange={(e) => {
 | 
						|
              setName(e.target.value);
 | 
						|
              setError(""); // Clearing error message when user starts typing
 | 
						|
            }}
 | 
						|
            className="input"
 | 
						|
            placeholder="Enter your name"
 | 
						|
            required
 | 
						|
          />
 | 
						|
          {error && !name.trim() && (
 | 
						|
            <p className="error-message">{error}</p> // Displaying error message if name is empty
 | 
						|
          )}
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div className="mb-5">
 | 
						|
          <video
 | 
						|
            ref={videoRef}
 | 
						|
            autoPlay
 | 
						|
            playsInline
 | 
						|
            className="w-full max-w-[500px] rounded-lg shadow-md scale-x-[-1]"
 | 
						|
          />
 | 
						|
          <Button
 | 
						|
            type="button"
 | 
						|
            onClick={captureImage}
 | 
						|
            className="capture-button"
 | 
						|
          >
 | 
						|
            Capture Image
 | 
						|
          </Button>
 | 
						|
        </div>
 | 
						|
        <div>Or</div>
 | 
						|
 | 
						|
        <div className="file-upload-container">
 | 
						|
          <label htmlFor="file-upload" className="label">
 | 
						|
            Upload Image:
 | 
						|
          </label>
 | 
						|
          <input
 | 
						|
            id="file-upload"
 | 
						|
            type="file"
 | 
						|
            accept="image/*"
 | 
						|
            onChange={handleFileUpload}
 | 
						|
            className="file-input"
 | 
						|
          />
 | 
						|
          <button
 | 
						|
            type="button"
 | 
						|
            onClick={submitUploadedFile}
 | 
						|
            // className="upload-button"
 | 
						|
            className="capture-button"
 | 
						|
          >
 | 
						|
            Submit Uploaded Image
 | 
						|
          </button>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <canvas
 | 
						|
          ref={canvasRef}
 | 
						|
          style={{ display: "none" }}
 | 
						|
          width="640"
 | 
						|
          height="480"
 | 
						|
        />
 | 
						|
 | 
						|
        {error && <p className="error-message">{error}</p>}
 | 
						|
      </form>
 | 
						|
    </div>
 | 
						|
  );
 | 
						|
};
 | 
						|
 | 
						|
export default Register;
 |