DGCchat / quote-calculator.html
John2121's picture
Style: Merge automotive theme with APT pipeline for industry-standard UI/UX
f2be9fe
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hooper Auto - Service Estimate</title>
<link rel="stylesheet" href="../llama-universal-netlify-proxy/style.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tailwindcss@3.3.3/dist/tailwind.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
body {
font-family: 'Inter', Arial, sans-serif;
background: #111827;
color: #f3f4f6;
}
.main-card,
.mobile-section {
background: #1f2937 !important;
border: 4px solid #e11d48 !important;
border-radius: 1.25rem !important;
box-shadow: 0 4px 32px 0 #0004, 0 1.5px 6px 0 #e11d48;
padding: 2rem !important;
}
.form-group .form-toggle {
background: #374151 !important;
color: #fbbf24 !important;
border-radius: 0.5rem !important;
}
.form-group .form-content {
background: #18181b !important;
border-radius: 0.5rem !important;
}
.form-group.open .form-content {
background: #18181b !important;
}
.apt-btn,
.mobile-btn,
.form-content button[type=submit] {
background: #e11d48 !important;
color: #fff !important;
font-weight: 700;
border-radius: 0.5rem !important;
padding: 0.9rem 1.2rem !important;
border: none;
cursor: pointer;
transition: background 0.2s;
font-size: 1.15rem;
box-shadow: 0 2px 8px #e11d4822;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.apt-btn:hover,
.mobile-btn:hover,
.form-content button[type=submit]:hover {
background: #fbbf24 !important;
color: #1f2937 !important;
}
.form-group input,
.form-group select,
.form-group textarea {
background: #23272f !important;
color: #f3f4f6 !important;
border: 1.5px solid #6b7280 !important;
border-radius: 0.5rem !important;
font-size: 1.05rem;
}
.form-group input::placeholder,
.form-group textarea::placeholder {
color: #9ca3af !important;
}
.form-group label {
color: #fbbf24 !important;
font-weight: 600;
}
.form-group {
border-radius: 0.5rem !important;
}
.form-content {
border-radius: 0.5rem !important;
}
.form-group.open .form-content {
border-radius: 0.5rem !important;
}
.text-accent-red {
color: #e11d48 !important;
}
.text-accent-yellow {
color: #fbbf24 !important;
}
.bg-accent-red {
background: #e11d48 !important;
}
.bg-accent-yellow {
background: #fbbf24 !important;
}
.text-automotive-50 {
color: #f3f4f6 !important;
}
.text-automotive-100 {
color: #e5e7eb !important;
}
.text-automotive-200 {
color: #d1d5db !important;
}
.bg-automotive-700 {
background: #111827 !important;
}
.bg-automotive-600 {
background: #1f2937 !important;
}
.border-accent-red {
border-color: #e11d48 !important;
}
.shadow-xl {
box-shadow: 0 4px 32px 0 #0004, 0 1.5px 6px 0 #e11d48 !important;
}
</style>
</head>
<body class="font-body bg-automotive-700 text-automotive-50 min-h-screen flex items-center justify-center py-8">
<!-- Consistent Call/Text Contact Block -->
<div class="w-full flex flex-col items-center mb-6">
<a href="tel:+17154219792" class="text-2xl font-bold text-amber-400 hover:text-amber-300 transition-colors">Call
Hooper Automotive: (715) 421-9792</a>
<span class="text-green-200 text-sm mt-1">2020 4th Street South, Wisconsin Rapids, WI 54494 &bull; Wood
County</span>
</div>
<!-- APT Step-by-Step Automotive Problem Calculator -->
<main class="w-full flex flex-col items-center justify-center min-h-screen bg-gray-900 text-white py-8">
<section class="w-full max-w-lg mobile-section bg-automotive-600/90 p-6 rounded-xl shadow-lg">
<h1 class="text-2xl font-bold text-accent-red mb-4 mobile-title">Hooper Automotive LLC - Problem Calculator
</h1>
<div id="apt-flow">
<!-- Llama AI Chat Integration -->
<div id="llama-chat-container" class="mt-8">
<h2 class="text-xl font-bold text-accent-red mb-2">Llama AI Chat</h2>
<div id="llama-messages"></div>
<div id="llama-input-row">
<input id="llama-user-input" type="text" placeholder="Type your message..." />
<button id="llama-send-btn">Send</button>
</div>
</div>
<!-- Step 1: Select Problem Category -->
<div id="step1" class="mb-4">
<label class="block text-accent-yellow font-semibold mb-2">What area is the problem in?</label>
<div class="grid grid-cols-2 gap-2">
<button class="apt-btn" data-category="Engine">Engine</button>
<button class="apt-btn" data-category="Brakes">Brakes</button>
<button class="apt-btn" data-category="Electrical">Electrical</button>
<button class="apt-btn" data-category="Tires">Tires</button>
<button class="apt-btn" data-category="AC">A/C & Heat</button>
<button class="apt-btn" data-category="Transmission">Transmission</button>
<button class="apt-btn" data-category="Suspension">Suspension</button>
<button class="apt-btn" data-category="Other">Other</button>
</div>
</div>
<!-- Step 2: Select Symptom -->
<div id="step2" class="mb-4 hidden">
<label class="block text-accent-yellow font-semibold mb-2">What best describes the issue?</label>
<div id="symptom-options" class="grid grid-cols-1 gap-2"></div>
</div>
<!-- Step 3: Vehicle Info -->
<div id="step3" class="mb-4 hidden">
<label class="block text-accent-yellow font-semibold mb-1">Vehicle Make/Model/Year</label>
<input type="text" id="vehicle"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-automotive-400 text-automotive-50 mb-2"
placeholder="e.g. 2020 Ford F-150">
<label class="block text-accent-yellow font-semibold mb-1">Mileage</label>
<input type="text" id="mileage"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-automotive-400 text-automotive-50 mb-2"
placeholder="e.g. 42,000">
<button id="step3-next" class="apt-btn w-full mt-2">Next</button>
</div>
<!-- Step 4: Output Recommendation -->
<div id="step4" class="mb-4 hidden">
<form id="apt-form" action="https://formspree.io/f/mjkaolga" method="POST"
class="bg-green-900/80 p-6 rounded-xl shadow-lg space-y-2 mobile-form overflow-visible">
<h1 class="text-2xl font-bold text-green-200 mb-2 mobile-title">Request a Quote</h1>
<p class="text-green-100 mb-2">Get a fast, friendly quote! Tell us about your project and how we
can help you.</p>
<div class="form-group open">
<div class="form-toggle" onclick="toggleGroup(this)">Contact Info <span
class="arrow"></span></div>
<div class="form-content">
<label for="user-name" class="block text-green-100 font-semibold mb-1">Name <span
aria-hidden="true" class="text-red-400">*</span></label>
<input type="text" id="user-name" name="name" required autocomplete="name"
aria-required="true"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="Your Name">
<label for="user-email" class="block text-green-100 font-semibold mb-1">Email <span
aria-hidden="true" class="text-red-400">*</span></label>
<input type="email" id="user-email" name="email" required autocomplete="email"
aria-required="true"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="you@email.com">
<label for="user-phone" class="block text-green-100 font-semibold mb-1">Phone</label>
<input type="tel" id="user-phone" name="phone" autocomplete="tel"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition"
placeholder="(optional)">
</div>
</div>
<div class="form-group">
<div class="form-toggle" onclick="toggleGroup(this)">Service & Price <span
class="arrow"></span></div>
<div class="form-content">
<label for="form-service" class="block text-green-100 font-semibold mb-1">Service
Requested <span aria-hidden="true" class="text-red-400">*</span></label>
<input type="text" id="form-service" name="service" required
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="Service">
<label for="form-price" class="block text-green-100 font-semibold mb-1">Price</label>
<input type="text" id="form-price" name="price"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="Price">
</div>
</div>
<div class="form-group">
<div class="form-toggle" onclick="toggleGroup(this)">Project Details <span
class="arrow"></span></div>
<div class="form-content">
<label for="form-vehicle" class="block text-green-100 font-semibold mb-1">Vehicle
Make/Model/Year</label>
<input type="text" id="form-vehicle" name="vehicle"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="e.g. 2020 Ford F-150">
<label for="form-mileage"
class="block text-green-100 font-semibold mb-1">Mileage</label>
<input type="text" id="form-mileage" name="mileage"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition mb-2"
placeholder="e.g. 42,000">
<label for="form-details" class="block text-green-100 font-semibold mb-1">Problem
Description</label>
<textarea id="form-details" name="details" rows="3"
class="w-full px-4 py-2 rounded-lg bg-white/10 border border-green-700 text-white placeholder-green-200 focus:ring-2 focus:ring-green-400 focus:border-transparent transition"
placeholder="Describe the issue, symptoms, or service needed..."></textarea>
</div>
</div>
<div class="form-group open">
<div class="form-content">
<button type="submit"
class="w-full bg-green-600 hover:bg-green-500 text-white font-bold py-3 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-amber-400 focus:ring-offset-2 mobile-btn">Send
Request</button>
</div>
</div>
<div id="apt-success" class="hidden text-green-200 text-center font-semibold mt-2">Request sent!
Hooper Automotive will contact you soon.<br>Email: <a
href="mailto:hooperautorepair70@gmail.com"
class="underline">hooperautorepair70@gmail.com</a><br>Phone: (715) 421-9792</div>
</form>
</div>
</div>
</section>
</main>
<!-- End APT Calculator -->
<!--
Previous form code commented out for reference
...existing code...
-->
<script>
// --- Llama AI Chat Only ---
(function () {
const messagesDiv = document.getElementById('llama-messages');
const userInput = document.getElementById('llama-user-input');
const sendBtn = document.getElementById('llama-send-btn');
const API_URL = "https://llama-universal-netlify-project.netlify.app/.netlify/functions/llama-proxy?path=/chat/completions";
function appendMessage(text, sender) {
const div = document.createElement('div');
div.className = 'msg ' + sender;
// Support markdown and preserve line breaks for AI output
if (sender === 'ai') {
// If text is markdown, render as HTML (basic)
div.innerHTML = text.replace(/\n/g, '<br>');
} else {
div.textContent = (sender === 'user' ? 'You: ' : 'AI: ') + text;
}
messagesDiv.appendChild(div);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
async function sendMessage() {
const text = userInput.value.trim();
if (!text) return;
appendMessage(text, 'user');
userInput.value = '';
sendBtn.disabled = true;
try {
const body = {
model: "Llama-3.3-8B-Instruct",
messages: [
{ role: 'system', content: "You are a helpful, friendly Hooper Automotive service phone representative. Greet the customer, ask clarifying questions, and provide expert auto advice." },
{ role: 'user', content: text }
]
};
const res = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
let data, aiMsg;
try {
data = await res.json();
} catch (jsonErr) {
appendMessage('Non-JSON response: ' + await res.text(), 'ai');
return;
}
// Industry-standard: handle OpenAI and HF-style, fallback to completion_message.content.text
if (data.choices?.[0]?.message?.content) {
aiMsg = data.choices[0].message.content;
} else if (data.completion_message?.content?.text) {
aiMsg = data.completion_message.content.text;
} else if (data.completion_message?.content) {
aiMsg = data.completion_message.content;
} else if (data.error) {
aiMsg = 'API error: ' + (data.error.message || JSON.stringify(data.error));
} else {
aiMsg = 'Raw response: ' + JSON.stringify(data);
}
appendMessage(aiMsg, 'ai');
} catch (e) {
appendMessage('Error: ' + e.message, 'ai');
} finally {
sendBtn.disabled = false;
}
}
sendBtn.onclick = sendMessage;
userInput.addEventListener('keydown', e => {
if (e.key === 'Enter') sendMessage();
});
})();
// --- APT Step-by-Step Calculator ---
// Variables: x1=category, x2=symptom, r1=service/price, x3=vehicle info, y1=output
// Pipeline: y1 = f(r1(x1, x2), x3)
// Problem categories and symptoms
const aptSymptoms = {
Engine: [
{ sym: "Won't start", svc: "Engine Diagnostics", price: "$100-150" },
{ sym: "Rough idle", svc: "Tune-up", price: "$200-500" },
{ sym: "Check engine light", svc: "Check Engine Light", price: "$100-300" },
{ sym: "Overheating", svc: "Coolant Service", price: "$100-200" },
{ sym: "Oil leak", svc: "Oil Change / Leak Repair", price: "$35-200" }
],
Brakes: [
{ sym: "Squealing noise", svc: "Brake Service", price: "$150-400" },
{ sym: "Soft pedal", svc: "Brake Service", price: "$150-400" },
{ sym: "ABS light", svc: "Brake Diagnostics", price: "$100-200" },
{ sym: "Vibration", svc: "Brake Service", price: "$150-400" }
],
Electrical: [
{ sym: "Battery dead", svc: "Battery Replacement", price: "$120-200" },
{ sym: "Lights not working", svc: "Electrical Diagnosis", price: "$100-200" },
{ sym: "Starter issue", svc: "Electrical Diagnosis", price: "$100-200" }
],
Tires: [
{ sym: "Flat tire", svc: "Tire Service", price: "$80-250 per tire" },
{ sym: "Vibration", svc: "Tire Service", price: "$80-250 per tire" },
{ sym: "TPMS light", svc: "Tire Service", price: "$80-250 per tire" }
],
AC: [
{ sym: "No cold air", svc: "Air Conditioning", price: "$150-400" },
{ sym: "Weak airflow", svc: "Air Conditioning", price: "$150-400" },
{ sym: "Strange smell", svc: "Air Conditioning", price: "$150-400" }
],
Transmission: [
{ sym: "Won't shift", svc: "Transmission Service", price: "$100-300" },
{ sym: "Slipping", svc: "Transmission Service", price: "$100-300" },
{ sym: "Fluid leak", svc: "Transmission Service", price: "$100-300" }
],
Suspension: [
{ sym: "Bouncing ride", svc: "Suspension Repair", price: "$300-1200" },
{ sym: "Clunking noise", svc: "Suspension Repair", price: "$300-1200" },
{ sym: "Steering pull", svc: "Suspension Repair", price: "$300-1200" }
],
Other: [
{ sym: "Other/Not listed", svc: "General Repair", price: "Quote needed" }
]
};
// Step state
let selectedCategory = null;
let selectedSymptom = null;
let selectedService = null;
let selectedPrice = null;
// Step 1: Category
document.querySelectorAll('.apt-btn[data-category]').forEach(btn => {
btn.onclick = function () {
selectedCategory = btn.getAttribute('data-category');
// Show symptoms for this category
const opts = aptSymptoms[selectedCategory] || [];
const so = document.getElementById('symptom-options');
so.innerHTML = '';
opts.forEach((o, i) => {
const b = document.createElement('button');
b.className = 'apt-btn';
b.textContent = o.sym;
b.onclick = function () {
selectedSymptom = o.sym;
selectedService = o.svc;
selectedPrice = o.price;
document.getElementById('step2').classList.add('hidden');
document.getElementById('step3').classList.remove('hidden');
};
so.appendChild(b);
});
document.getElementById('step1').classList.add('hidden');
document.getElementById('step2').classList.remove('hidden');
};
});
// Step 3: Vehicle info
document.getElementById('step3-next').onclick = function (e) {
e.preventDefault();
document.getElementById('step3').classList.add('hidden');
// Output recommendation
document.getElementById('apt-recommend').textContent = `${selectedService} (${selectedSymptom})`;
document.getElementById('apt-price').textContent = selectedPrice;
// Autofill form fields for Formspree
document.getElementById('form-service').value = selectedService || '';
document.getElementById('form-price').value = selectedPrice || '';
document.getElementById('form-vehicle').value = document.getElementById('vehicle')?.value || '';
document.getElementById('form-mileage').value = document.getElementById('mileage')?.value || '';
document.getElementById('step4').classList.remove('hidden');
};
// Collapsible form groups (BuckRub style)
function toggleGroup(el) {
const group = el.parentElement;
group.classList.toggle('open');
}
// Show success message after submit
const aptForm = document.getElementById('apt-form');
if (aptForm) {
aptForm.addEventListener('submit', function (e) {
setTimeout(() => {
document.getElementById('apt-success').classList.remove('hidden');
}, 500);
});
}
// Style for APT buttons
const style = document.createElement('style');
style.textContent = `.apt-btn { background: #e11d48; color: #fff; font-weight: 600; border-radius: 0.5rem; padding: 0.7rem 1rem; border: none; cursor: pointer; transition: background 0.2s; font-size: 1.1rem; } .apt-btn:hover { background: #fbbf24; color: #1f2937; }`;
document.head.appendChild(style);
</script>
</body>
</html>