Przeglądaj źródła

Add annual saving tooltip & add a striked-through text on the annual price to current plans page

Co-authored-by: Thomas Mees <thomas.mees@overleaf.com>
GitOrigin-RevId: 25a9b7b12ddd00588a8e4c43b55f2d7c57048818
M Fahru 4 lat temu
rodzic
commit
cf0b46ecf2

+ 42 - 11
services/web/app/views/subscriptions/plans-marketing/_mixins.pug

@@ -132,12 +132,20 @@ mixin gen_localized_price_for_plan_view(plan, view)
 			data-ol-currencyCode=currencyCode
 		) #{settings.localizedPlanPricing[currencyCode][plan][view]}
 
-mixin gen_localized_undiscounted_price_for_plan_view(plan, view)
+mixin gen_localized_undiscounted_price_for_plan_view_personal(view)
 	for currencyCode in Object.keys(settings.localizedPlanPricing)
 		span(
 			hidden=(currencyCode !== recommendedCurrency)
 			data-ol-currencyCode=currencyCode
-		) #{settings.localizedPlanPricing[currencyCode][plan]['withoutDiscount'][view]}
+		) #{settings.localizedPlanPricing[currencyCode]['personal']['withoutDiscount'][view]}
+
+mixin gen_localized_undiscounted_price_for_plan_view(plan)
+	for currencyCode in Object.keys(settings.localizedPlanPricing)
+		span(
+			hidden=(currencyCode !== recommendedCurrency)
+			data-ol-currencyCode=currencyCode
+		) #{settings.localizedPlanPricing[currencyCode][plan]['monthlyTimesTwelve']}
+
 
 mixin gen_localized_price_for_plan(plan)
 	div(data-ol-view='monthly')
@@ -147,27 +155,38 @@ mixin gen_localized_price_for_plan(plan)
 		+gen_localized_price_for_plan_view(plan, 'annual')
 		span.small /yr
 
-mixin gen_localized_undiscounted_price_for_plan(plan)
+mixin gen_localized_undiscounted_price_for_plan_personal()
 	div(data-ol-view='monthly')
-		.undiscounted-price.small
+		strike.undiscounted-price.small
 			span.sr-only Price reduced from
-			+gen_localized_undiscounted_price_for_plan_view(plan, 'monthly')
+			+gen_localized_undiscounted_price_for_plan_view_personal('monthly')
 			| /mo
 	div(hidden data-ol-view='annual')
-		.undiscounted-price.small
+		strike.undiscounted-price.small
+			span.sr-only Price reduced from
+			+gen_localized_undiscounted_price_for_plan_view_personal('annual')
+			| /yr
+
+mixin gen_localized_undiscounted_price_for_plan(plan)
+	div(hidden data-ol-view='annual')
+		strike.undiscounted-price.small
 			span.sr-only Price reduced from
-			+gen_localized_undiscounted_price_for_plan_view(plan, 'annual')
+			+gen_localized_undiscounted_price_for_plan_view(plan)
 			| /yr
 
 //- Prices
 mixin price_personal
 	+gen_localized_price_for_plan('personal')
 mixin price_personal_undiscounted
-	+gen_localized_undiscounted_price_for_plan('personal')
+	+gen_localized_undiscounted_price_for_plan_personal()
 mixin price_collaborator
 	+gen_localized_price_for_plan('collaborator')
+mixin price_collaborator_undiscounted
+	+gen_localized_undiscounted_price_for_plan('collaborator')
 mixin price_professional
 	+gen_localized_price_for_plan('professional')
+mixin price_professional_undiscounted
+	+gen_localized_undiscounted_price_for_plan('professional')
 mixin price_student_annual
 	+gen_localized_price_for_plan_view('student', 'annual')
 	span.small /yr
@@ -199,15 +218,25 @@ mixin currency_dropdown
 					) #{currencyCode} #{settings.localizedPlanPricing[currencyCode]['symbol']}
 
 mixin plan_switch(location)
-	ul.nav.nav-pills
+	ul.nav.nav-pills(class=(location === 'card' ? "above-cards" : ""))
 		li.active(data-ol-view-tab='monthly')
 			a.btn.btn-default-outline(
 				href="#"
 			) #{translate("monthly")}
-		li(data-ol-view-tab='annual')
+		li(data-ol-view-tab='annual' class=(location === 'card' ? "annual-saving-tooltip-container" : ""))
 			a.btn.btn-default-outline(
 				href="#"
 			) #{translate("annual")}
+			if (location === 'card')
+				.tooltip.in.bottom.annual-saving-tooltip(
+					role="tooltip"
+					data-ol-annual-saving-tooltip
+				)
+					.tooltip-arrow
+					.tooltip-inner
+						span(data-ol-view="monthly") #{translate("save_20_percent_by_paying_annually")}
+						span(hidden data-ol-view="annual") #{translate("saving_20_percent")}
+						span(hidden data-ol-view="student") #{translate("save_20_percent_by_paying_annually")}
 		li(data-ol-view-tab='student')
 			a.btn.btn-default-outline(
 				href="#"
@@ -217,7 +246,7 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
 	- var location = listLocation ? 'card_' + listLocation : 'card'
 	.row.top-switch(class=(controlsRowSpaced ? "row-spaced" : ""))
 		.col-md-6.col-md-offset-3
-			+plan_switch('card')
+			+plan_switch(location)
 		.col-md-2.text-right
 			+currency_dropdown
 
@@ -250,6 +279,7 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
 									h5.tagline #{translate("tagline_collaborator")}
 								.circle
 									+price_collaborator
+									+price_collaborator_undiscounted
 								+features_collaborator(location)
 						.col-md-4
 							.card.card-last
@@ -259,6 +289,7 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
 									h5.tagline #{translate("tagline_professional")}
 								.circle
 									+price_professional
+									+price_professional_undiscounted
 								+features_professional(location)
 
 				.card-group.text-centered(hidden data-ol-view='student')

+ 11 - 1
services/web/frontend/js/pages/user/subscription/plans.js

@@ -1,6 +1,5 @@
 import '../../../marketing'
 import '../../../features/plans/group-plan-modal'
-
 import * as eventTracking from '../../../infrastructure/event-tracking'
 import getMeta from '../../../utils/meta'
 
@@ -18,6 +17,7 @@ function selectView(view) {
   document.querySelectorAll('[data-ol-view]').forEach(el => {
     el.hidden = el.getAttribute('data-ol-view') !== view
   })
+  updateAnnualSavingBanner(view)
   currentView = view
   updateLinkTargets()
 }
@@ -81,6 +81,16 @@ function updateLinkTargets() {
   })
 }
 
+function updateAnnualSavingBanner(view) {
+  const tooltipEl = document.querySelector('[data-ol-annual-saving-tooltip]')
+
+  if (view === 'annual') {
+    tooltipEl.classList.add('annual-selected')
+  } else {
+    tooltipEl.classList.remove('annual-selected')
+  }
+}
+
 function selectViewFromHash() {
   try {
     const params = new URLSearchParams(window.location.hash.substring(1))

+ 42 - 1
services/web/frontend/stylesheets/app/plans.less

@@ -85,7 +85,7 @@
       font-size: @font-size-base * 0.8;
     }
     .undiscounted-price {
-      text-decoration: line-through;
+      display: block;
       margin-top: -48px;
     }
   }
@@ -135,14 +135,42 @@
   ul.nav-pills {
     text-align: center;
     margin-bottom: @line-height-computed;
+    display: flex;
+    justify-content: center;
     li {
       float: none;
       display: inline-block;
+      position: relative;
+      .annual-saving-tooltip {
+        white-space: nowrap;
+        left: 50%;
+        width: 200px;
+        margin-left: -100px;
+        &.bottom {
+          margin-top: 0px;
+        }
+        &.annual-selected {
+          width: 94px;
+          margin-left: -47px;
+          .tooltip-inner {
+            background-color: @ol-green;
+          }
+          .tooltip-arrow {
+            border-bottom-color: @ol-green;
+          }
+        }
+        .tooltip-inner {
+          max-width: none;
+        }
+      }
     }
     > li + li {
       margin-left: @line-height-computed / 2;
     }
   }
+  ul.nav-pills.above-cards {
+    margin-bottom: @line-height-computed * 2;
+  }
 }
 
 #changePlanSection {
@@ -210,6 +238,19 @@
     }
   }
 }
+@media (max-width: @screen-xs-max) {
+  .plans ul.nav-pills {
+    li {
+      a {
+        font-size: @font-size-small;
+        padding: 8px 10px;
+      }
+    }
+    > li + li {
+      margin-left: @margin-sm;
+    }
+  }
+}
 @media (min-width: @screen-md-min) {
   .plans {
     blockquote {

+ 3 - 1
services/web/locales/en.json

@@ -1640,5 +1640,7 @@
   "change_primary_email_address_instructions": "To change your primary email, please add your new primary email address first (by clicking <0>Add another email</0>) and confirm it. Then click the <0>Make Primary</0> button. <1>Learn more</1> about managing your __appName__ emails.",
   "help_improve_overleaf_fill_out_this_survey": "If you would like to help us improve Overleaf, please take a moment to fill out <0>this survey</0>.",
   "unlink_dropbox_folder": "Unlink Dropbox Account",
-  "unlink_dropbox_warning": "Any projects that you have synced with Dropbox will be disconnected and no longer kept in sync with Dropbox. Are you sure you want to unlink your Dropbox account?"
+  "unlink_dropbox_warning": "Any projects that you have synced with Dropbox will be disconnected and no longer kept in sync with Dropbox. Are you sure you want to unlink your Dropbox account?",
+  "save_20_percent_by_paying_annually": "Save 20% by paying annually",
+  "saving_20_percent": "Saving 20%!"
 }