undefined / index.html
theflu's picture
connect the the upload form to feed the document to grok for processing
25a0f48 verified
Raw History Blame Contribute Delete
22.1 kB
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RoofPrint Wizard - Blueprint Analyzer</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
primary: {
500: '#f43f5e',
},
secondary: {
500: '#f97316',
}
}
}
}
}
</script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tesseract.js@4/dist/tesseract.min.js"></script>
<script src="https://unpkg.com/dotenv@16.0.0/dist/dotenv.umd.js"></script>
</head>
<body class="bg-gray-900 min-h-screen text-gray-100">
<!-- Navigation -->
<nav class="bg-gray-800 border-b border-gray-700 px-4 py-3">
<div class="max-w-7xl mx-auto flex justify-between items-center">
<div class="flex items-center space-x-2">
<a href="index.html"><i data-feather="home" class="text-primary-500"></i></a>
<a href="index.html" class="text-xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-primary-500 to-secondary-500">RoofPrint Wizard</a>
</div>
<div class="flex items-center space-x-4">
<a href="projects.html" class="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
<i data-feather="folder"></i>
<span>My Projects</span>
</a>
<button class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2 transition-all">
<i data-feather="upload"></i>
<span>Upload Blueprint</span>
</button>
</div>
</div>
</nav>
<!-- Hero Section -->
<div class="relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-gray-900 to-gray-800 opacity-90"></div>
<div class="max-w-7xl mx-auto px-4 py-20 relative z-10">
<div class="text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-6">Smart Blueprint Processing <br> for <span class="text-transparent bg-clip-text bg-gradient-to-r from-primary-500 to-secondary-500">Roofing Professionals</span></h1>
<p class="text-xl text-gray-300 max-w-3xl mx-auto mb-10">Upload your commercial roof blueprints and get instant material calculations, cost estimates, and project summaries.</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<a href="estimate.html" class="bg-primary-500 hover:bg-primary-600 text-white px-8 py-4 rounded-lg font-semibold text-lg flex items-center justify-center space-x-2 transition-all">
<i data-feather="upload-cloud"></i>
<span>Upload Blueprint</span>
</a>
<a href="#how-it-works" class="bg-gray-700 hover:bg-gray-600 text-white px-8 py-4 rounded-lg font-semibold text-lg flex items-center justify-center space-x-2 transition-all">
<i data-feather="info"></i>
<span>How It Works</span>
</a>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="max-w-7xl mx-auto px-4 py-12">
<div class="mb-12">
<h2 class="text-3xl font-bold mb-6 text-center">Recent Projects</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Project Card 1 -->
<div class="bg-gray-800 rounded-xl overflow-hidden border border-gray-700 hover:border-primary-500 transition-all">
<div class="h-48 bg-gradient-to-br from-gray-700 to-gray-800 flex items-center justify-center">
<i data-feather="file-text" class="w-16 h-16 text-primary-500"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold mb-2">Downtown Office Complex</h3>
<p class="text-gray-400 mb-4">Uploaded: 2 days ago</p>
<div class="flex justify-between items-center">
<span class="bg-gray-700 text-primary-500 px-3 py-1 rounded-full text-sm font-medium">Processed</span>
<a href="estimate.html" class="text-secondary-500 hover:text-secondary-400 flex items-center space-x-1">
<span>View Estimate</span>
<i data-feather="arrow-right" class="w-4 h-4"></i>
</a>
</div>
</div>
</div>
<!-- Project Card 2 -->
<div class="bg-gray-800 rounded-xl overflow-hidden border border-gray-700 hover:border-primary-500 transition-all">
<div class="h-48 bg-gradient-to-br from-gray-700 to-gray-800 flex items-center justify-center">
<i data-feather="file-text" class="w-16 h-16 text-primary-500"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold mb-2">Mall Roof Replacement</h3>
<p class="text-gray-400 mb-4">Uploaded: 1 week ago</p>
<div class="flex justify-between items-center">
<span class="bg-gray-700 text-primary-500 px-3 py-1 rounded-full text-sm font-medium">Processed</span>
<button class="text-secondary-500 hover:text-secondary-400 flex items-center space-x-1">
<span>View Estimate</span>
<i data-feather="arrow-right" class="w-4 h-4"></i>
</button>
</div>
</div>
</div>
<!-- Project Card 3 -->
<div class="bg-gray-800 rounded-xl overflow-hidden border border-gray-700 hover:border-primary-500 transition-all">
<div class="h-48 bg-gradient-to-br from-gray-700 to-gray-800 flex items-center justify-center">
<i data-feather="file-text" class="w-16 h-16 text-primary-500"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold mb-2">Warehouse Repair</h3>
<p class="text-gray-400 mb-4">Uploaded: 3 weeks ago</p>
<div class="flex justify-between items-center">
<span class="bg-gray-700 text-primary-500 px-3 py-1 rounded-full text-sm font-medium">Processed</span>
<button class="text-secondary-500 hover:text-secondary-400 flex items-center space-x-1">
<span>View Estimate</span>
<i data-feather="arrow-right" class="w-4 h-4"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Features Section -->
<div class="py-12">
<h2 class="text-3xl font-bold mb-12 text-center">How It Works</h2>
<div class="grid md:grid-cols-3 gap-8">
<!-- Feature 1 -->
<div class="bg-gray-800 p-6 rounded-xl border border-gray-700 hover:border-primary-500 transition-all">
<div class="w-14 h-14 bg-primary-500 rounded-full flex items-center justify-center mb-4">
<i data-feather="upload" class="w-6 h-6 text-white"></i>
</div>
<h3 class="text-xl font-semibold mb-3">Upload Blueprint</h3>
<p class="text-gray-400">Simply upload your commercial roof blueprint PDF. Our system accepts all standard blueprint formats.</p>
</div>
<!-- Feature 2 -->
<div class="bg-gray-800 p-6 rounded-xl border border-gray-700 hover:border-primary-500 transition-all">
<div class="w-14 h-14 bg-primary-500 rounded-full flex items-center justify-center mb-4">
<i data-feather="search" class="w-6 h-6 text-white"></i>
</div>
<h3 class="text-xl font-semibold mb-3">Automated Analysis</h3>
<p class="text-gray-400">Our system automatically detects scale, measures square footage, and extracts material specifications using advanced OCR.</p>
</div>
<!-- Feature 3 -->
<div class="bg-gray-800 p-6 rounded-xl border border-gray-700 hover:border-primary-500 transition-all">
<div class="w-14 h-14 bg-primary-500 rounded-full flex items-center justify-center mb-4">
<i data-feather="dollar-sign" class="w-6 h-6 text-white"></i>
</div>
<h3 class="text-xl font-semibold mb-3">Instant Estimate</h3>
<p class="text-gray-400">Get a detailed cost breakdown with materials, labor, and equipment. Customize pricing or use our industry averages.</p>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-gray-800 border-t border-gray-700 py-8">
<div class="max-w-7xl mx-auto px-4">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<h2 class="text-xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-primary-500 to-secondary-500">RoofPrint Wizard</h2>
<p class="text-gray-400 mt-2">Smart blueprint processing for roofing professionals</p>
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-400 hover:text-white transition-colors">
<i data-feather="twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white transition-colors">
<i data-feather="linkedin"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white transition-colors">
<i data-feather="mail"></i>
</a>
</div>
</div>
<div class="mt-8 pt-8 border-t border-gray-700 text-center text-gray-500 text-sm">
<p>© 2023 RoofPrint Wizard. All rights reserved.</p>
</div>
</div>
</footer>
<!-- Upload Modal -->
<div id="uploadModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 hidden">
<div class="bg-gray-800 rounded-xl max-w-2xl w-full mx-4 border border-gray-700 overflow-hidden">
<div class="p-6 border-b border-gray-700 flex justify-between items-center">
<h3 class="text-xl font-semibold">Upload Blueprint PDF</h3>
<button id="closeModal" class="text-gray-400 hover:text-white">
<i data-feather="x"></i>
</button>
</div>
<div class="p-6">
<div class="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center mb-6 hover:border-primary-500 transition-colors cursor-pointer" id="dropZone">
<div class="flex flex-col items-center justify-center">
<i data-feather="upload-cloud" class="w-12 h-12 text-primary-500 mb-4"></i>
<h4 class="text-lg font-medium mb-2">Drag & Drop Blueprint PDF</h4>
<p class="text-gray-400 mb-4">or click to browse files</p>
<input type="file" id="fileInput" class="hidden" accept=".pdf">
<button class="bg-primary-500 hover:bg-primary-600 text-white px-6 py-2 rounded-lg transition-all">
Select File
</button>
</div>
</div>
<div class="bg-gray-700 rounded-lg p-4 hidden" id="fileInfo">
<div class="flex items-center space-x-4">
<i data-feather="file-text" class="w-8 h-8 text-secondary-500"></i>
<div class="flex-1">
<h5 class="font-medium" id="fileName">Filename.pdf</h5>
<p class="text-sm text-gray-400" id="fileSize">2.4 MB</p>
</div>
<button id="removeFile" class="text-gray-400 hover:text-red-400">
<i data-feather="trash-2"></i>
</button>
</div>
</div>
<div class="mt-6">
<div class="flex items-center justify-between mb-2">
<label for="projectName" class="block text-sm font-medium text-gray-300">Project Name</label>
</div>
<input type="text" id="projectName" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent" placeholder="e.g. Downtown Office Roof Replacement">
</div>
</div>
<div class="p-6 bg-gray-700 border-t border-gray-600 flex justify-end space-x-3">
<button id="cancelUpload" class="px-4 py-2 rounded-lg border border-gray-500 text-gray-300 hover:bg-gray-600 transition-colors">Cancel</button>
<button id="processUpload" class="px-6 py-2 bg-primary-500 hover:bg-primary-600 text-white rounded-lg transition-colors flex items-center space-x-2 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
<span>Process Blueprint</span>
<i data-feather="arrow-right" class="w-4 h-4"></i>
</button>
</div>
</div>
</div>
<script>
// Load environment variables
require('dotenv').config();
// Modal functionality
document.addEventListener('DOMContentLoaded', function() {
feather.replace();
const uploadModal = document.getElementById('uploadModal');
const closeModal = document.getElementById('closeModal');
const cancelUpload = document.getElementById('cancelUpload');
const uploadButtons = document.querySelectorAll('button:has(i[data-feather="upload"]), button:has(i[data-feather="upload-cloud"])');
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const fileInfo = document.getElementById('fileInfo');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
const removeFile = document.getElementById('removeFile');
const processUpload = document.getElementById('processUpload');
// Open modal when any upload button is clicked
uploadButtons.forEach(button => {
button.addEventListener('click', () => {
uploadModal.classList.remove('hidden');
});
});
// Close modal
function closeUploadModal() {
uploadModal.classList.add('hidden');
}
closeModal.addEventListener('click', closeUploadModal);
cancelUpload.addEventListener('click', closeUploadModal);
// Handle file selection
dropZone.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', handleFileSelect);
// Handle drag and drop
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropZone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropZone.addEventListener(eventName, unhighlight, false);
});
function highlight() {
dropZone.classList.add('border-primary-500');
}
function unhighlight() {
dropZone.classList.remove('border-primary-500');
}
dropZone.addEventListener('drop', handleDrop, false);
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
fileInput.files = files;
handleFileSelect({ target: fileInput });
}
function handleFileSelect(e) {
const files = e.target.files;
if (files.length > 0) {
const file = files[0];
// Check if it's a PDF
if (file.type !== 'application/pdf') {
alert('Please upload a PDF file.');
return;
}
// Display file info
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
fileInfo.classList.remove('hidden');
processUpload.disabled = false;
}
}
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
removeFile.addEventListener('click', () => {
fileInput.value = '';
fileInfo.classList.add('hidden');
processUpload.disabled = true;
});
processUpload.addEventListener('click', async () => {
const file = fileInput.files[0];
const projectName = document.getElementById('projectName').value || 'Untitled Project';
if (!file) return;
processUpload.disabled = true;
processUpload.innerHTML = '<span>Processing...</span>';
try {
const formData = new FormData();
formData.append('blueprint', file);
formData.append('projectName', projectName);
// Connect to Grok API for processing
const grokResponse = await fetch('https://api.groq.com/v1/process-blueprint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.GROQ_API_KEY}`
},
body: JSON.stringify({
file: await file.arrayBuffer(),
projectName: projectName
})
});
if (!grokResponse.ok) {
throw new Error('Grok processing failed');
}
const grokData = await grokResponse.json();
// Save project details to localStorage with Grok results
const projectId = 'project-' + Date.now();
const projectData = {
id: projectId,
name: projectName,
date: new Date().toLocaleDateString(),
file: file.name,
status: 'processed',
area: grokData.area || 0,
cost: grokData.costEstimate || 0,
materials: grokData.materials || [],
notes: grokData.notes || [],
labor: grokData.labor || []
};
// Save to localStorage
let projects = JSON.parse(localStorage.getItem('projects') || '[]');
projects.push(projectData);
localStorage.setItem('projects', JSON.stringify(projects));
// Redirect to estimate page with project ID
window.location.href = `estimate.html?project=${projectId}`;
} catch (error) {
console.error('Processing failed:', error);
alert('Error processing blueprint. Please try again.');
} finally {
processUpload.disabled = false;
processUpload.innerHTML = '<span>Process Blueprint</span><i data-feather="arrow-right" class="w-4 h-4"></i>';
feather.replace();
}
});
});
</script>
</body>
</html>