Quellcode durchsuchen

:recycle: refactor components into more reusable pieces | map components to step types by prompt

tags/0.0.3^2
j vor 3 Jahren
Ursprung
Commit
67113953cc

+ 41
- 0
frontend/src/components/onboarding/FormDropdown.vue Datei anzeigen

@@ -0,0 +1,41 @@
1
+<template lang="pug">
2
+.role
3
+    h3 {{ question.response_key_category }}
4
+    p {{ question.response_key_prompt }}
5
+    w-select.mt4(:items='items' placeholder='i am' v-model='selection')
6
+    w-button.ma1.grow(@click='handleSubmit') NEXT
7
+</template>
8
+
9
+<script>
10
+export default {
11
+    name: 'FormDropdown',
12
+    props: {
13
+        question: {
14
+            required: true,
15
+            type: Object,
16
+        },
17
+    },
18
+    emits: ['update-answers'],
19
+    data: () => ({
20
+        selection: null,
21
+    }),
22
+    computed: {
23
+        items() {
24
+            return this.question.responses.map(res => ({ label: res }))
25
+        },
26
+    },
27
+    methods: {
28
+        handleSubmit() {
29
+            if (!this.selection) {
30
+                console.warn('Please select a role.')
31
+                return
32
+            }
33
+            let payload = {
34
+                question: this.question,
35
+                answer: this.selection,
36
+            }
37
+            this.$emit('update-answers', payload)
38
+        },
39
+    },
40
+}
41
+</script>

+ 31
- 0
frontend/src/components/onboarding/FormInput.vue Datei anzeigen

@@ -0,0 +1,31 @@
1
+<template lang="pug">
2
+.form-input
3
+    h3 {{ question.response_key_category }}
4
+    p {{ question.response_key_prompt }}
5
+    input(placeholder='i am a little teapot' type='text' v-model='input')
6
+    w-button.ma1.grow(@click='handleSubmit') NEXT
7
+</template>
8
+<script>
9
+export default {
10
+    name: 'FormInput',
11
+    props: {
12
+        question: {
13
+            required: true,
14
+            type: Object,
15
+        },
16
+    },
17
+    emits: ['update-answers'],
18
+    data: () => ({
19
+        input: null,
20
+    }),
21
+    methods: {
22
+        handleSubmit() {
23
+            let payload = {
24
+                question: this.question,
25
+                answer: this.input,
26
+            }
27
+            this.$emit('update-answers', payload)
28
+        },
29
+    },
30
+}
31
+</script>

+ 36
- 0
frontend/src/components/onboarding/FormTags.vue Datei anzeigen

@@ -0,0 +1,36 @@
1
+<template lang="pug">
2
+.form-tags
3
+    h3 {{ question.response_key_category }}
4
+    p {{ question.response_key_prompt }}
5
+    DynamicTagList(:placeholder='"a tag"' :tags='tags')
6
+    w-button.ma1.grow(@click='handleSubmit') NEXT
7
+</template>
8
+<script>
9
+import DynamicTagList from '../DynamicTagList.vue'
10
+
11
+export default {
12
+    name: 'FormTags',
13
+    components: {
14
+        DynamicTagList,
15
+    },
16
+    props: {
17
+        question: {
18
+            required: true,
19
+            type: Object,
20
+        },
21
+    },
22
+    emits: ['update-answers'],
23
+    data: () => ({
24
+        tags: [],
25
+    }),
26
+    methods: {
27
+        handleSubmit() {
28
+            let payload = {
29
+                question: this.question,
30
+                answer: this.tags,
31
+            }
32
+            this.$emit('update-answers', payload)
33
+        },
34
+    },
35
+}
36
+</script>

+ 7
- 1
frontend/src/components/onboarding/index.js Datei anzeigen

@@ -7,6 +7,9 @@ import Location from './Location.vue'
7 7
 import Interests from './Interests.vue'
8 8
 import LicensesAndCertifications from './LicensesAndCertifications.vue'
9 9
 import Aspects from './Aspects.vue'
10
+import FormInput from './FormInput.vue'
11
+import FormTags from './FormTags.vue'
12
+import FormDropdown from './FormDropdown.vue'
10 13
 
11 14
 export default {
12 15
     Splash,
@@ -18,4 +21,7 @@ export default {
18 21
     Interests,
19 22
     LicensesAndCertifications,
20 23
     Aspects,
21
-}
24
+    FormDropdown,
25
+    FormTags,
26
+    FormInput,
27
+}

+ 27
- 10
frontend/src/entities/survey/survey.js Datei anzeigen

@@ -2,24 +2,41 @@
2 2
 import { _baseRecord } from '../index.js'
3 3
 import { surveySchema } from './survey.schema.js'
4 4
 
5
+const SCORED = [1, 2, 3, 4, 5, 6]
6
+const _isScored = id => SCORED.includes(id)
7
+const _makeCategoryFriendly = responseCategory => {
8
+    const labels = responseCategory.split('_vs_')
9
+    labels.forEach((a, i) => {
10
+        if (a.indexOf('_') == -1) return
11
+        labels[i] = a.split('_').join(' ')
12
+    })
13
+    return labels
14
+}
15
+const _formatAspectQuestions = steps => {
16
+    return steps
17
+        .map(q => {
18
+            if (!_isScored(q.response_key_id)) return null
19
+            return {
20
+                id: q.response_key_id,
21
+                question: q.response_key_prompt,
22
+                labels: _makeCategoryFriendly(q.response_key_category),
23
+                answer: null,
24
+            }
25
+        })
26
+        .filter(step => step != null)
27
+}
28
+
5 29
 class Survey extends _baseRecord {
6
-    constructor(questionSteps, roles) {
30
+    constructor(questionSteps) {
7 31
         super()
8 32
 
9 33
         this.type = this.constructor.name.toLowerCase()
10 34
 
11 35
         /**  Fields */
12 36
         this.steps = [...questionSteps] // ! required
13
-        this.roleTree = roles
14
-
15
-        return this
16
-    }
17
-    setRoleResponses(position) {
18
-        const roleStep = this.steps.filter(
19
-            step => step.response_key_prompt == 'role',
20
-        )[0]
21
-        roleStep.responses = this.roleTree[position]
37
+        this.aspectQuestions = _formatAspectQuestions(this.steps)
22 38
     }
39
+
23 40
     isValid() {
24 41
         const validate = surveySchema.validate(this)
25 42
 

+ 1
- 1
frontend/src/utils/index.js Datei anzeigen

@@ -41,7 +41,7 @@ const makeKebob = input => {
41 41
     return input.toLowerCase().split(' ').join('-')
42 42
 }
43 43
 
44
-const surveyFactory = new SurveyFactory(possible['usa'])
44
+const surveyFactory = new SurveyFactory()
45 45
 
46 46
 const mixins = { pidMixin, profileMixin }
47 47
 

+ 1
- 11
frontend/src/utils/lang.js Datei anzeigen

@@ -37,17 +37,7 @@ possible.usa = {
37 37
     email: [],
38 38
     name: [],
39 39
     seeking: ['position', 'candidate'],
40
-    language: [
41
-        'javascript',
42
-        'python',
43
-        'c#',
44
-        'c++',
45
-        'go',
46
-        'java',
47
-        'ruby',
48
-        'html',
49
-        'css',
50
-    ],
40
+    language: ['english', 'spanish'],
51 41
     // key 13
52 42
     urgency: [
53 43
         'actively_looking',

+ 50
- 18
frontend/src/utils/survey.js Datei anzeigen

@@ -1,9 +1,52 @@
1 1
 import { Survey } from '../entities/index.js'
2 2
 import { fetchQuestions } from '../services/index.js'
3
+import { possible } from './lang.js'
4
+
5
+const promptToComponent = {
6
+    email: 'FormInput',
7
+    name: 'FormInput',
8
+    seeking: 'FormDropdown',
9
+    urgency: 'FormDropdown',
10
+    presence: 'FormDropdown',
11
+    duration: 'FormDropdown',
12
+    experience: 'FormTags',
13
+    pronouns: 'FormDropdown',
14
+    language: 'FormDropdown',
15
+    image: 'FormInput',
16
+    distance: 'FormInput',
17
+    zipcode: 'FormInput',
18
+    blurb: 'FormInput',
19
+}
20
+/**
21
+ * Make a step from match or step information
22
+ * @param {object} match
23
+ * @param {object} step
24
+ * @returns something like a response_key with possible responses
25
+ */
26
+const formatStep = (match, step) => {
27
+    const responsesByCategory = possible['usa']
28
+    const responseKey = {
29
+        response_key_id: match ? match.response_key_id : null,
30
+        response_key_category: match ? match.response_key_category : 'profile',
31
+        response_key_prompt: match ? match.response_key_prompt : step,
32
+        response_key_description: match ? match.response_key_description : null,
33
+    }
34
+    return {
35
+        ...responseKey,
36
+        responses: responsesByCategory[step] ? responsesByCategory[step] : [],
37
+    }
38
+}
39
+const associateWithComponent = responseKeyLike => {
40
+    let component = promptToComponent[responseKeyLike.response_key_prompt]
41
+    return { ...responseKeyLike, component }
42
+}
43
+
44
+const hasMatch = (step, inArray) => {
45
+    return inArray.find(q => q.response_key_prompt == step)
46
+}
3 47
 
4 48
 class SurveyFactory {
5
-    constructor(responses) {
6
-        this.responsesByCategory = responses
49
+    constructor() {
7 50
         this.questionsFromDb = []
8 51
     }
9 52
     _setSteps(langFile) {
@@ -11,25 +54,14 @@ class SurveyFactory {
11 54
         const seenIds = []
12 55
         const stepsInCommon = stepsToProcess.map(step => {
13 56
             // Match question to step
14
-            const match = this.questionsFromDb.filter(
15
-                q => q.response_key_prompt == step,
16
-            )[0]
57
+            const match = hasMatch(step, this.questionsFromDb)
17 58
             if (match) {
18 59
                 seenIds.push(match.response_key_id)
19 60
             }
20
-            return {
21
-                response_key_id: match ? match.response_key_id : null,
22
-                response_key_category: match
23
-                    ? match.response_key_category
24
-                    : 'profile',
25
-                response_key_prompt: match ? match.response_key_prompt : step,
26
-                response_key_description: match
27
-                    ? match.response_key_description
28
-                    : null,
29
-                responses: this.responsesByCategory[step]
30
-                    ? this.responsesByCategory[step]
31
-                    : [],
32
-            }
61
+            const responseKeyLike = formatStep(match, step)
62
+            const withComponent = associateWithComponent(responseKeyLike)
63
+            console.log('withComponent :>> ', withComponent)
64
+            return withComponent
33 65
         })
34 66
         const unseen = this.questionsFromDb.filter(
35 67
             q => !seenIds.includes(q.response_key_id),

+ 31
- 54
frontend/src/views/OnboardingView.vue Datei anzeigen

@@ -1,48 +1,36 @@
1 1
 <template lang="pug">
2 2
 main.view--onboarding
3
-    article(style='display: flex; flex-direction: column; align-items: center')
4
-        component(
5
-            :aspect-questions='steps[currentStep] == "Aspects" ? aspectQuestions : null'
6
-            :current-step='currentStep'
7
-            :is='steps[currentStep]'
8
-            @go-to-step='goToStep'
9
-            @handle-submit='onSubmit'
10
-            @update-answers='updateAnswers'
11
-        )
3
+    article(
4
+        style='display: flex; flex-direction: column; align-items: center'
5
+        v-if='survey'
6
+    )
7
+        .step(v-for='(step, i) in survey.steps')
8
+            component(
9
+                :aspect-questions='step.component == "Aspects" ? survey.aspectQuestions : null'
10
+                :is='step.component'
11
+                :question='step'
12
+                @handle-submit='onSubmit'
13
+                @update-answers='updateAnswers'
14
+                v-if='step.component'
15
+            )
16
+            p(v-else) {{ step }}
17
+            p step: {{ i + 1 }} of {{ survey.steps.length }}
18
+            //- component(
19
+            //-     :aspect-questions='step.component == "Aspects" ? survey.aspectQuestions : null'
20
+            //-     :is='step.component'
21
+            //-     :question='step'
22
+            //-     @handle-submit='onSubmit'
23
+            //-     @update-answers='updateAnswers'
24
+            //-     v-if='step && currentStep == i'
25
+            //- )
26
+            //- p(v-if='currentStep == i') step: {{ i+1 }} of {{ survey.steps.length }}
12 27
 </template>
13 28
 
14 29
 <script>
15 30
 import { surveyFactory } from '@/utils'
16
-import { allSteps, possible } from '@/utils/lang'
31
+import { allSteps } from '@/utils/lang'
17 32
 import stepViews from '@/components/onboarding'
18 33
 
19
-const SCORED = [1, 2, 3, 4, 5, 6]
20
-
21
-const _isScored = id => SCORED.includes(id)
22
-
23
-const _makeCategoryFriendly = responseCategory => {
24
-    const labels = responseCategory.split('_vs_')
25
-    labels.forEach((a, i) => {
26
-        if (a.indexOf('_') == -1) return
27
-        labels[i] = a.split('_').join(' ')
28
-    })
29
-    return labels
30
-}
31
-
32
-const _formatAspectQuestions = steps => {
33
-    return steps
34
-        .map(q => {
35
-            if (!_isScored(q.response_key_id)) return null
36
-            return {
37
-                id: q.response_key_id,
38
-                question: q.response_key_prompt,
39
-                labels: _makeCategoryFriendly(q.response_key_category),
40
-                answer: null,
41
-            }
42
-        })
43
-        .filter(step => step != null)
44
-}
45
-
46 34
 // import savesurveybyprfileid - call it on submit
47 35
 // paginate to save every steps answers
48 36
 export default {
@@ -54,24 +42,10 @@ export default {
54 42
         answered: {},
55 43
         aspectQuestions: [],
56 44
         currentStep: 0,
57
-        steps: [
58
-            'Splash',
59
-            'AccountType',
60
-            'CompanyID',
61
-            'Role',
62
-            'Skills',
63
-            'Location',
64
-            'Interests',
65
-            'LicensesAndCertifications',
66
-            'Aspects',
67
-        ],
45
+        survey: null,
68 46
     }),
69 47
     async created() {
70
-        const survey = await surveyFactory.createSurvey(
71
-            allSteps['usa'],
72
-            possible['usa']['roles'],
73
-        )
74
-        this.aspectQuestions = _formatAspectQuestions(survey.steps)
48
+        this.survey = await surveyFactory.createSurvey(allSteps['usa'])
75 49
     },
76 50
     methods: {
77 51
         onSubmit() {
@@ -81,7 +55,10 @@ export default {
81 55
             this.currentStep = num
82 56
         },
83 57
         updateAnswers(payload) {
84
-            this.answered[payload.key] = payload.answer
58
+            const k = payload.question.response_key_prompt
59
+            this.answered[k] = payload.answer
60
+            console.log(`${k}:`, this.answered[k])
61
+            this.goToStep(this.currentStep + 1)
85 62
         },
86 63
     },
87 64
 }

Laden…
Abbrechen
Speichern