Explorar el Código

:recycle: a bunch of random changes before we get started

tags/0.0.1
J hace 3 años
padre
commit
0d2a0d3050

+ 6
- 7
backend/README.md Ver fichero

@@ -14,10 +14,10 @@ You will need...
14 14
 ## :package: Installation
15 15
 
16 16
 1. Install dependencies with `npm install`
17
-2. Copy the environments sample file from `./server/.env.sample` and rename it to `./server/.env`
18
-3. Fill out your database connection details in `./server/.env`
19
-4. A test database container is provided and can be started with `docker-compose --env-file ./backend/server/.env up -d`
20
-5. Populate some basic tables for your database using `npx knex migrate:latest`
17
+2. Copy the environments sample file from `./backend/.env.sample` and rename it to `./backend/.env`
18
+3. Fill out your database connection details in `./backend/.env`
19
+4. A test database container is provided and can be started with `docker-compose up -d`
20
+5. Populate some basic tables for your database using `npm run generate && npm run reseed`
21 21
 
22 22
 ## :package: Migrations
23 23
 
@@ -37,9 +37,8 @@ Since we can't unseed the database, it's best to destroy the `dev` database and
37 37
 
38 38
 1. Stop the database by navigating to the project root directory `cd ../` and running `docker-compose down`
39 39
 2. Destroy the database volume `docker volume rm siimee_siimee_db`. BE CAREFUL.
40
-3. Restart the database while still at the project root with `docker-compose --env-file ./backend/server/.env up -d`
41
-4. Recreate schemas and tables but navigating to `./backend` and running `npm run migrate`
42
-5. Reseed the dummy data with `npm run seed`
40
+3. Restart the database while still at the project root with `docker-compose up -d`
41
+4. Recreate schemas,tables and dummy data by navigating to `./backend` and running `npm run reseed`
43 42
 
44 43
 ## :electric_plug: Run
45 44
 

+ 2
- 2
backend/db/data-generator/config.json Ver fichero

@@ -1,8 +1,8 @@
1 1
 {
2 2
     "mockOutputPath": "./db/generated",
3 3
     "magic": 10000,
4
-    "total": 5,
5
-    "batchSize": 5,
4
+    "total": 10,
5
+    "batchSize": 10,
6 6
     "percentageOfSeekers": 90,
7 7
     "scoreVals": [107, 414, 721, 1028, 1336, 1648, 2056],
8 8
     "header": "/**\n* GENERATED MOCK SIIMEE DATA\n*/",

+ 6
- 7
backend/db/data-generator/index.js Ver fichero

@@ -111,7 +111,6 @@ const generateProfiles = jobPosterIds => {
111 111
 /**
112 112
  * Generate Responses
113 113
  */
114
-const _ZIPCODEKEY = 7
115 114
 const generateResponses = profiles => {
116 115
     // Generate responses first, before filling in details
117 116
     let responses = generate(
@@ -126,18 +125,18 @@ const generateResponses = profiles => {
126 125
             resToEdit.response_key_id = k + 1
127 126
             resToEdit.profile_id = profile.profile_id
128 127
 
129
-            if(resToEdit.response_key_id < _ZIPCODEKEY) {
128
+            if(resToEdit.response_key_id < config.zipcodeKey) {
130 129
                 resToEdit.val = random.valFrom(Object.values(possibleResponses))
131 130
             }
132
-            else if(resToEdit.response_key_id == _ZIPCODEKEY) {
131
+            else if(resToEdit.response_key_id == config.zipcodeKey) {
133 132
                 resToEdit.val = random.valFrom(config.possibleZipcodes)
134 133
             }
135 134
             else {
136 135
                 switch (resToEdit.response_key_id) {
137
-                case 8:
136
+                case config.mediaKey:
138 137
                     resToEdit.val = random.media()
139 138
                     break
140
-                case 9:
139
+                case config.langKey:
141 140
                     resToEdit.val = random.language()
142 141
                     break
143 142
                 case 10:
@@ -146,14 +145,14 @@ const generateResponses = profiles => {
146 145
                 case 11:
147 146
                     resToEdit.val = random.location()
148 147
                     break
149
-                case 12:
148
+                case config.blurbKey:
150 149
                     resToEdit.val = random.blurb()
151 150
                     break
152 151
                 }
153 152
             }
154 153
         }
155 154
     })
156
-    // generatedResponseCount = generatedResponseCount + responses.length
155
+    generatedResponseCount = generatedResponseCount + responses.length
157 156
     console.log('COMPLETED: Generated Responses...')
158 157
     return responses
159 158
 }

backend/lib/services/profile.js → backend/lib/services/profile/index.js Ver fichero

@@ -1,131 +1,10 @@
1 1
 const Schmervice = require('@hapipal/schmervice')
2 2
 const haversine = require('haversine')
3
-const config = require('../../db/data-generator/config.json')
4
-
5
-const _isScorableResponse = res_key_id => {
6
-    let isScorable = false
7
-    if(config.resKeys.includes(res_key_id)) {
8
-        isScorable = true
9
-    }
10
-    return isScorable
11
-}
12
-
13
-const scoreResponses = (seeker, potentialMatch, prescoreLookup) => {
14
-    if (seeker.responses.length != potentialMatch.responses.length)
15
-        return {
16
-            error: `complete responses for profile: ${seeker.profile_id} unqeual to profile: ${potentialMatch.profile_id} | ${seeker.responses.length}:${potentialMatch.responses.length}`,
17
-        }
18
-
19
-    const aRes = seeker.responses.filter(
20
-        res =>  _isScorableResponse(res.response_key_id)
21
-    )
22
-    const bRes = potentialMatch.responses.filter(
23
-        res =>  _isScorableResponse(res.response_key_id)
24
-    )
25
-
26
-    const composite = []
27
-    while (aRes.length + bRes.length > 0) {
28
-        const mKey = resList => {
29
-            let el = resList.shift()
30
-            let pair = el.val
31
-            el = resList.shift()
32
-            return `${pair}:${el.val}`
33
-        }
34
-        composite.push(prescoreLookup[mKey(aRes)][mKey(bRes)])
35
-    }
36
-    const scoreAvg = composite.reduce((a, b) => a + b) / composite.length
37
-    return {
38
-        total: Math.round(scoreAvg),
39
-        aspects: composite,
40
-    }
41
-}
42
-const filterByDistance = (profileList, max) => {
43
-    return profileList.filter(profile => {
44
-        const profileDistance = Math.floor(parseFloat(profile.distance) * 100)
45
-        const adjustedMaxDistance = Math.floor(parseFloat(max) * 100)
46
-        return profileDistance <= adjustedMaxDistance
47
-    })
48
-}
49
-const scoreAll = (profileList, userProfile, prescoreLookup) => {
50
-    return profileList.map(profile => {
51
-        return {
52
-            // Uncomment to return the whole profile
53
-            // ...profile,
54
-            profile_id: profile.profile_id,
55
-            score: scoreResponses(userProfile, profile, prescoreLookup),
56
-            distance: profile.distance,
57
-        }
58
-    })
59
-}
60
-/**
61
- * Grab the zip code string
62
- */
63
-const getZipCodeFromProfile = profile => {
64
-    // There should only be one zip code entry per profile
65
-    let zipRes = profile.responses.find(
66
-        res => res.response_key_id == 7
67
-    )
68
-    return zipRes.val
69
-}
70
-
71
-const makeScoreLookup = (aspects, labels) => {
72
-    const labelLookup = {}
73
-    labels.forEach(label => (labelLookup[label.aspect_id] = label))
74
-
75
-    const scoreLookup = {}
76
-    aspects.forEach(aspect => {
77
-        const key = labelLookup[aspect.aspect_id]
78
-        scoreLookup[`${key.a}:${key.b}`] = {}
79
-        Object.keys(aspect).forEach(aspect_id => {
80
-            if (!labelLookup[aspect_id]) return
81
-            const comp = labelLookup[aspect_id]
82
-            const score = aspect[aspect_id]
83
-            scoreLookup[`${key.a}:${key.b}`][`${comp.a}:${comp.b}`] = score
84
-        })
85
-    })
86
-    return scoreLookup
87
-}
88
-
89
-/**
90
- * Class to hold our retrieved profile information
91
- * in a convenient wrapper
92
- * !: This needs to match the responseSchema in profiles.js
93
- */
94
-class CompleteProfile {
95
-    constructor(profile, type) {
96
-        this.user_id = profile.user_id // int user_id
97
-        this.profile_id = profile.profile_id // int profile_id
98
-        this.user_name = profile.user.user_name // string user_name
99
-        this.user_email = profile.user.user_email
100
-        this.responses = []
101
-        this.user_type = type
102
-        this.tags = profile.tags.filter(t => t.category != 'reveal')
103
-        this.reveal = profile.tags.filter(t => t.category == 'reveal')
104
-
105
-        // TODO: generalize this for multiple images, and languages
106
-        this.profile_description = ''
107
-        this.profile_media = []
108
-        this.profile_languages = []
109
-        this.profile_prefs = {}
110
-
111
-        // TODO: filter these correctly
112
-        if (profile?.responses?.length) {
113
-            // [] of all "profile" responses
114
-            this.responses = profile.responses
115
-            // image, language, duration, presence, blurb, urgency, role, pronouns, distance
116
-            const prefs = ['zipcode', 'duration', 'presence', 'urgency', 'role', 'pronouns', 'distance']
117
-            const prefsKeys = config.prefKeys
118
-            prefs.forEach((pref, i) => {
119
-                this.profile_prefs[pref] = this.responses.filter(
120
-                    r => r.response_key_id === prefsKeys[i]
121
-                )[0]
122
-            })
123
-            this.profile_description = this.responses.filter(r => r.response_key_id === config.blurbKey).map(r => r.val)[0]
124
-            this.profile_media = this.responses.filter(r => r.response_key_id === config.mediaKey).map(r => r.val)
125
-            this.profile_languages = this.responses.filter(r => r.response_key_id === config.langKey).map(r => r.val)
126
-        }
127
-    }
128
-}
3
+const config = require('../../../db/data-generator/config.json')
4
+const profiler = require('./profiler')
5
+const scoring = require('./scorer')
6
+const zipcoder = require('./zipcoder')
7
+const tagger = require('./tagger')
129 8
 
130 9
 module.exports = class ProfileService extends Schmervice.Service {
131 10
     constructor(...args) {
@@ -141,7 +20,7 @@ module.exports = class ProfileService extends Schmervice.Service {
141 20
             const { Aspect, AspectLabel } = this.server.models()
142 21
             const aspects = await Aspect.query()
143 22
             const labels = await AspectLabel.query()
144
-            this.scoreLookup = makeScoreLookup(aspects, labels)
23
+            this.scoreLookup = scoring.makeScoreLookup(aspects, labels)
145 24
         }
146 25
     }
147 26
     async _setTagLookup() {
@@ -186,13 +65,8 @@ module.exports = class ProfileService extends Schmervice.Service {
186 65
             .withGraphFetched('responses')
187 66
             .withGraphFetched('user')
188 67
 
189
-        if(matchingProfile?.tags.length){
190
-            matchingProfile.tags = matchingProfile.tags.map(
191
-                tag => this.tagLookup[tag.tag_id],
192
-            )
193
-        }
194
-
195
-        return new CompleteProfile(matchingProfile)
68
+        tagger.setProfileTags(matchingProfile, matchingProfile, this.tagLookup)
69
+        return new profiler.CompleteProfile(matchingProfile)
196 70
     }
197 71
 
198 72
     async getCompleteProfilesFor(userId, type) {
@@ -208,15 +82,8 @@ module.exports = class ProfileService extends Schmervice.Service {
208 82
             // CHECKTHIS: Added this because we added user.user_name to CompleteProfile
209 83
             // so without this, we get undefined user_name
210 84
             .withGraphFetched('user')
211
-
212
-        profilesEntries.forEach(profile => {
213
-            profile.tags = profile.tags.map(tag => this.tagLookup[tag.tag_id])
214
-        })
215
-
216
-        //** Get responses asociated with each profile_id */
217
-        return profilesEntries.map(profile => {
218
-            return new CompleteProfile(profile, type)
219
-        })
85
+        
86
+        return profiler.makeCompleteProfilesFromProfile(profilesEntries, type, this.tagLookup)
220 87
     }
221 88
 
222 89
     async getProfilesFor(profileIdArray, type, includeResponses = true) {
@@ -234,24 +101,13 @@ module.exports = class ProfileService extends Schmervice.Service {
234 101
         // taking the info from profilesEntries
235 102
         // to repack into completeProfiles
236 103
         // in same order as profileIdArray
237
-        const completeProfiles = []
238
-        profileIdArray.forEach(pid => {
239
-            profilesEntries.forEach(entry => {
240
-                if (entry.profile_id == pid) {
241
-                    const complete = new CompleteProfile(entry, type)
242
-                    if (!includeResponses) {
243
-                        delete complete['responses']
244
-                    }
245
-                    if (entry?.tags?.length) {
246
-                        complete.tags = entry.tags.map(
247
-                            tag => this.tagLookup[tag.tag_id],
248
-                        )
249
-                    }
250
-                    completeProfiles.push(complete)
251
-                }
252
-            })
253
-        })
254
-        return completeProfiles
104
+        return profiler.makeCompleteProfiles(
105
+            profileIdArray,
106
+            profilesEntries,
107
+            type,
108
+            includeResponses,
109
+            this.tagLookup
110
+        )
255 111
     }
256 112
 
257 113
     /**
@@ -274,7 +130,7 @@ module.exports = class ProfileService extends Schmervice.Service {
274 130
              * DUPLICATE:See saveResponseForProfile() line 343
275 131
              */ 
276 132
             let convertedResponse = responseToSave
277
-            if(_isScorableResponse(responseToSave.response_key_id)) {
133
+            if(scoring._isScorableResponse(responseToSave.response_key_id)) {
278 134
                 // Convert -3 to 0, 0 to 3, 3 to 6
279 135
                 const offset = (config.scoreVals.length - 1) / 2
280 136
                 const indexFromInput = parseInt(responseToSave.val) + offset
@@ -352,7 +208,7 @@ module.exports = class ProfileService extends Schmervice.Service {
352 208
          * of the generated possible prescore array in config
353 209
          */ 
354 210
         let convertedResponse = responseToSave
355
-        if(_isScorableResponse(responseToSave.response_key_id)) {
211
+        if(scoring._isScorableResponse(responseToSave.response_key_id)) {
356 212
             // Convert -3 to 0, 0 to 3, 3 to 6
357 213
             const offset = (config.scoreVals.length - 1) / 2
358 214
             const indexFromInput = parseInt(responseToSave.val) + offset
@@ -397,7 +253,7 @@ module.exports = class ProfileService extends Schmervice.Service {
397 253
             .withGraphFetched('user')
398 254
         
399 255
         // Move unneeded responses
400
-        const userZip = getZipCodeFromProfile(userProfile)
256
+        const userZip = zipcoder.getZipCodeFromProfile(userProfile)
401 257
 
402 258
         // Find all Profiles that are NOT of our userProfile.type
403 259
         // ie. If userProfile.type == seeker, then find: poster
@@ -411,12 +267,12 @@ module.exports = class ProfileService extends Schmervice.Service {
411 267
             return profile.user.is_poster == isPosterOpposite
412 268
         }).filter(profile => {
413 269
             // Only include profiles that included zipcode response
414
-            return getZipCodeFromProfile(profile) ? true : false
270
+            return zipcoder.getZipCodeFromProfile(profile) ? true : false
415 271
         })
416 272
         
417 273
         const profilePlusDistance = await Promise.all(
418 274
             profileIdsOfOppositeType.map(async profile => {
419
-                const targetZip = getZipCodeFromProfile(profile)
275
+                const targetZip = zipcoder.getZipCodeFromProfile(profile)
420 276
 
421 277
                 if (!userZip || !targetZip)
422 278
                     return { ...profile, distance: [9999, distanceUnit] }
@@ -432,11 +288,11 @@ module.exports = class ProfileService extends Schmervice.Service {
432 288
                 }
433 289
             }),
434 290
         )
435
-        const distanceFilteredProfiles = filterByDistance(
291
+        const distanceFilteredProfiles = zipcoder.filterByDistance(
436 292
             profilePlusDistance,
437 293
             maxDistance,
438 294
         )
439
-        const scoredProfilesWithDistance = scoreAll(
295
+        const scoredProfilesWithDistance = scoring.scoreAll(
440 296
             distanceFilteredProfiles,
441 297
             userProfile,
442 298
             this.scoreLookup,
@@ -455,15 +311,11 @@ module.exports = class ProfileService extends Schmervice.Service {
455 311
      */
456 312
     async _latLonForZip(zipCode) {
457 313
         const { ZipCode } = this.server.models()
458
-
459 314
         const zipInfo = await ZipCode.query().findOne(
460 315
             'zip_code_id',
461 316
             parseInt(zipCode),
462 317
         )
463
-        if (!zipInfo) {
464
-            console.error('zip:', zipCode)
465
-        }
466
-
318
+        if (!zipInfo) { console.error('zip:', zipCode) }
467 319
         return {
468 320
             latitude: parseFloat(zipInfo.latitude),
469 321
             longitude: parseFloat(zipInfo.longitude),
@@ -478,10 +330,8 @@ module.exports = class ProfileService extends Schmervice.Service {
478 330
      */
479 331
     async _compareDistance(start_zip, end_zip, distanceUnit) {
480 332
         if (!start_zip || !end_zip || isNaN(start_zip) || isNaN(end_zip)) return
481
-
482 333
         const start = await this._latLonForZip(start_zip)
483 334
         const end = await this._latLonForZip(end_zip)
484
-
485 335
         return haversine(start, end, { unit: distanceUnit })
486 336
     }
487 337
 }

+ 78
- 0
backend/lib/services/profile/profiler.js Ver fichero

@@ -0,0 +1,78 @@
1
+const config = require('../../../db/data-generator/config.json')
2
+const tagger = require('./tagger')
3
+
4
+/**
5
+ * Class to hold our retrieved profile information
6
+ * in a convenient wrapper
7
+ * !: This needs to match the responseSchema in profiles.js
8
+ */
9
+class CompleteProfile {
10
+    constructor(profile, type, includeResponses = false) {
11
+        this.user_id = profile.user_id // int user_id
12
+        this.profile_id = profile.profile_id // int profile_id
13
+        this.user_name = profile.user.user_name // string user_name
14
+        this.user_email = profile.user.user_email
15
+        this.responses = []
16
+        this.user_type = type
17
+        this.tags = profile.tags.filter(t => t.category != 'reveal')
18
+
19
+        // TODO: generalize this for multiple images, and languages
20
+        this.profile_description = ''
21
+        this.profile_media = []
22
+        this.profile_languages = []
23
+        this.profile_prefs = {}
24
+
25
+        // TODO: Use reveal tags to add or remove information from profile!
26
+        // TODO: ---
27
+        // TODO: Use reveal tags to rebuild profile based on group/membership
28
+        // TODO: and include for certain profiles
29
+
30
+        this.reveal = profile.tags.filter(t => t.category == 'reveal')
31
+        // TODO: filter these correctly
32
+        if (profile?.responses?.length && includeResponses) {
33
+            // [] of all "profile" responses
34
+            this.responses = profile.responses
35
+            // image, language, duration, presence, blurb, urgency, role, pronouns, distance
36
+            const prefs = ['zipcode', 'duration', 'presence', 'urgency', 'role', 'pronouns', 'distance']
37
+            const prefsKeys = config.prefKeys
38
+            prefs.forEach((pref, i) => {
39
+                this.profile_prefs[pref] = this.responses.filter(
40
+                    r => r.response_key_id === prefsKeys[i]
41
+                )[0]
42
+            })
43
+            this.profile_description = this.responses.filter(r => r.response_key_id === config.blurbKey).map(r => r.val)[0]
44
+            this.profile_media = this.responses.filter(r => r.response_key_id === config.mediaKey).map(r => r.val)
45
+            this.profile_languages = this.responses.filter(r => r.response_key_id === config.langKey).map(r => r.val)
46
+        }
47
+    }
48
+}
49
+
50
+const makeCompleteProfiles = (profileIdArray, profilesEntries, type, includeResponses, tagLookup) => {
51
+    const completeProfiles = []
52
+    profileIdArray.forEach(pid => {
53
+        profilesEntries.forEach(entry => {
54
+            if (entry.profile_id == pid) {
55
+                const complete = new CompleteProfile(entry, type, includeResponses)
56
+                tagger.setProfileTags(entry, complete, tagLookup)
57
+                completeProfiles.push(complete)
58
+            }
59
+        })
60
+    })
61
+    return completeProfiles
62
+}
63
+const makeCompleteProfilesFromProfile = (profilesEntries, type, tagLookup)=> {
64
+    profilesEntries.forEach(profile => {
65
+        tagger.setProfileTags(profile, profile, tagLookup)
66
+    })
67
+
68
+    //** Get responses asociated with each profile_id */
69
+    return profilesEntries.map(profile => {
70
+        return new CompleteProfile(profile, type)
71
+    })
72
+}
73
+
74
+module.exports = {
75
+    CompleteProfile,
76
+    makeCompleteProfiles,
77
+    makeCompleteProfilesFromProfile
78
+}

+ 76
- 0
backend/lib/services/profile/scorer.js Ver fichero

@@ -0,0 +1,76 @@
1
+const config = require('../../../db/data-generator/config.json')
2
+
3
+const makeScoreLookup = (aspects, labels) => {
4
+    const labelLookup = {}
5
+    labels.forEach(label => (labelLookup[label.aspect_id] = label))
6
+
7
+    const scoreLookup = {}
8
+    aspects.forEach(aspect => {
9
+        const key = labelLookup[aspect.aspect_id]
10
+        scoreLookup[`${key.a}:${key.b}`] = {}
11
+        Object.keys(aspect).forEach(aspect_id => {
12
+            if (!labelLookup[aspect_id]) return
13
+            const comp = labelLookup[aspect_id]
14
+            const score = aspect[aspect_id]
15
+            scoreLookup[`${key.a}:${key.b}`][`${comp.a}:${comp.b}`] = score
16
+        })
17
+    })
18
+    return scoreLookup
19
+}
20
+
21
+const _isScorableResponse = res_key_id => {
22
+    let isScorable = false
23
+    if(config.resKeys.includes(res_key_id)) {
24
+        isScorable = true
25
+    }
26
+    return isScorable
27
+}
28
+
29
+const scoreResponses = (seeker, potentialMatch, prescoreLookup) => {
30
+    if (seeker.responses.length != potentialMatch.responses.length)
31
+        return {
32
+            error: `complete responses for profile: ${seeker.profile_id} unqeual to profile: ${potentialMatch.profile_id} | ${seeker.responses.length}:${potentialMatch.responses.length}`,
33
+        }
34
+
35
+    const aRes = seeker.responses.filter(
36
+        res =>  _isScorableResponse(res.response_key_id)
37
+    )
38
+    const bRes = potentialMatch.responses.filter(
39
+        res =>  _isScorableResponse(res.response_key_id)
40
+    )
41
+
42
+    const composite = []
43
+    while (aRes.length + bRes.length > 0) {
44
+        const mKey = resList => {
45
+            let el = resList.shift()
46
+            let pair = el.val
47
+            el = resList.shift()
48
+            return `${pair}:${el.val}`
49
+        }
50
+        composite.push(prescoreLookup[mKey(aRes)][mKey(bRes)])
51
+    }
52
+    const scoreAvg = composite.reduce((a, b) => a + b) / composite.length
53
+    return {
54
+        total: Math.round(scoreAvg),
55
+        aspects: composite,
56
+    }
57
+}
58
+
59
+const scoreAll = (profileList, userProfile, prescoreLookup) => {
60
+    return profileList.map(profile => {
61
+        return {
62
+            // Uncomment to return the whole profile
63
+            // ...profile,
64
+            profile_id: profile.profile_id,
65
+            score: scoreResponses(userProfile, profile, prescoreLookup),
66
+            distance: profile.distance,
67
+        }
68
+    })
69
+}
70
+
71
+module.exports = {
72
+    _isScorableResponse,
73
+    scoreResponses,
74
+    makeScoreLookup,
75
+    scoreAll
76
+}

+ 7
- 0
backend/lib/services/profile/tagger.js Ver fichero

@@ -0,0 +1,7 @@
1
+const setProfileTags = (inProfile, outProfile, tagLookup) => {
2
+    outProfile.tags = inProfile.tags.map(tag => tagLookup[tag.tag_id])
3
+}
4
+
5
+module.exports = {
6
+    setProfileTags
7
+}

+ 25
- 0
backend/lib/services/profile/zipcoder.js Ver fichero

@@ -0,0 +1,25 @@
1
+const config = require('../../../db/data-generator/config.json')
2
+
3
+/**
4
+ * Grab the zip code string
5
+ */
6
+const getZipCodeFromProfile = profile => {
7
+    // There should only be one zip code entry per profile
8
+    let zipRes = profile.responses.find(
9
+        res => res.response_key_id == config.zipcodeKey
10
+    )
11
+    return zipRes.val
12
+}
13
+
14
+const filterByDistance = (profileList, max) => {
15
+    return profileList.filter(profile => {
16
+        const profileDistance = Math.floor(parseFloat(profile.distance) * 100)
17
+        const adjustedMaxDistance = Math.floor(parseFloat(max) * 100)
18
+        return profileDistance <= adjustedMaxDistance
19
+    })
20
+}
21
+
22
+module.exports = {
23
+    getZipCodeFromProfile,
24
+    filterByDistance
25
+}

+ 1
- 1
frontend/src/entities/profile/profile.schema.js Ver fichero

@@ -28,7 +28,7 @@ const profileSchema = {
28 28
         user_id: Joi.number(),
29 29
         user_email: Joi.string(),
30 30
         profile_id: Joi.number(),
31
-        profile_description: Joi.string(),
31
+        profile_description: Joi.string().allow(null, ''),
32 32
         profile_media: Joi.array().items(Joi.string()),
33 33
         profile_languages: Joi.array().items(Joi.string()),
34 34
         profile_prefs: Joi.object(),

+ 6
- 6
frontend/src/views/ProfileView.vue Ver fichero

@@ -5,17 +5,17 @@ main.view--profile.f-col.start.w-full
5 5
  
6 6
     article(v-if="!loading")
7 7
         h3 name: {{ profile.user_name }}
8
-            span(v-if="profile.profile_prefs.pronouns") &nbsp;({{ profile.profile_prefs.pronouns.val }})
8
+            span(v-if="profile.profile_prefs?.pronouns") &nbsp;({{ profile.profile_prefs?.pronouns.val }})
9 9
         p(v-if="profile.user_email") {{ profile.user_email }}
10 10
         
11 11
         p I am looking for a&nbsp;
12
-            span {{ profile.profile_prefs.presence.val }}&nbsp;
13
-            span {{ profile.profile_prefs.role.val }}&nbsp;
12
+            span {{ profile.profile_prefs?.presence?.val }}&nbsp;
13
+            span {{ profile.profile_prefs?.role?.val }}&nbsp;
14 14
             span role&nbsp;
15
-            span no further than {{ profile.profile_prefs.distance.val }} miles away&nbsp;
16
-            span from {{ profile.profile_prefs.zipcode.val }}
15
+            span no further than {{ profile.profile_prefs?.distance?.val }} miles away&nbsp;
16
+            span from {{ profile.profile_prefs?.zipcode?.val }}
17 17
 
18
-        p I am {{ profile.profile_prefs.urgency.val.split("_").join(" ") }}.
18
+        p I am {{ profile.profile_prefs?.urgency?.val.split("_").join(" ") }}.
19 19
         
20 20
         img(v-if="profile.reveal.map(t => t.description).includes('image')" :src="profile.profile_media[0]" alt="profile-avatar" style="max-height: 200px; width: auto;")
21 21
         h3(v-else) image not revealed

+ 0
- 1
frontend/src/views/SurveyView.vue Ver fichero

@@ -203,7 +203,6 @@ export default {
203 203
         async onSave() {
204 204
             const [ user, survey] = this._separateUserInfoFromResponses(Object.values(this.responseLikes))
205 205
             const maxDistanceRes = survey.find(res => res.response_key_id == maxDistanceKey)
206
-
207 206
             /**
208 207
              * Creating a profile only returns the created
209 208
              * user id and profile id

Loading…
Cancelar
Guardar