page.tsx
1 "use client" 2 import Link from "next/link" 3 import { Button } from "@/components/ui/button" 4 import { useEffect, useRef, useState } from "react"; 5 import Image from 'next/image' 6 7 8 9 export default function NewPhoto() { 10 // const videoRef = useRef(null); 11 const videoRef = useRef<HTMLVideoElement>(null); 12 const canvasRef = useRef(null); 13 const [image, setImage] = useState(''); 14 const [loading, setLoading] = useState(false); 15 16 const startVideo = async () => { 17 try { 18 const stream = await navigator.mediaDevices.getUserMedia({ video: true }); 19 if(videoRef.current) { 20 videoRef.current.srcObject = stream; 21 } 22 } catch (err) { 23 console.error('Error accessing the camera', err); 24 } 25 }; 26 27 const stopVideo = () => { 28 if(videoRef.current && videoRef.current.srcObject) { 29 const stream = videoRef.current.srcObject as MediaStream; 30 const tracks = stream.getTracks(); 31 32 tracks.forEach((track) => { 33 track.stop(); 34 }); 35 36 videoRef.current.srcObject = null; 37 } 38 } 39 40 41 const sendImageToAPI = async (imageDataUrl) => { 42 console.log('Sending image to API'); 43 setLoading(true); 44 // const url ="https://whomane-sand.vercel.app/api/facecheck" 45 const url ="/api/facecheck" 46 47 try { 48 const response = await fetch(url, { 49 method: 'POST', 50 headers: { 51 'Content-Type': 'application/json', 52 }, 53 body: JSON.stringify({ imageData: imageDataUrl }), 54 }); 55 const data = await response.json(); 56 console.log(data); 57 if (response.ok) { 58 // window.location.href = '/network'; 59 } else { 60 console.error(data.error); 61 } 62 } catch (error) { 63 console.error('Error:', error); 64 } finally { 65 setLoading(false); 66 } 67 }; 68 69 const takePhoto = () => { 70 if(canvasRef.current && videoRef.current) { 71 const context = (canvasRef.current as HTMLCanvasElement).getContext('2d'); 72 if(context && videoRef.current) { 73 context.drawImage(videoRef.current, 0, 0, (canvasRef.current as HTMLCanvasElement).width, (canvasRef.current as HTMLCanvasElement).height); 74 } 75 const imageDataUrl = (canvasRef.current as HTMLCanvasElement).toDataURL('image/png'); 76 sendImageToAPI(imageDataUrl); 77 // stopVideo(); 78 setImage(imageDataUrl); 79 // window.location.href = '/network'; 80 } 81 82 83 }; 84 85 useEffect(() => { 86 startVideo(); 87 }, []); 88 89 return ( 90 <div className="flex flex-col min-h-screen mt-16"> 91 <main className="flex-1"> 92 <div className="container py-6.5 grid gap-6 px-4 md:grid-cols-2 md:gap-8 lg:px-6 lg:py-8.5"> 93 <div className="flex flex-col justify-center space-y-4"> 94 <div className="space-y-2"> 95 <h1 className="text-3xl font-bold">Whomane Demo</h1> 96 <p className="text-gray-500 dark:text-gray-400">Take a photo of yourself to see what we know about you.</p> 97 </div> 98 <form> 99 <Button onClick={takePhoto}>Take photo</Button> 100 </form> 101 </div> 102 <div className="flex items-center justify-center"> 103 <div className="border border-gray-200 w-full max-w-sm rounded-lg dark:border-gray-800"> 104 <div className="aspect-[1/1] overflow-hidden rounded-lg"> 105 {loading ? ( 106 <p>Loading...</p> 107 ) : ( 108 <> 109 <video ref={videoRef} autoPlay style={{ display: image ? 'none' : 'flex', width: '100%', height: '100%', objectFit: 'cover', transform: 'rotateY(180deg)' }}></video> 110 <canvas ref={canvasRef} style={{ display: 'none' }} width="640" height="480"></canvas> 111 {image && ( 112 <Image 113 src={image} 114 alt="Captured" 115 width={640} 116 height={480} 117 style={{ transform: 'rotateY(180deg)' }} 118 loader={({ src }) => src} 119 unoptimized // since you're handling optimization 120 /> 121 )} 122 </> 123 )} 124 </div> 125 </div> 126 </div> 127 </div> 128 <div className="mt-64 flex justify-center"> 129 <Button className="bg-blue-500 text-white" onClick={()=>{window.location.href="/network"}}>View other scans</Button> 130 </div> 131 </main> 132 <footer className="border-t"> 133 <div className="container flex justify-between items-center h-14 px-4 md:px-6"> 134 <div className="text-sm text-gray-500 dark:text-gray-400">© 2024 Whomane</div> 135 <nav className="flex gap-4 text-sm"> 136 <Link className="text-gray-500 dark:text-gray-400" href="#"> 137 Terms 138 </Link> 139 <Link className="text-gray-500 dark:text-gray-400" href="#"> 140 Privacy 141 </Link> 142 </nav> 143 </div> 144 </footer> 145 </div> 146 ) 147 } 148 149 function HomeIcon(props) { 150 return ( 151 <svg 152 {...props} 153 xmlns="http://www.w3.org/2000/svg" 154 width="24" 155 height="24" 156 viewBox="0 0 24 24" 157 fill="none" 158 stroke="currentColor" 159 strokeWidth="2" 160 strokeLinecap="round" 161 strokeLinejoin="round" 162 > 163 <path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" /> 164 <polyline points="9 22 9 12 15 12 15 22" /> 165 </svg> 166 ) 167 } 168 169 170 function UserIcon(props) { 171 return ( 172 <svg 173 {...props} 174 xmlns="http://www.w3.org/2000/svg" 175 width="24" 176 height="24" 177 viewBox="0 0 24 24" 178 fill="none" 179 stroke="currentColor" 180 strokeWidth="2" 181 strokeLinecap="round" 182 strokeLinejoin="round" 183 > 184 <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /> 185 <circle cx="12" cy="7" r="4" /> 186 </svg> 187 ) 188 }