Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

OnboardingView.vue 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <template lang="pug">
  2. main.view--onboarding
  3. article(
  4. style='display: flex; flex-direction: column; align-items: center'
  5. v-if='currentStep !== survey.steps.length'
  6. )
  7. .answers(v-for='(value, key) in answered')
  8. span(v-if='key == "name" && value && currentStep == 2') Hi {{ value }}!
  9. br
  10. .step(v-for='(step, i) in survey.steps')
  11. component(
  12. :is='step.component'
  13. :question='step'
  14. :answered='answered'
  15. :responses='responses'
  16. :survey='survey'
  17. :currentStep='currentStep'
  18. :surveyStepsCount='survey.steps.length'
  19. @handle-submit='onSubmit'
  20. @update-answers='updateAnswers'
  21. v-if='step && currentStep == i'
  22. )
  23. .invalidResponseMessage(
  24. style='text-align: center'
  25. v-if='invalidResponse'
  26. )
  27. p {{ survey.steps[currentStep].invalidInputPrompt }}
  28. footer
  29. p(v-if='currentStep != 0') You have completed: {{ currentStep }} / {{ survey.steps.length }} survey steps
  30. article(v-else)
  31. SurveyCompleteView(:answers='answered' :surveySteps='survey.steps' :currentProfileId='currentProfileId')
  32. </template>
  33. <script>
  34. import { Authenticator } from '../services/auth.service.js'
  35. import { surveyFactory } from '@/utils'
  36. import { currentProfile } from '../services/'
  37. import stepViews from '@/components/onboarding'
  38. import SurveyCompleteView from './SurveyCompleteView.vue'
  39. // import savesurveybyprofileid - call it on submit
  40. // paginate to save every steps answers
  41. export default {
  42. name: 'OnboardingView',
  43. components: {
  44. ...stepViews,
  45. SurveyCompleteView,
  46. },
  47. data: () => ({
  48. answered: {},
  49. aspectQuestions: [],
  50. responses: [],
  51. currentStep: 0,
  52. survey: null,
  53. currentProfileId: null,
  54. invalidResponse: false,
  55. authenticator: {},
  56. sessionToken: '',
  57. accessToken: '',
  58. }),
  59. computed: {
  60. cP() {
  61. return currentProfile ? currentProfile : null
  62. },
  63. },
  64. async created() {
  65. this.survey = await surveyFactory.createSurvey()
  66. this.authenticator = new Authenticator()
  67. if (document.cookie.length) {
  68. // TODO: Heavy Refactor needed, obvious code smells
  69. // BUG: NEEDS BROWSER REFRESH TO SEE UPDATED COOKIES
  70. const siimeeAnswered = this.grabCookie('siimee_answered')
  71. const myCurrentStep = this.grabCookie('siimee_current_step')
  72. console.log('myCurrentStep :=>', myCurrentStep)
  73. if (siimeeAnswered) {
  74. const siimeeAnswers = JSON.parse(siimeeAnswered)
  75. this.sessionToken = this.grabCookie('siimee_session')
  76. const sessionTokenIsValid =
  77. await this.authenticator.validateJwt(this.sessionToken)
  78. this.accessToken = this.grabCookie('siimee_access')
  79. if (sessionTokenIsValid.isValid) {
  80. this.answered = {
  81. name: siimeeAnswers.name,
  82. email: siimeeAnswers.email,
  83. seeking: siimeeAnswers.seeking,
  84. }
  85. this.currentProfileId = siimeeAnswers.profile_id
  86. this.currentStep = 6
  87. this.responses = [
  88. { response_key_id: 8, val: siimeeAnswers.email },
  89. { response_key_id: 7, val: siimeeAnswers.name },
  90. { response_key_id: 11, val: siimeeAnswers.seeking },
  91. ]
  92. document.cookie = `siimee_current_step=${this.currentStep}; max-age=600 ; path=/onboarding ; secure`
  93. document.cookie = `siimee_cache_answered=${JSON.stringify(
  94. this.answered,
  95. )}; max-age=600 ; path=/onboarding ; secure`
  96. document.cookie = `siimee_cache_responses=${JSON.stringify(
  97. this.responses,
  98. )}; max-age=600 ; path=/onboarding ; secure`
  99. document.cookie = 'siimee_answered='
  100. this.goToStep(this.currentStep)
  101. }
  102. } else if (myCurrentStep) {
  103. const myCurrentAnswers = this.grabCookie(
  104. 'siimee_cache_answered',
  105. )
  106. const myCurrentResponses = this.grabCookie(
  107. 'siimee_cache_responses',
  108. )
  109. this.answered = JSON.parse(myCurrentAnswers)
  110. this.responses = JSON.parse(myCurrentResponses)
  111. this.currentStep = myCurrentStep
  112. this.goToStep(Number(myCurrentStep) + 1)
  113. } else {
  114. this.goToStep(0)
  115. }
  116. }
  117. },
  118. methods: {
  119. onSubmit() {
  120. console.log(JSON.stringify(this.answered))
  121. },
  122. async goToStep(num) {
  123. document.cookie = `siimee_current_step=${Number(
  124. this.currentStep,
  125. )}; max-age=600 ; path=/onboarding ; secure`
  126. document.cookie = `siimee_cache_answered=${JSON.stringify(
  127. this.answered,
  128. )}; max-age=600 ; path=/onboarding ; secure`
  129. document.cookie = `siimee_cache_responses=${JSON.stringify(
  130. this.responses,
  131. )}; max-age=600 ; path=/onboarding ; secure`
  132. if (num > 6) {
  133. this.validateAccessToken()
  134. }
  135. this.currentStep = num
  136. },
  137. // TODO: Refactor to use cookie's max-age attribute instead of network call for jwt auth
  138. async validateAccessToken() {
  139. const validatedAccessToken = await this.authenticator.validateJwt(
  140. this.accessToken,
  141. )
  142. if (!validatedAccessToken.isValid) {
  143. const sessionTokenIsValid = await this.validateSessionToken()
  144. if (!sessionTokenIsValid) {
  145. this.goToStep(0)
  146. }
  147. }
  148. },
  149. async validateSessionToken() {
  150. const validatedSessionToken = await this.authenticator.validateJwt(
  151. this.sessionToken,
  152. )
  153. if (validatedSessionToken.isValid) {
  154. this.accessToken = await this.authenticator.generateJwt({
  155. ...this.answered,
  156. expiration: 60 * 3,
  157. })
  158. return true
  159. } else return false
  160. },
  161. grabCookie(cookieKey) {
  162. const cookieString = document.cookie
  163. const cookies = cookieString.split('; ').reduce((prev, current) => {
  164. const [name, ...value] = current.split('=')
  165. prev[name] = value.join('=')
  166. return prev
  167. }, {})
  168. return cookieKey in cookies ? cookies[`${cookieKey}`] : undefined
  169. },
  170. async updateAnswers(payload) {
  171. if (payload) {
  172. // this.invalidResponse = false
  173. const k = payload.question.survey_stage
  174. this.answered[k] = payload.input
  175. if (!this.survey.validateAnswer(payload)) {
  176. this.invalidResponse = true
  177. return
  178. }
  179. // once validated, don't log password in answered object
  180. this.answered[k] = k === 'password' ? undefined : payload.input
  181. // formats initial responses for response table
  182. const response = {}
  183. response.response_key_id = payload.question.response_key_id
  184. response.val = payload.input
  185. this.responses.push(response)
  186. // sends latest survey response to db
  187. if (this.currentProfileId) {
  188. surveyFactory.addNewSurveyAnswer(
  189. this.responses[this.responses.length - 1],
  190. this.currentProfileId,
  191. )
  192. }
  193. if (k === 'aspects') return
  194. }
  195. if (this.currentStep > this.survey.steps.length) {
  196. this.onSubmit(this.answered)
  197. } else {
  198. this.goToStep(this.currentStep + 1)
  199. }
  200. },
  201. },
  202. }
  203. </script>
  204. <style lang="sass">
  205. .view--onboarding
  206. width: 100%
  207. max-width: 428px
  208. background-color: #fff
  209. color: #1F2024
  210. font-family: Century Gothic,CenturyGothic,AppleGothic,sans-serif
  211. margin: 0 auto
  212. article
  213. height: 100vh
  214. .answers
  215. text-align: center
  216. .w-button
  217. display: flex
  218. width: 315px
  219. height: 60px
  220. border-radius: 6
  221. background-color: #D5D5D5
  222. color: #1F2024
  223. margin: 11px auto
  224. font-weight: bold
  225. font-size: 16px
  226. text-transform: uppercase
  227. &.next-btn
  228. border-radius: 6px
  229. background-color: #5BA626
  230. color: #1F2024
  231. height: 50px
  232. width: 315px
  233. font-size: 18px
  234. padding: 7px
  235. .w-card
  236. background-color: #1F2024
  237. justify-content: center
  238. align-items: center
  239. width: 100%
  240. h3
  241. text-transform: uppercase
  242. text-align: center
  243. font-size: 28px
  244. font-weight: bold
  245. color: white
  246. margin-top: 88px
  247. p
  248. color: white
  249. font-size: 18px
  250. padding: 11px
  251. text-align: center
  252. margin: 22px auto
  253. font-weight: bold
  254. input
  255. display: flex
  256. width: 315px
  257. height: 60px
  258. padding: 11px
  259. border-radius: 6
  260. background-color: #D5D5D5
  261. color: #1F2024
  262. margin: 11px auto
  263. font-weight: bold
  264. font-size: 16px
  265. .w-select
  266. padding: 11px
  267. color: #1F2024
  268. .search-type
  269. color: #1F2024
  270. height: 50px
  271. &.question
  272. p
  273. font-size: 18px
  274. text-align: left
  275. margin: 7px auto
  276. font-weight: normal
  277. section
  278. p
  279. margin: 0
  280. font-weight: bold
  281. text-transform: capitalize
  282. .w-radio__input
  283. &.primary
  284. background-color: #FFFFFF
  285. border: #BCC5D3 1px solid
  286. .w-card__content
  287. .w-button
  288. height: 50px
  289. background-color: #5BA626
  290. </style>