Преглед на файлове

:recyce: chopping down components using a mixin | removing more cruft and inconsistencies

tags/0.0.1
J преди 4 години
родител
ревизия
b7e6ab337b

+ 19
- 22
frontend/src/components/Messages.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
-.sidebar__messages
3
-  h5.message__title {{ title }}
2
+.sidebar--messages
3
+  h5.message__title messages from matches
4
   router-link(
4
   router-link(
5
-      :to="'/chats/' + user.uid" 
6
-      v-for='user in users' 
7
-      :key='user.uid' 
8
-      :class="[uid == user.uid ? 'active' : '', 'sidebar__message', 'f-col', 'start']"
9
-      )
5
+        :to="`/chats/${profile.profile_id}`" 
6
+        v-for='profile in matches' 
7
+        :key='profile.profile_id' 
8
+        :class="[pid == profile.profile_id ? 'active' : '', 'sidebar__message', 'f-col', 'start']"
9
+    )
10
     .f-row.start
10
     .f-row.start
11
-      img(:src='user.avatar')
12
-      .message__right.f-col
13
-        h4.message__name {{ user.name }}
14
-        p.message__content
15
-          | {{ user.metadata.rawMetadata || &quot;Hello I&apos;m using tinder!&quot; }}
11
+        img(:src='profile.avatar')
12
+        .message__right.f-col
13
+            h4.message__name {{ profile.name }}
14
+            p.message__content {{ profile.metadata.rawMetadata || &quot;Hello I&apos;m using tinder!&quot; }}
16
 </template>
15
 </template>
17
 
16
 
18
 <script>
17
 <script>
19
 export default {
18
 export default {
20
-    name: 'UserMessages',
19
+    name: 'ProfileMessages',
21
     props: {
20
     props: {
22
-        title: { type: String, default: 'Messages' },
23
-        users: {
21
+        matches: {
24
             type: [Object, Array],
22
             type: [Object, Array],
25
-            default: []
26
-        },
27
-    },
28
-    computed: {
29
-        uid() {
30
-            return this.$route.params.uid
23
+            default: () => []
31
         },
24
         },
25
+        pid: {
26
+            required: true,
27
+            type: Number
28
+        }
32
     },
29
     },
33
 }
30
 }
34
 </script>
31
 </script>
36
 <style lang="postcss">
33
 <style lang="postcss">
37
 
34
 
38
 .sidebar
35
 .sidebar
39
-    &__messages
36
+    &--messages
40
         padding: 20px 10px
37
         padding: 20px 10px
41
         /* overflow-y: scroll */
38
         /* overflow-y: scroll */
42
         text-align: left
39
         text-align: left

+ 3
- 3
frontend/src/components/ProfileCardList.vue Целия файл

43
 } from '../services'
43
 } from '../services'
44
 
44
 
45
 const router = useRouter()
45
 const router = useRouter()
46
-const emit = defineEmits(['reload-queue'])
46
+const emit = defineEmits(['reload'])
47
 // TODO: Please review this conversion from script to script setup
47
 // TODO: Please review this conversion from script to script setup
48
 // converted from the props section
48
 // converted from the props section
49
 const props = defineProps({
49
 const props = defineProps({
95
         console.log('Make membership')
95
         console.log('Make membership')
96
         postMembershipByProfileId({ profileId, targetId })
96
         postMembershipByProfileId({ profileId, targetId })
97
     }
97
     }
98
-    emit('reload-queue')
98
+    emit('reload')
99
 }
99
 }
100
 const view = pid => {
100
 const view = pid => {
101
     router.push({
101
     router.push({
109
     const profileId = props.pid
109
     const profileId = props.pid
110
     const targetId = props.profiles[0].pid
110
     const targetId = props.profiles[0].pid
111
     updateQueueByProfileId(profileId, targetId, true)
111
     updateQueueByProfileId(profileId, targetId, true)
112
-    emit('reload-queue')
112
+    emit('reload')
113
 }
113
 }
114
 
114
 
115
 // from the data() section
115
 // from the data() section

+ 11
- 12
frontend/src/components/SideBar.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
-aside.sidebar.p-1.f-col.between
3
-    h3 Profile: {{ pid }}
4
-    button(@click="$emit('hide')") hide
5
-    messages(:title="title" :users="users")
6
-    .spacer.f-grow
2
+aside.sidebar.p-1.f-col
7
     .temp-control-box.f-row.start.center
3
     .temp-control-box.f-row.start.center
8
-        input(v-model='switchToPID' style="width: 50px")
4
+        input(v-model="switchToPID")
9
         button(@click="$emit('updatePid', switchToPID)").t-up.p-0 switch profile
5
         button(@click="$emit('updatePid', switchToPID)").t-up.p-0 switch profile
6
+    
7
+    Messages(:matches="matches" :pid="pid")
8
+    
9
+    .spacer.f-grow
10
 </template>
10
 </template>
11
 
11
 
12
 <script>
12
 <script>
13
-import messages from './Messages.vue'
13
+import Messages from './Messages.vue'
14
 
14
 
15
 export default {
15
 export default {
16
-    components: { messages }, 
16
+    components: { Messages }, 
17
     props: {
17
     props: {
18
         pid: {
18
         pid: {
19
             required: true,
19
             required: true,
21
         }
21
         }
22
     },
22
     },
23
     data: () => ({
23
     data: () => ({
24
-        title:'Messages from Matches',
25
         switchToPID: null,
24
         switchToPID: null,
26
-        users: [
25
+        matches: [
27
             {
26
             {
28
                 name: 'Bob McRob',
27
                 name: 'Bob McRob',
29
-                uid: 111,
28
+                profile_id: 111,
30
                 avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
29
                 avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
31
                 metadata: { rawMetadata: 'howdy howdy howdy' },
30
                 metadata: { rawMetadata: 'howdy howdy howdy' },
32
             },
31
             },
33
             {
32
             {
34
                 name: 'Rob Bebob',
33
                 name: 'Rob Bebob',
35
-                uid: 112,
34
+                profile_id: 112,
36
                 avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
35
                 avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
37
                 metadata: { rawMetadata: 'this is the last message' },
36
                 metadata: { rawMetadata: 'this is the last message' },
38
             },
37
             },

+ 21
- 0
frontend/src/entities/card/card.js Целия файл

1
+/** @module entities/card */
2
+
3
+/** Class representing a card */
4
+class Card {
5
+    /**
6
+     * Create the a card object.
7
+     * @param {number} pid
8
+     * @param {string} name
9
+     * @param {string} avatar
10
+     * @return {Card} the card instance object
11
+     */
12
+    constructor({ pid, name, avatar }) {
13
+        this.pid = pid
14
+        this.name = name
15
+        this.avatar = avatar
16
+
17
+        return this
18
+    }
19
+}
20
+
21
+export { Card }

+ 1
- 0
frontend/src/entities/card/index.js Целия файл

1
+export * from './card'

+ 2
- 1
frontend/src/entities/index.js Целия файл

4
 export * from './response'
4
 export * from './response'
5
 export * from './profile'
5
 export * from './profile'
6
 export * from './survey'
6
 export * from './survey'
7
-export * from './grouping'
7
+export * from './grouping'
8
+export * from './card'

+ 6
- 0
frontend/src/entities/profile/profile.schema.js Целия файл

24
         }),
24
         }),
25
 
25
 
26
         /** fields that should match backend service*/
26
         /** fields that should match backend service*/
27
+        user_name: Joi.string(),
27
         user_id: Joi.number(),
28
         user_id: Joi.number(),
28
         profile_id: Joi.number(),
29
         profile_id: Joi.number(),
30
+        profile_description: Joi.string(),
31
+        profile_media: Joi.array().items(Joi.string()),
32
+        profile_languages: Joi.array().items(Joi.string()),
33
+        profile_prefs: Joi.object(),
29
         responses: Joi.array().items(responseSchema), // response entity schema goes here
34
         responses: Joi.array().items(responseSchema), // response entity schema goes here
35
+        tags: Joi.array().items(),
30
         user_type: Joi.string(),
36
         user_type: Joi.string(),
31
 
37
 
32
         /** tricky module system fields */
38
         /** tricky module system fields */

+ 11
- 2
frontend/src/services/grouping.service.js Целия файл

1
 import { db } from '../utils/db'
1
 import { db } from '../utils/db'
2
-import { Grouping } from '../entities'
2
+import { Grouping, Profile } from '../entities'
3
 
3
 
4
 /**
4
 /**
5
  * Get Memberships associated with a single Profile from the database and
5
  * Get Memberships associated with a single Profile from the database and
14
     for (let membership of membershipsForProfileId) {
14
     for (let membership of membershipsForProfileId) {
15
         const grouping = new Grouping(membership)
15
         const grouping = new Grouping(membership)
16
         if (grouping.isValid()) {
16
         if (grouping.isValid()) {
17
+            // Reformat incoming profile data into Profile entity
18
+            grouping.profile = new Profile(grouping.profile)
17
             validGroupingInstances.push(grouping)
19
             validGroupingInstances.push(grouping)
18
         }
20
         }
19
     }
21
     }
20
     return validGroupingInstances
22
     return validGroupingInstances
21
 }
23
 }
22
 
24
 
25
+/**
26
+ * Create memberships to a grouping between profileId and targetId
27
+ * @param {number} profileId
28
+ * @param {number} targetId
29
+ * @param {string} groupingType
30
+ * @returns {object} the created membership
31
+ */
23
 const postMembershipByProfileId = async ({
32
 const postMembershipByProfileId = async ({
24
     profileId,
33
     profileId,
25
     targetId,
34
     targetId,
31
         grouping_type: groupingType,
40
         grouping_type: groupingType,
32
         grouping_name: `${utcDateInSeconds}_${profileId}_${targetId}`,
41
         grouping_name: `${utcDateInSeconds}_${profileId}_${targetId}`,
33
     }
42
     }
34
-    console.log('Membership Created')
43
+    console.warn(`${groupingType} created between ${profileId} and ${targetId}`)
35
     const createdMembershipRecord = await db.post(
44
     const createdMembershipRecord = await db.post(
36
         `/membership/${profileId}/join`,
45
         `/membership/${profileId}/join`,
37
         membership,
46
         membership,

+ 6
- 1
frontend/src/services/login.service.js Целия файл

1
 import { ref } from 'vue'
1
 import { ref } from 'vue'
2
-import { fetchQueueByProfileId, fetchResponsesByProfileId } from '../services'
2
+import { fetchResponsesByProfileId } from '../services'
3
 import { surveyFactory } from '../utils'
3
 import { surveyFactory } from '../utils'
4
 
4
 
5
+/**
6
+ * Logged in profile state manager
7
+ * Sort of a util and service hybrid
8
+ * @returns {array} profiles
9
+ */
5
 class Login {
10
 class Login {
6
     constructor() {
11
     constructor() {
7
         this._loading = false
12
         this._loading = false

+ 18
- 18
frontend/src/services/queue.service.js Целия файл

1
 import { db } from '../utils/db'
1
 import { db } from '../utils/db'
2
 import { Profile } from '../entities'
2
 import { Profile } from '../entities'
3
 
3
 
4
-// TODO: queue services
4
+/**
5
+ * Get a match queue of profiles
6
+ * @param {number} profileId
7
+ * @returns {array} profiles
8
+ */
5
 const fetchQueueByProfileId = async profileId => {
9
 const fetchQueueByProfileId = async profileId => {
6
     let queue
10
     let queue
7
     
11
     
10
             `/profile/${profileId}/queue?include_profile=true`,
14
             `/profile/${profileId}/queue?include_profile=true`,
11
         )
15
         )
12
         if(!queue?.length) {
16
         if(!queue?.length) {
13
-            throw 'could not retrieve match queue. Please take the survey and rescore.'
17
+            throw 'Could not retrieve match queue. Please take the survey and rescore.'
14
         }
18
         }
15
     } catch (err) {
19
     } catch (err) {
16
         console.error(err)
20
         console.error(err)
17
     }
21
     }
18
 
22
 
19
     return queue ? queue.map(profileData => {
23
     return queue ? queue.map(profileData => {
20
-        return new Profile({ email: null, ...profileData })
24
+        return new Profile({ email: 'fixme@gmail.com', ...profileData })
21
     }) : []
25
     }) : []
22
 }
26
 }
23
 
27
 
28
+/**
29
+ * Remove or reinsert a profile in match queue
30
+ * @param {number} profileId profile viewing the queue
31
+ * @param {number} targetId
32
+ * @param {boolean} reinsert FALSE if profileId accepted targetId; TRUE to reinsert into match queue
33
+ * @returns {array} profiles
34
+ */
24
 const updateQueueByProfileId = async (profileId, targetId, reinsert) => {
35
 const updateQueueByProfileId = async (profileId, targetId, reinsert) => {
25
-    // Arguments
26
-    // profileId - the id of the profile viewing the queue
27
-    // targetId - the id of the profile viewed by the profileId
28
-    // reinsert - if profileId accepted targetId, FALSE reinsert so no reinsert; if profileId passed targetId, TRUE reinsert so reinsert at end
29
-    //
30
     const updateQueue = await db.patch(
36
     const updateQueue = await db.patch(
31
         `/profile/${profileId}/queue/${targetId}/delete?include_profile=true&reinsert=${reinsert}`,
37
         `/profile/${profileId}/queue/${targetId}/delete?include_profile=true&reinsert=${reinsert}`,
32
-        // HELP: responseScheme says the structure should be array of either:
33
-        // 1) NUMBER
34
-        // or
35
-        // 2) {profile_id, user_id, user_name, user_media, responses, user_type}
36
-        // ~However~ how do we call (2) here? It seems too much to call another API just to fill out a payload, so I just went with (1)
37
-        [
38
-            targetId,
39
-        ],
38
+        [ targetId ],
40
     )
39
     )
41
-    console.log('updateQueue', updateQueue)
42
-    return updateQueue
40
+    return updateQueue ? updateQueue.map(profileData => {
41
+        return new Profile({ email: 'fixme@gmail.com', ...profileData })
42
+    }) : []
43
 }
43
 }
44
 
44
 
45
 export { fetchQueueByProfileId, updateQueueByProfileId }
45
 export { fetchQueueByProfileId, updateQueueByProfileId }

+ 0
- 1
frontend/src/utils/index.js Целия файл

1
 import Joi from 'joi'
1
 import Joi from 'joi'
2
-import { fetchQuestions } from '../services'
3
 
2
 
4
 import { Connector } from './db'
3
 import { Connector } from './db'
5
 import { SurveyFactory } from './survey'
4
 import { SurveyFactory } from './survey'

+ 23
- 32
frontend/src/views/HomeView.vue Целия файл

4
         h2 home - profile: {{ pid }}
4
         h2 home - profile: {{ pid }}
5
 
5
 
6
     article(v-if="cards.length && !loading")
6
     article(v-if="cards.length && !loading")
7
-        ProfileCardList(:profiles="cards" :pid="pid" @reload-queue="getQueue")
7
+        ProfileCardList(:profiles="cards" :pid="pid" @reload="getCards")
8
 
8
 
9
     p(v-else) Loading...
9
     p(v-else) Loading...
10
 
10
 
14
 <script>
14
 <script>
15
 import ProfileCardList from '../components/ProfileCardList.vue'
15
 import ProfileCardList from '../components/ProfileCardList.vue'
16
 
16
 
17
+import { Card } from '../entities'
17
 import { fetchQueueByProfileId } from '../services'
18
 import { fetchQueueByProfileId } from '../services'
19
+import { pidMixin } from './mixins'
20
+
21
+/** Callback used to format incoming into card */
22
+const convertToCard = profile => {
23
+    if(profile.type !== 'profile') {
24
+        console.error(`Cannot convert ${profile} to Card. Invalid entity.`)
25
+    }
26
+    if(!profile.isValid()) {
27
+        console.warn(`Profile ${profile.profile_id} is not a valid profile.`)
28
+    }
29
+    return new Card({
30
+        pid: profile.profile_id,
31
+        name: profile.user_name,
32
+        avatar: profile.profile_media[0],
33
+    })
34
+}
18
 
35
 
19
 export default {
36
 export default {
20
     name: 'HomeView',
37
     name: 'HomeView',
21
     components: { ProfileCardList },
38
     components: { ProfileCardList },
22
-    props: {
23
-        pid: {
24
-            type: Number,
25
-            required: true,
26
-        },
27
-    },
28
-    data: () => ({
29
-        cards: [],
30
-        loading: true,
31
-    }),
32
-    watch: {
33
-        /** Fetch the queue if pid changes */
34
-        async pid() { await this.getQueue() },
35
-    },
36
-    async mounted() {
37
-        await this.getQueue()
38
-    },
39
+    mixins: [ pidMixin ],
39
     methods: {
40
     methods: {
40
-        _reformatProfiles(profiles) {
41
-            return profiles.map(profile => {
42
-                return {
43
-                    pid: profile.profile_id,
44
-                    name: profile.user_name,
45
-                    avatar: profile.profile_media[0],
46
-                }
47
-            })
48
-        },
49
-        async getQueue() {
41
+        /** Gets called from pidMixins */
42
+        async getCards() {
50
             this.loading = true
43
             this.loading = true
51
             try {
44
             try {
52
                 const queueList = await fetchQueueByProfileId(this.pid)
45
                 const queueList = await fetchQueueByProfileId(this.pid)
53
-                this.cards = this._reformatProfiles(queueList)
54
-            } catch (err) {
55
-                console.error(err)
56
-            }
46
+                this.cards = this._reformat(queueList, convertToCard)
47
+            } catch (err) { console.error(err) }
57
             this.loading = false
48
             this.loading = false
58
         },
49
         },
59
     },
50
     },

+ 24
- 31
frontend/src/views/MatchesView.vue Целия файл

13
 
13
 
14
 <script>
14
 <script>
15
 import ProfileCardList from '../components/ProfileCardList.vue'
15
 import ProfileCardList from '../components/ProfileCardList.vue'
16
+
17
+import { Card } from '../entities'
16
 import { fetchMembershipsByProfileId } from '../services'
18
 import { fetchMembershipsByProfileId } from '../services'
19
+import { pidMixin } from './mixins'
20
+
21
+/** Callback used to format incoming into card */
22
+const convertToCard = grouping => {
23
+    if(grouping.type !== 'grouping') {
24
+        console.error(`Cannot convert ${grouping} to Card. Invalid entity.`)
25
+    }
26
+    if(!grouping.profile.isValid()) {
27
+        console.warn(`Profile in ${grouping} is not a valid profile.`)
28
+    }
29
+    return new Card({
30
+        pid: grouping.profile.profile_id,
31
+        name: grouping.profile.user_name,
32
+        avatar: grouping.profile.profile_media[0],
33
+    })
34
+}
17
 
35
 
18
 export default {
36
 export default {
37
+    name: 'MatchView',
19
     components: { ProfileCardList },
38
     components: { ProfileCardList },
20
-    props: {
21
-        pid: {
22
-            type: Number,
23
-            required: true,
24
-        },
25
-    },
26
-    data: () => ({
27
-        cards: [],
28
-        loading: true,
29
-    }),
30
-    watch: {
31
-        pid() { this.getMatches() },
32
-    },
33
-    async created() {
34
-        await this.getMatches()
35
-    },
39
+    mixins: [ pidMixin ],
36
     methods: {
40
     methods: {
37
-        _reformatMatches(matches) {
38
-            return matches.map(m => {
39
-                return {
40
-                    pid: m.profile.profile_id,
41
-                    name: m.profile.user_name,
42
-                    avatar: m.profile.profile_media[0],
43
-                }
44
-            })
45
-        },
46
-        async getMatches() {
41
+        /** Gets called from pidMixins */
42
+        async getCards() {
47
             this.loading = true
43
             this.loading = true
48
             try {
44
             try {
49
                 const matchList = await fetchMembershipsByProfileId(this.pid)
45
                 const matchList = await fetchMembershipsByProfileId(this.pid)
50
-                console.log('matchList :', matchList)
51
-                this.cards = this._reformatMatches(matchList)
52
-            } catch (err) {
53
-                console.error(err)
54
-            }
46
+                this.cards = this._reformat(matchList, convertToCard)
47
+            } catch (err) { console.error(err) }
55
             this.loading = false
48
             this.loading = false
56
         },
49
         },
57
     },
50
     },

+ 27
- 0
frontend/src/views/mixins.js Целия файл

1
+const pidMixin = {
2
+    props: {
3
+        pid: {
4
+            type: Number,
5
+            required: true,
6
+            validator: prop => typeof prop === 'number' || prop === null
7
+        },
8
+    },
9
+    data: () => ({
10
+        cards: [],
11
+        loading: true,
12
+    }),
13
+    watch: {
14
+        /** Fetch the queue if pid changes */
15
+        pid() { this.getCards() },
16
+    },
17
+    async created() {
18
+        await this.getCards()
19
+    },
20
+    methods: {
21
+        _reformat(data, mapCb) {
22
+            return data.map(mapCb)
23
+        }
24
+    }
25
+}
26
+
27
+export { pidMixin }

Loading…
Отказ
Запис