new.pug 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. extends ../layout
  2. block head-scripts
  3. script(src="https://js.recurly.com/v4/recurly.js")
  4. script(type='text/javascript').
  5. window.countryCode = '#{countryCode}'
  6. window.plan_code = '#{plan_code}'
  7. window.recurlyApiKey = "!{settings.apis.recurly.publicKey}"
  8. window.couponCode = !{StringHelper.stringifyJsonForScript(couponCode)}
  9. window.recomendedCurrency = !{StringHelper.stringifyJsonForScript(currency.slice(0,3))}
  10. window.ITMCampaign = '#{ITMCampaign}'
  11. window.ITMContent = '#{ITMContent}'
  12. block content
  13. .content.content-alt
  14. .container(ng-controller="NewSubscriptionController" ng-cloak)
  15. .row.card-group
  16. .col-md-5.col-md-push-4
  17. .card.card-highlighted.card-border(ng-hide="threeDSecureFlow")
  18. .alert.alert-danger(ng-show="recurlyLoadError")
  19. strong #{translate('payment_provider_unreachable_error')}
  20. .page-header(ng-hide="recurlyLoadError")
  21. .row
  22. .col-xs-9
  23. h2 {{planName}}
  24. .col-xs-3
  25. div.dropdown.changePlanButton.pull-right(ng-cloak, dropdown)
  26. a.btn.btn-default.dropdown-toggle(
  27. href="#",
  28. data-toggle="dropdown",
  29. dropdown-toggle
  30. )
  31. | {{currencyCode}} ({{allCurrencies[currencyCode]['symbol']}})
  32. span.caret
  33. ul.dropdown-menu(role="menu")
  34. li(ng-repeat="(currency, value) in availableCurrencies")
  35. a(
  36. ng-click="changeCurrency(currency)",
  37. ) {{currency}} ({{value['symbol']}})
  38. .row(ng-if="planCode == 'student-annual' || planCode == 'student-monthly' || planCode == 'student_free_trial_7_days'")
  39. .col-xs-12
  40. p.student-disclaimer #{translate('student_disclaimer')}
  41. hr.thin
  42. .row
  43. .col-md-12.text-center
  44. div(ng-if="trialLength")
  45. span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})}
  46. span(ng-if="coupon.discountMonths && coupon.discountRate")   - {{coupon.discountMonths}} #{translate("month")}s {{coupon.discountRate}}% Off
  47. div(ng-if="price")
  48. - var priceAngularExp = "<strong>{{ availableCurrencies[currencyCode]['symbol'] }}{{ price.total }}</strong>";
  49. span(ng-if="!coupon.singleUse && monthlyBilling")
  50. | !{translate("x_price_per_month", { price: priceAngularExp } )}
  51. span(ng-if="!coupon.singleUse && !monthlyBilling")
  52. | !{translate("x_price_per_year", { price: priceAngularExp } )}
  53. span(ng-if="coupon.singleUse && monthlyBilling")
  54. | !{translate("x_price_for_first_month", { price: priceAngularExp } )}
  55. span(ng-if="coupon.singleUse && !monthlyBilling")
  56. | !{translate("x_price_for_first_year", { price: priceAngularExp } )}
  57. div(ng-if="coupon && coupon.normalPrice")
  58. - var noDiscountPriceAngularExp = "{{ availableCurrencies[currencyCode]['symbol']}}{{coupon.normalPrice | number:2 }}";
  59. span.small(ng-if="!coupon.singleUse && monthlyBilling")
  60. | !{translate("normally_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  61. span.small(ng-if="!coupon.singleUse && !monthlyBilling")
  62. | !{translate("normally_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  63. span.small(ng-if="coupon.singleUse && monthlyBilling")
  64. | !{translate("then_x_price_per_month", { price: noDiscountPriceAngularExp } )}
  65. span.small(ng-if="coupon.singleUse && !monthlyBilling")
  66. | !{translate("then_x_price_per_year", { price: noDiscountPriceAngularExp } )}
  67. .row(ng-hide="recurlyLoadError")
  68. div()
  69. .col-md-12()
  70. form(
  71. name="simpleCCForm"
  72. novalidate
  73. )
  74. div.payment-method-toggle
  75. a.payment-method-toggle-switch(
  76. href
  77. ng-click="setPaymentMethod('credit_card');"
  78. ng-class="paymentMethod.value === 'credit_card' ? 'payment-method-toggle-switch-selected' : ''"
  79. )
  80. i.fa.fa-cc-mastercard.fa-2x(aria-hidden="true")
  81. span &nbsp;
  82. i.fa.fa-cc-visa.fa-2x(aria-hidden="true")
  83. span &nbsp;
  84. i.fa.fa-cc-amex.fa-2x(aria-hidden="true")
  85. span.sr-only Pay with Mastercard, Visa, or Amex
  86. a.payment-method-toggle-switch(
  87. href
  88. ng-click="setPaymentMethod('paypal');"
  89. ng-class="paymentMethod.value === 'paypal' ? 'payment-method-toggle-switch-selected' : ''"
  90. )
  91. i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")
  92. span.sr-only Pay with PayPal
  93. .alert.alert-warning.small(ng-show="genericError")
  94. strong {{genericError}}
  95. div(ng-show="paymentMethod.value === 'credit_card'")
  96. .row
  97. .col-xs-6
  98. .form-group(ng-class="validation.errorFields.first_name || inputHasError(simpleCCForm.firstName) ? 'has-external-error' : ''")
  99. label(for="first-name") #{translate('first_name')}
  100. input#first-name.form-control(
  101. type="text"
  102. maxlength='255'
  103. data-recurly="first_name"
  104. name="firstName"
  105. ng-model="data.first_name"
  106. required
  107. )
  108. span.input-feedback-message {{ simpleCCForm.firstName.$error.required ? 'This field is required' : '' }}
  109. .col-xs-6
  110. .form-group(for="last-name",ng-class="validation.errorFields.last_name || inputHasError(simpleCCForm.lastName)? 'has-external-error' : ''")
  111. label(for="last-name") #{translate('last_name')}
  112. input#last-name.form-control(
  113. type="text"
  114. maxlength='255'
  115. data-recurly="last_name"
  116. name="lastName"
  117. ng-model="data.last_name"
  118. required
  119. )
  120. .form-group(ng-class="validation.errorFields.number ? 'has-external-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-external-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-external-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-external-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. .form-group(ng-class="validation.errorFields.country || inputHasError(simpleCCForm.country) ? 'has-external-error' : ''")
  164. label(for="country") #{translate('country')}
  165. select#country.form-control(
  166. data-recurly="country"
  167. ng-model="data.country"
  168. name="country"
  169. ng-change="updateCountry()"
  170. ng-selected="{{country.code == data.country}}"
  171. ng-model-options="{ debounce: 200 }"
  172. required
  173. )
  174. option(value='', disabled) #{translate("country")}
  175. option(value='-', disabled) --------------
  176. option(ng-repeat="country in countries" ng-bind-html="country.name" value="{{country.code}}")
  177. span.input-feedback-message {{ simpleCCForm.country.$error.required ? 'This field is required' : '' }}
  178. .form-group
  179. .checkbox
  180. label
  181. input(
  182. type="checkbox"
  183. ng-model="ui.addCompanyDetails"
  184. )
  185. |
  186. | #{translate("add_company_details")}
  187. .form-group(ng-show="ui.addCompanyDetails")
  188. label(for="company-name") #{translate("company_name")}
  189. input#company-name.form-control(
  190. type="text"
  191. name="companyName"
  192. ng-model="data.company"
  193. )
  194. .form-group(ng-show="ui.addCompanyDetails && taxes.length")
  195. label(for="vat-number") #{translate("vat_number")}
  196. input#vat-number.form-control(
  197. type="text"
  198. name="vatNumber"
  199. ng-model="data.vat_number"
  200. ng-blur="applyVatNumber()"
  201. )
  202. if (showCouponField)
  203. .form-group
  204. label(for="coupon-code") #{translate('coupon_code')}
  205. input#coupon-code.form-control(
  206. type="text"
  207. ng-blur="applyCoupon()"
  208. ng-model="data.coupon"
  209. )
  210. p(ng-if="paymentMethod.value === 'paypal'") #{translate("paypal_upgrade")}
  211. div.price-breakdown(
  212. ng-show="taxes.length"
  213. )
  214. - var priceBreakdownAngularExp = "<strong>{{ availableCurrencies[currencyCode]['symbol'] }}{{ price.total }}</strong>";
  215. - priceBreakdownAngularExp += " ({{availableCurrencies[currencyCode]['symbol']}}{{ price.subtotal }}";
  216. - priceBreakdownAngularExp += " + " ;
  217. - priceBreakdownAngularExp += "{{availableCurrencies[currencyCode]['symbol']}}{{ price.tax }} tax)";
  218. hr.thin
  219. span
  220. | Total:
  221. |
  222. span(ng-if="!coupon.singleUse && monthlyBilling")
  223. | !{translate("x_price_per_month", { price: priceBreakdownAngularExp } )}
  224. span(ng-if="!coupon.singleUse && !monthlyBilling")
  225. | !{translate("x_price_per_year", { price: priceBreakdownAngularExp } )}
  226. span(ng-if="coupon.singleUse && monthlyBilling")
  227. | !{translate("x_price_for_first_month", { price: priceBreakdownAngularExp } )}
  228. span(ng-if="coupon.singleUse && !monthlyBilling")
  229. | !{translate("x_price_for_first_year", { price: priceBreakdownAngularExp } )}
  230. hr.thin
  231. div.payment-submit
  232. button.btn.btn-success.btn-block(
  233. ng-click="submit()"
  234. ng-disabled="processing || !isFormValid(simpleCCForm);"
  235. )
  236. span(ng-show="processing")
  237. i.fa.fa-spinner.fa-spin(aria-hidden="true")
  238. span.sr-only #{translate('processing')}
  239. | &nbsp;
  240. span(ng-if="paymentMethod.value === 'credit_card'")
  241. | {{ monthlyBilling ? '#{translate("upgrade_cc_btn")}' : '#{translate("upgrade_now")}'}}
  242. span(ng-if="paymentMethod.value !== 'credit_card'") #{translate("upgrade_paypal_btn")}
  243. p.tos-agreement-notice
  244. | By subscribing, you agree to our
  245. |
  246. a(
  247. href="/legal#Terms"
  248. target="_blank"
  249. rel="noopener noreferrer"
  250. ) terms of service
  251. | .
  252. div.three-d-secure-container.card.card-highlighted.card-border(ng-show="threeDSecureFlow")
  253. .alert.alert-info.small(aria-live="assertive")
  254. strong #{translate('card_must_be_authenticated_by_3dsecure')}
  255. div.three-d-secure-recurly-container
  256. .col-md-3.col-md-pull-4
  257. if showStudentPlan == 'true'
  258. a.btn-primary.btn.plansPageStudentLink(
  259. href,
  260. ng-click="switchToStudent()"
  261. ) #{translate("half_price_student")}
  262. .card.card-first
  263. .paymentPageFeatures
  264. h3 #{translate("unlimited_projects")}
  265. p #{translate("create_unlimited_projects")}
  266. h3
  267. if plan.features.collaborators == -1
  268. - var collaboratorCount = 'Unlimited'
  269. else
  270. - var collaboratorCount = plan.features.collaborators
  271. | #{translate("collabs_per_proj", {collabcount:collaboratorCount})}
  272. p #{translate("work_on_single_version")}. #{translate("view_collab_edits")} in real time.
  273. h3 #{translate("full_doc_history")}
  274. p.track-changes-example
  275. | #{translate("see_what_has_been")} #[span.added #{translate("added")}]
  276. | &nbsp;#{translate("and")} #[span.removed #{translate("removed")}].
  277. p
  278. | #{translate("restore_to_any_older_version")}.
  279. h3 #{translate("sync_to_dropbox")}
  280. p
  281. | #{translate("acces_work_from_anywhere")}.
  282. | #{translate("work_offline_and_sync_with_dropbox")}.
  283. hr
  284. p.small.text-center(ng-non-bindable) We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
  285. script(type="text/javascript").
  286. ga('send', 'event', 'pageview', 'payment_form', "#{plan_code}")
  287. script(
  288. type="text/ng-template"
  289. id="cvv-tooltip-tpl.html"
  290. )
  291. p For #[strong Visa, MasterCard and Discover], the #[strong 3 digits] on the #[strong back] of your card.
  292. p For #[strong American Express], the #[strong 4 digits] on the #[strong front] of your card.