Skip to content

Commit fdbd95b

Browse files
feat: Create TeamMemberCard component and refactor TeamPage
This pull request extracts team member display logic into a reusable `TeamMemberCard` component to improve code maintainability and reduce duplication. Key changes: * Create `TeamMemberCard` component in `src/components/TeamMemberCard.vue` * Refactor `TeamPage` to use `TeamMemberCard` for both active and inactive members * Remove duplicate team member display code from `TeamPage` * Remove unused `smoothScroll` and `onGoToPanel` code * Add `:key` attributes to template loops for better Vue performance This reduces code duplication and makes team member display logic reusable across the application.
1 parent dca89fd commit fdbd95b

File tree

2 files changed

+49
-75
lines changed

2 files changed

+49
-75
lines changed

src/components/TeamMemberCard.vue

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<template lang="pug">
2+
div(data-aos="fade-up").col-xs-12.col-md-2.q-pa-md.text-center
3+
q-img(
4+
:src="require(`@/assets/images/${team.photo}`)"
5+
:alt="`${team.name} - ${team.role}`"
6+
).q-mb-md
7+
div
8+
span.text-h4 {{team.name}}
9+
div
10+
span.text-body1 {{team.role}}
11+
div(v-if="team.socials.length")
12+
q-btn(
13+
label="Connect"
14+
color="primary"
15+
flat
16+
no-caps
17+
).full-width
18+
q-menu(fit)
19+
q-list
20+
template(v-for="social in team.socials" :key="social.name")
21+
q-item(
22+
target="_blank"
23+
v-close-popup
24+
clickable
25+
:href="social.link"
26+
)
27+
q-item-section(avatar)
28+
q-icon(:name="social.icon")
29+
q-item-section {{social.name}}
30+
</template>
31+
32+
<script>
33+
export default {
34+
name: 'TeamMemberCard',
35+
props: {
36+
team: {
37+
type: Object,
38+
required: true,
39+
},
40+
},
41+
};
42+
</script>

src/pages/TeamPage.vue

Lines changed: 7 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -23,66 +23,12 @@ generic-panel(
2323
)
2424
h1.text-h4 Active Volunteers
2525
div.row.wrap
26-
template(v-for="team in activeTeamData")
27-
div(data-aos="fade-up").col-xs-12.col-md-2.q-pa-md.text-center
28-
q-img(
29-
:src="require(`@/assets/images/${team.photo}`)"
30-
:alt="`${team.name} - ${team.role}`"
31-
).q-mb-md
32-
div
33-
span.text-h4 {{team.name}}
34-
div
35-
span.text-body1 {{team.role}}
36-
div(v-if="team.socials.length")
37-
q-btn(
38-
label="Connect"
39-
color="primary"
40-
flat
41-
no-caps
42-
).full-width
43-
q-menu(fit)
44-
q-list
45-
template(v-for="social in team.socials")
46-
q-item(
47-
target="_blank"
48-
v-close-popup
49-
clickable
50-
:href="social.link"
51-
)
52-
q-item-section(avatar)
53-
q-icon(:name="social.icon")
54-
q-item-section {{social.name}}
26+
template(v-for="team in activeTeamData" :key="team.name")
27+
team-member-card(:team="team")
5528
h1.text-h4 Past Volunteers
5629
div.row.wrap
57-
template(v-for="team in inactiveTeamData")
58-
div(data-aos="fade-up").col-xs-12.col-md-2.q-pa-md.text-center
59-
q-img(
60-
:src="require(`@/assets/images/${team.photo}`)"
61-
:alt="`${team.name} - ${team.role}`"
62-
).q-mb-md
63-
div
64-
span.text-h4 {{team.name}}
65-
div
66-
span.text-body1 {{team.role}}
67-
div(v-if="team.socials.length")
68-
q-btn(
69-
label="Connect"
70-
color="primary"
71-
flat
72-
no-caps
73-
).full-width
74-
q-menu(fit)
75-
q-list
76-
template(v-for="social in team.socials")
77-
q-item(
78-
target="_blank"
79-
v-close-popup
80-
clickable
81-
:href="social.link"
82-
)
83-
q-item-section(avatar)
84-
q-icon(:name="social.icon")
85-
q-item-section {{social.name}}
30+
template(v-for="team in inactiveTeamData" :key="team.name")
31+
team-member-card(:team="team")
8632

8733
div.row.wrap.justify-center
8834
div.col-xs-12.q-mt-lg.text-center.q-gutter-sm
@@ -108,18 +54,19 @@ generic-panel(
10854
</template>
10955

11056
<script>
111-
import { inject, computed, ref } from 'vue';
57+
import { computed, ref } from 'vue';
11258
import { useBuildMeta } from '@/composables/meta';
11359
import { useMeta, useQuasar } from 'quasar';
11460
import GenericPanel from '@/components/commons/GenericPanel.vue';
61+
import TeamMemberCard from '@/components/TeamMemberCard.vue';
11562
import teamData from '@/assets/fixtures/team';
11663
export default {
11764
components: {
11865
GenericPanel,
66+
TeamMemberCard,
11967
},
12068
setup () {
12169
useMeta(useBuildMeta({ page: 'The Team', description: 'Here are the amazing people behind OSSPH\'s initiatives' }));
122-
const smoothScroll = inject('smoothScroll');
12370
const $q = useQuasar();
12471
const isMobile = computed(() => $q.screen.lt.md);
12572
const selectedRole = ref(null);
@@ -150,25 +97,10 @@ export default {
15097
return filtered;
15198
});
15299
153-
function onGoToPanel (card) {
154-
const panelId = card.panelId;
155-
if (card.panelId) {
156-
smoothScroll({
157-
scrollTo: document.getElementById(panelId),
158-
updateHistory: false,
159-
});
160-
}
161-
162-
if (card.link) {
163-
window.open(card.link, '_blank').focus();
164-
}
165-
}
166-
167100
return {
168101
isMobile,
169102
activeTeamData,
170103
inactiveTeamData,
171-
onGoToPanel,
172104
selectedRole,
173105
roleOptions,
174106
};

0 commit comments

Comments
 (0)