{% include '@Application/inc/central_header.html.twig' %}
{% set breakdown = breakdown is defined ? breakdown : {} %}
{% set prefill = prefill is defined ? prefill : {} %}
<style>
.qr-shell {
min-height: 100vh;
background: linear-gradient(135deg,#f4f8ff 0%,#edf3fb 100%);
padding: 40px 0 60px;
}
.qr-card {
max-width: 820px;
margin: 0 auto;
background: #fff;
border-radius: 20px;
box-shadow: 0 12px 50px rgba(17,42,84,0.10);
overflow: hidden;
}
.qr-card__header {
background: linear-gradient(135deg,#1d5b9e,#0f3565);
padding: 32px 40px 28px;
color: #fff;
}
.qr-card__header h1 { font-size: 1.5rem; font-weight: 700; margin: 0 0 4px; }
.qr-card__header p { opacity: 0.75; margin: 0; font-size: 0.92rem; }
.qr-card__body { padding: 36px 40px; }
.qr-section-title {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #7a8ba8;
margin: 0 0 14px;
}
.qr-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 20px; }
.qr-row--3 { grid-template-columns: 1fr 1fr 1fr; }
.qr-row--1 { grid-template-columns: 1fr; }
.qr-field label {
display: block;
font-size: 0.82rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 5px;
}
.qr-field input, .qr-field select, .qr-field textarea {
width: 100%;
border: 1.5px solid #dce4ef;
border-radius: 9px;
padding: 9px 13px;
font-size: 0.92rem;
background: #fafbfd;
transition: border-color 0.2s;
box-sizing: border-box;
}
.qr-field input:focus, .qr-field select:focus, .qr-field textarea:focus {
border-color: #1d5b9e;
outline: none;
background: #fff;
}
.qr-field--counter { position: relative; }
.qr-field--counter input { padding-right: 50px; }
.qr-field--counter .qr-price-hint {
position: absolute;
right: 12px; top: 50%; transform: translateY(-50%);
font-size: 0.75rem;
color: #7a8ba8;
pointer-events: none;
}
.qr-divider { height: 1px; background: #eef1f6; margin: 28px 0; }
.qr-price-box {
background: linear-gradient(135deg,#f4f8ff,#edf3fb);
border: 1.5px solid #dce4ef;
border-radius: 14px;
padding: 22px 26px;
margin-bottom: 24px;
}
.qr-price-box__label { font-size: 0.8rem; color: #7a8ba8; margin-bottom: 4px; }
.qr-price-box__total { font-size: 2rem; font-weight: 800; color: #1d5b9e; }
.qr-price-box__sub { font-size: 0.82rem; color: #7a8ba8; margin-top: 2px; }
.qr-price-box__breakdown { margin-top: 12px; font-size: 0.82rem; color: #4a6080; }
.qr-price-box__breakdown .row-item {
display: flex; justify-content: space-between;
padding: 3px 0; border-bottom: 1px dashed #e0e8f0;
}
.qr-price-box__breakdown .row-item:last-child { border: 0; }
.qr-btn-group { display: flex; gap: 14px; }
.qr-btn {
padding: 12px 28px;
border-radius: 10px;
font-size: 0.95rem;
font-weight: 700;
border: none;
cursor: pointer;
transition: transform 0.1s, box-shadow 0.1s;
}
.qr-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0,0,0,0.12); }
.qr-btn--primary { background: #1d5b9e; color: #fff; }
.qr-btn--secondary { background: #f0f4fa; color: #1d5b9e; border: 1.5px solid #d0dce8; }
.qr-plan-badge {
display: inline-flex; align-items: center; gap: 6px;
background: #e8f0fb; color: #1d5b9e;
border-radius: 20px; padding: 4px 14px;
font-size: 0.82rem; font-weight: 700; margin-bottom: 22px;
}
</style>
<div class="qr-shell">
<div class="qr-card">
<div class="qr-card__header">
<h1>{{ page_title|default('Request a Quote') }}</h1>
<p>Fill in the details below and our team will prepare your custom proposal.</p>
</div>
<div class="qr-card__body">
{% for type, messages in app.flashes %}
{% for msg in messages %}
<div class="alert alert-{{ type == 'error' ? 'danger' : type }} mb-3">{{ msg }}</div>
{% endfor %}
{% endfor %}
<span class="qr-plan-badge">
<i class="ft-package"></i>
{{ prefill.plan_type|default('team')|title }} Plan
</span>
<form method="POST" action="{{ path('quote_request') }}" id="quoteForm">
<input type="hidden" name="plan_type" value="{{ prefill.plan_type|default('team') }}">
{# ── Contact Information ── #}
<div class="qr-section-title">Contact Information</div>
<div class="qr-row">
<div class="qr-field">
<label>Email Address *</label>
<input type="email" name="customer_email"
value="{{ prefill.customer_email|default('') }}"
required placeholder="you@company.com">
</div>
<div class="qr-field">
<label>Full Name</label>
<input type="text" name="customer_name"
value="{{ prefill.customer_name|default('') }}"
placeholder="Your name">
</div>
</div>
<div class="qr-row">
<div class="qr-field">
<label>Phone</label>
<input type="text" name="customer_phone"
value="{{ prefill.customer_phone|default('') }}"
placeholder="+31 6 12345678">
</div>
<div class="qr-field">
<label>Company Name</label>
<input type="text" name="company_name"
value="{{ prefill.company_name|default('') }}"
placeholder="Your company">
</div>
</div>
<div class="qr-row">
<div class="qr-field">
<label>Company Address</label>
<input type="text" name="company_address"
value="{{ prefill.company_address|default('') }}"
placeholder="Street, City, Postal code">
</div>
<div class="qr-field">
<label>Country</label>
<input type="text" name="country" list="country-list"
value="{{ prefill.country|default('') }}"
placeholder="e.g. Netherlands">
<datalist id="country-list">
<option value="Netherlands"><option value="Germany"><option value="France">
<option value="Belgium"><option value="United Kingdom"><option value="Sweden">
<option value="Norway"><option value="Denmark"><option value="Finland">
<option value="Spain"><option value="Italy"><option value="Portugal">
<option value="Poland"><option value="Austria"><option value="Switzerland">
<option value="United States"><option value="Canada"><option value="Australia">
<option value="Singapore"><option value="India"><option value="Bangladesh">
<option value="United Arab Emirates"><option value="South Africa">
</datalist>
</div>
</div>
<div class="qr-divider"></div>
{# ── User Seats (both plans) ── #}
<div class="qr-section-title">Team Size</div>
<div class="qr-row qr-row--3">
<div class="qr-field qr-field--counter">
<label>Normal Users</label>
<input type="number" name="normal_users" id="normalUsers" min="0"
value="{{ prefill.normal_users|default(prefill.plan_type|default('team') == 'enterprise' ? 0 : 1) }}"
class="seat-counter">
{% if prefill.plan_type|default('team') == 'team' %}
<span class="qr-price-hint">€8/mo</span>
{% endif %}
</div>
<div class="qr-field qr-field--counter">
<label>Admin Users</label>
<input type="number" name="admin_users" id="adminUsers" min="0"
value="{{ prefill.admin_users|default(0) }}"
class="seat-counter">
{% if prefill.plan_type|default('team') == 'team' %}
<span class="qr-price-hint">€20/mo</span>
{% endif %}
</div>
<div class="qr-field qr-field--counter">
<label>AI-enabled Users</label>
<input type="number" name="ml_users" id="mlUsers" min="0"
value="{{ prefill.ml_users|default(0) }}"
class="seat-counter">
{% if prefill.plan_type|default('team') == 'team' %}
<span class="qr-price-hint">€25/mo</span>
{% endif %}
</div>
</div>
{# ── Billing & Payment ── #}
<div class="qr-section-title" style="margin-top:10px;">Billing Preferences</div>
{% if prefill.plan_type|default('team') == 'team' %}
<div class="qr-row">
<div class="qr-field">
<label>Billing Cycle</label>
<select name="billing_cycle" id="billingCycle">
<option value="monthly" {{ prefill.billing_cycle|default('monthly') == 'monthly' ? 'selected' : '' }}>Monthly</option>
<option value="yearly" {{ prefill.billing_cycle|default('monthly') == 'yearly' ? 'selected' : '' }}>Yearly (save 20%)</option>
</select>
</div>
<div class="qr-field">
<label>Payment Method</label>
<select name="payment_type">
<option value="automatic" {{ prefill.payment_type|default('automatic') == 'automatic' ? 'selected' : '' }}>Card / Automatic</option>
<option value="manual" {{ prefill.payment_type|default('automatic') == 'manual' ? 'selected' : '' }}>Bank Transfer</option>
</select>
</div>
</div>
{# ── Live Price Box ── #}
<div class="qr-price-box" id="priceBox">
<div class="qr-price-box__label">Estimated Price</div>
<div class="qr-price-box__total" id="priceTotal">
€{{ breakdown.base_amount|default(0)|number_format(2) }}
<span style="font-size:1rem;font-weight:400;color:#7a8ba8;">
/ {{ prefill.billing_cycle|default('monthly') }}
</span>
</div>
<div class="qr-price-box__sub" id="priceSub"></div>
<div class="qr-price-box__breakdown" id="priceBreakdown">
{% if breakdown %}
{% if breakdown.subtotal_base > 0 %}
<div class="row-item"><span>Package base</span><span>€{{ breakdown.subtotal_base|number_format(2) }}</span></div>
{% endif %}
{% if breakdown.extra_users > 0 %}
<div class="row-item"><span>+{{ breakdown.extra_users }} extra users × €{{ breakdown.price_normal_monthly }}</span><span>€{{ breakdown.subtotal_normal|number_format(2) }}</span></div>
{% endif %}
{% if breakdown.extra_admins > 0 %}
<div class="row-item"><span>+{{ breakdown.extra_admins }} extra admins × €{{ breakdown.price_admin_monthly }}</span><span>€{{ breakdown.subtotal_admin|number_format(2) }}</span></div>
{% endif %}
{% if breakdown.ml_users > 0 %}
<div class="row-item"><span>AI-enabled users ({{ breakdown.ml_users }} × €{{ breakdown.price_ml_monthly }})</span><span>€{{ breakdown.subtotal_ml|number_format(2) }}</span></div>
{% endif %}
{% endif %}
</div>
</div>
{% else %}
{# Enterprise — payment preference only, no pricing shown #}
<input type="hidden" name="billing_cycle" value="monthly">
<div class="qr-row">
<div class="qr-field">
<label>Payment Method Preference</label>
<select name="payment_type">
<option value="manual">Bank Transfer</option>
<option value="automatic">Card / Automatic</option>
</select>
</div>
</div>
<div style="background:#f4f8ff;border:1.5px solid #d0dce8;border-radius:10px;padding:13px 16px;font-size:0.85rem;color:#4a6080;margin-top:6px;">
Our team will review your team size and prepare a custom price. You will receive the quote by email.
</div>
{% endif %}
<div class="qr-divider"></div>
{# ── Promo Code ── #}
<div class="qr-section-title">Promo Code</div>
<input type="hidden" name="promo_code_id" id="promoCodeId" value="">
<div class="qr-row qr-row--1" style="margin-bottom:20px;">
<div class="qr-field">
<label>Have a promo code? <span style="font-weight:400;color:#7a8ba8;">(optional)</span></label>
<div style="display:flex;gap:10px;">
<input type="text" id="promoCodeInput" placeholder="Enter code…" style="flex:1;">
<button type="button" id="promoApplyBtn"
style="padding:9px 18px;border-radius:9px;border:1.5px solid #1d5b9e;background:#fff;color:#1d5b9e;font-weight:700;cursor:pointer;white-space:nowrap;">
Apply
</button>
</div>
<div id="promoResult" style="margin-top:6px;font-size:0.82rem;"></div>
</div>
</div>
<div class="qr-divider"></div>
<div class="qr-row qr-row--1" style="margin-bottom:24px;">
<div class="qr-field">
<label>Notes / Special Requirements</label>
<textarea name="customer_notes" rows="3"
placeholder="Any special requirements or questions…">{{ prefill.customer_notes|default('') }}</textarea>
</div>
</div>
<div class="qr-btn-group">
<button type="submit" class="qr-btn qr-btn--primary">
<i class="ft-send"></i> Submit Quote Request
</button>
<a href="/" class="qr-btn qr-btn--secondary">Cancel</a>
</div>
</form>
</div>
</div>
</div>
<script>
(function() {
var promoLookUrl = '{{ path('quote_promo_lookup') }}';
var promoDiscount = 0;
// Promo code lookup (works for both Team and Enterprise)
var promoBtn = document.getElementById('promoApplyBtn');
if (promoBtn) {
promoBtn.addEventListener('click', function() {
var code = document.getElementById('promoCodeInput').value.trim();
if (!code) return;
var resultEl = document.getElementById('promoResult');
resultEl.innerHTML = '<span style="color:#7a8ba8;">Checking…</span>';
fetch(promoLookUrl + '?code=' + encodeURIComponent(code))
.then(function(r){ return r.json(); })
.then(function(data) {
if (!data.success) {
resultEl.innerHTML = '<span style="color:#e74c3c;">✗ ' + data.message + '</span>';
document.getElementById('promoCodeId').value = '';
promoDiscount = 0;
if (typeof recalc === 'function') recalc();
return;
}
document.getElementById('promoCodeId').value = data.id;
resultEl.innerHTML = '<span style="color:#27ae60;">✓ ' + data.label + ' applied!</span>';
// Store for team plan price calc
if (data.promo_type === 1) {
promoDiscount = data.max_discount !== null ? Math.min(data.promo_value, data.max_discount) : data.promo_value;
} else {
promoDiscount = data.promo_value; // pct — applied in recalc
promoDiscount = -data.promo_value; // signal: negative = percent
}
if (typeof recalc === 'function') recalc();
});
});
document.getElementById('promoCodeInput').addEventListener('keydown', function(e) {
if (e.key === 'Enter') { e.preventDefault(); promoBtn.click(); }
});
}
{% if prefill.plan_type|default('team') == 'team' %}
var calcUrl = '{{ path('quote_calculate_price') }}';
var debounce;
function recalc() {
clearTimeout(debounce);
debounce = setTimeout(function() {
var fd = new FormData();
fd.append('normal_users', document.getElementById('normalUsers').value);
fd.append('admin_users', document.getElementById('adminUsers').value);
fd.append('ml_users', document.getElementById('mlUsers').value);
fd.append('billing_cycle', document.getElementById('billingCycle').value);
fd.append('plan_type', 'team');
fetch(calcUrl, { method: 'POST', body: fd })
.then(function(r){ return r.json(); })
.then(function(d) {
var cycle = d.billing_cycle;
// Apply promo discount
var promoOff = 0;
if (promoDiscount < 0) {
// Percent promo
promoOff = Math.round(d.base_amount * (-promoDiscount / 100) * 100) / 100;
} else {
promoOff = promoDiscount;
}
var total = Math.max(0, d.base_amount - promoOff);
document.getElementById('priceTotal').innerHTML =
'€' + total.toFixed(2) +
'<span style="font-size:1rem;font-weight:400;color:#7a8ba8;"> / ' + cycle + '</span>';
var sub = '';
if (cycle === 'yearly') {
sub = 'Save €' + d.yearly_savings.toFixed(2) + ' vs. monthly billing (20% off)';
}
if (promoOff > 0) {
sub += (sub ? ' · ' : '') + 'Promo: −€' + promoOff.toFixed(2);
}
document.getElementById('priceSub').textContent = sub;
var breakdown = '';
if (d.subtotal_base > 0) {
breakdown += '<div class="row-item"><span>Package base</span><span>€' + d.subtotal_base.toFixed(2) + '</span></div>';
}
if (d.extra_users > 0) {
breakdown += '<div class="row-item"><span>+' + d.extra_users + ' extra users × €' + d.price_normal_monthly.toFixed(2) + '</span><span>€' + d.subtotal_normal.toFixed(2) + '</span></div>';
}
if (d.extra_admins > 0) {
breakdown += '<div class="row-item"><span>+' + d.extra_admins + ' extra admins × €' + d.price_admin_monthly.toFixed(2) + '</span><span>€' + d.subtotal_admin.toFixed(2) + '</span></div>';
}
if (d.ml_users > 0) {
breakdown += '<div class="row-item"><span>AI-enabled users (' + d.ml_users + ' × €' + d.price_ml_monthly.toFixed(2) + ')</span><span>€' + d.subtotal_ml.toFixed(2) + '</span></div>';
}
if (promoOff > 0) {
breakdown += '<div class="row-item" style="color:#27ae60;"><span>Promo discount</span><span>−€' + promoOff.toFixed(2) + '</span></div>';
}
document.getElementById('priceBreakdown').innerHTML = breakdown;
});
}, 350);
}
document.querySelectorAll('.seat-counter, #billingCycle').forEach(function(el){
el.addEventListener('input', recalc);
el.addEventListener('change', recalc);
});
recalc();
{% endif %}
})();
</script>