new.pug 15 KB

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