plans.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /* eslint-disable
  2. camelcase,
  3. max-len
  4. */
  5. import App from '../base'
  6. import getMeta from '../utils/meta'
  7. App.factory('MultiCurrencyPricing', function () {
  8. const currencyCode = getMeta('ol-recomendedCurrency')
  9. return {
  10. currencyCode,
  11. plans: {
  12. USD: {
  13. symbol: '$',
  14. student: {
  15. monthly: '$8',
  16. annual: '$80',
  17. },
  18. personal: {
  19. monthly: '$10',
  20. annual: '$120',
  21. },
  22. collaborator: {
  23. monthly: '$15',
  24. annual: '$180',
  25. },
  26. professional: {
  27. monthly: '$30',
  28. annual: '$360',
  29. },
  30. },
  31. EUR: {
  32. symbol: '€',
  33. student: {
  34. monthly: '€7',
  35. annual: '€70',
  36. },
  37. personal: {
  38. monthly: '€9',
  39. annual: '€108',
  40. },
  41. collaborator: {
  42. monthly: '€14',
  43. annual: '€168',
  44. },
  45. professional: {
  46. monthly: '€28',
  47. annual: '€336',
  48. },
  49. },
  50. GBP: {
  51. symbol: '£',
  52. student: {
  53. monthly: '£6',
  54. annual: '£60',
  55. },
  56. personal: {
  57. monthly: '£8',
  58. annual: '£96',
  59. },
  60. collaborator: {
  61. monthly: '£12',
  62. annual: '£144',
  63. },
  64. professional: {
  65. monthly: '£24',
  66. annual: '£288',
  67. },
  68. },
  69. SEK: {
  70. symbol: 'kr',
  71. student: {
  72. monthly: '60 kr',
  73. annual: '600 kr',
  74. },
  75. personal: {
  76. monthly: '73 kr',
  77. annual: '876 kr',
  78. },
  79. collaborator: {
  80. monthly: '110 kr',
  81. annual: '1320 kr',
  82. },
  83. professional: {
  84. monthly: '220 kr',
  85. annual: '2640 kr',
  86. },
  87. },
  88. CAD: {
  89. symbol: '$',
  90. student: {
  91. monthly: '$9',
  92. annual: '$90',
  93. },
  94. personal: {
  95. monthly: '$11',
  96. annual: '$132',
  97. },
  98. collaborator: {
  99. monthly: '$17',
  100. annual: '$204',
  101. },
  102. professional: {
  103. monthly: '$34',
  104. annual: '$408',
  105. },
  106. },
  107. NOK: {
  108. symbol: 'kr',
  109. student: {
  110. monthly: '60 kr',
  111. annual: '600 kr',
  112. },
  113. personal: {
  114. monthly: '73 kr',
  115. annual: '876 kr',
  116. },
  117. collaborator: {
  118. monthly: '110 kr',
  119. annual: '1320 kr',
  120. },
  121. professional: {
  122. monthly: '220 kr',
  123. annual: '2640 kr',
  124. },
  125. },
  126. DKK: {
  127. symbol: 'kr',
  128. student: {
  129. monthly: '50 kr',
  130. annual: '500 kr',
  131. },
  132. personal: {
  133. monthly: '60 kr',
  134. annual: '720 kr',
  135. },
  136. collaborator: {
  137. monthly: '90 kr',
  138. annual: '1080 kr',
  139. },
  140. professional: {
  141. monthly: '180 kr',
  142. annual: '2160 kr',
  143. },
  144. },
  145. AUD: {
  146. symbol: '$',
  147. student: {
  148. monthly: '$10',
  149. annual: '$100',
  150. },
  151. personal: {
  152. monthly: '$12',
  153. annual: '$144',
  154. },
  155. collaborator: {
  156. monthly: '$18',
  157. annual: '$216',
  158. },
  159. professional: {
  160. monthly: '$35',
  161. annual: '$420',
  162. },
  163. },
  164. NZD: {
  165. symbol: '$',
  166. student: {
  167. monthly: '$10',
  168. annual: '$100',
  169. },
  170. personal: {
  171. monthly: '$12',
  172. annual: '$144',
  173. },
  174. collaborator: {
  175. monthly: '$18',
  176. annual: '$216',
  177. },
  178. professional: {
  179. monthly: '$35',
  180. annual: '$420',
  181. },
  182. },
  183. CHF: {
  184. symbol: 'Fr',
  185. student: {
  186. monthly: 'Fr 8',
  187. annual: 'Fr 80',
  188. },
  189. personal: {
  190. monthly: 'Fr 10',
  191. annual: 'Fr 120',
  192. },
  193. collaborator: {
  194. monthly: 'Fr 15',
  195. annual: 'Fr 180',
  196. },
  197. professional: {
  198. monthly: 'Fr 30',
  199. annual: 'Fr 360',
  200. },
  201. },
  202. SGD: {
  203. symbol: '$',
  204. student: {
  205. monthly: '$12',
  206. annual: '$120',
  207. },
  208. personal: {
  209. monthly: '$13',
  210. annual: '$156',
  211. },
  212. collaborator: {
  213. monthly: '$20',
  214. annual: '$240',
  215. },
  216. professional: {
  217. monthly: '$40',
  218. annual: '$480',
  219. },
  220. },
  221. },
  222. }
  223. })
  224. App.controller(
  225. 'PlansController',
  226. function (
  227. $scope,
  228. $modal,
  229. eventTracking,
  230. MultiCurrencyPricing,
  231. $http,
  232. $filter,
  233. $location
  234. ) {
  235. $scope.plans = MultiCurrencyPricing.plans
  236. $scope.currencyCode = MultiCurrencyPricing.currencyCode
  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_free_trial_7_days`
  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_free_trial_7_days`
  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. const eventLabel = (label, location) => label
  303. function switchEvent(e, label, location) {
  304. e.preventDefault()
  305. const gaLabel = eventLabel(label, location)
  306. eventTracking.send('subscription-funnel', 'plans-page', gaLabel)
  307. }
  308. }
  309. )
  310. App.controller(
  311. 'GroupPlansModalPurchaseController',
  312. function ($scope, $modal, $location, $httpParamSerializer) {
  313. $scope.options = {
  314. plan_codes: [
  315. {
  316. display: 'Collaborator',
  317. code: 'collaborator',
  318. },
  319. {
  320. display: 'Professional',
  321. code: 'professional',
  322. },
  323. ],
  324. currencies: [
  325. {
  326. display: 'USD ($)',
  327. code: 'USD',
  328. },
  329. {
  330. display: 'GBP (£)',
  331. code: 'GBP',
  332. },
  333. {
  334. display: 'EUR (€)',
  335. code: 'EUR',
  336. },
  337. ],
  338. currencySymbols: {
  339. USD: '$',
  340. EUR: '€',
  341. GBP: '£',
  342. },
  343. sizes: [2, 3, 4, 5, 10, 20, 50],
  344. usages: [
  345. {
  346. display: 'Enterprise',
  347. code: 'enterprise',
  348. },
  349. {
  350. display: 'Educational',
  351. code: 'educational',
  352. },
  353. ],
  354. }
  355. $scope.prices = getMeta('ol-groupPlans')
  356. let currency = 'USD'
  357. const recomendedCurrency = getMeta('ol-recomendedCurrency')
  358. if (['USD', 'GBP', 'EUR'].includes(recomendedCurrency)) {
  359. currency = recomendedCurrency
  360. }
  361. // default selected
  362. $scope.selected = {
  363. plan_code: 'collaborator',
  364. currency,
  365. size: '10',
  366. usage: 'enterprise',
  367. }
  368. // selected via query
  369. if ($location.search()) {
  370. // usage
  371. if ($location.search().usage) {
  372. $scope.options.usages.forEach(usage => {
  373. if (usage.code === $location.search().usage) {
  374. $scope.selected.usage = usage.code
  375. }
  376. })
  377. }
  378. // plan
  379. if ($location.search().plan) {
  380. $scope.options.plan_codes.forEach(plan => {
  381. if (plan.code === $location.search().plan) {
  382. $scope.selected.plan_code = plan.code
  383. }
  384. })
  385. }
  386. // number
  387. if ($location.search().number) {
  388. // $location.search().number is a string,
  389. // but $scope.options.sizes are numbers
  390. // and $scope.selected.size is a string
  391. const groupCount = parseInt($location.search().number, 10)
  392. if ($scope.options.sizes.indexOf(groupCount) !== -1) {
  393. $scope.selected.size = $location.search().number
  394. }
  395. }
  396. // currency
  397. if ($location.search().currency) {
  398. $scope.options.currencies.forEach(currency => {
  399. if (currency.code === $location.search().currency) {
  400. $scope.selected.currency = currency.code
  401. }
  402. })
  403. }
  404. }
  405. $scope.recalculatePrice = function () {
  406. const { usage, plan_code, currency, size } = $scope.selected
  407. const price = $scope.prices[usage][plan_code][currency][size]
  408. const currencySymbol = $scope.options.currencySymbols[currency]
  409. $scope.displayPrice = `${currencySymbol}${price}`
  410. }
  411. $scope.$watch('selected', $scope.recalculatePrice, true)
  412. $scope.recalculatePrice()
  413. $scope.purchase = function () {
  414. const { plan_code, size, usage, currency } = $scope.selected
  415. const queryParams = {
  416. planCode: `group_${plan_code}_${size}_${usage}`,
  417. currency,
  418. itm_campaign: 'groups',
  419. }
  420. if ($location.search().itm_content) {
  421. queryParams.itm_content = $location.search().itm_content
  422. }
  423. window.location = `/user/subscription/new?${$httpParamSerializer(
  424. queryParams
  425. )}`
  426. }
  427. }
  428. )