| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- <template lang="pug">
- main.view--survey.f-col.start.w-full
- header.w-full.f-col
- p survey for profile: {{ current }}
- article.match.w-full
- ul.w-full
- template(
- :key='q.response_key_prompt'
- v-for='(q, i) in profileQuestions'
- )
- li(v-if='step == i + 1')
- p {{ q.response_key_category }}:
- span in db:
- span(v-if='q.response_key_id') true - id:{{ q.response_key_id }} |
- span(v-else) false |
- span {{ q.response_key_prompt }}?
- span {{ q.response_key_description }}
-
- //- Select
- div(v-if='q.responses.length')
- button.p-0(
- :key='index'
- @click='storeResponseLike(step, q.response_key_id, q.response_key_prompt, res); step++'
- v-for='(res, index) in q.responses'
- ) {{ res }}
-
- //- Fill in the blank
- div(v-else-if='q.response_key_category === "profile"')
- input(
- @input='storeResponseLike(step, q.response_key_id, q.response_key_prompt, profile[q.response_key_prompt])'
- @keyup.enter='step++'
- v-model='profile[q.response_key_prompt]'
- )
- label >{{ profile[q.response_key_prompt] }}
-
- //- Aspects
- .f-col(v-else)
- input.w-full(
- @input='storeResponseLike(step, q.response_key_id, q.response_key_prompt, aspects[q.response_key_category])'
- list='ticks'
- max='3'
- min='-3'
- type='range'
- v-model='aspects[q.response_key_category]'
- )
- label {{ aspectResponses[parseInt(aspects[q.response_key_category]) + 3] }}
-
- nav.f-row
- button(:disabled='step == 0' @click='step--') back
- p {{ step }} of {{ profile.length }}
- button(
- @click='storeResponseLike(step, q.response_key_id, q.response_key_prompt, profile[q.response_key_prompt]); step++'
- v-if='q.response_key_category === "profile"'
- ) next
- button(
- @click='storeResponseLike(step, q.response_key_id, q.response_key_prompt, aspects[q.response_key_category]); step++'
- v-else
- ) next
-
- //- Confirmation
- li(v-if='step == profileQuestions.length + 1')
- p Does this look correct?
- h4 {{ profile }}
- h4 {{ aspects }}
- nav.f-row
- button(@click='step--') back
- p.p-1(@click='step = 1') start over
- button(@click='onSave') save
- //- button(@click="$router.push({ name: 'HomeView' })") save
- footer
- button(@click='bypass') +30 user profiles
-
- MainNav
- </template>
-
- <script>
- import { surveyFactory, randomSurveyResponses } from '@/utils'
- import { allSteps, aspectResponses, possible } from '@/utils/lang'
-
- import {
- currentProfile,
- createProfileForUserId,
- fetchProfileByProfileId,
- scoreSurveyByProfileId,
- signupUser,
- } from '@/services'
-
- import { distanceKey } from '../../../backend/db/data-generator/config.json'
-
- export default {
- props: {
- pid: {
- type: String,
- default: () => '1',
- },
- },
- data() {
- return {
- bypassCount: 0,
- validSurvey: null,
- step: 1,
- responseLikes: {},
- profile: {},
- aspects: {
- grit: 0,
- openness: 0,
- bravery: 0,
- empathy: 0,
- honesty: 0,
- respect: 0,
- },
- aspectResponses: Object.values(aspectResponses.usa),
- }
- },
- computed: {
- current() {
- return currentProfile
- },
- profileQuestions() {
- if (!this.validSurvey) return []
- return this.validSurvey.steps
- },
- },
- async created() {
- /**
- * Before this ever gets called, surveyFactory.questionsFromDb
- * must be set by App.created()
- */
- this.validSurvey = await surveyFactory.createSurvey(
- allSteps['usa'],
- possible['usa']['roles'],
- )
- },
- methods: {
- // Just for testing quicker
- bypass() {
- const n = 30
- const toGen = [...Array(n).keys()]
- toGen.forEach(async () => {
- const randRes = randomSurveyResponses(this.bypassCount)
- randRes.forEach((tr, i) => {
- this.storeResponseLike(
- i,
- tr.idOrPrompt,
- tr.idOrPrompt,
- tr.val,
- )
- })
- this.bypassCount++
- await this.onSave()
- })
- this.step = 21
- console.warn(`Auto-filling survey ${n} times...`)
- },
- storeResponseLike(step, id, prompt, val) {
- // Also update the form model state for now
- // We probably can refactor this out
- this.profile[prompt] = val
-
- /**
- * If NO response id is present, that means the answer
- * is required and associated with a User and NOT a Profile
- **/
- this.responseLikes[`step-${step}`] = {
- idOrPrompt: id ? id : prompt,
- val: val.toString(),
- }
- },
- _formatIntoResponses(survey) {
- return survey.map(resLike => {
- resLike.response_key_id = resLike.idOrPrompt
- delete resLike.idOrPrompt
- return resLike
- })
- },
- /**
- * Survey responses have User information
- * mixed in with scoring information so we
- * need to separate them
- * @param {array} responseLikes answered by the survey
- */
- _separateUserInfoFromResponses(responseLikes) {
- let survey = []
- const user = {}
- responseLikes.forEach(resLike => {
- if (
- resLike.idOrPrompt &&
- Number.isFinite(parseInt(resLike.idOrPrompt))
- ) {
- survey.push(resLike)
- } else {
- user[resLike.idOrPrompt] = resLike.val
- }
- })
- return [user, this._formatIntoResponses(survey)]
- },
- async _createUserProfileRel(user, survey) {
- /** A User is required before creating a profile */
- const createdUser = await signupUser(user)
- if (!createdUser) return
-
- const userProfileRel = await createProfileForUserId(
- createdUser.user_id,
- survey,
- )
- if (!userProfileRel) return
-
- return userProfileRel
- },
- async _getProfileWithScore(createdProfileId, maxDistance) {
- /** A Profile is associated with n:1 user and referenced by profile id */
- const fetchedProfile = await fetchProfileByProfileId(
- createdProfileId,
- )
- if (!fetchedProfile) {
- console.error(
- `Could not fetch Profile ${createdProfileId}. Please check that a User and Profile were created.`,
- )
- return
- }
-
- /** Use profile answers to compare against other profile answers */
- const scored = await scoreSurveyByProfileId(
- createdProfileId,
- maxDistance,
- )
- if (!scored) {
- console.error(`Could not score Profile ${createdProfileId}.`)
- return
- }
- return fetchedProfile
- },
- async _setLoginForProfile(profile) {
- const currentId = currentProfile.login(profile.profile_id)
- if (currentId && profile.responses.length) {
- // Stores responses without fetching again
- currentProfile.setResponses(profile.responses)
- }
- if (!currentProfile.isComplete) {
- console.error(
- `Profile ${currentProfile.id} is incomplete. Please make sure all survey questions have been answered.`,
- )
- return
- }
- },
- async onSave() {
- const [user, survey] = this._separateUserInfoFromResponses(
- Object.values(this.responseLikes),
- )
- const maxDistanceRes = survey.find(
- res => res.response_key_id == distanceKey,
- )
- /**
- * Creating a profile only returns the created
- * user id and profile id
- **/
- const userProfileRel = await this._createUserProfileRel(
- user,
- survey,
- )
- const createdProfileId = userProfileRel.profile_id
-
- /** A Profile is associated with n:1 user and referenced by profile id */
- const fetchedProfile = await this._getProfileWithScore(
- createdProfileId,
- maxDistanceRes.val,
- )
-
- /**
- * Login only after there is a user and
- * that user has a profile and all responses
- */
- this._setLoginForProfile(fetchedProfile)
-
- this.$router.push({ name: 'HomeView' })
- },
- back(prompt) {
- this[prompt] = ''
- this.step--
- },
- },
- }
- </script>
|