const video = document.getElementById('video'); const previewImg = document.getElementById('preview-img'); const canvas = document.getElementById('canvas'); const cameraStatus = document.getElementById('camera-status'); const studentNumberInput = document.getElementById('student-number'); const inputError = document.getElementById('input-error'); const captureBtn = document.getElementById('capture-btn'); const downloadLink = document.getElementById('download-link'); const OUTPUT_WIDTH = 145; const OUTPUT_HEIGHT = 185; const TARGET_RATIO = OUTPUT_WIDTH / OUTPUT_HEIGHT; let captured = false; async function startCamera() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false }); video.srcObject = stream; cameraStatus.classList.add('hidden'); captureBtn.disabled = false; } catch (err) { cameraStatus.textContent = 'Unable to access camera: ' + err.message; } } function sanitizeFilename(name) { return name.trim().replace(/[^a-z0-9_-]+/gi, '_'); } function showLiveView() { previewImg.classList.add('hidden'); video.classList.remove('hidden'); downloadLink.classList.add('hidden'); captureBtn.textContent = 'Capture Photo'; captured = false; } function showCapturedView() { video.classList.add('hidden'); previewImg.classList.remove('hidden'); captureBtn.textContent = 'Retake Photo'; captured = true; } function capturePhoto() { if (captured) { showLiveView(); return; } const studentNumber = studentNumberInput.value.trim(); if (!studentNumber) { inputError.classList.remove('hidden'); studentNumberInput.focus(); return; } inputError.classList.add('hidden'); const videoWidth = video.videoWidth; const videoHeight = video.videoHeight; const videoRatio = videoWidth / videoHeight; let sx, sy, sw, sh; if (videoRatio > TARGET_RATIO) { sh = videoHeight; sw = sh * TARGET_RATIO; sx = (videoWidth - sw) / 2; sy = 0; } else { sw = videoWidth; sh = sw / TARGET_RATIO; sx = 0; sy = (videoHeight - sh) / 2; } canvas.width = OUTPUT_WIDTH; canvas.height = OUTPUT_HEIGHT; const ctx = canvas.getContext('2d'); ctx.drawImage(video, sx, sy, sw, sh, 0, 0, OUTPUT_WIDTH, OUTPUT_HEIGHT); const dataUrl = canvas.toDataURL('image/png'); const filename = `${sanitizeFilename(studentNumber)}.png`; previewImg.src = dataUrl; downloadLink.href = dataUrl; downloadLink.download = filename; downloadLink.classList.remove('hidden'); showCapturedView(); downloadLink.click(); } captureBtn.addEventListener('click', capturePhoto); studentNumberInput.addEventListener('keydown', (event) => { if (event.key === 'Enter') { event.preventDefault(); capturePhoto(); } }); startCamera();