Răsfoiți Sursa

Merge pull request #5722 from overleaf/hb-improve-group-buy-ux

Update the UX for the group subscription modal

GitOrigin-RevId: 6700a5c4907e0c966ee3b2954b6417ccf9edf37e
Hugh O'Brien 4 ani în urmă
părinte
comite
7d932f0b92

+ 21 - 27
services/web/app/views/subscriptions/plans-marketing/_group_plan_modal.pug

@@ -2,8 +2,9 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
 	.modal-dialog(role="document")
 	.modal-dialog(role="document")
 		.modal-content
 		.modal-content
 			.modal-header
 			.modal-header
-				h3 Save 30% or more with a group license
-			.modal-body.plans
+				h2 Customise your group subscription
+				h3 Save 30% or more
+			.modal-body.plans.group-subscription-modal
 				.container-fluid
 				.container-fluid
 					.row
 					.row
 						.col-md-6.text-center
 						.col-md-6.text-center
@@ -11,7 +12,7 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
 								span(data-ol-group-plan-display-price) ...
 								span(data-ol-group-plan-display-price) ...
 								span.small / year
 								span.small / year
 								br
 								br
-								span.circle-subtext(data-ol-group-plan-for-n-users) For ... users
+								span.circle-subtext(data-ol-group-plan-price-per-user) ...
 							ul.list-unstyled
 							ul.list-unstyled
 								li Each user will have access to:
 								li Each user will have access to:
 								li  
 								li  
@@ -31,12 +32,10 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
 								.form-group
 								.form-group
 									label(for='plan_code')
 									label(for='plan_code')
 										| Plan
 										| Plan
-									select.form-control(id="plan_code")
-										for plan_code in groupPlanModalOptions.plan_codes
-											option(
-												value=plan_code.code
-												selected=(plan_code.code === groupPlanModalDefaults.plan_code)
-											) #{plan_code.display}
+									for plan_code in groupPlanModalOptions.plan_codes
+										label.group-plan-option
+											input(type="radio" name="plan_code" checked=(plan_code.code === "collaborator") value=plan_code.code )
+											span #{plan_code.display}
 								.form-group
 								.form-group
 									label(for='size')
 									label(for='size')
 										| Number of users
 										| Number of users
@@ -57,24 +56,19 @@ div.modal.fade(tabindex="-1" role="dialog" data-ol-group-plan-modal)
 											) #{currency.display}
 											) #{currency.display}
 								.form-group
 								.form-group
 									label(for='usage')
 									label(for='usage')
-										| Usage
-									select.form-control(id="usage")
-										for usage in groupPlanModalOptions.usages
-											option(
-												value=usage.code
-												selected=(usage.code === groupPlanModalDefaults.usage)
-											) #{usage.display}
-									p.small.text-center.row-spaced-small
-										span(
-											hidden=(groupPlanModalDefaults.usage !== 'educational')
-											data-ol-group-plan-usage='educational'
-										)
-											| The 40% educational discount can be used by students or faculty using Overleaf for teaching
-										span(
-											hidden=(groupPlanModalDefaults.usage !== 'enterprise')
-											data-ol-group-plan-usage='enterprise'
-										)
-											| Save an additional 40% on groups of 10 or more with our educational discount
+										| Overleaf offers a 40% educational discount for groups of 10 or more.
+								label.group-plan-option
+									input(id="usage", type="checkbox")
+									span This licence is for educational purposes (applies to students or faculty using Overleaf for teaching)
+
+					.row
+						.col-md-12.text-center
+							.educational-discount-badge
+								div(hidden=(groupPlanModalDefaults.usage !== 'educational') data-ol-group-plan-educational-discount)
+									p.applied(hidden=true data-ol-group-plan-educational-discount-applied)
+										| 40% educational discount applied!
+									p.ineligible(hidden=true data-ol-group-plan-educational-discount-ineligible)
+										| The educational discount is available for groups of 10 or more
 			.modal-footer
 			.modal-footer
 				.text-center
 				.text-center
 					button.btn.btn-primary.btn-lg(data-ol-purchase-group-plan) Purchase Now
 					button.btn.btn-primary.btn-lg(data-ol-purchase-group-plan) Purchase Now

+ 22 - 4
services/web/frontend/js/features/plans/group-plan-modal/index.js

@@ -4,10 +4,13 @@ import * as eventTracking from '../../../infrastructure/event-tracking'
 
 
 function getFormValues() {
 function getFormValues() {
   const modalEl = document.querySelector('[data-ol-group-plan-modal]')
   const modalEl = document.querySelector('[data-ol-group-plan-modal]')
-  const planCode = modalEl.querySelector('#plan_code').value
+  const planCode = modalEl.querySelector('input[name="plan_code"]:checked')
+    .value
   const size = modalEl.querySelector('#size').value
   const size = modalEl.querySelector('#size').value
   const currency = modalEl.querySelector('#currency').value
   const currency = modalEl.querySelector('#currency').value
-  const usage = modalEl.querySelector('#usage').value
+  const usage = modalEl.querySelector('#usage').checked
+    ? 'educational'
+    : 'enterprise'
   return { planCode, size, currency, usage }
   return { planCode, size, currency, usage }
 }
 }
 
 
@@ -21,6 +24,7 @@ function updateGroupPlanView() {
   const price = prices[usage][planCode][currency][size]
   const price = prices[usage][planCode][currency][size]
   const currencySymbol = currencySymbols[currency]
   const currencySymbol = currencySymbols[currency]
   const displayPrice = `${currencySymbol}${price}`
   const displayPrice = `${currencySymbol}${price}`
+  const perUserPrice = parseFloat((price / size).toFixed(2))
 
 
   modalEl.querySelectorAll('[data-ol-group-plan-plan-code]').forEach(el => {
   modalEl.querySelectorAll('[data-ol-group-plan-plan-code]').forEach(el => {
     el.hidden = el.getAttribute('data-ol-group-plan-plan-code') !== planCode
     el.hidden = el.getAttribute('data-ol-group-plan-plan-code') !== planCode
@@ -32,8 +36,19 @@ function updateGroupPlanView() {
     '[data-ol-group-plan-display-price]'
     '[data-ol-group-plan-display-price]'
   ).innerText = displayPrice
   ).innerText = displayPrice
   modalEl.querySelector(
   modalEl.querySelector(
-    '[data-ol-group-plan-for-n-users]'
-  ).innerText = `For ${size} users`
+    '[data-ol-group-plan-price-per-user]'
+  ).innerText = `${currencySymbol}${perUserPrice} per user`
+
+  modalEl.querySelector('[data-ol-group-plan-educational-discount]').hidden =
+    usage !== 'educational'
+
+  modalEl.querySelector(
+    '[data-ol-group-plan-educational-discount-applied]'
+  ).hidden = size < 10
+
+  modalEl.querySelector(
+    '[data-ol-group-plan-educational-discount-ineligible]'
+  ).hidden = size >= 10
 }
 }
 
 
 const modalEl = $('[data-ol-group-plan-modal]')
 const modalEl = $('[data-ol-group-plan-modal]')
@@ -58,6 +73,9 @@ function showGroupPlanModal() {
 document
 document
   .querySelectorAll('[data-ol-group-plan-form] select')
   .querySelectorAll('[data-ol-group-plan-form] select')
   .forEach(el => el.addEventListener('change', updateGroupPlanView))
   .forEach(el => el.addEventListener('change', updateGroupPlanView))
+document
+  .querySelectorAll('[data-ol-group-plan-form] input')
+  .forEach(el => el.addEventListener('change', updateGroupPlanView))
 document.querySelectorAll('[data-ol-purchase-group-plan]').forEach(el =>
 document.querySelectorAll('[data-ol-purchase-group-plan]').forEach(el =>
   el.addEventListener('click', e => {
   el.addEventListener('click', e => {
     e.preventDefault()
     e.preventDefault()

+ 38 - 0
services/web/frontend/stylesheets/app/plans.less

@@ -484,3 +484,41 @@
     }
     }
   }
   }
 }
 }
+
+.group-subscription-modal {
+  .modal-header {
+    text-align: center;
+  }
+
+  .group-plan-option {
+    display: block;
+
+    span {
+      padding-left: 5px;
+      font-weight: normal;
+    }
+  }
+
+  .educational-discount-badge {
+    height: 50px;
+    padding-top: 25px;
+
+    p {
+      display: inline-block;
+      padding-left: 5px;
+      padding-right: 5px;
+      font-weight: bold;
+      font-size: @font-size-small;
+    }
+
+    .applied {
+      background-color: rgba(@ol-dark-green, 0.1);
+      color: @ol-dark-green;
+    }
+
+    .ineligible {
+      background-color: @ol-blue-gray-0;
+      color: @ol-blue-gray-4;
+    }
+  }
+}