Spaces:
Runtime error
Runtime error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Flask Camera App</title> | |
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| background-color: #f4f4f4; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 50px auto; | |
| text-align: center; | |
| position: relative; /* Ensure container works with absolute positioning of back button */ | |
| } | |
| h1 { | |
| color: #333; | |
| } | |
| .btn { | |
| background-color: #007bff; | |
| color: white; | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| margin: 10px; | |
| } | |
| .btn:hover { | |
| background-color: #0056b3; | |
| } | |
| #videoElement { | |
| width: 100%; | |
| max-width: 600px; | |
| margin: 20px 0; | |
| } | |
| #cameraSelect { | |
| padding: 5px; | |
| margin: 10px; | |
| } | |
| #capturedImage { | |
| margin-top: 20px; | |
| } | |
| #hfResult { | |
| text-align: left; | |
| background: #fff; | |
| padding: 10px; | |
| border-radius: 5px; | |
| margin-top: 20px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| } | |
| /* Green Back Button styling */ | |
| .back-button { | |
| position: absolute; | |
| top: 35px; | |
| left: 15px; | |
| display: inline-block; | |
| background-color: green; | |
| color: white; | |
| padding: 10px 20px; | |
| text-decoration: none; | |
| font-weight: bold; | |
| border-radius: 4px; | |
| z-index: 10; | |
| } | |
| .back-button:hover { | |
| background-color: darkgreen; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <a href="{{ url_for('menu.menu') }}" class="back-button"><i class="fa fa-arrow-left"></i></a> | |
| <h1>Camera Capture App</h1> | |
| <button id="openCamera" class="btn">Open Camera</button> | |
| <div id="cameraContainer" style="display: none;"> | |
| <select id="cameraSelect"> | |
| <option value="user">Front Camera</option> | |
| <option value="environment">Back Camera</option> | |
| </select> | |
| <video id="videoElement" autoplay playsinline></video> | |
| <button id="captureButton" class="btn">Capture Image</button> | |
| </div> | |
| <canvas id="canvas" style="display: none;"></canvas> | |
| <div id="result"> | |
| <img id="capturedImage" style="display: none; max-width: 100%;"> | |
| <div id="actionButtons" style="display: none; margin-top: 10px;"> | |
| <button id="retakeButton" class="btn">Retake</button> | |
| <button id="uploadButton" class="btn">Upload to Instagram</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| $(document).ready(function() { | |
| const video = document.getElementById('videoElement'); | |
| const canvas = document.getElementById('canvas'); | |
| const capturedImage = document.getElementById('capturedImage'); | |
| const cameraSelect = document.getElementById('cameraSelect'); | |
| const actionButtons = document.getElementById('actionButtons'); | |
| let stream = null; | |
| let currentImageUrl = null; | |
| // Open camera | |
| $('#openCamera').click(function() { | |
| $('#cameraContainer').show(); | |
| actionButtons.style.display = 'none'; | |
| capturedImage.style.display = 'none'; | |
| startCamera(cameraSelect.value); | |
| }); | |
| // Switch camera | |
| cameraSelect.addEventListener('change', function() { | |
| if (stream) { | |
| stopCamera(); | |
| startCamera(this.value); | |
| } | |
| }); | |
| // Capture image | |
| $('#captureButton').click(function() { | |
| canvas.width = video.videoWidth; | |
| canvas.height = video.videoHeight; | |
| canvas.getContext('2d').drawImage(video, 0, 0); | |
| const dataUrl = canvas.toDataURL('image/jpeg'); | |
| // Send to server | |
| $.ajax({ | |
| type: 'POST', | |
| url: '/capture', | |
| data: { image: dataUrl }, | |
| success: function(response) { | |
| if (response.status === 'success') { | |
| capturedImage.src = response.image_url; | |
| capturedImage.style.display = 'block'; | |
| actionButtons.style.display = 'block'; | |
| currentImageUrl = response.image_url; | |
| stopCamera(); | |
| $('#cameraContainer').hide(); | |
| } else { | |
| alert('Error: ' + response.message); | |
| } | |
| }, | |
| error: function() { | |
| alert('Failed to capture image.'); | |
| } | |
| }); | |
| }); | |
| // Retake button | |
| $('#retakeButton').click(function() { | |
| $('#cameraContainer').show(); | |
| actionButtons.style.display = 'none'; | |
| capturedImage.style.display = 'none'; | |
| startCamera(cameraSelect.value); | |
| }); | |
| // Upload to Zapier | |
| $('#uploadButton').click(function() { | |
| if (!currentImageUrl) { | |
| alert('No image to upload.'); | |
| return; | |
| } | |
| $.ajax({ | |
| type: 'POST', | |
| url: '/upload_zapier', | |
| data: { image_url: currentImageUrl }, | |
| success: function(response) { | |
| if (response.status === 'success') { | |
| alert('Image sent to Zapier successfully!'); | |
| actionButtons.style.display = 'none'; | |
| capturedImage.style.display = 'none'; | |
| } else { | |
| alert('Error sending to Zapier: ' + response.message); | |
| } | |
| }, | |
| error: function() { | |
| alert('Failed to send image to Zapier.'); | |
| } | |
| }); | |
| }); | |
| function startCamera(facingMode) { | |
| const constraints = { | |
| video: { facingMode: facingMode } | |
| }; | |
| navigator.mediaDevices.getUserMedia(constraints) | |
| .then(function(mediaStream) { | |
| stream = mediaStream; | |
| video.srcObject = stream; | |
| }) | |
| .catch(function(err) { | |
| alert('Error accessing camera: ' + err.message); | |
| }); | |
| } | |
| function stopCamera() { | |
| if (stream) { | |
| stream.getTracks().forEach(track => track.stop()); | |
| stream = null; | |
| video.srcObject = null; | |
| } | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |