Files
docupulse/templates/components/pricing_section.html
2025-06-25 17:14:03 +02:00

292 lines
16 KiB
HTML

<!-- Pricing Section Component -->
<section id="pricing" class="py-5">
<div class="container">
<div class="text-center mb-5">
<h2 class="display-5 fw-bold mb-3">Simple, Transparent Pricing</h2>
<p class="lead text-muted">Choose the plan that fits your organization's needs</p>
</div>
{% set pricing_plans = PricingPlan.get_active_plans() %}
{% if pricing_plans %}
<div class="row g-4 justify-content-center">
{% for plan in pricing_plans %}
<div class="col-md-3">
<div class="card pricing-card h-100 d-flex flex-column {% if plan.is_popular %}border-primary position-relative{% endif %}"
{% if plan.is_popular %}style="border: 3px solid var(--primary-color) !important;"{% endif %}>
{% if plan.is_popular %}
<div class="position-absolute top-0 start-0" style="z-index: 10;">
<span class="badge px-3 py-2" style="background: var(--primary-color); color: white; font-size: 0.8rem; font-weight: 600; border-radius: 0 0 15px 0; margin-top: 0; border-top-left-radius: 10px;">
Most Popular
</span>
</div>
{% endif %}
<div class="card-body text-center p-5 d-flex flex-column">
<div class="flex-grow-1">
<h3 class="card-title">{{ plan.name }}</h3>
{% if plan.is_custom %}
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">Custom</div>
{% else %}
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">
<span class="monthly-price">€{{ "%.0f"|format(plan.monthly_price) }}</span>
<span class="annual-price" style="display: none;">€{{ "%.0f"|format(plan.annual_price) }}</span>
<span class="fs-6 text-muted">/month</span>
</div>
{% endif %}
{% if plan.description %}
<p class="text-muted mb-3">{{ plan.description }}</p>
{% endif %}
<ul class="list-unstyled mb-4">
{% for feature in plan.features %}
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>{{ feature }}</li>
{% endfor %}
</ul>
</div>
<!-- Dynamic Payment Button -->
{% if plan.is_custom %}
<a href="{{ contact_url }}" class="btn {% if plan.is_popular %}btn-primary{% else %}btn-outline-primary{% endif %} btn-lg w-100 mt-auto px-4 py-3">
{{ plan.button_text }}
</a>
{% else %}
{% if plan.monthly_stripe_link or plan.annual_stripe_link %}
<a href="{{ plan.monthly_stripe_link or plan.annual_stripe_link }}"
class="btn {% if plan.is_popular %}btn-primary{% else %}btn-outline-primary{% endif %} btn-lg w-100 mt-auto px-4 py-3 payment-button"
data-plan-id="{{ plan.id }}"
data-monthly-link="{{ plan.monthly_stripe_link or '' }}"
data-annual-link="{{ plan.annual_stripe_link or '' }}"
target="_blank">
{{ plan.button_text }}
</a>
{% else %}
<a href="{{ contact_url }}" class="btn {% if plan.is_popular %}btn-primary{% else %}btn-outline-primary{% endif %} btn-lg w-100 mt-auto px-4 py-3">
{{ plan.button_text }}
</a>
{% endif %}
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
<!-- Billing Toggle - Only show if there are non-custom plans -->
{% set has_non_custom_plans = pricing_plans | selectattr('is_custom', 'equalto', false) | list | length > 0 %}
{% if has_non_custom_plans %}
<div class="d-flex justify-content-center align-items-center mt-4 mb-3">
<span class="me-3">Monthly</span>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="annualBilling" style="width: 3rem; height: 1.5rem; background-color: var(--border-color); border-color: var(--border-color);">
<label class="form-check-label" for="annualBilling"></label>
</div>
<span class="ms-3">Annual <span class="badge text-white px-2 py-1 ms-1" style="background: var(--primary-color); font-size: 0.75rem;">Save 20%</span></span>
</div>
{% endif %}
{% else %}
<!-- Fallback to default pricing if no plans are configured -->
<div class="row g-4 justify-content-center">
<div class="col-md-3">
<div class="card pricing-card h-100 d-flex flex-column">
<div class="card-body text-center p-5 d-flex flex-column">
<div class="flex-grow-1">
<h3 class="card-title">Starter</h3>
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">
<span class="monthly-price">€29</span>
<span class="annual-price" style="display: none;">€23</span>
<span class="fs-6 text-muted">/month</span>
</div>
<ul class="list-unstyled mb-4">
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 5 rooms</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 10 conversations</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>10GB storage</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 10 managers</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Email support</li>
</ul>
</div>
<a href="{{ contact_url }}" class="btn btn-outline-primary btn-lg w-100 mt-auto px-4 py-3">Get Started</a>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card pricing-card h-100 border-primary d-flex flex-column position-relative" style="border: 3px solid var(--primary-color) !important;">
<div class="position-absolute top-0 start-0" style="z-index: 10;">
<span class="badge px-3 py-2" style="background: var(--primary-color); color: white; font-size: 0.8rem; font-weight: 600; border-radius: 0 0 15px 0; margin-top: 0; border-top-left-radius: 10px;">
Most Popular
</span>
</div>
<div class="card-body text-center p-5 d-flex flex-column">
<div class="flex-grow-1">
<h3 class="card-title">Professional</h3>
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">
<span class="monthly-price">€99</span>
<span class="annual-price" style="display: none;">€79</span>
<span class="fs-6 text-muted">/month</span>
</div>
<ul class="list-unstyled mb-4">
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 25 rooms</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 50 conversations</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>100GB storage</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 50 managers</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Priority support</li>
</ul>
</div>
<a href="{{ contact_url }}" class="btn btn-primary btn-lg w-100 mt-auto px-4 py-3">Get Started</a>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card pricing-card h-100 d-flex flex-column">
<div class="card-body text-center p-5 d-flex flex-column">
<div class="flex-grow-1">
<h3 class="card-title">Enterprise</h3>
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">
<span class="monthly-price">€299</span>
<span class="annual-price" style="display: none;">€239</span>
<span class="fs-6 text-muted">/month</span>
</div>
<ul class="list-unstyled mb-4">
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 100 rooms</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 200 conversations</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>500GB storage</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Up to 200 managers</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>24/7 dedicated support</li>
</ul>
</div>
<a href="{{ contact_url }}" class="btn btn-outline-primary btn-lg w-100 mt-auto px-4 py-3">Get Started</a>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card pricing-card h-100 d-flex flex-column">
<div class="card-body text-center p-5 d-flex flex-column">
<div class="flex-grow-1">
<h3 class="card-title">Custom</h3>
<div class="display-4 fw-bold mb-3" style="color: var(--primary-color);">Custom</div>
<ul class="list-unstyled mb-4">
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Unlimited rooms</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Unlimited conversations</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Unlimited storage</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Unlimited users</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Custom integrations</li>
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Dedicated account manager</li>
</ul>
</div>
<a href="{{ contact_url }}" class="btn btn-outline-primary btn-lg w-100 mt-auto px-4 py-3">Contact Sales</a>
</div>
</div>
</div>
</div>
<!-- Billing Toggle -->
<div class="d-flex justify-content-center align-items-center mt-4 mb-3">
<span class="me-3">Monthly</span>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="annualBilling" style="width: 3rem; height: 1.5rem; background-color: var(--border-color); border-color: var(--border-color);">
<label class="form-check-label" for="annualBilling"></label>
</div>
<span class="ms-3">Annual <span class="badge text-white px-2 py-1 ms-1" style="background: var(--primary-color); font-size: 0.75rem;">Save 20%</span></span>
</div>
{% endif %}
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function() {
const billingToggle = document.getElementById('annualBilling');
if (!billingToggle) return;
const monthlyPrices = document.querySelectorAll('.monthly-price');
const annualPrices = document.querySelectorAll('.annual-price');
// Add CSS for switch styling
const style = document.createElement('style');
style.textContent = `
.form-check-input:checked {
background-color: var(--primary-color) !important;
border-color: var(--primary-color) !important;
}
.form-check-input:focus {
box-shadow: 0 0 0 0.25rem rgba(var(--primary-color-rgb), 0.25) !important;
}
.price-number {
display: inline-block;
transition: all 0.3s ease;
}
`;
document.head.appendChild(style);
// Function to animate number counting
function animateNumber(element, startValue, endValue, duration = 500) {
const start = performance.now();
const difference = endValue - startValue;
function updateNumber(currentTime) {
const elapsed = currentTime - start;
const progress = Math.min(elapsed / duration, 1);
// Easing function for smooth animation
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
const currentValue = startValue + (difference * easeOutQuart);
element.textContent = '€' + Math.round(currentValue);
if (progress < 1) {
requestAnimationFrame(updateNumber);
} else {
// Ensure the final value is correct
element.textContent = '€' + endValue;
}
}
requestAnimationFrame(updateNumber);
}
billingToggle.addEventListener('change', function() {
if (this.checked) {
// Switch to annual prices with animation
monthlyPrices.forEach((price, index) => {
const monthlyValue = parseInt(price.textContent.replace('€', ''));
const annualValue = parseInt(annualPrices[index].textContent.replace('€', ''));
// Store the original monthly value for later use
price.setAttribute('data-original-monthly', monthlyValue);
// Simply animate the number change
animateNumber(price, monthlyValue, annualValue);
});
// Update payment links to annual
document.querySelectorAll('.payment-button').forEach(button => {
const annualLink = button.getAttribute('data-annual-link');
if (annualLink) {
button.href = annualLink;
}
});
} else {
// Switch to monthly prices with animation
monthlyPrices.forEach((price, index) => {
const currentValue = parseInt(price.textContent.replace('€', ''));
const originalMonthlyValue = parseInt(price.getAttribute('data-original-monthly'));
// Simply animate the number change back to monthly
animateNumber(price, currentValue, originalMonthlyValue);
});
// Update payment links to monthly
document.querySelectorAll('.payment-button').forEach(button => {
const monthlyLink = button.getAttribute('data-monthly-link');
if (monthlyLink) {
button.href = monthlyLink;
}
});
}
});
});
</script>
</script>