new-updated.pug 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. extends ../layout
  2. block append meta
  3. meta(name="ol-countryCode" content=countryCode)
  4. meta(name="ol-recurlyApiKey" content=settings.apis.recurly.publicKey)
  5. meta(name="ol-recommendedCurrency" content=String(currency).slice(0,3))
  6. block head-scripts
  7. script(type="text/javascript", nonce=scriptNonce, src="https://js.recurly.com/v4/recurly.js")
  8. block content
  9. main.content.content-alt#main-content
  10. .container(ng-controller="NewSubscriptionController" ng-cloak)
  11. .row.card-group
  12. .col-md-3.col-md-push-1
  13. if showStudentPlan
  14. a.btn-primary.btn.plansPageStudentLink(
  15. href,
  16. ng-click="switchToStudent()"
  17. ) #{translate("special_price_student")}
  18. .card.card-first
  19. .price-feature-description
  20. h4(ng-if="planName") {{planName}}
  21. h4(ng-if="!planName") #{plan.name}
  22. if plan.features
  23. ul.small
  24. if plan.features.collaborators === 1
  25. li #{translate("collabs_per_proj_single", {collabcount: 1})}
  26. if plan.features.collaborators === -1
  27. li #{translate("unlimited_collabs")}
  28. if plan.features.collaborators > 1
  29. li #{translate("collabs_per_proj", {collabcount: plan.features.collaborators})}
  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.symbolyPalette
  43. li #{translate("symboly_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. div.small.price-details-spacing(ng-if="trialLength || coupon")
  72. div.small(ng-if="trialLength") !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})}
  73. div.small(ng-if="recurlyPrice")
  74. - var priceVars = { price: "{{ availableCurrencies[currencyCode]['symbol'] }}{{ recurlyPrice.total }}", discountMonths: "{{ coupon.discountMonths }}" };
  75. span(ng-if="!coupon.singleUse && coupon.discountMonths > 0 && monthlyBilling")
  76. | !{translate("x_price_for_y_months", priceVars, ['strong'] )}
  77. span(ng-if="coupon.singleUse && monthlyBilling")
  78. | !{translate("x_price_for_first_month", priceVars, ['strong'] )}
  79. span(ng-if="coupon.singleUse && !monthlyBilling")
  80. | !{translate("x_price_for_first_year", priceVars, ['strong'] )}
  81. div.small(ng-if="coupon && coupon.normalPrice")
  82. - var noDiscountPriceAngularExp = "{{ availableCurrencies[currencyCode]['symbol']}}{{coupon.normalPrice | number:2 }}";
  83. span(ng-if="!coupon.singleUse && coupon.discountMonths > 0 && monthlyBilling")
  84. | !{translate("then_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  85. span(ng-if="!coupon.singleUse && !coupon.discountMonths && monthlyBilling")
  86. | !{translate("normally_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  87. span(ng-if="!coupon.singleUse && !monthlyBilling")
  88. | !{translate("normally_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  89. span(ng-if="coupon.singleUse && monthlyBilling")
  90. | !{translate("then_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  91. span(ng-if="coupon.singleUse && !monthlyBilling")
  92. | !{translate("then_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  93. hr
  94. p.price-cancel-anytime.text-center(ng-non-bindable) !{translate("cancel_anytime", { appName:'{{settings.appName}}' })}
  95. .col-md-5.col-md-push-1
  96. .card.card-highlighted.card-border(ng-hide="threeDSecureFlow")
  97. .alert.alert-danger(ng-show="recurlyLoadError")
  98. strong #{translate('payment_provider_unreachable_error')}
  99. .price-switch-header(ng-hide="recurlyLoadError")
  100. .row
  101. .col-xs-9
  102. h2 {{planName}}
  103. .col-xs-3
  104. div.dropdown.changePlanButton.pull-right(ng-cloak, dropdown)
  105. a.btn.btn-default.dropdown-toggle(
  106. href="#",
  107. data-toggle="dropdown",
  108. dropdown-toggle
  109. )
  110. | {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}})
  111. span.caret
  112. ul.dropdown-menu(role="menu")
  113. li(ng-repeat="(currency, value) in availableCurrencies")
  114. a(
  115. ng-click="changeCurrency(currency)",
  116. ) {{currency}} ({{value['symbol']}})
  117. .row(ng-if="planCode == 'student-annual' || planCode == 'student-monthly' || planCode == 'student_free_trial_7_days'")
  118. .col-xs-12
  119. p.student-disclaimer #{translate('student_disclaimer')}
  120. .row(ng-hide="recurlyLoadError")
  121. div()
  122. .col-md-12()
  123. form(
  124. name="simpleCCForm"
  125. novalidate
  126. )
  127. div.payment-method-toggle
  128. a.payment-method-toggle-switch(
  129. href
  130. ng-click="setPaymentMethod('credit_card');"
  131. ng-class="paymentMethod.value === 'credit_card' ? 'payment-method-toggle-switch-selected' : ''"
  132. )
  133. i.fa.fa-cc-mastercard.fa-2x(aria-hidden="true")
  134. span  
  135. i.fa.fa-cc-visa.fa-2x(aria-hidden="true")
  136. span  
  137. i.fa.fa-cc-amex.fa-2x(aria-hidden="true")
  138. span.sr-only Pay with Mastercard, Visa, or Amex
  139. a.payment-method-toggle-switch(
  140. href
  141. ng-click="setPaymentMethod('paypal');"
  142. ng-class="paymentMethod.value === 'paypal' ? 'payment-method-toggle-switch-selected' : ''"
  143. )
  144. i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")
  145. span.sr-only Pay with PayPal
  146. .alert.alert-warning.small(ng-show="genericError")
  147. strong {{genericError}}
  148. .alert.alert-warning.small(ng-show="couponError")
  149. strong {{couponError}}
  150. div(ng-show="paymentMethod.value === 'credit_card'")
  151. .row
  152. .col-xs-6
  153. .form-group(ng-class="validation.errorFields.first_name || inputHasError(simpleCCForm.firstName) ? 'has-error' : ''")
  154. label(for="first-name") #{translate('first_name')}
  155. input#first-name.form-control(
  156. type="text"
  157. maxlength='255'
  158. data-recurly="first_name"
  159. name="firstName"
  160. ng-model="data.first_name"
  161. required
  162. )
  163. span.input-feedback-message(ng-if="simpleCCForm.firstName.$error.required") #{translate('this_field_is_required')}
  164. .col-xs-6
  165. .form-group(ng-class="validation.errorFields.last_name || inputHasError(simpleCCForm.lastName)? 'has-error' : ''")
  166. label(for="last-name") #{translate('last_name')}
  167. input#last-name.form-control(
  168. type="text"
  169. maxlength='255'
  170. data-recurly="last_name"
  171. name="lastName"
  172. ng-model="data.last_name"
  173. required
  174. )
  175. span.input-feedback-message(ng-if="simpleCCForm.lastName.$error.required") #{translate('this_field_is_required')}
  176. .form-group(ng-class="validation.errorFields.number ? 'has-error' : ''")
  177. label(for="card-no") #{translate("credit_card_number")}
  178. div#card-no(
  179. type="text"
  180. name="ccNumber"
  181. data-recurly='number'
  182. )
  183. .row
  184. .col-xs-3
  185. .form-group.has-feedback(ng-class="validation.errorFields.month ? 'has-error' : ''")
  186. label(for="month").capitalised #{translate("month")}
  187. div(
  188. type="number"
  189. name="month"
  190. data-recurly="month"
  191. )
  192. .col-xs-3
  193. .form-group.has-feedback(ng-class="validation.errorFields.year ? 'has-error' : ''")
  194. label(for="year").capitalised #{translate("year")}
  195. div(
  196. type="number"
  197. name="year"
  198. data-recurly="year"
  199. )
  200. .col-xs-6
  201. .form-group.has-feedback(ng-class="validation.errorFields.cvv ? 'has-error' : ''")
  202. label #{translate("security_code")}
  203. div(
  204. type="number"
  205. ng-model="data.cvv"
  206. data-recurly="cvv"
  207. name="cvv"
  208. cc-format-sec-code
  209. )
  210. .form-control-feedback
  211. a.form-helper(
  212. href
  213. tabindex="-1"
  214. tooltip-template="'cvv-tooltip-tpl.html'"
  215. tooltip-trigger="mouseenter"
  216. tooltip-append-to-body="true"
  217. ) ?
  218. div
  219. .row
  220. .col-xs-12
  221. .form-group(ng-class="validation.errorFields.address1 || inputHasError(simpleCCForm.address1) ? 'has-error' : ''")
  222. label(for="address-line-1") #{translate('address_line_1')}
  223. input#address-line-1.form-control(
  224. type="text"
  225. maxlength="255"
  226. data-recurly="address1"
  227. name="address1"
  228. ng-model="data.address1"
  229. required
  230. )
  231. span.input-feedback-message(ng-if="simpleCCForm.address1.$error.required") #{translate('this_field_is_required')}
  232. .row
  233. .col-xs-12
  234. .form-group.has-feedback(ng-class="validation.errorFields.address2 ? 'has-error' : ''")
  235. label(for="address-line-2") #{translate('address_line_2')}
  236. input#address-line-2.form-control(
  237. type="text"
  238. maxlength="255"
  239. data-recurly="address2"
  240. name="address2"
  241. ng-model="data.address2"
  242. )
  243. .row
  244. .col-xs-4
  245. .form-group(ng-class="validation.errorFields.postal_code || inputHasError(simpleCCForm.postalCode) ? 'has-error' : ''")
  246. label(for="postal-code") #{translate('postal_code')}
  247. input#postal-code.form-control(
  248. type="text"
  249. maxlength="255"
  250. data-recurly="postal_code"
  251. name="postalCode"
  252. ng-model="data.postal_code"
  253. required
  254. )
  255. span.input-feedback-message(ng-if="simpleCCForm.postalCode.$error.required") #{translate('this_field_is_required')}
  256. .col-xs-8
  257. .form-group(ng-class="validation.errorFields.country || inputHasError(simpleCCForm.country) ? 'has-error' : ''")
  258. label(for="country") #{translate('country')}
  259. select#country.form-control(
  260. data-recurly="country"
  261. ng-model="data.country"
  262. name="country"
  263. ng-change="updateCountry()"
  264. ng-selected="{{country.code == data.country}}"
  265. ng-model-options="{ debounce: 200 }"
  266. required
  267. )
  268. option(value='', disabled) #{translate("country")}
  269. option(value='-', disabled) --------------
  270. option(ng-repeat="country in countries" ng-bind-html="country.name" value="{{country.code}}")
  271. span.input-feedback-message(ng-if="simpleCCForm.country.$error.required") #{translate('this_field_is_required')}
  272. .form-group
  273. .checkbox
  274. label
  275. input(
  276. type="checkbox"
  277. ng-model="ui.addCompanyDetails"
  278. )
  279. |
  280. | #{translate("add_company_details")}
  281. .form-group(ng-show="ui.addCompanyDetails")
  282. label(for="company-name") #{translate("company_name")}
  283. input#company-name.form-control(
  284. type="text"
  285. name="companyName"
  286. ng-model="data.company"
  287. )
  288. .form-group(ng-show="ui.addCompanyDetails && taxes.length")
  289. label(for="vat-number") #{translate("vat_number")}
  290. input#vat-number.form-control(
  291. type="text"
  292. name="vatNumber"
  293. ng-model="data.vat_number"
  294. ng-blur="applyVatNumber()"
  295. )
  296. if (showCouponField)
  297. .form-group
  298. label(for="coupon-code") #{translate('coupon_code')}
  299. input#coupon-code.form-control(
  300. type="text"
  301. ng-blur="applyCoupon()"
  302. ng-model="data.coupon"
  303. )
  304. p(ng-if="paymentMethod.value === 'paypal'") #{translate("paypal_upgrade")}
  305. div.payment-submit
  306. button.btn.btn-success.btn-block(
  307. ng-click="submit()"
  308. ng-disabled="processing || !isFormValid(simpleCCForm);"
  309. )
  310. span(ng-show="processing")
  311. i.fa.fa-spinner.fa-spin(aria-hidden="true")
  312. span.sr-only #{translate('processing')}
  313. |  
  314. span(ng-if="paymentMethod.value === 'credit_card'")
  315. | {{ trialLength ? '#{translate("upgrade_cc_btn")}' : '#{translate("upgrade_now")}'}}
  316. span(ng-if="paymentMethod.value !== 'credit_card'") #{translate("upgrade_paypal_btn")}
  317. 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'}}])}
  318. div.three-d-secure-container.card.card-highlighted.card-border(ng-show="threeDSecureFlow")
  319. .alert.alert-info.small(aria-live="assertive")
  320. strong #{translate('card_must_be_authenticated_by_3dsecure')}
  321. div.three-d-secure-recurly-container
  322. script(type="text/javascript", nonce=scriptNonce).
  323. ga('send', 'event', 'pageview', 'payment_form', "#{plan_code}")
  324. script(
  325. type="text/ng-template"
  326. id="cvv-tooltip-tpl.html"
  327. )
  328. p !{translate("for_visa_mastercard_and_discover", {}, ['strong', 'strong', 'strong'])}
  329. p !{translate("for_american_express", {}, ['strong', 'strong', 'strong'])}