plans.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /* eslint-disable
  2. camelcase,
  3. max-len
  4. */
  5. import App from '../base'
  6. App.factory('MultiCurrencyPricing', function() {
  7. const currencyCode = window.recomendedCurrency
  8. return {
  9. currencyCode,
  10. plans: {
  11. USD: {
  12. symbol: '$',
  13. student: {
  14. monthly: '$8',
  15. annual: '$80'
  16. },
  17. collaborator: {
  18. monthly: '$15',
  19. annual: '$180'
  20. },
  21. professional: {
  22. monthly: '$30',
  23. annual: '$360'
  24. }
  25. },
  26. EUR: {
  27. symbol: '€',
  28. student: {
  29. monthly: '€7',
  30. annual: '€70'
  31. },
  32. collaborator: {
  33. monthly: '€14',
  34. annual: '€168'
  35. },
  36. professional: {
  37. monthly: '€28',
  38. annual: '€336'
  39. }
  40. },
  41. GBP: {
  42. symbol: '£',
  43. student: {
  44. monthly: '£6',
  45. annual: '£60'
  46. },
  47. collaborator: {
  48. monthly: '£12',
  49. annual: '£144'
  50. },
  51. professional: {
  52. monthly: '£24',
  53. annual: '£288'
  54. }
  55. },
  56. SEK: {
  57. symbol: 'kr',
  58. student: {
  59. monthly: '60 kr',
  60. annual: '600 kr'
  61. },
  62. collaborator: {
  63. monthly: '110 kr',
  64. annual: '1320 kr'
  65. },
  66. professional: {
  67. monthly: '220 kr',
  68. annual: '2640 kr'
  69. }
  70. },
  71. CAD: {
  72. symbol: '$',
  73. student: {
  74. monthly: '$9',
  75. annual: '$90'
  76. },
  77. collaborator: {
  78. monthly: '$17',
  79. annual: '$204'
  80. },
  81. professional: {
  82. monthly: '$34',
  83. annual: '$408'
  84. }
  85. },
  86. NOK: {
  87. symbol: 'kr',
  88. student: {
  89. monthly: '60 kr',
  90. annual: '600 kr'
  91. },
  92. collaborator: {
  93. monthly: '110 kr',
  94. annual: '1320 kr'
  95. },
  96. professional: {
  97. monthly: '220 kr',
  98. annual: '2640 kr'
  99. }
  100. },
  101. DKK: {
  102. symbol: 'kr',
  103. student: {
  104. monthly: '50 kr',
  105. annual: '500 kr'
  106. },
  107. collaborator: {
  108. monthly: '90 kr',
  109. annual: '1080 kr'
  110. },
  111. professional: {
  112. monthly: '180 kr',
  113. annual: '2160 kr'
  114. }
  115. },
  116. AUD: {
  117. symbol: '$',
  118. student: {
  119. monthly: '$10',
  120. annual: '$100'
  121. },
  122. collaborator: {
  123. monthly: '$18',
  124. annual: '$216'
  125. },
  126. professional: {
  127. monthly: '$35',
  128. annual: '$420'
  129. }
  130. },
  131. NZD: {
  132. symbol: '$',
  133. student: {
  134. monthly: '$10',
  135. annual: '$100'
  136. },
  137. collaborator: {
  138. monthly: '$18',
  139. annual: '$216'
  140. },
  141. professional: {
  142. monthly: '$35',
  143. annual: '$420'
  144. }
  145. },
  146. CHF: {
  147. symbol: 'Fr',
  148. student: {
  149. monthly: 'Fr 8',
  150. annual: 'Fr 80'
  151. },
  152. collaborator: {
  153. monthly: 'Fr 15',
  154. annual: 'Fr 180'
  155. },
  156. professional: {
  157. monthly: 'Fr 30',
  158. annual: 'Fr 360'
  159. }
  160. },
  161. SGD: {
  162. symbol: '$',
  163. student: {
  164. monthly: '$12',
  165. annual: '$120'
  166. },
  167. collaborator: {
  168. monthly: '$20',
  169. annual: '$240'
  170. },
  171. professional: {
  172. monthly: '$40',
  173. annual: '$480'
  174. }
  175. }
  176. }
  177. }
  178. })
  179. App.controller('PlansController', function(
  180. $scope,
  181. $modal,
  182. eventTracking,
  183. MultiCurrencyPricing,
  184. $http,
  185. $filter,
  186. $location
  187. ) {
  188. let switchEvent
  189. $scope.plans = MultiCurrencyPricing.plans
  190. $scope.currencyCode = MultiCurrencyPricing.currencyCode
  191. $scope.trial_len = 7
  192. $scope.planQueryString = '_free_trial_7_days'
  193. $scope.ui = { view: 'monthly' }
  194. $scope.changeCurreny = function(e, newCurrency) {
  195. e.preventDefault()
  196. $scope.currencyCode = newCurrency
  197. }
  198. // because ternary logic in angular bindings is hard
  199. $scope.getCollaboratorPlanCode = function() {
  200. const { view } = $scope.ui
  201. if (view === 'annual') {
  202. return 'collaborator-annual'
  203. } else {
  204. return `collaborator${$scope.planQueryString}`
  205. }
  206. }
  207. $scope.signUpNowClicked = function(plan, location) {
  208. if ($scope.ui.view === 'annual') {
  209. plan = `${plan}_annual`
  210. }
  211. plan = eventLabel(plan, location)
  212. eventTracking.sendMB('plans-page-start-trial')
  213. eventTracking.send('subscription-funnel', 'sign_up_now_button', plan)
  214. }
  215. $scope.switchToMonthly = function(e, location) {
  216. const uiView = 'monthly'
  217. switchEvent(e, uiView + '-prices', location)
  218. $scope.ui.view = uiView
  219. }
  220. $scope.switchToStudent = function(e, location) {
  221. const uiView = 'student'
  222. switchEvent(e, uiView + '-prices', location)
  223. $scope.ui.view = uiView
  224. }
  225. $scope.switchToAnnual = function(e, location) {
  226. const uiView = 'annual'
  227. switchEvent(e, uiView + '-prices', location)
  228. $scope.ui.view = uiView
  229. }
  230. $scope.openGroupPlanModal = function() {
  231. const path = `${window.location.pathname}${window.location.search}`
  232. history.replaceState(null, document.title, path + '#groups')
  233. $modal
  234. .open({
  235. templateUrl: 'groupPlanModalPurchaseTemplate',
  236. controller: 'GroupPlansModalPurchaseController'
  237. })
  238. .result.finally(() =>
  239. history.replaceState(null, document.title, window.location.pathname)
  240. )
  241. eventTracking.send(
  242. 'subscription-funnel',
  243. 'plans-page',
  244. 'group-inquiry-potential'
  245. )
  246. }
  247. if ($location.hash() === 'groups') {
  248. $scope.openGroupPlanModal()
  249. }
  250. var eventLabel = (label, location) => label
  251. switchEvent = function(e, label, location) {
  252. e.preventDefault()
  253. const gaLabel = eventLabel(label, location)
  254. eventTracking.send('subscription-funnel', 'plans-page', gaLabel)
  255. }
  256. })
  257. App.controller('GroupPlansModalPurchaseController', function(
  258. $scope,
  259. $modal,
  260. $location,
  261. $httpParamSerializer
  262. ) {
  263. $scope.options = {
  264. plan_codes: [
  265. {
  266. display: 'Collaborator',
  267. code: 'collaborator'
  268. },
  269. {
  270. display: 'Professional',
  271. code: 'professional'
  272. }
  273. ],
  274. currencies: [
  275. {
  276. display: 'USD ($)',
  277. code: 'USD'
  278. },
  279. {
  280. display: 'GBP (£)',
  281. code: 'GBP'
  282. },
  283. {
  284. display: 'EUR (€)',
  285. code: 'EUR'
  286. }
  287. ],
  288. currencySymbols: {
  289. USD: '$',
  290. EUR: '€',
  291. GBP: '£'
  292. },
  293. sizes: [2, 3, 4, 5, 10, 20, 50],
  294. usages: [
  295. {
  296. display: 'Enterprise',
  297. code: 'enterprise'
  298. },
  299. {
  300. display: 'Educational',
  301. code: 'educational'
  302. }
  303. ]
  304. }
  305. $scope.prices = window.groupPlans
  306. let currency = 'USD'
  307. if (['USD', 'GBP', 'EUR'].includes(window.recomendedCurrency)) {
  308. currency = window.recomendedCurrency
  309. }
  310. // default selected
  311. $scope.selected = {
  312. plan_code: 'collaborator',
  313. currency,
  314. size: '10',
  315. usage: 'educational'
  316. }
  317. // selected via query
  318. if ($location.search()) {
  319. // usage
  320. if ($location.search().usage) {
  321. $scope.options.usages.forEach(usage => {
  322. if (usage.code === $location.search().usage) {
  323. $scope.selected.usage = usage.code
  324. }
  325. })
  326. }
  327. // plan
  328. if ($location.search().plan) {
  329. $scope.options.plan_codes.forEach(plan => {
  330. if (plan.code === $location.search().plan) {
  331. $scope.selected.plan_code = plan.code
  332. }
  333. })
  334. }
  335. // number
  336. if ($location.search().number) {
  337. // $location.search().number is a string,
  338. // but $scope.options.sizes are numbers
  339. // and $scope.selected.size is a string
  340. const groupCount = parseInt($location.search().number, 10)
  341. if ($scope.options.sizes.indexOf(groupCount) !== -1) {
  342. $scope.selected.size = $location.search().number
  343. }
  344. }
  345. // currency
  346. if ($location.search().currency) {
  347. $scope.options.currencies.forEach(currency => {
  348. if (currency.code === $location.search().currency) {
  349. $scope.selected.currency = currency.code
  350. }
  351. })
  352. }
  353. }
  354. $scope.recalculatePrice = function() {
  355. let { usage, plan_code, currency, size } = $scope.selected
  356. const price = $scope.prices[usage][plan_code][currency][size]
  357. const currencySymbol = $scope.options.currencySymbols[currency]
  358. $scope.displayPrice = `${currencySymbol}${price}`
  359. }
  360. $scope.$watch('selected', $scope.recalculatePrice, true)
  361. $scope.recalculatePrice()
  362. $scope.purchase = function() {
  363. const { plan_code, size, usage, currency } = $scope.selected
  364. const queryParams = {
  365. planCode: `group_${plan_code}_${size}_${usage}`,
  366. currency,
  367. itm_campaign: 'groups'
  368. }
  369. if ($location.search().itm_content) {
  370. queryParams.itm_content = $location.search().itm_content
  371. }
  372. window.location = `/user/subscription/new?${$httpParamSerializer(
  373. queryParams
  374. )}`
  375. }
  376. })