This commit is contained in:
101
app.js
101
app.js
@@ -288,6 +288,106 @@ function showSnackbar(message, type = '') {
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Set PDF.js worker
|
||||
if (typeof pdfjsLib !== 'undefined') {
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
|
||||
}
|
||||
|
||||
// Handle PDF import
|
||||
async function setupPdfImport() {
|
||||
const pdfInput = document.getElementById('pdfInput');
|
||||
const importBtn = document.getElementById('importPdfBtn');
|
||||
|
||||
if (!pdfInput || !importBtn) return;
|
||||
|
||||
pdfInput.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
importBtn.classList.add('loading');
|
||||
|
||||
try {
|
||||
const text = await extractTextFromPdf(file);
|
||||
const data = parseRegistrationData(text);
|
||||
fillFormWithData(data);
|
||||
showSnackbar('Data imported successfully!', 'success');
|
||||
} catch (error) {
|
||||
console.error('PDF import failed:', error);
|
||||
showSnackbar('Failed to import PDF', 'error');
|
||||
} finally {
|
||||
importBtn.classList.remove('loading');
|
||||
pdfInput.value = ''; // Reset input
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Extract text from PDF using PDF.js
|
||||
async function extractTextFromPdf(file) {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
|
||||
|
||||
let fullText = '';
|
||||
for (let i = 1; i <= pdf.numPages; i++) {
|
||||
const page = await pdf.getPage(i);
|
||||
const textContent = await page.getTextContent();
|
||||
const pageText = textContent.items.map(item => item.str).join(' ');
|
||||
fullText += pageText + '\n';
|
||||
}
|
||||
|
||||
return fullText;
|
||||
}
|
||||
|
||||
// Parse registration data from extracted text
|
||||
function parseRegistrationData(text) {
|
||||
const data = {};
|
||||
|
||||
// Registry Number
|
||||
const regMatch = text.match(/Registry Number\s*([A-Z0-9]+)/i);
|
||||
if (regMatch) data.regNumber = regMatch[1];
|
||||
|
||||
// Model Number
|
||||
const modelMatch = text.match(/Model Number\s*([A-Z0-9\-\.]+)/i);
|
||||
if (modelMatch) data.modelNumber = modelMatch[1];
|
||||
|
||||
// Chassis Number
|
||||
const chassisMatch = text.match(/Chassis Number\s*([A-Z0-9]+)/i);
|
||||
if (chassisMatch) data.chassisNumber = chassisMatch[1];
|
||||
|
||||
// Engine Number/Motor Serial No
|
||||
const engineMatch = text.match(/Engine Number\/Motor Serial No\s*([A-Z0-9\-]+)/i);
|
||||
if (engineMatch) data.engineSerial = engineMatch[1];
|
||||
|
||||
// Engine/Motor Capacity
|
||||
const capacityMatch = text.match(/Engine\/Motor Capacity\s*(\d+)/i);
|
||||
if (capacityMatch) data.engineCapacity = capacityMatch[1] + '.000';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Fill form with parsed data
|
||||
function fillFormWithData(data) {
|
||||
if (data.regNumber) {
|
||||
regNumberInput.value = data.regNumber;
|
||||
}
|
||||
if (data.modelNumber) {
|
||||
modelNumberInput.value = data.modelNumber;
|
||||
}
|
||||
if (data.chassisNumber) {
|
||||
chassisNumberInput.value = data.chassisNumber;
|
||||
}
|
||||
if (data.engineSerial) {
|
||||
engineSerialInput.value = data.engineSerial;
|
||||
}
|
||||
if (data.engineCapacity) {
|
||||
engineCapacityInput.value = data.engineCapacity;
|
||||
}
|
||||
|
||||
// Update preview
|
||||
if (currentTemplateId) {
|
||||
renderTemplate(currentTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle disclaimer modal
|
||||
function setupDisclaimer() {
|
||||
const modal = document.getElementById('disclaimerModal');
|
||||
@@ -313,5 +413,6 @@ function setupDisclaimer() {
|
||||
// Initialize when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setupDisclaimer();
|
||||
setupPdfImport();
|
||||
init();
|
||||
});
|
||||
|
||||
41
index.html
41
index.html
@@ -61,15 +61,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vehicle Registration -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="regNumber">Vehicle Registration Number</label>
|
||||
<input type="text" id="regNumber" class="form-input"
|
||||
placeholder="X0X0000" required
|
||||
pattern="[A-Za-z0-9]+" maxlength="10">
|
||||
<span class="form-hint">Letters and numbers only</span>
|
||||
</div>
|
||||
|
||||
<!-- Date Range -->
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
@@ -83,6 +74,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="form-divider">
|
||||
<span>Vehicle Details</span>
|
||||
</div>
|
||||
|
||||
<!-- Import from PDF -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Import from Registration PDF</label>
|
||||
<label class="btn btn-outline" id="importPdfBtn">
|
||||
<span class="material-icons">upload_file</span>
|
||||
Import PDF
|
||||
<input type="file" id="pdfInput" accept=".pdf" hidden>
|
||||
</label>
|
||||
<span class="form-hint">Upload vehicle registration PDF to auto-fill</span>
|
||||
</div>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="form-divider">
|
||||
<span>or</span>
|
||||
</div>
|
||||
|
||||
<!-- Vehicle Registration -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="regNumber">Vehicle Registration Number</label>
|
||||
<input type="text" id="regNumber" class="form-input"
|
||||
placeholder="X0X0000" required
|
||||
pattern="[A-Za-z0-9]+" maxlength="10">
|
||||
<span class="form-hint">Letters and numbers only</span>
|
||||
</div>
|
||||
|
||||
<!-- Model Number -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="modelNumber">Model Number</label>
|
||||
@@ -137,6 +158,8 @@
|
||||
<div id="snackbar" class="snackbar"></div>
|
||||
</div>
|
||||
|
||||
<!-- PDF.js for PDF parsing -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
||||
<!-- JsBarcode for barcode generation -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.6/dist/JsBarcode.all.min.js"></script>
|
||||
<!-- jsPDF for PDF generation -->
|
||||
|
||||
37
styles.css
37
styles.css
@@ -342,6 +342,26 @@ body {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* Form Divider */
|
||||
.form-divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: var(--md-sys-color-outline);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.form-divider::before,
|
||||
.form-divider::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
||||
}
|
||||
|
||||
.form-divider span {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
/* Button Styles */
|
||||
.btn {
|
||||
font: var(--md-sys-typescale-label-large);
|
||||
@@ -372,6 +392,23 @@ body {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
color: var(--md-sys-color-primary);
|
||||
border: 2px solid var(--md-sys-color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--md-sys-color-primary);
|
||||
color: var(--md-sys-color-on-primary);
|
||||
}
|
||||
|
||||
.btn-outline.loading {
|
||||
pointer-events: none;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.btn .material-icons {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user