new-site/site/public/portal/upload-id/index.html

259 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<title>Upload Photo ID | Performance West</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<script>
window.__PW_API = (function() {
var h = window.location.hostname;
if (h === "localhost" || h === "127.0.0.1") return "http://" + h + ":3001";
if (h === "dev.performancewest.net") return "https://api.dev.performancewest.net";
return "https://api.performancewest.net";
})();
</script>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, system-ui, sans-serif; background: #f8fafc; min-height: 100vh; display: flex; flex-direction: column; }
.header { background: #1a2744; padding: 16px 20px; text-align: center; }
.header img { height: 36px; }
.header p { color: #94a3b8; font-size: 12px; margin-top: 4px; }
.main { flex: 1; padding: 20px; max-width: 480px; margin: 0 auto; width: 100%; }
h1 { font-size: 20px; color: #1a2744; margin-bottom: 8px; text-align: center; }
.subtitle { font-size: 14px; color: #64748b; text-align: center; margin-bottom: 20px; }
.security { display: flex; gap: 8px; align-items: flex-start; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; padding: 10px 14px; margin-bottom: 16px; font-size: 11px; color: #1e40af; }
.upload-area { border: 3px dashed #d1d5db; border-radius: 12px; padding: 32px 20px; text-align: center; background: #fff; }
.upload-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; padding: 18px 24px; background: #f97316; color: #fff; border: none; border-radius: 10px; cursor: pointer; font-size: 17px; font-weight: 600; box-shadow: 0 4px 12px rgba(249,115,22,0.3); }
.upload-btn:active { transform: scale(0.98); }
.hint { font-size: 12px; color: #94a3b8; margin-top: 10px; }
.preview { text-align: center; margin: 16px 0; }
.preview img { max-width: 100%; max-height: 300px; border-radius: 8px; border: 2px solid #d1d5db; }
.status { text-align: center; padding: 20px; }
.status.success { background: #f0fdf4; border: 2px solid #86efac; border-radius: 12px; }
.status.error { background: #fef2f2; border: 2px solid #fca5a5; border-radius: 12px; }
.actions { display: flex; gap: 8px; justify-content: center; margin-top: 12px; }
.btn-green { padding: 12px 28px; background: #059669; color: #fff; border: none; border-radius: 8px; font-size: 15px; font-weight: 600; cursor: pointer; }
.btn-outline { padding: 12px 28px; background: #fff; color: #374151; border: 1px solid #d1d5db; border-radius: 8px; font-size: 14px; cursor: pointer; }
.footer { padding: 16px; text-align: center; font-size: 11px; color: #94a3b8; border-top: 1px solid #e2e8f0; }
</style>
</head>
<body>
<div class="header">
<img src="/images/logo.png" alt="Performance West">
<p>Secure ID Upload</p>
</div>
<div class="main">
<h1>📷 Take a Photo of Your ID</h1>
<p class="subtitle">Hold your ID flat and take a clear photo of the front. Make sure all text is readable.</p>
<div class="security">
<span>🔒</span>
<span>Your photo is encrypted and transmitted securely. It is used only to verify your identity for your FMCSA filing and is automatically deleted afterward.</span>
</div>
<div id="upload-section">
<div class="upload-area">
<input type="file" id="id-file" accept="image/*" capture="environment" style="display:none">
<button type="button" id="take-photo-btn" class="upload-btn">
📷 Take Photo of ID
</button>
<p class="hint">Tap the button to open your camera</p>
</div>
</div>
<div id="preview-section" style="display:none">
<div class="preview">
<img id="preview-img" alt="Your ID">
</div>
<div id="quality-info" style="font-size:12px;color:#374151;text-align:center;margin-bottom:12px"></div>
<div class="actions">
<button type="button" id="submit-btn" class="btn-green">✓ Submit ID</button>
<button type="button" id="retake-btn" class="btn-outline">Retake</button>
</div>
</div>
<div id="uploading-section" style="display:none">
<div style="text-align:center;padding:32px">
<div style="font-size:32px;margin-bottom:12px"></div>
<p style="font-size:15px;color:#374151;font-weight:500">Uploading securely...</p>
</div>
</div>
<div id="success-section" style="display:none">
<div class="status success">
<div style="font-size:32px;margin-bottom:8px"></div>
<p style="font-size:16px;font-weight:600;color:#166534">ID Uploaded Successfully</p>
<p style="font-size:13px;color:#374151;margin-top:8px">You can close this page and return to the form on your computer. Your ID has been attached to your order.</p>
</div>
</div>
<div id="error-section" style="display:none">
<div class="status error">
<div style="font-size:32px;margin-bottom:8px"></div>
<p style="font-size:16px;font-weight:600;color:#991b1b">Upload Failed</p>
<p id="error-msg" style="font-size:13px;color:#7f1d1d;margin-top:8px"></p>
<p style="font-size:12px;color:#7f1d1d;margin-top:8px">If the problem continues, you can upload your ID from the intake form on your computer instead.</p>
<div class="actions">
<button type="button" id="retry-btn" class="btn-outline">Try Again</button>
</div>
</div>
</div>
</div>
<div class="footer">
Performance West Inc. &middot; (888) 411-0383 &middot; performancewest.net
</div>
<script>
var API = window.__PW_API;
var params = new URLSearchParams(window.location.search);
var orderNumber = params.get("order") || "";
var token = params.get("token") || "";
var fileInput = document.getElementById("id-file");
var takeBtn = document.getElementById("take-photo-btn");
var previewSection = document.getElementById("preview-section");
var uploadSection = document.getElementById("upload-section");
var uploadingSection = document.getElementById("uploading-section");
var successSection = document.getElementById("success-section");
var errorSection = document.getElementById("error-section");
var previewImg = document.getElementById("preview-img");
var qualityInfo = document.getElementById("quality-info");
var submitBtn = document.getElementById("submit-btn");
var retakeBtn = document.getElementById("retake-btn");
var retryBtn = document.getElementById("retry-btn");
var selectedFile = null;
takeBtn.addEventListener("click", function() { fileInput.click(); });
fileInput.addEventListener("change", function() {
var file = fileInput.files[0];
if (!file) return;
selectedFile = file;
var reader = new FileReader();
reader.onload = function(e) {
previewImg.src = e.target.result;
previewImg.onload = function() {
var w = previewImg.naturalWidth;
var h = previewImg.naturalHeight;
var sizeMB = (file.size / 1024 / 1024).toFixed(1);
var ok = w >= 400 && h >= 250 && file.size >= 50000;
qualityInfo.innerHTML = ok
? '<span style="color:#059669">✓ ' + w + '×' + h + ' pixels, ' + sizeMB + 'MB — looks good</span>'
: '<span style="color:#dc2626">⚠ ' + w + '×' + h + ' pixels, ' + sizeMB + 'MB — image may be too small. Try getting closer to the ID.</span>';
};
};
reader.readAsDataURL(file);
uploadSection.style.display = "none";
previewSection.style.display = "block";
});
retakeBtn.addEventListener("click", function() {
selectedFile = null;
fileInput.value = "";
previewSection.style.display = "none";
uploadSection.style.display = "block";
});
retryBtn.addEventListener("click", function() {
errorSection.style.display = "none";
uploadSection.style.display = "block";
});
submitBtn.addEventListener("click", function() {
if (!selectedFile || !orderNumber) return;
previewSection.style.display = "none";
uploadingSection.style.display = "block";
var uploadToken = params.get("upload_token") || "";
if (!uploadToken) {
document.getElementById("error-msg").textContent = "Missing upload token. Please use the QR code link from the form.";
uploadingSection.style.display = "none";
errorSection.style.display = "block";
return;
}
// Resize image if too large, then send as base64
function resizeAndUpload(file) {
var maxWidth = 2000;
var maxHeight = 1500;
var maxBytes = 2 * 1024 * 1024; // 2MB target
var img = new Image();
img.onload = function() {
var w = img.width;
var h = img.height;
// Only resize if image is larger than limits
if (w > maxWidth || h > maxHeight || file.size > maxBytes) {
var scale = Math.min(maxWidth / w, maxHeight / h, 1);
var canvas = document.createElement("canvas");
canvas.width = Math.round(w * scale);
canvas.height = Math.round(h * scale);
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// Compress as JPEG
var quality = file.size > 5 * 1024 * 1024 ? 0.7 : 0.85;
var dataUrl = canvas.toDataURL("image/jpeg", quality);
sendUpload(dataUrl);
} else {
// Small enough — send as-is
var reader3 = new FileReader();
reader3.onload = function(e) { sendUpload(e.target.result); };
reader3.readAsDataURL(file);
}
};
img.onerror = function() {
// Not an image (PDF?) — send as-is
var reader3 = new FileReader();
reader3.onload = function(e) { sendUpload(e.target.result); };
reader3.readAsDataURL(file);
};
var reader2 = new FileReader();
reader2.onload = function(e) { img.src = e.target.result; };
reader2.readAsDataURL(file);
}
function sendUpload(dataUrl) {
fetch(API + "/api/v1/id-upload/" + uploadToken, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
image_data: dataUrl,
filename: selectedFile.name,
content_type: "image/jpeg",
}),
})
.then(function(r) {
if (!r.ok) return r.json().then(function(d) { throw new Error(d.error || "Upload failed"); });
return r.json();
})
.then(function() {
uploadingSection.style.display = "none";
successSection.style.display = "block";
})
.catch(function(err) {
uploadingSection.style.display = "none";
errorSection.style.display = "block";
document.getElementById("error-msg").textContent = err.message;
});
}
resizeAndUpload(selectedFile);
});
// If no order number, show error
if (!orderNumber) {
uploadSection.innerHTML = '<div class="status error"><p style="font-size:14px;color:#991b1b">Invalid link — no order number found. Please use the link from your email.</p></div>';
}
</script>
</body>
</html>