Browse Source

:construction: Started work on saving survey state by sending responses to db

tags/0.0.3^2
tomit4 3 years ago
parent
commit
d16fea20cf

+ 2
- 0
backend/lib/plugins/profile.js View File

@@ -16,6 +16,7 @@ const MatchService = require('../services/match')
16 16
 
17 17
 const ProfileScoreRoute = require('../routes/profile/score')
18 18
 const ProfileUpdateRoute = require('../routes/profile/update')
19
+const ProfileInsertRoute = require('../routes/profile/insert')
19 20
 const ProfileRespondRoute = require('../routes/profile/respond')
20 21
 const ProfileMatchRoute = require('../routes/profile/match')
21 22
 const ProfileQueueRoute = require('../routes/profile/queue')
@@ -51,6 +52,7 @@ module.exports = {
51 52
         await server.route(ProfileScoreRoute)
52 53
         await server.route(ProfileRespondRoute)
53 54
         await server.route(ProfileUpdateRoute)
55
+        await server.route(ProfileInsertRoute)
54 56
         await server.route(ProfileMatchRoute)
55 57
         await server.route(ProfileQueueRoute)
56 58
         await server.route(ProfileGetRoute)

+ 99
- 0
backend/lib/routes/profile/insert.js View File

@@ -0,0 +1,99 @@
1
+'use strict'
2
+
3
+const Joi = require('joi')
4
+const apiSchema = require('../../schemas/api')
5
+const errorSchema = require('../../schemas/errors')
6
+const surveyResponseSchema = require('../../schemas/responses')
7
+const params = require('../../schemas/params')
8
+
9
+const pluginConfig = {
10
+    handlerType: 'profile',
11
+    docs: {
12
+        description: 'Insert profile',
13
+        notes: 'Insert new profile responses',
14
+    },
15
+}
16
+
17
+const responseSchemas = {
18
+    response: surveyResponseSchema.list,
19
+    error: errorSchema.single,
20
+}
21
+
22
+const validators = {
23
+    /** Validate the header (cookie check) */
24
+    // headers: true,
25
+
26
+    /** Validate the route params (/active/{thing}) */
27
+    params: params.profileId,
28
+
29
+    /** Validate the route query (/active/{thing}?limit=10&offset=10) */
30
+    // query: true,
31
+    /** Validate the incoming payload (POST method) */
32
+    payload: responseSchemas.responses,
33
+}
34
+
35
+module.exports = {
36
+    method: 'POST',
37
+    path: '/{profile_id}/insert/{response_id?}',
38
+    options: {
39
+        ...pluginConfig.docs,
40
+        tags: ['api'],
41
+        /** Protect this route with authentication? */
42
+        auth: false,
43
+
44
+        handler: async function (request, h) {
45
+            const { profileService } = request.services()
46
+            const profileId = request.params.profile_id
47
+
48
+            /** Grab payload info */
49
+            const res = request.payload
50
+            console.log('res :=>', res)
51
+
52
+            try {
53
+                const allResponses = profileService.saveResponseForProfile(profileId, res)
54
+
55
+                if (!allResponses) {
56
+                    throw new RangeError('Response not inserted')
57
+                }
58
+
59
+                return h
60
+                    .response({
61
+                        ok: true,
62
+                        handler: pluginConfig.handlerType,
63
+                        data: allResponses,
64
+                    })
65
+                    .code(200)
66
+            } catch (err) {
67
+                return h
68
+                    .response({
69
+                        ok: false,
70
+                        handler: pluginConfig.handlerType,
71
+                        data: { error: `${err}` },
72
+                    })
73
+                    .code(409)
74
+            }
75
+        },
76
+
77
+        /** Validate based on validators object */
78
+        validate: {
79
+            ...validators,
80
+            failAction: 'log',
81
+        },
82
+
83
+        /** Validate the server response */
84
+        response: {
85
+            status: {
86
+                200: apiSchema.single
87
+                    .append({
88
+                        data: responseSchemas.response,
89
+                    })
90
+                    .label('response_list_res'),
91
+                409: apiSchema.single
92
+                    .append({
93
+                        data: responseSchemas.error,
94
+                    })
95
+                    .label('error_single_res'),
96
+            },
97
+        },
98
+    },
99
+}

+ 8
- 0
frontend/src/entities/survey/survey.js View File

@@ -43,6 +43,14 @@ class Survey extends _baseRecord {
43 43
         )
44 44
     }
45 45
 
46
+    hasMinResponsesToCreateProfile(responses) {
47
+        if (responses.name &&
48
+            responses.email &&
49
+            responses.seeking) {
50
+            return true
51
+        } else return false
52
+    }
53
+
46 54
     validateAnswer(payload) {
47 55
         const { question, input } = payload
48 56
 

+ 19
- 0
frontend/src/services/survey.service.js View File

@@ -22,6 +22,23 @@ const fetchQuestions = async () => {
22 22
     return withResponses
23 23
 }
24 24
 
25
+const insertNewSurveyResponses = async (surveyResponses, profileId) => {
26
+    surveyResponses.forEach(responseKeyIdwithVal => {
27
+        const keyId = responseKeyIdwithVal.response_key_id
28
+        const val = responseKeyIdwithVal.val
29
+        // POST
30
+        // TODO: create this route on the backend
31
+        db.post(`/profile/${profileId}/insert/${keyId}`, [
32
+            {
33
+                profile_id: profileId,
34
+                reponse_key_id: keyId,
35
+                val: val,
36
+            }
37
+        ])
38
+    })
39
+}
40
+
41
+// similar to this
25 42
 const updateSurveyByProfileId = async (surveyResponses, profileId) => {
26 43
     surveyResponses.forEach(responseKeyIdwithVal => {
27 44
         const keyId = responseKeyIdwithVal.response_key_id
@@ -38,6 +55,7 @@ const updateSurveyByProfileId = async (surveyResponses, profileId) => {
38 55
     })
39 56
 }
40 57
 
58
+// and similar to this
41 59
 const scoreSurveyByProfileId = async (profileId, maxDistance = 99) => {
42 60
     const scoreSurvey = await db.get(
43 61
         `/profile/${profileId}/score?max_distance=${maxDistance}`,
@@ -51,6 +69,7 @@ const fetchResponsesByProfileId = async profileId => {
51 69
 
52 70
 export {
53 71
     fetchQuestions,
72
+    insertNewSurveyResponses,
54 73
     updateSurveyByProfileId,
55 74
     scoreSurveyByProfileId,
56 75
     fetchResponsesByProfileId,

+ 2
- 2
frontend/src/utils/lang.js View File

@@ -19,17 +19,17 @@ const splash = {
19 19
 const allSteps = {
20 20
     usa: {
21 21
         name: 'name',
22
+        email: 'email',
23
+        seeking: 'seeking',
22 24
         aspect01: 'aspect-1',
23 25
         aspect02: 'aspect-2',
24 26
         aspect03: 'aspect-3',
25 27
         password: 'password',
26 28
         zipcode: 'zipcode',
27
-        seeking: 'seeking',
28 29
         urgency: 'urgency',
29 30
         aspect04: 'aspect-4',
30 31
         aspect05: 'aspect-5',
31 32
         aspect06: 'aspect-6',
32
-        email: 'email',
33 33
         presence: 'presence',
34 34
         duration: 'duration',
35 35
         pronouns: 'pronouns',

+ 11
- 1
frontend/src/utils/survey.js View File

@@ -1,10 +1,11 @@
1 1
 import { Survey } from '../entities/index.js'
2
-import { fetchQuestions } from '../services/index.js'
2
+import { fetchQuestions, insertNewSurveyResponses } from '../services/index.js'
3 3
 import { splash, possible, surveyStages, allSteps } from './lang.js'
4 4
 
5 5
 class SurveyFactory {
6 6
     constructor() {
7 7
         this.questionsFromDb = []
8
+        this.responsesFromDb = []
8 9
     }
9 10
     _addResponses(responseKeys, responsesByCategory) {
10 11
         const existingResponses = {}
@@ -82,6 +83,15 @@ class SurveyFactory {
82 83
             console.error(err)
83 84
         }
84 85
     }
86
+    async addNewSurveyAnswers(responses, profileId) {
87
+        try {
88
+            this.responsesFromDb = await insertNewSurveyResponses(responses, profileId)
89
+            return this.responsesFromDb
90
+        }
91
+        catch (err) {
92
+            console.error(err)
93
+        }
94
+    }
85 95
     async createSurvey(roleTree) {
86 96
         if (!this.questionsFromDb.length) {
87 97
             const res = await this.getQuestions()

+ 32
- 3
frontend/src/views/OnboardingView.vue View File

@@ -34,11 +34,14 @@ main.view--onboarding
34 34
 </template>
35 35
 
36 36
 <script>
37
+// import { currentProfile } from '@/services'
38
+// import { createProfileForUserId } from '../services/profile.service'
37 39
 import { surveyFactory } from '@/utils'
40
+import { signupUser, createProfileForUserId } from '@/services/'
38 41
 import stepViews from '@/components/onboarding'
39 42
 import SurveyCompleteView from './SurveyCompleteView.vue'
40 43
 
41
-// import savesurveybyprfileid - call it on submit
44
+// import savesurveybyprofileid - call it on submit
42 45
 // paginate to save every steps answers
43 46
 export default {
44 47
     name: 'OnboardingView',
@@ -49,12 +52,17 @@ export default {
49 52
     data: () => ({
50 53
         answered: {},
51 54
         aspectQuestions: [],
55
+        responses: [],
52 56
         currentStep: 0,
53 57
         survey: null,
58
+        currentProfileId: null,
54 59
         invalidResponse: false,
55 60
     }),
56 61
     async created() {
62
+        // uses createSurvey/getQuestions from from utils/survey.service.js 
63
+        // which calls in fetchQuestions from services/survey.service.js
57 64
         this.survey = await surveyFactory.createSurvey()
65
+        // TODO: create boolean value based off if a passed user_email is found in user db (i.e. login)
58 66
     },
59 67
     methods: {
60 68
         onSubmit() {
@@ -63,7 +71,7 @@ export default {
63 71
         goToStep(num) {
64 72
             this.currentStep = num
65 73
         },
66
-        updateAnswers(payload) {
74
+        async updateAnswers(payload) {
67 75
             // null payload is passed on splash page
68 76
             if (payload) {
69 77
                 this.invalidResponse = false
@@ -77,7 +85,28 @@ export default {
77 85
 
78 86
                 // once validated, don't log password in answered object
79 87
                 this.answered[k] = k === 'password' ? undefined : payload.input
80
-                console.log(`Updated answers: ${JSON.stringify(this.answered)}`)
88
+                console.log('this.answered :=>', this.answered)
89
+
90
+                // formats initial responses for response table
91
+                const response = {}
92
+                response.response_key_id = payload.question.response_key_id
93
+                response.val = payload.input
94
+                this.responses.push(response)
95
+
96
+                // save endpoint here
97
+                // start with utils/surve.js
98
+                if (this.currentProfileId) {
99
+                    surveyFactory.addNewSurveyAnswers(this.responses, this.currentProfileId)
100
+                }
101
+
102
+                // creates a user in db as long as name, email, and seeking are defined
103
+                if (!this.currentProfileId && this.survey.hasMinResponsesToCreateProfile(this.answered)) {
104
+                    const newUser = await signupUser(this.answered)
105
+                    const newUserId = newUser.user_id
106
+                    const newProfile = await createProfileForUserId(newUserId, this.responses)
107
+                    this.currentProfileId = newProfile.profile_id
108
+                }
109
+
81 110
                 if (k === 'aspects') return
82 111
             }
83 112
             if (this.currentStep > this.survey.steps.length) {

Loading…
Cancel
Save