diff --git a/hub/services/static/css/price-calculator.css b/hub/services/static/css/price-calculator.css
index de8074e..5efe5f6 100644
--- a/hub/services/static/css/price-calculator.css
+++ b/hub/services/static/css/price-calculator.css
@@ -33,4 +33,37 @@
to {
opacity: 1;
}
+}
+
+
+/* Subtle styling for the best plan */
+.card.border-success.border-2 {
+ box-shadow: 0 0.25rem 0.75rem rgba(25, 135, 84, 0.1) !important;
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
+}
+
+.card.border-success.border-2:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 0.5rem 1rem rgba(25, 135, 84, 0.15) !important;
+}
+
+/* Best choice badge styling */
+.badge.bg-success {
+ background: linear-gradient(135deg, #198754 0%, #20c997 100%) !important;
+ border: 2px solid white;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+ white-space: nowrap;
+ font-size: 0.75rem;
+ padding: 0.5rem 0.75rem;
+ min-width: max-content;
+}
+
+/* Subtle enhancement for best plan button */
+.btn-success.shadow {
+ transition: all 0.2s ease-in-out;
+}
+
+.btn-success.shadow:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 0.25rem 0.75rem rgba(25, 135, 84, 0.2) !important;
}
\ No newline at end of file
diff --git a/hub/services/static/js/price-calculator.js b/hub/services/static/js/price-calculator.js
index 54b2af9..9ea66bb 100644
--- a/hub/services/static/js/price-calculator.js
+++ b/hub/services/static/js/price-calculator.js
@@ -1834,4 +1834,22 @@ document.addEventListener('DOMContentLoaded', () => {
if (document.getElementById('cpuRange')) {
new PriceCalculator();
}
-});
\ No newline at end of file
+});
+
+function selectPlan(element) {
+ const planId = element.getAttribute('data-plan-id');
+ const planName = element.getAttribute('data-plan-name');
+
+ // Find the plan dropdown in the contact form
+ const planDropdown = document.getElementById('id_choice');
+ if (planDropdown) {
+ // Find the option with matching plan id and select it
+ for (let i = 0; i < planDropdown.options.length; i++) {
+ const optionValue = planDropdown.options[i].value;
+ if (optionValue.startsWith(planId + '|')) {
+ planDropdown.selectedIndex = i;
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/hub/services/templates/services/offering_detail.html b/hub/services/templates/services/offering_detail.html
index 15e9e72..7263024 100644
--- a/hub/services/templates/services/offering_detail.html
+++ b/hub/services/templates/services/offering_detail.html
@@ -9,62 +9,7 @@
-
{% json_ld_structured_data %}
-
-
-
{% endblock %}
{% block content %}
diff --git a/hub/services/templatetags/json_ld_tags.py b/hub/services/templatetags/json_ld_tags.py
index e95ba70..eb18007 100644
--- a/hub/services/templatetags/json_ld_tags.py
+++ b/hub/services/templatetags/json_ld_tags.py
@@ -225,19 +225,21 @@ def json_ld_structured_data(context):
# Add offers if available
if hasattr(offering, "plans") and offering.plans.exists():
# Get all plans with pricing
- plans_with_prices = offering.plans.filter(plan_prices__isnull=False).distinct()
-
+ plans_with_prices = offering.plans.filter(
+ plan_prices__isnull=False
+ ).distinct()
+
if plans_with_prices.exists():
# Create individual offers for each plan
offers = []
all_prices = []
-
+
for plan in plans_with_prices:
plan_prices = plan.plan_prices.all()
if plan_prices.exists():
first_price = plan_prices.first()
all_prices.extend([p.amount for p in plan_prices])
-
+
offer = {
"@type": "Offer",
"name": plan.name,
@@ -245,25 +247,19 @@ def json_ld_structured_data(context):
"priceCurrency": first_price.currency,
"availability": "https://schema.org/InStock",
"url": offering_url + "#plan-order-form",
- "seller": {
- "@type": "Organization",
- "name": "VSHN"
- }
+ "seller": {"@type": "Organization", "name": "VSHN"},
}
offers.append(offer)
-
+
# Add aggregate offer with all individual offers
data["offers"] = {
"@type": "AggregateOffer",
"availability": "https://schema.org/InStock",
"offerCount": len(offers),
"offers": offers,
- "seller": {
- "@type": "Organization",
- "name": "VSHN"
- }
+ "seller": {"@type": "Organization", "name": "VSHN"},
}
-
+
# Add lowPrice, highPrice and priceCurrency if we have prices
if all_prices:
data["offers"]["lowPrice"] = str(min(all_prices))
@@ -272,7 +268,7 @@ def json_ld_structured_data(context):
first_plan_with_prices = plans_with_prices.first()
first_currency = first_plan_with_prices.plan_prices.first().currency
data["offers"]["priceCurrency"] = first_currency
-
+
# Note: aggregateRating and review fields are not included as this is a B2B
# service marketplace without a review system. These could be added in the future
# if customer reviews/ratings are implemented.
@@ -289,10 +285,7 @@ def json_ld_structured_data(context):
"@type": "AggregateOffer",
"availability": "https://schema.org/InStock",
"offerCount": offering.plans.count(),
- "seller": {
- "@type": "Organization",
- "name": "VSHN"
- }
+ "seller": {"@type": "Organization", "name": "VSHN"},
}
else: