plans.js 10.0 KB

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