Преглед изворни кода

:recycle: dynamically set responses for roles | correctly stepping through survey with dynamic cmponent and madlib

tags/0.0.1
J пре 4 година
родитељ
комит
d632bf520d

+ 8
- 2
frontend/src/components/form/button-choice.vue Прегледај датотеку

@@ -1,7 +1,7 @@
1 1
 <template lang="pug">
2 2
 .form--step.button-choice
3 3
     header
4
-        p selections {{selected}}
4
+        p selections {{selected}} {{opts}}
5 5
     main(:class="{ 'f-row': opts.length > 2, 'f-col': opts.length <= 2 }")
6 6
         button(v-for="op in opts" :class="isSelected(op)" @click="selectOption(op)") {{ op }}
7 7
 </template>
@@ -18,6 +18,10 @@ const props = defineProps({
18 18
         default: () => ['up', 'down'],
19 19
         // default: () => ['up', 'left', 'right', 'down'],
20 20
     },
21
+    prompt: {
22
+        required: true,
23
+        type: String
24
+    },
21 25
 })
22 26
 
23 27
 const selected = ref([])
@@ -32,7 +36,9 @@ const selectOption = optionVal => {
32 36
     } else {
33 37
         selected.value = selected.value.filter(val => val != optionVal)
34 38
     }
35
-    emit('selected', selected.value)
39
+    const sel = {}
40
+    sel[props.prompt] = selected.value[0]
41
+    emit('selected', sel)
36 42
 }
37 43
 </script>
38 44
 

+ 22
- 14
frontend/src/components/form/button-multi.vue Прегледај датотеку

@@ -1,20 +1,14 @@
1 1
 <template lang="pug">
2 2
 .form--step.button-multi
3
-    header.f-row
4
-        p {{selected.length}} | {{selected.length == opts.length}}
5
-        p
6
-            span(v-for="sel in selected") {{ sel }}&nbsp;
7
-
8
-    main.f-col(v-for="(op, i) in opts" :class="[{ 'selected': selected.length == i }, `step-${i}`, 'step']")
9
-        button(v-for="val in op" @click="selectOption(i, val)") {{ val }}
10
-    main(v-if="opts.length == selected.length").selected
11
-        button(@click="next") next
3
+    main(:class="{ 'f-row': opts.length > 2, 'f-col': opts.length <= 2 }")
4
+        button(v-for="op in opts" :class="isSelected(op)" @click="selectOption(op)" :disabled="selected.includes(op)") {{ op }}
5
+    button(@click="next") next
12 6
 </template>
13 7
 
14 8
 <script setup>
15 9
 import { defineProps, defineEmits, ref } from 'vue'
16 10
 
17
-const emit = defineEmits(['selected', 'next'])
11
+const emit = defineEmits(['onButtonSelect'])
18 12
 
19 13
 const props = defineProps({
20 14
     opts: {
@@ -25,17 +19,31 @@ const props = defineProps({
25 19
             ['left', 'right'],
26 20
         ],
27 21
     },
22
+    prompt: {
23
+        required: true,
24
+        type: String
25
+    },
28 26
 })
29 27
 
28
+
30 29
 const selected = ref([])
31 30
 
32
-const selectOption = (step, optionVal) => {
33
-    selected.value[step] = optionVal
34
-    emit('selected', selected.value)
31
+const isSelected = val => {
32
+    return selected.value.includes(val) ? 'selected' : ''
33
+}
34
+
35
+const selectOption = optionVal => {
36
+    if (!selected.value.includes(optionVal)) {
37
+        selected.value.push(optionVal)
38
+    } else {
39
+        selected.value = selected.value.filter(val => val != optionVal)
40
+    }
35 41
 }
36 42
 
37 43
 const next = () => {
38
-    emit('next', selected.value)
44
+    const sel = {}
45
+    sel[props.prompt] = selected.value
46
+    emit('selected', sel)
39 47
     selected.value = []
40 48
 }
41 49
 </script>

+ 11
- 5
frontend/src/components/form/input-string.vue Прегледај датотеку

@@ -5,18 +5,18 @@
5 5
     main.f-col
6 6
         input(v-if="!multiline" v-model="input")
7 7
         textarea(v-else cols="50" rows="8" v-model="input")
8
-        button(@click="next").w-full next
8
+        button(@click="selectOption").w-full next
9 9
 </template>
10 10
 
11 11
 <script setup>
12 12
 import { defineProps, defineEmits, ref } from 'vue'
13 13
 
14
-const emit = defineEmits(['next'])
14
+const emit = defineEmits(['onButtonSelect'])
15 15
 
16 16
 const props = defineProps({
17 17
     default: {
18 18
         required: true,
19
-        type: Array,
19
+        type: String,
20 20
         default: () => 'start',
21 21
     },
22 22
     multiline: {
@@ -24,12 +24,18 @@ const props = defineProps({
24 24
         type: Boolean,
25 25
         default: true,
26 26
     },
27
+    prompt: {
28
+        required: true,
29
+        type: String
30
+    },
27 31
 })
28 32
 
29 33
 const input = ref(props.default)
30 34
 
31
-const next = () => {
32
-    emit('next', input.value)
35
+const selectOption = () => {
36
+    const sel = {}
37
+    sel[props.prompt] = input.value
38
+    emit('selected', sel)
33 39
 }
34 40
 </script>
35 41
 

+ 9
- 3
frontend/src/entities/survey/survey.js Прегледај датотеку

@@ -3,7 +3,7 @@ import { _baseRecord } from '..'
3 3
 import { surveySchema } from './survey.schema'
4 4
 
5 5
 class Survey extends _baseRecord {
6
-    constructor(questionSteps) {
6
+    constructor(questionSteps, roles) {
7 7
         super()
8 8
 
9 9
         this.type = this.constructor.name.toLowerCase()
@@ -12,10 +12,16 @@ class Survey extends _baseRecord {
12 12
         this.steps = [
13 13
             ...questionSteps
14 14
         ] // ! required
15
-        
15
+        this.roleTree = roles
16
+
16 17
         return this
17 18
     }
18
-
19
+    setRoleResponses(position) {
20
+        const roleStep = this.steps.filter(step => step.response_key_prompt == 'role')[0]
21
+        roleStep.responses = this.roleTree[position]
22
+        console.log(roleStep)
23
+        console.log(this.roleTree[position])
24
+    }
19 25
     isValid() {
20 26
         const validate = surveySchema.validate(this)
21 27
 

+ 7
- 5
frontend/src/utils/lang.js Прегледај датотеку

@@ -2,10 +2,11 @@ const DELIMITER = '_'
2 2
 
3 3
 const stepToComponentMap = {
4 4
     name: 'InputString',
5
-    seeking: 'ButtonMulti',
5
+    seeking: 'ButtonChoice',
6 6
     urgency: 'ButtonChoice',
7
-    distance: 'ButtonChoice',
7
+    role: 'ButtonChoice',
8 8
     duration: 'ButtonChoice',
9
+    distance: 'ButtonChoice',
9 10
     language: 'ButtonMulti',
10 11
 }
11 12
 
@@ -14,8 +15,9 @@ const allSteps = {
14 15
         name: 'name',
15 16
         seeking: 'seeking',
16 17
         urgency: 'urgency',
17
-        distance: 'distance',
18
+        role: 'role',
18 19
         duration: 'duration',
20
+        distance: 'distance',
19 21
         language: 'language',
20 22
     }
21 23
 }
@@ -77,7 +79,7 @@ possible.usa = {
77 79
             'system',
78 80
             'test',
79 81
         ],
80
-        seeker: [
82
+        position: [
81 83
             'administrator',
82 84
             'analyst',
83 85
             'architect',
@@ -86,7 +88,7 @@ possible.usa = {
86 88
             'manager',
87 89
             'technician',
88 90
         ],
89
-        provider: [
91
+        candidate: [
90 92
             'hiring_manager',
91 93
             'recruiter',
92 94
         ]

+ 2
- 3
frontend/src/utils/survey.js Прегледај датотеку

@@ -7,7 +7,6 @@ class SurveyFactory {
7 7
     }
8 8
     async setSteps(langFile) {
9 9
         const stepsToProcess = [...Object.values(langFile) ]
10
-        console.log(stepsToProcess)
11 10
         const questions = await fetchQuestionsByProfileId()
12 11
         const seenIds = []
13 12
         const stepsInCommon = stepsToProcess.map(step => {
@@ -25,9 +24,9 @@ class SurveyFactory {
25 24
         const unseen = questions.filter(q => !seenIds.includes(q.response_key_id))
26 25
         return [...stepsInCommon, ...unseen]
27 26
     }
28
-    async createSurvey(langFile) {
27
+    async createSurvey(langFile, roleTree) {
29 28
         const steps = await this.setSteps(langFile)
30
-        return new Survey(steps)
29
+        return new Survey(steps, roleTree)
31 30
     }
32 31
 }
33 32
 

+ 53
- 114
frontend/src/views/Survey.vue Прегледај датотеку

@@ -1,119 +1,48 @@
1 1
 <template lang="pug">
2 2
 main.f-col.start.w-full
3
-    ButtonMulti
3
+    //- ButtonMulti
4 4
     //- ButtonChoice
5 5
     //- InputString
6
-    h5(v-if="profileQuestions.length" v-for="q in profileQuestions")
7
-        span(v-if="componentMap[q.response_key_prompt]") {{ componentMap[q.response_key_prompt] }}:
8
-        span(v-else) InputString:
9
-        span {{ q.response_key_prompt }} | 
10
-        span(v-if="q.responses")
11
-            button(v-for="resp in q.responses") {{ resp }}
6
+    header.w-full.f-col
7
+        h3(v-if="!name") hello, what shall i call you?
8
+        h3(v-if="step == 1") What can i help you with, 
9
+            span {{ name }}?
10
+            br
11
+            span I am seeking a ___________.
12
+        h3(v-else-if="step == 2") A {{ seeking }} then. You're in the right place.
13
+            span How would you like to use siimee? 
14
+            br
15
+            span I am ________________.
16
+        h3(v-else-if="[3, 4, 5].includes(step)")
17
+            span I am a _________. 
18
+            br
19
+            span Looking for a ________
20
+            span  ________ 
21
+            span in _______.
12 22
 
13 23
     article.match.w-full
14 24
         ul.w-full
15
-            li(v-if="step == 0")
16
-                header
17
-                    p step 1
18
-                section
19
-                    input(v-model="name")
20
-                footer
21
-                    button(@click="step++").w-full next
22
-            
23
-            li(v-if="step == 1")
24
-                header
25
-                    p step 1
26
-                section
27
-                    p 
28
-                        span(v-if="name") {{ name }}  
29
-                        span(v-else) ______________
30
-                        span .  
31
-                        span Let's get started on you profile while we verify your account.
32
-                footer.f-row
33
-                    button(@click="step--").w-full back
34
-                    button(@click="step++").w-full next
35
-            
36
-            li(v-if="step == 2")
37
-                header
38
-                    p step 2
39
-                section
40
-                    p
41
-                        span What are you looking for 
42
-                        span {{ name }}
43
-                        span ?
44
-                footer.f-col.w-full
45
-                    button(@click="saveNext('position')") a position
46
-                    button(@click="saveNext('cadidate')") a candidate
47
-            
48
-            li(v-if="step == 3")
49
-                header
50
-                    p step 3
51
-                section
52
-                    p
53
-                        span {{ seeking }} 
54
-                        span . 
55
-                        span You're in the right place. How would you like to use siimee?
56
-                section
57
-                    p
58
-                        span i am 
59
-                        select
60
-                            option actively searching
61
-                            option networking
62
-                            option exploring
63
-                footer.f-row
64
-                    button(@click="step--").w-full back
65
-                    button(@click="step++").w-full next
66
-            
67
-            li(v-if="step == 4")
68
-                header
69
-                    p step 4
70
-                section
71
-                    p
72
-                        span i am 
73
-                        span(v-if="role") a {{ role }}. 
74
-                        span(v-else) ______________. 
75
-                section
76
-                    p
77
-                        span(v-if="location") Looking for a {{ location }}, 
78
-                        span(v-else) Looking for a ______________, 
79
-                        span(v-if="experience") {{ experience }}&nbsp;
80
-                        span(v-else) ______________ 
81
-                        span(v-if="position") {{ position }}ing role. 
82
-                        span(v-else) ______________ role. 
83
-                
84
-                footer(v-if="!role").f-row
85
-                    button(@click="role = 'recruiter'") a recruiter
86
-                    button(@click="role = 'hiring_manager'") a hiring manager
87
-                footer.f-row(v-else-if="!location")
88
-                    button(@click="location = 'remote'") remote
89
-                    button(@click="location = 'in_person'") in person
90
-                footer.f-row(v-else-if="location == 'in_person' && zipcode.length > 5")
91
-                    input(v-model="zipcode")
92
-                footer.f-row(v-else-if="!experience")
93
-                    button(@click="experience = 'junior'") junior
94
-                    button(@click="experience = 'mid-level'") mid-level
95
-                    button(@click="experience = 'senior'") senior
96
-                    button(@click="experience = 'staff'") staff
97
-                footer.f-row(v-else-if="!position")
98
-                    button(@click="position = 'engineer'") engineering
99
-                footer.f-row(v-else)
100
-                    button(@click="step++").w-full next
101
-
102
-            li(v-if="step == 5")
103
-                header
104
-                    p step 5
105
-                section
106
-                    SurveyForm(v-if="validSurvey && validSurvey.steps" :form="validSurvey.steps" :pid="pid")
107
-                footer.f-row
108
-                    button(@click="step--").w-full back
109
-                    button(@click="step=0").w-full save
25
+            template(v-for="(q, i) in profileQuestions" :key="q.response_key_prompt")
26
+                li(v-if="step == i").f-col
27
+                    p step: {{ i }}
28
+                        component(
29
+                            v-if="componentMap[q.response_key_prompt]"
30
+                            :is="componentMap[q.response_key_prompt]"
31
+                            :opts="q.responses"
32
+                            :prompt="q.response_key_prompt"
33
+                            @selected="onButtonSelect"
34
+                        )
35
+                        div(v-else-if="step >= priorityQuestions.length")
36
+                            button(@click="step = 0") save
37
+                    footer.f-row
38
+                        button(@click="step--").w-full back
110 39
         //- SurveyForm(v-if="validSurvey && validSurvey.steps" :form="validSurvey.steps" :pid="pid")
111 40
     MainNav(:pid="pid" @show-sidebar="$emit('show-sidebar')")
112 41
 </template>
113 42
 
114 43
 <script>
115 44
 import { surveyFactory } from '../utils'
116
-import { allSteps, stepToComponentMap } from '../utils/lang'
45
+import { allSteps, possible, stepToComponentMap } from '../utils/lang'
117 46
 import SurveyForm from '../components/form.vue'
118 47
 import ButtonMulti from '../components/form/button-multi.vue'
119 48
 import ButtonChoice from '../components/form/button-choice.vue'
@@ -137,6 +66,7 @@ export default {
137 66
             role: '',
138 67
             experience: '',
139 68
             position: '',
69
+            language: '',
140 70
             location: '',
141 71
             zipcode: '',
142 72
         }
@@ -152,13 +82,21 @@ export default {
152 82
         }
153 83
     },
154 84
     async created() {
155
-        this.validSurvey = await surveyFactory.createSurvey(allSteps['usa'])
156
-        console.log('profile:', this.profileQuestions)
85
+        this.validSurvey = await surveyFactory.createSurvey(allSteps['usa'], possible['usa']['roles'])
157 86
     },
158 87
     methods: {
159
-        saveNext(val) {
160
-            console.log(val)
161
-            this.seeking = val
88
+        /**
89
+         * Set state from promptVal key:value object
90
+         * from button-coice or button-multi
91
+         */
92
+        onButtonSelect(promptVal){
93
+            console.log('promptVal :', promptVal)
94
+            for(const [prompt, val] of Object.entries(promptVal)) {
95
+                this[prompt] = val
96
+                if(prompt == 'seeking') {
97
+                    this.validSurvey.setRoleResponses(val)
98
+                }
99
+            }
162 100
             this.step++
163 101
         },
164 102
     },
@@ -172,6 +110,13 @@ h1
172 110
 main
173 111
     padding: 5vh
174 112
     display: flex
113
+    header
114
+        p
115
+            color: #666
116
+            line-height: 1.3em
117
+        color: #ccc
118
+        font-style: italic
119
+        text-align: left
175 120
 
176 121
 article
177 122
     height: 100%
@@ -188,12 +133,6 @@ article
188 133
 .form
189 134
     border: 1px solid #fff
190 135
     width: 100%
191
-    header
192
-        color: #ccc
193
-        font-style: italic
194
-        p
195
-            line-height: 1.3em
196
-            text-align: left
197 136
     header, footer, ul
198 137
         padding: 1vh
199 138
     ul

Loading…
Откажи
Сачувај