|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Verification | Rainbow Rendezvous</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://unpkg.com/feather-icons"></script> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); |
|
|
body { |
|
|
font-family: 'Poppins', sans-serif; |
|
|
background-color: #000000; |
|
|
color: #FFFFFF; |
|
|
} |
|
|
.verification-container { |
|
|
background: linear-gradient(180deg, #0A0A0A 0%, #000000 100%); |
|
|
} |
|
|
.verification-circle { |
|
|
border: 3px dashed #F4C430; |
|
|
background-color: rgba(244, 196, 48, 0.05); |
|
|
} |
|
|
.verification-btn { |
|
|
background-color: #F4C430; |
|
|
color: #000000; |
|
|
box-shadow: 0 4px 15px rgba(244, 196, 48, 0.4); |
|
|
} |
|
|
.verification-btn:hover { |
|
|
background-color: #F4C430; |
|
|
transform: translateY(-2px); |
|
|
} |
|
|
.silhouette-overlay { |
|
|
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M50 15c-10 0-15 5-15 15 0 5 5 10 5 15 0 5-5 10-5 15 0 10 10 25 15 25s15-15 15-25c0-5-5-10-5-15 0-5 5-10 5-15 0-10-5-15-15-15z" fill="none" stroke="%23F4C430" stroke-width="0.5"/></svg>'); |
|
|
background-size: 60%; |
|
|
background-position: center; |
|
|
background-repeat: no-repeat; |
|
|
opacity: 0.5; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="min-h-screen verification-container"> |
|
|
<div class="max-w-md mx-auto min-h-screen flex flex-col px-6 py-12"> |
|
|
<header class="mb-8"> |
|
|
<div class="flex justify-center mb-6"> |
|
|
<div class="w-16 h-16 bg-yellow-500 rounded-full flex items-center justify-center"> |
|
|
<i data-feather="shield" class="text-black w-8 h-8"></i> |
|
|
</div> |
|
|
</div> |
|
|
<h1 class="text-2xl font-bold text-center text-yellow-500 mb-2">Photo Verification</h1> |
|
|
<p class="text-center text-white/80">Secure your profile and help protect our community</p> |
|
|
</header> |
|
|
|
|
|
<main class="flex-1 flex flex-col"> |
|
|
<div class="relative mb-8"> |
|
|
<div class="verification-circle w-full aspect-square rounded-full mx-auto overflow-hidden relative"> |
|
|
<div class="absolute inset-0 silhouette-overlay"></div> |
|
|
<video id="cameraFeed" autoplay playsinline class="w-full h-full object-cover"></video> |
|
|
</div> |
|
|
<div class="absolute bottom-4 left-0 right-0 flex justify-center"> |
|
|
<button id="flipCamera" class="bg-black/50 text-white p-2 rounded-full"> |
|
|
<i data-feather="refresh-ccw" class="w-5 h-5"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="text-center mb-8"> |
|
|
<h2 class="font-medium text-white mb-2">Follow these steps:</h2> |
|
|
<div class="flex justify-center space-x-4 mb-4"> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-8 h-8 rounded-full bg-yellow-500 text-black flex items-center justify-center mr-2">1</div> |
|
|
<span class="text-sm">Remove sunglasses</span> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<div class="w-8 h-8 rounded-full bg-yellow-500 text-black flex items-center justify-center mr-2">2</div> |
|
|
<span class="text-sm">Face forward</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<button id="captureBtn" class="verification-btn py-4 px-6 rounded-full font-bold text-lg mb-4 transition-transform"> |
|
|
Take Photo |
|
|
</button> |
|
|
<a href="index.html" class="text-white/60 text-center w-full py-2"> |
|
|
Skip for now |
|
|
</a> |
|
|
</main> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
let currentFacingMode = "user"; |
|
|
let stream = null; |
|
|
|
|
|
async function startCamera(facingMode = "user") { |
|
|
try { |
|
|
if (stream) { |
|
|
stream.getTracks().forEach(track => track.stop()); |
|
|
} |
|
|
|
|
|
stream = await navigator.mediaDevices.getUserMedia({ |
|
|
video: { |
|
|
facingMode: facingMode, |
|
|
width: { ideal: 1280 }, |
|
|
height: { ideal: 1280 } |
|
|
}, |
|
|
audio: false |
|
|
}); |
|
|
|
|
|
const videoElement = document.getElementById('cameraFeed'); |
|
|
videoElement.srcObject = stream; |
|
|
currentFacingMode = facingMode; |
|
|
} catch (err) { |
|
|
console.error("Error accessing camera:", err); |
|
|
alert("Could not access the camera. Please check permissions."); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.getElementById('flipCamera').addEventListener('click', () => { |
|
|
const newFacingMode = currentFacingMode === "user" ? "environment" : "user"; |
|
|
startCamera(newFacingMode); |
|
|
}); |
|
|
|
|
|
document.getElementById('captureBtn').addEventListener('click', async () => { |
|
|
try { |
|
|
const video = document.getElementById('cameraFeed'); |
|
|
const canvas = document.createElement('canvas'); |
|
|
canvas.width = video.videoWidth; |
|
|
canvas.height = video.videoHeight; |
|
|
const ctx = canvas.getContext('2d'); |
|
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height); |
|
|
|
|
|
|
|
|
canvas.toBlob((blob) => { |
|
|
const formData = new FormData(); |
|
|
formData.append('verification_photo', blob, 'verification.jpg'); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
alert("Verification photo submitted successfully!"); |
|
|
window.location.href = "index.html"; |
|
|
}, 1000); |
|
|
}, 'image/jpeg', 0.9); |
|
|
|
|
|
} catch (err) { |
|
|
console.error("Error capturing photo:", err); |
|
|
alert("Couldn't capture photo. Please try again."); |
|
|
} |
|
|
}); |
|
|
|
|
|
window.addEventListener('DOMContentLoaded', async () => { |
|
|
try { |
|
|
await startCamera(); |
|
|
feather.replace(); |
|
|
} catch (err) { |
|
|
console.error("Camera initialization failed:", err); |
|
|
|
|
|
document.getElementById('captureBtn').disabled = true; |
|
|
document.getElementById('captureBtn').textContent = "Camera Access Required"; |
|
|
} |
|
|
}); |
|
|
|
|
|
window.addEventListener('beforeunload', () => { |
|
|
if (stream) { |
|
|
stream.getTracks().forEach(track => track.stop()); |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|