new-refreshed.pug 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. extends ../layout
  2. include ./_new_mixins
  3. block vars
  4. - var suppressNavbarRight = true
  5. - var suppressFooter = true
  6. block append meta
  7. meta(name="ol-countryCode" content=countryCode)
  8. meta(name="ol-recurlyApiKey" content=settings.apis.recurly.publicKey)
  9. meta(name="ol-recommendedCurrency" content=String(currency).slice(0,3))
  10. block head-scripts
  11. script(type="text/javascript", nonce=scriptNonce, src="https://js.recurly.com/v4/recurly.js")
  12. block content
  13. main.content.content-alt#main-content
  14. .container(ng-controller="NewSubscriptionController" ng-cloak)
  15. .row.card-group
  16. .col-md-3.col-md-push-1
  17. .card.card-highlighted
  18. .price-feature-description
  19. h4(ng-if="planName") {{planName}}
  20. h4(ng-if="!planName") #{plan.name}
  21. if plan.features
  22. if plan.features.collaborators === 1
  23. .text-small.number-of-collaborators #{translate("collabs_per_proj_single", {collabcount: 1})}
  24. if plan.features.collaborators === -1
  25. .text-small.number-of-collaborators #{translate("unlimited_collabs")}
  26. if plan.features.collaborators > 1
  27. .text-small.number-of-collaborators #{translate("collabs_per_proj", {collabcount: plan.features.collaborators})}
  28. .text-small #{translate("all_premium_features_including")}
  29. ul.small
  30. if plan.features.compileTimeout > 1
  31. li #{translate("increased_compile_timeout")}
  32. if plan.features.dropbox && plan.features.github
  33. li #{translate("sync_dropbox_github")}
  34. if plan.features.versioning
  35. li #{translate("full_doc_history")}
  36. if plan.features.trackChanges
  37. li #{translate("track_changes")}
  38. if plan.features.references
  39. li #{translate("reference_search")}
  40. if plan.features.mendeley || plan.features.zotero
  41. li #{translate("reference_sync")}
  42. if plan.features.symbolPalette
  43. li #{translate("symbol_palette")}
  44. div.price-summary(ng-if="recurlyPrice")
  45. - var priceVars = { price: "{{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.total }}"};
  46. hr
  47. h4 #{translate("payment_summary")}
  48. div.small
  49. .price-summary-line
  50. span
  51. | {{planName}}
  52. span(ng-if="coupon")
  53. | {{ availableCurrencies[currencyCode]['symbol'] }}{{ coupon.normalPriceWithoutTax | number:2 }}
  54. span(ng-if="!coupon")
  55. | {{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.subtotal }}
  56. .price-summary-line(ng-if="coupon")
  57. span
  58. | {{ coupon.name }}
  59. span
  60. | –{{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.discount}}
  61. .price-summary-line(ng-if="taxes && taxes[0] && taxes[0].rate > 0")
  62. span
  63. | #{translate("vat")} {{taxes[0].rate * 100}}%
  64. span
  65. | {{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.tax }}
  66. .price-summary-line.price-summary-total-line
  67. span
  68. b {{ monthlyBilling ? '#{translate("total_per_month")}' : '#{translate("total_per_year")}'}}
  69. span
  70. b {{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.total }}
  71. .change-currency
  72. div.dropdown(ng-cloak dropdown)
  73. button.btn.btn-link.dropdown-toggle.change-currency-toggle(
  74. href="#",
  75. data-toggle="dropdown",
  76. dropdown-toggle
  77. ) Change currency
  78. ul.dropdown-menu(role="menu")
  79. li(ng-repeat="(currency, value) in limitedCurrencies")
  80. a(
  81. ng-click="changeCurrency(currency)",
  82. )
  83. span.change-currency-dropdown-selected-icon(ng-show="currency == currencyCode")
  84. i.fa.fa-check
  85. | {{currency}} ({{value['symbol']}})
  86. hr.thin(ng-if="trialLength || coupon")
  87. div.trial-coupon-summary
  88. div(ng-if="trialLength")
  89. - var trialPriceVars = { price: "{{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.total }}", trialLen:'{{trialLength}}' };
  90. | !{translate("first_x_days_free_after_that_y_per_month", trialPriceVars, ['strong'] )}
  91. div(ng-if="recurlyPrice")
  92. - var priceVars = { price: "{{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.total }}", discountMonths: "{{ coupon.discountMonths }}" };
  93. span(ng-if="!coupon.singleUse && coupon.discountMonths > 0 && monthlyBilling")
  94. | !{translate("x_price_for_y_months", priceVars, ['strong'] )}
  95. span(ng-if="coupon.singleUse && monthlyBilling")
  96. | !{translate("x_price_for_first_month", priceVars, ['strong'] )}
  97. span(ng-if="coupon.singleUse && !monthlyBilling")
  98. | !{translate("x_price_for_first_year", priceVars, ['strong'] )}
  99. div(ng-if="coupon && coupon.normalPrice")
  100. - var noDiscountPriceAngularExp = "{{ availableCurrencies[currencyCode]['symbol']}}{{coupon.normalPrice | number:2 }}";
  101. span(ng-if="!coupon.singleUse && coupon.discountMonths > 0 && monthlyBilling")
  102. | !{translate("then_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  103. span(ng-if="!coupon.singleUse && !coupon.discountMonths && monthlyBilling")
  104. | !{translate("normally_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  105. span(ng-if="!coupon.singleUse && !monthlyBilling")
  106. | !{translate("normally_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  107. span(ng-if="coupon.singleUse && monthlyBilling")
  108. | !{translate("then_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  109. span(ng-if="coupon.singleUse && !monthlyBilling")
  110. | !{translate("then_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  111. hr.thin
  112. p.price-cancel-anytime.text-center(ng-non-bindable) #{translate("cancel_anytime")}
  113. .col-md-5.col-md-push-1
  114. .card.card-highlighted.card-border(ng-hide="threeDSecureFlow")
  115. .alert.alert-danger(ng-show="recurlyLoadError")
  116. strong #{translate('payment_provider_unreachable_error')}
  117. .price-switch-header(ng-hide="recurlyLoadError")
  118. .row
  119. .col-xs-9
  120. h2 #{translate('select_a_payment_method')}
  121. .row(ng-if="planCode == 'student-annual' || planCode == 'student-monthly' || planCode == 'student_free_trial_7_days'")
  122. .col-xs-12
  123. p.student-disclaimer #{translate('student_disclaimer')}
  124. .row(ng-hide="recurlyLoadError")
  125. div()
  126. .col-md-12()
  127. form(
  128. name="simpleCCForm"
  129. novalidate
  130. )
  131. .alert.alert-warning.small(ng-show="genericError")
  132. strong {{genericError}}
  133. .alert.alert-warning.small(ng-show="couponError")
  134. strong {{couponError}}
  135. div
  136. .form-group.payment-method-toggle
  137. hr.thin
  138. .radio
  139. .col-xs-8
  140. label
  141. input(
  142. type="radio"
  143. ng-model="paymentMethod.value"
  144. name="payment_method"
  145. checked=true
  146. value="credit_card"
  147. )
  148. strong
  149. | #{translate("card_payment")}
  150. span.hidden-xs
  151. |  
  152. i.fa.fa-cc-visa(aria-hidden="true")
  153. |  
  154. i.fa.fa-cc-mastercard(aria-hidden="true")
  155. |  
  156. i.fa.fa-cc-amex(aria-hidden="true")
  157. .col-xs-4
  158. label
  159. input(
  160. type="radio"
  161. ng-model="paymentMethod.value"
  162. name="payment_method"
  163. checked=false
  164. value="paypal"
  165. )
  166. strong PayPal
  167. span.hidden-xs
  168. |  
  169. i.fa.fa-cc-paypal(aria-hidden="true")
  170. div(ng-show="paymentMethod.value === 'credit_card'")
  171. .form-group(ng-class="showCardElementInvalid ? 'has-error' : ''")
  172. label(for="recurly-card-input") #{translate("card_details")}
  173. div#recurly-card-input
  174. span.input-feedback-message(ng-if="showCardElementInvalid") Card details are not valid
  175. .row
  176. .col-xs-6
  177. .form-group(ng-class="validation.errorFields.first_name || inputHasError(simpleCCForm.firstName) ? 'has-error' : ''")
  178. label(for="first-name") #{translate('first_name')}
  179. input#first-name.form-control(
  180. type="text"
  181. maxlength='255'
  182. data-recurly="first_name"
  183. name="firstName"
  184. ng-model="data.first_name"
  185. required
  186. )
  187. span.input-feedback-message(ng-if="simpleCCForm.firstName.$error.required") #{translate('this_field_is_required')}
  188. .col-xs-6
  189. .form-group(ng-class="validation.errorFields.last_name || inputHasError(simpleCCForm.lastName)? 'has-error' : ''")
  190. label(for="last-name") #{translate('last_name')}
  191. input#last-name.form-control(
  192. type="text"
  193. maxlength='255'
  194. data-recurly="last_name"
  195. name="lastName"
  196. ng-model="data.last_name"
  197. required
  198. )
  199. span.input-feedback-message(ng-if="simpleCCForm.lastName.$error.required") #{translate('this_field_is_required')}
  200. div
  201. .row
  202. .col-xs-12
  203. .form-group(ng-class="validation.errorFields.address1 || inputHasError(simpleCCForm.address1) ? 'has-error' : ''")
  204. label(for="address-line-1") #{translate('address_line_1')}  
  205. i.fa.fa-question-circle(
  206. aria-label=translate('this_address_will_be_shown_on_the_invoice'),
  207. tooltip=translate('this_address_will_be_shown_on_the_invoice'),
  208. tooltip-placement="right",
  209. tooltip-append-to-body="true",
  210. )
  211. input#address-line-1.form-control(
  212. type="text"
  213. maxlength="255"
  214. data-recurly="address1"
  215. name="address1"
  216. ng-model="data.address1"
  217. required
  218. )
  219. span.input-feedback-message(ng-if="simpleCCForm.address1.$error.required") #{translate('this_field_is_required')}
  220. .row.toggle-address-second-line(ng-hide="ui.showAddressSecondLine")
  221. .col-xs-12
  222. a.text-small(
  223. href="#"
  224. ng-click="showAddressSecondLine($event)"
  225. ) + Add another address line
  226. .row(ng-show="ui.showAddressSecondLine")
  227. .col-xs-12
  228. .form-group.has-feedback(ng-class="validation.errorFields.address2 ? 'has-error' : ''")
  229. label(for="address-line-2") #{translate('address_second_line_optional')}
  230. input#address-line-2.form-control(
  231. type="text"
  232. maxlength="255"
  233. data-recurly="address2"
  234. name="address2"
  235. ng-model="data.address2"
  236. )
  237. .row
  238. .col-xs-4
  239. .form-group(ng-class="validation.errorFields.postal_code || inputHasError(simpleCCForm.postalCode) ? 'has-error' : ''")
  240. label(for="postal-code") #{translate('postal_code')}
  241. input#postal-code.form-control(
  242. type="text"
  243. maxlength="255"
  244. data-recurly="postal_code"
  245. name="postalCode"
  246. ng-model="data.postal_code"
  247. required
  248. )
  249. span.input-feedback-message(ng-if="simpleCCForm.postalCode.$error.required") #{translate('this_field_is_required')}
  250. .col-xs-8
  251. .form-group(ng-class="validation.errorFields.country || inputHasError(simpleCCForm.country) ? 'has-error' : ''")
  252. label(for="country") #{translate('country')}
  253. select#country.form-control(
  254. data-recurly="country"
  255. ng-model="data.country"
  256. name="country"
  257. ng-change="updateCountry()"
  258. ng-selected="{{country.code == data.country}}"
  259. ng-model-options="{ debounce: 200 }"
  260. required
  261. )
  262. option(value='', disabled) #{translate("country")}
  263. option(value='-', disabled) --------------
  264. option(ng-repeat="country in countries" ng-bind-html="country.name" value="{{country.code}}")
  265. span.input-feedback-message(ng-if="simpleCCForm.country.$error.required") #{translate('this_field_is_required')}
  266. .form-group
  267. .checkbox
  268. label
  269. input(
  270. type="checkbox"
  271. ng-model="ui.addCompanyDetails"
  272. )
  273. |
  274. | #{translate("add_company_details")}
  275. .form-group(ng-show="ui.addCompanyDetails")
  276. label(for="company-name") #{translate("company_name")}
  277. input#company-name.form-control(
  278. type="text"
  279. name="companyName"
  280. ng-model="data.company"
  281. )
  282. .form-group(ng-show="ui.addCompanyDetails && taxes.length")
  283. label(for="vat-number") #{translate("vat_number")}
  284. input#vat-number.form-control(
  285. type="text"
  286. name="vatNumber"
  287. ng-model="data.vat_number"
  288. ng-blur="applyVatNumber()"
  289. )
  290. if (showCouponField)
  291. .form-group
  292. label(for="coupon-code") #{translate('coupon_code')}
  293. input#coupon-code.form-control(
  294. type="text"
  295. ng-blur="applyCoupon()"
  296. ng-model="data.coupon"
  297. )
  298. p(ng-if="paymentMethod.value === 'paypal'") #{translate("proceeding_to_paypal_takes_you_to_the_paypal_site_to_pay")}
  299. hr.thin
  300. div.payment-submit
  301. button.btn.btn-primary.btn-block(
  302. ng-click="submit()"
  303. ng-disabled="processing || !isFormValid(simpleCCForm);"
  304. )
  305. span(ng-show="processing")
  306. i.fa.fa-spinner.fa-spin(aria-hidden="true")
  307. span.sr-only #{translate('processing')}
  308. |  
  309. span(ng-if="paymentMethod.value === 'credit_card'")
  310. | {{ trialLength ? '#{translate("upgrade_cc_btn")}' : '#{translate("upgrade_now")}'}}
  311. span(ng-if="paymentMethod.value !== 'credit_card'") #{translate("proceed_to_paypal")}
  312. p.tos-agreement-notice !{translate("by_subscribing_you_agree_to_our_terms_of_service", {}, [{name: 'a', attrs: {href: '/legal#Terms', target:'_blank', rel:'noopener noreferrer'}}])}
  313. div.three-d-secure-container.card.card-highlighted.card-border(ng-show="threeDSecureFlow")
  314. .alert.alert-info.small(aria-live="assertive")
  315. strong #{translate('card_must_be_authenticated_by_3dsecure')}
  316. div.three-d-secure-recurly-container
  317. script(type="text/javascript", nonce=scriptNonce).
  318. ga('send', 'event', 'pageview', 'payment_form', "#{plan_code}")
  319. script(
  320. type="text/ng-template"
  321. id="cvv-tooltip-tpl.html"
  322. )
  323. p !{translate("for_visa_mastercard_and_discover", {}, ['strong', 'strong', 'strong'])}
  324. p !{translate("for_american_express", {}, ['strong', 'strong', 'strong'])}
  325. +studentCheckModal