fix(BUG-004): extract inline JS to app.js for CSP compliance

This commit is contained in:
DocFast Bot 2026-02-14 15:02:02 +00:00
parent 6276d61aa3
commit 2638f6638c
2 changed files with 84 additions and 85 deletions

83
public/app.js Normal file
View file

@ -0,0 +1,83 @@
function openSignup() {
document.getElementById('signupModal').classList.add('active');
document.getElementById('signupForm').style.display = 'block';
document.getElementById('keyResult').style.display = 'none';
document.getElementById('signupEmail').value = '';
document.getElementById('signupError').style.display = 'none';
setTimeout(function() { document.getElementById('signupEmail').focus(); }, 100);
}
function closeSignup() {
document.getElementById('signupModal').classList.remove('active');
}
// Close on overlay click
document.getElementById('signupModal').addEventListener('click', function(e) {
if (e.target === this) closeSignup();
});
// Submit on Enter
document.getElementById('signupEmail').addEventListener('keydown', function(e) {
if (e.key === 'Enter') submitSignup();
});
async function submitSignup() {
var email = document.getElementById('signupEmail').value.trim();
var errEl = document.getElementById('signupError');
var btn = document.getElementById('signupBtn');
if (!email) {
errEl.textContent = 'Please enter your email.';
errEl.style.display = 'block';
return;
}
btn.textContent = 'Creating...';
btn.disabled = true;
try {
var res = await fetch('/v1/signup/free', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email })
});
var data = await res.json();
if (!res.ok) {
errEl.textContent = data.error || 'Something went wrong.';
errEl.style.display = 'block';
btn.textContent = 'Get API Key';
btn.disabled = false;
return;
}
// Show key
document.getElementById('signupForm').style.display = 'none';
document.getElementById('keyResult').style.display = 'block';
document.getElementById('apiKeyDisplay').textContent = data.apiKey;
} catch (err) {
errEl.textContent = 'Network error. Please try again.';
errEl.style.display = 'block';
btn.textContent = 'Get API Key';
btn.disabled = false;
}
}
function copyKey() {
var key = document.getElementById('apiKeyDisplay').textContent;
navigator.clipboard.writeText(key).then(function() {
document.querySelector('.copy-hint').textContent = '✓ Copied!';
setTimeout(function() { document.querySelector('.copy-hint').textContent = 'Click to copy'; }, 2000);
});
}
async function checkout() {
try {
var res = await fetch('/v1/billing/checkout', { method: 'POST' });
var data = await res.json();
if (data.url) window.location.href = data.url;
else alert('Something went wrong. Please try again.');
} catch (err) {
alert('Something went wrong. Please try again.');
}
}

View file

@ -238,90 +238,6 @@ footer { padding: 40px 0; text-align: center; color: var(--muted); font-size: 0.
</div>
</div>
<script>
function openSignup() {
document.getElementById('signupModal').classList.add('active');
document.getElementById('signupForm').style.display = 'block';
document.getElementById('keyResult').style.display = 'none';
document.getElementById('signupEmail').value = '';
document.getElementById('signupError').style.display = 'none';
setTimeout(() => document.getElementById('signupEmail').focus(), 100);
}
function closeSignup() {
document.getElementById('signupModal').classList.remove('active');
}
// Close on overlay click
document.getElementById('signupModal').addEventListener('click', function(e) {
if (e.target === this) closeSignup();
});
// Submit on Enter
document.getElementById('signupEmail').addEventListener('keydown', function(e) {
if (e.key === 'Enter') submitSignup();
});
async function submitSignup() {
const email = document.getElementById('signupEmail').value.trim();
const errEl = document.getElementById('signupError');
const btn = document.getElementById('signupBtn');
if (!email) {
errEl.textContent = 'Please enter your email.';
errEl.style.display = 'block';
return;
}
btn.textContent = 'Creating...';
btn.disabled = true;
try {
const res = await fetch('/v1/signup/free', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
});
const data = await res.json();
if (!res.ok) {
errEl.textContent = data.error || 'Something went wrong.';
errEl.style.display = 'block';
btn.textContent = 'Get API Key';
btn.disabled = false;
return;
}
// Show key
document.getElementById('signupForm').style.display = 'none';
document.getElementById('keyResult').style.display = 'block';
document.getElementById('apiKeyDisplay').textContent = data.apiKey;
} catch (err) {
errEl.textContent = 'Network error. Please try again.';
errEl.style.display = 'block';
btn.textContent = 'Get API Key';
btn.disabled = false;
}
}
function copyKey() {
const key = document.getElementById('apiKeyDisplay').textContent;
navigator.clipboard.writeText(key).then(() => {
document.querySelector('.copy-hint').textContent = '✓ Copied!';
setTimeout(() => document.querySelector('.copy-hint').textContent = 'Click to copy', 2000);
});
}
async function checkout() {
try {
const res = await fetch('/v1/billing/checkout', { method: 'POST' });
const data = await res.json();
if (data.url) window.location.href = data.url;
else alert('Something went wrong. Please try again.');
} catch (err) {
alert('Something went wrong. Please try again.');
}
}
</script>
<script src="/app.js"></script>
</body>
</html>