Files
konesaliturku.fi/tarjouspyynto.html
Jukka Lampikoski 3d0215130f Simplify quote form with expandable details section
Show only name, email and message by default. Detailed fields
(units, connections, VPN, extras) and price calculator open via
"Tarkemmat tiedot & hintalaskuri" button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:49:06 +02:00

510 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Jätä tarjouspyyntö | Konesali Turku</title>
<meta name="description" content="Pyydä tarjous konesalipalveluista. Automaattinen hintalaskuri auttaa arvioimaan kuukausikustannukset.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Header -->
<header class="header" id="header">
<div class="container header-inner">
<a href="/" class="logo">
<svg class="logo-icon" viewBox="0 0 38 38" fill="none">
<rect class="logo-icon-bg" width="38" height="38" rx="10"/>
<rect x="10" y="8" width="18" height="22" rx="2.5" fill="none" stroke="white" stroke-width="1.2" opacity="0.9"/>
<rect x="13" y="11.5" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<rect x="13" y="17" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<rect x="13" y="22.5" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<circle cx="15.5" cy="13.25" r="1" class="logo-icon-led"/>
<circle cx="15.5" cy="18.75" r="1" class="logo-icon-led"/>
<circle cx="15.5" cy="24.25" r="1" class="logo-icon-led"/>
<path d="M15 33a4 4 0 014-4" stroke="white" stroke-width="1.2" stroke-linecap="round" opacity="0.5"/>
<path d="M12.5 35a7 7 0 017-7" stroke="white" stroke-width="1" stroke-linecap="round" opacity="0.3"/>
</svg>
<span class="logo-text">
<span class="logo-text-top">Konesali</span>
<span class="logo-text-bottom">TURKU</span>
</span>
</a>
<nav class="nav" id="nav">
<a href="index.html#palvelut">Palvelut</a>
<a href="index.html#hinnat">Hinnat</a>
<a href="konesali.html">Konesali</a>
<a href="yhteydet.html">Yhteydet</a>
<a href="tarjouspyynto.html" class="nav-cta active">Jätä tarjouspyyntö</a>
</nav>
<button class="nav-toggle" id="nav-toggle" aria-label="Avaa valikko">
<span></span>
<span></span>
<span></span>
</button>
</div>
</header>
<!-- Page Hero -->
<section class="page-hero">
<div class="container">
<h1>Jätä tarjouspyyntö</h1>
<p>Valitse tarvitsemasi palvelut ja näet arviohinnan heti. Lähetä tarjouspyyntö niin otamme yhteyttä vuorokauden sisällä.</p>
</div>
</section>
<!-- Calculator + Form -->
<section class="section">
<div class="container">
<div class="calculator-layout">
<!-- Form side -->
<div class="calculator-form">
<form id="quote-form">
<!-- Yhteystiedot (aina näkyvissä) -->
<div class="form-section-title">Yhteystiedot</div>
<div class="form-group">
<label for="name">Nimi</label>
<input type="text" id="name" name="name">
</div>
<div class="form-group">
<label for="email">Sähköposti *</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group form-group-full">
<label for="message">Viesti</label>
<textarea id="message" name="message" rows="4" placeholder="Kerro tarpeistasi: laitemäärät, tehovaatimukset, aikataulu, erityistoiveet..."></textarea>
</div>
<!-- Koko lomake -nappi -->
<button type="button" class="btn-expand-form" id="btn-expand-form">
<span class="btn-expand-icon">+</span>
Tarkemmat tiedot &amp; hintalaskuri
</button>
<!-- Yksityiskohtainen lomake (piilotettu oletuksena) -->
<div class="form-details" id="form-details" style="display:none;">
<div class="form-group">
<label for="company">Yritys</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="phone">Puhelinnumero</label>
<input type="tel" id="phone" name="phone">
</div>
<!-- Laitepaikat -->
<div class="form-section-title">Laitepaikat</div>
<div class="form-group form-group-full">
<label for="units-1u">1U laitepaikka &mdash; &euro;49/kk</label>
<select id="units-1u" name="units_1u" data-price="49">
<option value="0">Ei tarvetta</option>
<option value="1">1 kpl</option>
<option value="2">2 kpl</option>
<option value="3">3 kpl</option>
<option value="4">4 kpl</option>
<option value="5">5+ kpl</option>
</select>
</div>
<div class="form-group form-group-full">
<label for="units-2u">2U laitepaikka &mdash; &euro;79/kk</label>
<select id="units-2u" name="units_2u" data-price="79">
<option value="0">Ei tarvetta</option>
<option value="1">1 kpl</option>
<option value="2">2 kpl</option>
<option value="3">3 kpl</option>
<option value="4">4 kpl</option>
<option value="5">5+ kpl</option>
</select>
</div>
<div class="form-group form-group-full">
<label for="units-4u">4U laitepaikka &mdash; &euro;139/kk</label>
<select id="units-4u" name="units_4u" data-price="139">
<option value="0">Ei tarvetta</option>
<option value="1">1 kpl</option>
<option value="2">2 kpl</option>
<option value="3">3 kpl</option>
<option value="5">5+ kpl</option>
</select>
</div>
<div class="form-group form-group-full">
<label for="units-rack">Kokokaappi (42U)</label>
<select id="units-rack" name="units_rack" data-price="0">
<option value="0">Ei tarvetta</option>
<option value="1" data-custom>1 kpl (pyydä tarjous)</option>
<option value="2" data-custom>2 kpl (pyydä tarjous)</option>
<option value="3" data-custom>3+ kpl (pyydä tarjous)</option>
</select>
</div>
<!-- Yhteysnopeus -->
<div class="form-section-title">Yhteysnopeus</div>
<div class="form-group form-group-full">
<label for="connection">Haluttu yhteysnopeus</label>
<select id="connection" name="connection" data-type="connection">
<option value="0">1 Gbit/s jaettu (sis. hintaan)</option>
<option value="99">1 Gbit/s dedicated (&euro;99/kk)</option>
<option value="299">10 Gbit/s dedicated (&euro;299/kk)</option>
<option value="custom">100 Gbit/s (räätälöity)</option>
</select>
</div>
<div class="checkbox-group">
<label class="checkbox-label">
<input type="checkbox" name="redundant_port" value="1" data-price="10">
<span>Varmennettu portti (&euro;10/kk)</span>
</label>
</div>
<div class="form-group form-group-full">
<label for="bgp">BGP-reititys</label>
<select id="bgp" name="bgp">
<option value="0">Ei tarvetta</option>
<option value="20">Default-route (&euro;20/kk)</option>
<option value="50">Koko internet (&euro;50/kk)</option>
</select>
</div>
<!-- VPN -->
<div class="form-section-title">Site-to-Site VPN</div>
<div class="form-group form-group-full">
<label for="vpn">VPN toimitilan ja konesalin väliin</label>
<select id="vpn" name="vpn">
<option value="0">Ei tarvetta</option>
<option value="95">1G Site-to-Site (alk. &euro;95/kk)</option>
<option value="129">10G Site-to-Site (alk. &euro;129/kk)</option>
<option value="custom">Dedicated L2/MPLS (räätälöity)</option>
</select>
</div>
<!-- Lisäpalvelut -->
<div class="form-section-title">Lisäpalvelut</div>
<div class="checkbox-group">
<label class="checkbox-label">
<input type="checkbox" name="anycast_dns" value="1" data-price="19">
<span>Anycast DNS (&euro;19/kk)</span>
</label>
<label class="checkbox-label">
<input type="checkbox" name="block_storage" value="1" data-price="29">
<span>Blokkitason storage (alk. &euro;29/kk)</span>
</label>
<label class="checkbox-label">
<input type="checkbox" name="s3_storage" value="1" data-price="19">
<span>S3-levypinta (alk. &euro;19/kk)</span>
</label>
<label class="checkbox-label">
<input type="checkbox" name="remote_hands" value="1" data-price="0">
<span>Remote Hands (tuntiveloitus)</span>
</label>
</div>
</div>
<!-- Captcha -->
<div class="form-section-title">Varmistus</div>
<div class="form-group">
<label for="captcha" id="captcha-label"></label>
<input type="text" id="captcha" name="captcha" required autocomplete="off" inputmode="numeric" placeholder="Vastaus">
<input type="hidden" id="captcha-answer" name="captcha_answer">
</div>
<!-- Honeypot -->
<div style="display:none" aria-hidden="true">
<input type="text" name="website" tabindex="-1" autocomplete="off">
</div>
<button type="submit" class="btn btn-primary btn-submit">Lähetä tarjouspyyntö</button>
<div class="form-status" id="form-status"></div>
</form>
</div>
<!-- Price calculator side (sticky) -->
<div class="calculator-sidebar">
<div class="price-calculator" id="price-calculator">
<h3>Arvioitu kuukausihinta</h3>
<div class="calculator-total">
<span class="calculator-amount" id="calc-total">&euro;0</span>
<span class="calculator-period">/kk</span>
</div>
<p class="calculator-vat">Hinnat alv 0%</p>
<div class="calculator-breakdown" id="calc-breakdown">
<p class="calculator-empty">Valitse palvelut vasemmalta niin näet arviohinnan täällä.</p>
</div>
<div class="calculator-note" id="calc-note" style="display:none;">
<svg viewBox="0 0 20 20" width="16" height="16" fill="currentColor"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/></svg>
<span>Osa valituista palveluista on räätälöitäviä &mdash; lopullinen hinta tarjouksessa.</span>
</div>
</div>
<div class="calculator-contact">
<h4>Tarvitsetko apua?</h4>
<p>Soita tai lähetä sähköpostia, autamme mielellämme.</p>
<a href="mailto:asiakaspalvelu@konesaliturku.fi" class="calculator-email">asiakaspalvelu@konesaliturku.fi</a>
<div class="calculator-address">
<strong>Web1 Oy</strong><br>
Latokarinkatu 3<br>
20200 Turku
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container footer-inner">
<div class="footer-brand">
<a href="/" class="logo">
<svg class="logo-icon" viewBox="0 0 38 38" fill="none">
<rect class="logo-icon-bg" width="38" height="38" rx="10"/>
<rect x="10" y="8" width="18" height="22" rx="2.5" fill="none" stroke="white" stroke-width="1.2" opacity="0.9"/>
<rect x="13" y="11.5" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<rect x="13" y="17" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<rect x="13" y="22.5" width="12" height="3.5" rx="1" class="logo-icon-rack" opacity="0.85"/>
<circle cx="15.5" cy="13.25" r="1" class="logo-icon-led"/>
<circle cx="15.5" cy="18.75" r="1" class="logo-icon-led"/>
<circle cx="15.5" cy="24.25" r="1" class="logo-icon-led"/>
<path d="M15 33a4 4 0 014-4" stroke="white" stroke-width="1.2" stroke-linecap="round" opacity="0.5"/>
<path d="M12.5 35a7 7 0 017-7" stroke="white" stroke-width="1" stroke-linecap="round" opacity="0.3"/>
</svg>
<span class="logo-text">
<span class="logo-text-top">Konesali</span>
<span class="logo-text-bottom">TURKU</span>
</span>
</a>
<p>Luotettavat konesalipalvelut Turussa.</p>
</div>
<div class="footer-links">
<h4>Sivusto</h4>
<a href="index.html#palvelut">Palvelut</a>
<a href="konesali.html">Konesali</a>
<a href="yhteydet.html">Yhteydet</a>
<a href="index.html#hinnat">Hinnat</a>
<a href="tarjouspyynto.html">Tarjouspyyntö</a>
</div>
<div class="footer-links">
<h4>Yhteystiedot</h4>
<a href="mailto:asiakaspalvelu@konesaliturku.fi">asiakaspalvelu@konesaliturku.fi</a>
<span>Web1 Oy</span>
<span>Latokarinkatu 3</span>
<span>20200 Turku</span>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<p>&copy; 2026 Konesali Turku. Kaikki oikeudet pidätetään.</p>
</div>
</div>
</footer>
<script src="script.js"></script>
<script>
// Captcha
(function() {
function generateCaptcha() {
const a = Math.floor(Math.random() * 10) + 1;
const b = Math.floor(Math.random() * 10) + 1;
const answer = a + b;
document.getElementById('captcha-label').textContent = 'Paljonko on ' + a + ' + ' + b + '? *';
document.getElementById('captcha-answer').value = answer;
}
generateCaptcha();
window._refreshCaptcha = generateCaptcha;
})();
// Expand form toggle
(function() {
var btn = document.getElementById('btn-expand-form');
var details = document.getElementById('form-details');
var sidebar = document.querySelector('.calculator-sidebar');
var expanded = false;
btn.addEventListener('click', function() {
expanded = !expanded;
details.style.display = expanded ? '' : 'none';
sidebar.classList.toggle('visible', expanded);
btn.classList.toggle('expanded', expanded);
btn.querySelector('.btn-expand-icon').textContent = expanded ? '' : '+';
btn.childNodes[btn.childNodes.length - 1].textContent = expanded ? ' Piilota tarkemmat tiedot' : ' Tarkemmat tiedot & hintalaskuri';
if (expanded) {
details.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
});
})();
// Price Calculator
(function() {
const form = document.getElementById('quote-form');
const totalEl = document.getElementById('calc-total');
const breakdownEl = document.getElementById('calc-breakdown');
const noteEl = document.getElementById('calc-note');
function calculate() {
let total = 0;
let lines = [];
let hasCustom = false;
// Laitepaikat (voi olla piilossa)
const units = [
{ el: document.getElementById('units-1u'), name: '1U laitepaikka', price: 49 },
{ el: document.getElementById('units-2u'), name: '2U laitepaikka', price: 79 },
{ el: document.getElementById('units-4u'), name: '4U laitepaikka', price: 139 },
];
units.forEach(u => {
if (!u.el) return;
const qty = parseInt(u.el.value) || 0;
if (qty > 0) {
const subtotal = qty * u.price;
total += subtotal;
lines.push({ label: u.name + ' x' + qty, amount: subtotal });
}
});
// Kokokaappi
const rackEl = document.getElementById('units-rack');
const rackQty = rackEl ? (parseInt(rackEl.value) || 0) : 0;
if (rackQty > 0) {
hasCustom = true;
lines.push({ label: 'Kokokaappi x' + rackQty, amount: null });
}
// Yhteysnopeus
const connEl = document.getElementById('connection');
const connVal = connEl ? connEl.value : '0';
let connPrice = 0;
if (connVal === 'custom') {
hasCustom = true;
lines.push({ label: '100 Gbit/s yhteys', amount: null });
} else {
connPrice = parseInt(connVal) || 0;
if (connPrice > 0) {
total += connPrice;
lines.push({ label: connEl.options[connEl.selectedIndex].text.split('(')[0].trim(), amount: connPrice });
}
}
// Varmennettu portti
const redundant = form.querySelector('[name="redundant_port"]');
if (redundant && redundant.checked) {
total += 10;
lines.push({ label: 'Varmennettu portti', amount: 10 });
}
// BGP
const bgpEl = document.getElementById('bgp');
const bgpPrice = bgpEl ? (parseInt(bgpEl.value) || 0) : 0;
if (bgpEl && bgpPrice > 0) {
total += bgpPrice;
lines.push({ label: bgpEl.options[bgpEl.selectedIndex].text.split('(')[0].trim(), amount: bgpPrice });
}
// VPN
const vpnEl = document.getElementById('vpn');
const vpnVal = vpnEl ? vpnEl.value : '0';
if (vpnVal === 'custom') {
hasCustom = true;
lines.push({ label: 'Dedicated L2/MPLS', amount: null });
} else {
const vpnPrice = parseInt(vpnVal) || 0;
if (vpnEl && vpnPrice > 0) {
total += vpnPrice;
lines.push({ label: vpnEl.options[vpnEl.selectedIndex].text.split('(')[0].trim(), amount: vpnPrice });
}
}
// Lisäpalvelut
const extras = [
{ name: 'anycast_dns', label: 'Anycast DNS', price: 19 },
{ name: 'block_storage', label: 'Blokkitason storage', price: 29 },
{ name: 's3_storage', label: 'S3-levypinta', price: 19 },
{ name: 'remote_hands', label: 'Remote Hands', price: 0, custom: true },
];
extras.forEach(e => {
const cb = form.querySelector('[name="' + e.name + '"]');
if (cb && cb.checked) {
if (e.custom || e.price === 0) {
hasCustom = true;
lines.push({ label: e.label, amount: null });
} else {
total += e.price;
lines.push({ label: e.label, amount: e.price });
}
}
});
// Render
totalEl.textContent = '€' + total;
if (lines.length === 0) {
breakdownEl.innerHTML = '<p class="calculator-empty">Valitse palvelut vasemmalta niin näet arviohinnan täällä.</p>';
} else {
let html = '';
lines.forEach(l => {
html += '<div class="calc-line">';
html += '<span>' + l.label + '</span>';
html += '<span>' + (l.amount !== null ? '€' + l.amount : 'Tarjouksessa') + '</span>';
html += '</div>';
});
breakdownEl.innerHTML = html;
}
noteEl.style.display = hasCustom ? 'flex' : 'none';
}
// Listen to all form changes
form.addEventListener('change', calculate);
form.addEventListener('input', calculate);
// Form submit
form.addEventListener('submit', function(e) {
e.preventDefault();
const status = document.getElementById('form-status');
const honeypot = form.querySelector('[name="website"]');
if (honeypot && honeypot.value) return;
// Captcha check
const captchaInput = document.getElementById('captcha').value.trim();
const captchaAnswer = document.getElementById('captcha-answer').value;
if (captchaInput !== captchaAnswer) {
status.textContent = 'Väärä vastaus varmistuskysymykseen.';
status.className = 'form-status form-status-error';
window._refreshCaptcha();
document.getElementById('captcha').value = '';
return;
}
const submitBtn = form.querySelector('.btn-submit');
submitBtn.disabled = true;
status.textContent = 'Lähetetään...';
status.className = 'form-status';
const formData = new FormData(form);
fetch('api.php?action=quote', {
method: 'POST',
body: formData
})
.then(function(res) { return res.json(); })
.then(function(data) {
if (data.error) {
status.textContent = data.error;
status.className = 'form-status form-status-error';
} else {
status.textContent = 'Kiitos! Tarjouspyyntösi on vastaanotettu. Otamme yhteyttä vuorokauden sisällä.';
status.className = 'form-status form-status-success';
form.reset();
calculate();
window._refreshCaptcha();
}
})
.catch(function() {
status.textContent = 'Virhe lähetyksessä. Yritä uudelleen tai ota yhteyttä sähköpostilla.';
status.className = 'form-status form-status-error';
})
.finally(function() {
submitBtn.disabled = false;
});
});
})();
</script>
</body>
</html>