alex 12407b74e4 Initial commit - Stage 1 working version
Saving current working state before proceeding to Stage 2.
Includes:
- Backend: Python-based QC validator with shapefile processing
- Frontend: Drag-and-drop file upload interface
- Sample files for testing
- Documentation and revision history

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:43:57 -07:00

153 lines
4.5 KiB
JavaScript

const dropArea = document.getElementById('drop-area')
const fileInput = document.getElementById('fileElem')
// Prevent default drag behaviors
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
})
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
// Highlight drop area on dragover
;['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.add('highlight'), false)
})
;['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, () => dropArea.classList.remove('highlight'), false)
})
// Handle dropped files
dropArea.addEventListener('drop', e => {
const dt = e.dataTransfer
const files = dt.files
handleFiles(files)
})
// Handle selected files from input
fileInput.addEventListener('change', e => {
handleFiles(fileInput.files)
})
function handleFiles(files) {
if (!files || files.length === 0) return
const file = files[0]
if (!file.name.endsWith('.zip')) {
alert('Please upload a ZIP file.')
return
}
uploadFile(file)
}
function uploadFile(file) {
const url = 'http://localhost:8000/upload'
const formData = new FormData()
formData.append('file', file)
dropArea.innerHTML = `<p>Uploading ${file.name}...</p>`
fetch(url, {
method: 'POST',
body: formData
})
.then(async response => {
const contentType = response.headers.get('Content-Type')
// Check if content type includes text/plain (for QC failure report)
if (contentType && contentType.includes('text/plain')) {
// QC Failed - download report
const blob = await response.blob()
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = 'QC_report.txt'
link.click()
dropArea.innerHTML = `<p>QC failed. Report downloaded.</p>`
} else if (contentType && contentType.includes('application/json')) {
// QC Passed - show success and VerofyMapID input
const data = await response.json()
if (data.message === 'success') {
showVerofyMapIdInput()
} else {
dropArea.innerHTML = `<p>Unexpected response from server.</p>`
}
} else {
// Unknown response type, try to handle as text
const text = await response.text()
dropArea.innerHTML = `<p>Unexpected response: ${text.substring(0, 100)}</p>`
}
})
.catch((error) => {
console.error('Upload error:', error)
dropArea.innerHTML = `<p>Upload failed. Check console.</p>`
})
}
function showVerofyMapIdInput() {
dropArea.innerHTML = `
<div style="padding: 20px;">
<p style="color: green; font-weight: bold; margin-bottom: 15px;">
Your files have passed QC!
</p>
<p style="margin-bottom: 10px;">Please provide VerofyMapID:</p>
<input type="number" id="verofyMapId" placeholder="Enter Map ID"
style="padding: 8px; width: 200px; margin-bottom: 10px; border: 1px solid #ccc; border-radius: 4px;" />
<br/>
<button onclick="submitMapId()"
style="padding: 10px 20px; background: #007BFF; color: white; border: none; border-radius: 5px; cursor: pointer;">
Submit
</button>
</div>
`
}
function submitMapId() {
const mapIdInput = document.getElementById('verofyMapId')
const mapId = mapIdInput.value
if (!mapId || mapId.trim() === '') {
alert('Please enter a VerofyMapID')
return
}
// Update the drop area to show success message
dropArea.innerHTML = `
<p style="color: green; font-weight: bold;">
Success! VerofyMapID ${mapId} received.
</p>
`
// Create overlay with celebration image
const overlay = document.createElement('div')
overlay.id = 'celebrationOverlay'
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
cursor: pointer;
`
overlay.innerHTML = `
<img src="celebrate.png" alt="Celebration"
style="max-width: 80%; max-height: 80%; object-fit: contain;" />
`
// Remove overlay on click
overlay.addEventListener('click', () => {
overlay.remove()
})
document.body.appendChild(overlay)
}