@dcrackel/meyersquaredui 1.0.43 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/meyersquaredui.es.js +615 -498
- package/dist/meyersquaredui.umd.js +1 -1
- package/package.json +4 -3
- package/src/index.js +1 -1
- package/src/mocks/getAllClubs.js +106 -0
- package/src/mocks/getClubById.js +130 -0
- package/src/mocks/getFencersByWeapon.js +2167 -0
- package/src/mocks/getTouranmentDetailsMock.js +92 -0
- package/src/stories/Atoms/BaseButton/BaseButton.vue +5 -3
- package/src/stories/Atoms/BaseText/BaseText.vue +1 -1
- package/src/stories/Atoms/Icon/Icon.vue +4 -2
- package/src/stories/Atoms/InputField/InputField.stories.js +28 -9
- package/src/stories/Atoms/InputField/InputField.vue +20 -2
- package/src/stories/Molecules/Calendar/Calendar.stories.js +39 -0
- package/src/stories/Molecules/Calendar/Calendar.vue +110 -0
- package/src/stories/Molecules/DropDowns/BasicDropDown.stories.js +31 -0
- package/src/stories/Molecules/DropDowns/BasicDropDown.vue +78 -0
- package/src/stories/Molecules/MapBox/MapBox.stories.js +30 -0
- package/src/stories/Molecules/MapBox/MapBox.vue +67 -0
- package/src/stories/Molecules/SearchBox/SearchBox.vue +2 -1
- package/src/stories/Molecules/SearchBox/Searchbox.stories.js +1 -1
- package/src/stories/Organisms/Cards/ArticleCard/ArticleCard.vue +8 -3
- package/src/stories/Organisms/Cards/ClubListCard/CLubListCard.stories.js +31 -0
- package/src/stories/Organisms/Cards/ClubListCard/ClubListCard.vue +72 -0
- package/src/stories/Organisms/Cards/ClubMember/ClubMember.stories.js +40 -0
- package/src/stories/Organisms/Cards/ClubMember/ClubMember.vue +56 -0
- package/src/stories/Organisms/Cards/EventListCard/EventListCard.stories.js +38 -0
- package/src/stories/Organisms/Cards/EventListCard/EventListCard.vue +64 -0
- package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +3 -5
- package/src/stories/Organisms/Cards/FencerListCard/FencerListCard.stories.js +30 -0
- package/src/stories/Organisms/Cards/FencerListCard/FencerListCard.vue +86 -0
- package/src/stories/Organisms/Cards/PhotoCard/PhotoCard.stories.js +28 -0
- package/src/stories/Organisms/Cards/PhotoCard/PhotoCard.vue +18 -0
- package/src/stories/Organisms/Cards/SocialMediaLinkCard/SocialMediaLinkCard.stories.js +40 -0
- package/src/stories/Organisms/Cards/SocialMediaLinkCard/SocialMediaLinkCard.vue +54 -0
- package/src/stories/Organisms/Cards/TournamentCard/TournamentCard.stories.js +1 -1
- package/src/stories/Organisms/Cards/TournamentCard/TournamentCard.vue +7 -2
- package/src/stories/Organisms/Cards/TournamentDetails/TournamentDetails.stories.js +35 -0
- package/src/stories/Organisms/Cards/TournamentDetails/TournamentDetails.vue +59 -0
- package/src/stories/Organisms/Cards/TournamentListCard/TournamentListCard.stories.js +26 -0
- package/src/stories/Organisms/Cards/TournamentListCard/TournamentListCard.vue +103 -0
- package/src/stories/Organisms/Column/HostColumn.stories.js +39 -0
- package/src/stories/Organisms/Column/HostColumn.vue +105 -0
- package/src/stories/Organisms/GridLayout/GridLayout.vue +28 -8
- package/src/stories/Organisms/Headers/ClubHeader/ClubHeader.stories.js +21 -0
- package/src/stories/Organisms/Headers/ClubHeader/ClubHeader.vue +58 -0
- package/src/stories/Organisms/Headers/LeaderboardHeader/LeaderboardHeader.stories.js +29 -0
- package/src/stories/Organisms/Headers/LeaderboardHeader/LeaderboardHeader.vue +59 -0
- package/src/stories/Organisms/Headers/{Header.stories.js → PageHeader/PageHeader.stories.js} +2 -2
- package/src/stories/Organisms/Headers/PageHeader/PageHeader.vue +101 -0
- package/src/stories/Organisms/Headers/TournamentHeader/TournamentHeader.stories.js +34 -0
- package/src/stories/Organisms/Headers/TournamentHeader/TournamentHeader.vue +73 -0
- package/src/stories/Organisms/HeroBanners/HomePage/HeroBanner.stories.js +3 -3
- package/src/stories/Organisms/HeroBanners/HomePage/HeroBanner.vue +1 -1
- package/src/stories/Organisms/HeroBanners/TournamentDetails/TournamentDetailsBanner.stories.js +39 -0
- package/src/stories/Organisms/HeroBanners/TournamentDetails/TournamentDetailsBanner.vue +129 -0
- package/src/stories/Organisms/HeroBanners/Tournaments/TournamentBanner.stories.js +25 -0
- package/src/stories/Organisms/HeroBanners/Tournaments/TournamentBanner.vue +79 -0
- package/src/stories/Organisms/SectionBanners/DoubleButtonBanner/DoubleButtonBanner.vue +3 -3
- package/src/stories/Organisms/SectionBanners/SingleButtonBanner/SingleButtonBanner.vue +1 -1
- package/src/stories/Templates/ClubDetailPage/ClubDetailPage.stories.js +43 -0
- package/src/stories/Templates/ClubDetailPage/ClubDetailPage.vue +127 -0
- package/src/stories/Templates/ClubListPage/ClubListPage.stories.js +43 -0
- package/src/stories/Templates/ClubListPage/ClubListPage.vue +84 -0
- package/src/stories/Templates/HomePage/HomePage.stories.js +6 -6
- package/src/stories/Templates/HomePage/HomePage.vue +21 -14
- package/src/stories/Templates/Leaderboard/Leaderboard.stories.js +43 -0
- package/src/stories/Templates/Leaderboard/Leaderboard.vue +93 -0
- package/src/stories/Templates/TournamentDetailPage/TournamentDetail.stories.js +32 -0
- package/src/stories/Templates/TournamentDetailPage/TournamentDetailPage.vue +121 -0
- package/src/stories/Templates/TournamentListPage/TournamentListPage.stories.js +41 -0
- package/src/stories/Templates/TournamentListPage/TournamentListPage.vue +91 -0
- package/src/stories/Organisms/Headers/Header.vue +0 -62
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import ClubDisplay from './ClubListCard.vue';
|
|
2
|
+
import mockAllClubs from "../../../../mocks/getAllClubs.js";
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Cards/ClubListCard',
|
|
5
|
+
component: ClubDisplay,
|
|
6
|
+
argTypes: {
|
|
7
|
+
club: {
|
|
8
|
+
control: 'object',
|
|
9
|
+
defaultValue: {
|
|
10
|
+
ClubName: 'Fencing Academy',
|
|
11
|
+
City: 'New York',
|
|
12
|
+
State: 'NY',
|
|
13
|
+
Description: 'A club with a rich history of training Olympic fencers. We provide lessons in saber, foil, and épée.',
|
|
14
|
+
membercount: 30,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const Template = (args) => ({
|
|
21
|
+
components: { ClubDisplay },
|
|
22
|
+
setup() {
|
|
23
|
+
return { args };
|
|
24
|
+
},
|
|
25
|
+
template: '<ClubDisplay v-bind="args" />',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const Default = Template.bind({});
|
|
29
|
+
Default.args = {
|
|
30
|
+
data: mockAllClubs,
|
|
31
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full flex flex-row p-4 bg-white md:bg-cloud cursor-pointer border-b pb-6 mb-2 last:border-b-0" @click="onCardClick">
|
|
3
|
+
<div class="flex flex-col md:flex-row w-full">
|
|
4
|
+
<!-- Club Logo -->
|
|
5
|
+
<section class="flex flex-grow-0 flex-shrink-0 md:w-auto">
|
|
6
|
+
<img
|
|
7
|
+
:src="clubImage"
|
|
8
|
+
class="w-16 h-16 md:w-24 md:h-24 object-cover rounded-full mr-2 md:mr-4"
|
|
9
|
+
alt=""
|
|
10
|
+
/>
|
|
11
|
+
<div class="flex flex-col ml-2 md:hidden">
|
|
12
|
+
<BaseText color="primary" tag="h2" size="lg" weight="bold">{{ data.Name }}</BaseText>
|
|
13
|
+
<BaseText color="primary" tag="h3" size="xs" weight="bold" class="mb-2">{{ data.Address.City }} | {{ data.Address.State }}</BaseText>
|
|
14
|
+
</div>
|
|
15
|
+
</section>
|
|
16
|
+
|
|
17
|
+
<!-- Club Info (Name, Location, Description) -->
|
|
18
|
+
<section class="flex-grow md:ml-4">
|
|
19
|
+
<BaseText color="primary" tag="h2" size="lg" weight="bold" class="hidden md:flex">{{ data.Name }}</BaseText>
|
|
20
|
+
<BaseText color="primary" tag="h3" size="xs" weight="bold" class="hidden md:flex justify-start">{{ data.Address.City }} | {{ data.Address.State }}</BaseText>
|
|
21
|
+
<BaseText color="primary" tag="p" size="xs" weight="normal" class="flex justify-start mt-2 md:text-sm" v-html="clubDescription"></BaseText>
|
|
22
|
+
</section>
|
|
23
|
+
|
|
24
|
+
<!-- Stats Section -->
|
|
25
|
+
<section class="flex flex-col mt-4 md:mt-0 md:w-48 md:flex-shrink-0">
|
|
26
|
+
<div class="flex md:justify-end">
|
|
27
|
+
<Icon icon="fa-users" size="xs" color="accent" class="mr-3" />
|
|
28
|
+
<BaseText color="primary" tag="h2" size="xs" weight="normal" class="md:text-sm w-40">
|
|
29
|
+
M2 Active Members: {{ data.MemberCount }}
|
|
30
|
+
</BaseText>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="flex md:justify-end mt-2">
|
|
33
|
+
<Icon icon="fa-house-blank" type="fa-regular" size="xs" color="accent" class="mr-3" />
|
|
34
|
+
<BaseText color="primary" tag="h3" size="xs" weight="normal" class="md:text-sm w-40">
|
|
35
|
+
Hosted: {{ data.HostedTournamentsCount }} Tournaments
|
|
36
|
+
</BaseText>
|
|
37
|
+
</div>
|
|
38
|
+
</section>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
import BaseText from "../../../Atoms/BaseText/BaseText.vue";
|
|
45
|
+
import Icon from "../../../Atoms/Icon/Icon.vue";
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
name: 'ClubListCard',
|
|
49
|
+
components: {Icon, BaseText},
|
|
50
|
+
props: {
|
|
51
|
+
data: {
|
|
52
|
+
type: Object,
|
|
53
|
+
required: true,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
computed: {
|
|
57
|
+
clubDescription() {
|
|
58
|
+
return this.data.Description ? this.data.Description.slice(0, 120) : '';
|
|
59
|
+
},
|
|
60
|
+
clubImage() {
|
|
61
|
+
return this.data.Images.length > 0 && this.data.Images[0].URL
|
|
62
|
+
? this.data.Images[0].URL
|
|
63
|
+
: 'https://via.placeholder.com/150';
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
methods: {
|
|
67
|
+
onCardClick() {
|
|
68
|
+
this.$emit('card-click', this.data);
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
</script>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ClubMember.stories.js
|
|
2
|
+
import ClubMember from './ClubMember.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Organisms/Cards/ClubMember',
|
|
6
|
+
component: ClubMember,
|
|
7
|
+
argTypes: {
|
|
8
|
+
data: { control: 'object' },
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Template = (args) => ({
|
|
13
|
+
components: { ClubMember },
|
|
14
|
+
setup() {
|
|
15
|
+
return { args };
|
|
16
|
+
},
|
|
17
|
+
template: '<ClubMember v-bind="args" />',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const Default = Template.bind({});
|
|
21
|
+
Default.args = {
|
|
22
|
+
data: {
|
|
23
|
+
DisplayName: 'John Doe',
|
|
24
|
+
M2Ratings: [{ WeaponId: 1, FormattedRating: 'A+' }],
|
|
25
|
+
ProfileImage: {
|
|
26
|
+
URL: 'https://via.placeholder.com/100',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const NoRating = Template.bind({});
|
|
32
|
+
NoRating.args = {
|
|
33
|
+
data: {
|
|
34
|
+
DisplayName: 'Jane Doe',
|
|
35
|
+
M2Ratings: [],
|
|
36
|
+
ProfileImage: {
|
|
37
|
+
URL: 'https://via.placeholder.com/100',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="mx-auto pt-4 items-center hover:cursor-pointer text-center" @click="onCardClick">
|
|
3
|
+
<div class="flex justify-center mb-4">
|
|
4
|
+
<img :src="portrait" alt="User Portrait" class="w-[150px] h-[150px] rounded-full object-cover" />
|
|
5
|
+
</div>
|
|
6
|
+
<BaseText tag="h2" size="md" weight="bold" class="mb-2">{{ displayName }}</BaseText>
|
|
7
|
+
<BaseText tag="p" size="xs" weight="semibold" class="text-accent">M2: {{ m2Rating }}</BaseText>
|
|
8
|
+
</section>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script>
|
|
12
|
+
import BaseText from "../../../Atoms/BaseText/BaseText.vue";
|
|
13
|
+
import defaultPortrait from '../../../../assets/images/portrait1.png';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'ClubMember',
|
|
17
|
+
components: {
|
|
18
|
+
BaseText,
|
|
19
|
+
},
|
|
20
|
+
props: {
|
|
21
|
+
data: {
|
|
22
|
+
type: Object,
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
isLoading: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
computed: {
|
|
31
|
+
portrait() {
|
|
32
|
+
return this.data.ProfileImage && this.data.ProfileImage.URL
|
|
33
|
+
? this.data.ProfileImage.URL
|
|
34
|
+
: defaultPortrait;
|
|
35
|
+
},
|
|
36
|
+
displayName() {
|
|
37
|
+
return this.data.DisplayName || 'Unknown Member';
|
|
38
|
+
},
|
|
39
|
+
m2Rating() {
|
|
40
|
+
const m2RatingForWeapon = this.data.M2Ratings.find(rating => rating.WeaponId === 1);
|
|
41
|
+
return m2RatingForWeapon ? m2RatingForWeapon.FormattedRating : 'U';
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
methods: {
|
|
45
|
+
onCardClick() {
|
|
46
|
+
this.$emit('card-click', this.data);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<style scoped>
|
|
53
|
+
section {
|
|
54
|
+
max-width: 150px;
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import EventListCard from './EventListCard.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Cards/EventListCard',
|
|
5
|
+
component: EventListCard,
|
|
6
|
+
argTypes: {
|
|
7
|
+
weaponIcon: {
|
|
8
|
+
control: 'object',
|
|
9
|
+
},
|
|
10
|
+
eventRating: {
|
|
11
|
+
control: 'text',
|
|
12
|
+
},
|
|
13
|
+
eventName: {
|
|
14
|
+
control: 'text',
|
|
15
|
+
},
|
|
16
|
+
fencerCount: {
|
|
17
|
+
control: 'number',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const Template = (args) => ({
|
|
23
|
+
components: { EventListCard },
|
|
24
|
+
setup() {
|
|
25
|
+
return { args };
|
|
26
|
+
},
|
|
27
|
+
template: '<EventListCard v-bind="args" />',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const data = { weaponIcon: "fa-saber",
|
|
31
|
+
eventRating: 'A',
|
|
32
|
+
eventName: 'Saber Tournament',
|
|
33
|
+
fencerCount: 32 }
|
|
34
|
+
|
|
35
|
+
export const Default = Template.bind({});
|
|
36
|
+
Default.args = {
|
|
37
|
+
data: data
|
|
38
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="p-2 w-full border-b md:py-6 last:border-b-0">
|
|
3
|
+
<div class="flex space-x-4 w-full">
|
|
4
|
+
<section class="w-10 pt-1 md:pt-0">
|
|
5
|
+
<div class="h-10 w-10 rounded-full flex justify-center items-center border border-accent z-1">
|
|
6
|
+
<Icon :icon="weaponIcon" color="primary" type="fa-kit" size="3xl" class="-rotate-90 z-1"/>
|
|
7
|
+
</div>
|
|
8
|
+
<div v-if="data.Rating" class="h-6 w-6 bg-accent rounded-full -mt-4 ml-7 pt-1 z-10 absolute items-center">
|
|
9
|
+
<BaseText color="secondary" size="xs" weight="normal" class="text-center">{{ data.Rating }}</BaseText>
|
|
10
|
+
</div>
|
|
11
|
+
</section>
|
|
12
|
+
<div class="flex w-full flex-col md:flex-row">
|
|
13
|
+
<section class="flex flex-col pl-2 items-start flex-grow">
|
|
14
|
+
<BaseText color="primary" size="lg" weight="bold">{{ data.EventName }}</BaseText>
|
|
15
|
+
<div class="flex flex-col md:flex-row">
|
|
16
|
+
<div class="flex row mt-1 md:mt-0">
|
|
17
|
+
<icon icon="fa-calendar-day" color="accent" type="fa-regular" size="xs" class="mr-2"/>
|
|
18
|
+
<BaseText color="primary" size="xs" weight="normal">{{ data.Date }} | {{data.StartTime}}</BaseText>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="flex row mt-1 md:mt-0">
|
|
21
|
+
<icon icon="fa-person" color="accent" type="fa-solid" size="xs" class="md:ml-6 mr-2"/>
|
|
22
|
+
<BaseText color="primary" size="xs" weight="normal">{{ data.ParticipantsCount }} Fencers Registered</BaseText>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
<section class="w-full md:w-20 flex justify-end md:pt-3" >
|
|
27
|
+
<div class="flex border-b border-white hover:border-accent md:h-8">
|
|
28
|
+
<div class="hidden md:flex">
|
|
29
|
+
<BaseText color="primary" size="md" weight="normal" class="mr-3 pt-0.5">More</BaseText>
|
|
30
|
+
<Icon icon="fa-arrow-right" color="primary" type="fa-thin" size="xl"/>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="flex md:hidden">
|
|
33
|
+
<BaseText color="primary" size="xs" weight="normal" class="mr-3">More</BaseText>
|
|
34
|
+
<Icon icon="fa-arrow-right" color="primary" type="fa-thin" size="xs" class="" />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</section>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
import Icon from "../../../Atoms/Icon/Icon.vue";
|
|
45
|
+
import BaseText from "../../../Atoms/BaseText/BaseText.vue";
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
name: 'EventListCard',
|
|
49
|
+
components: {BaseText, Icon},
|
|
50
|
+
props: {
|
|
51
|
+
data: {
|
|
52
|
+
type: Object,
|
|
53
|
+
required: true,
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
computed: {
|
|
57
|
+
weaponIcon() {
|
|
58
|
+
const weapon = this.data.Weapon.Name;
|
|
59
|
+
return `fa-${weapon.toLowerCase()}`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
</script>
|
|
64
|
+
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div v-if="isLoading" class="max-w-72 p-2 bg-secondary rounded-lg flex flex-col items-start">
|
|
3
3
|
<FencerCardSkeleton />
|
|
4
4
|
</div>
|
|
5
|
-
<section v-if="!isLoading" class="max-w-72 mr-4 md:mr-2 pt-4 items-center border border-secondary hover:border-accent rounded-lg" @click="onCardClick">
|
|
5
|
+
<section v-if="!isLoading" class="max-w-72 mr-4 md:mr-2 pt-4 items-center border border-secondary hover:border-accent hover:cursor-pointer rounded-lg" @click="onCardClick">
|
|
6
6
|
<div class="flex flex-col m-auto justify-center mb-4 items-center w-[130px]">
|
|
7
7
|
<img :src="portrait" alt="Fencer Portrait" class="w-[120px] h-[120px] md:w-32 md:h-32 rounded-full object-cover z-1 flex-shrink-0" />
|
|
8
8
|
</div>
|
|
@@ -48,6 +48,7 @@ export default {
|
|
|
48
48
|
return {
|
|
49
49
|
};
|
|
50
50
|
},
|
|
51
|
+
emits: ['grid-card-click'],
|
|
51
52
|
computed: {
|
|
52
53
|
portrait() {
|
|
53
54
|
return this.data.ProfileImage && this.data.ProfileImage.URL
|
|
@@ -64,13 +65,10 @@ export default {
|
|
|
64
65
|
const m2RatingForWeapon = this.data.M2Ratings.find(rating => rating.WeaponId === 1);
|
|
65
66
|
return m2RatingForWeapon ? m2RatingForWeapon.FormattedRating : 'U';
|
|
66
67
|
},
|
|
67
|
-
hrRating() {
|
|
68
|
-
return this.data.HEMARatings && this.data.HEMARatings[0] ? this.data.HEMARatings[0].Rating : 0;
|
|
69
|
-
},
|
|
70
68
|
},
|
|
71
69
|
methods: {
|
|
72
70
|
onCardClick() {
|
|
73
|
-
this.$emit('card-click', this.data);
|
|
71
|
+
this.$emit('grid-card-click', this.data);
|
|
74
72
|
}
|
|
75
73
|
}
|
|
76
74
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import FencerListCard from './FencerListCard.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Cards/FencerListCard',
|
|
5
|
+
component: FencerListCard,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
components: { FencerListCard },
|
|
10
|
+
setup() {
|
|
11
|
+
return { args };
|
|
12
|
+
},
|
|
13
|
+
template: '<FencerListCard v-bind="args" @card-click="onCardClick" />',
|
|
14
|
+
methods: {
|
|
15
|
+
onCardClick(fencer) {
|
|
16
|
+
alert(`Fencer selected: ${fencer.DisplayName}`);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const Default = Template.bind({});
|
|
22
|
+
Default.args = {
|
|
23
|
+
data: {
|
|
24
|
+
DisplayName: 'John Doe',
|
|
25
|
+
Club: { Name: 'Awesome Fencing Club' },
|
|
26
|
+
M2Ratings: [{ WeaponId: 1, FormattedRating: 'A23' }],
|
|
27
|
+
ProfileImage: { URL: 'https://via.placeholder.com/150' },
|
|
28
|
+
},
|
|
29
|
+
isLoading: false,
|
|
30
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section v-if="!isLoading" class="flex items-center p-4 hover:cursor-pointer" @click="handleCardClicked">
|
|
3
|
+
<img :src="portrait" alt="Fencer Portrait" class="w-[50px] h-[50px] md:w-[70px] md:h-[70px] rounded-full object-cover z-1 flex-shrink-0 mr-4" />
|
|
4
|
+
|
|
5
|
+
<div class="flex flex-col justify-center flex-grow">
|
|
6
|
+
<section class="hidden md:flex flex-col">
|
|
7
|
+
<BaseText tag="h3" size="2xl" weight="bold">{{ displayName }}</BaseText>
|
|
8
|
+
<BaseText tag="p" size="md" weight="normal">{{ clubName }}</BaseText>
|
|
9
|
+
</section>
|
|
10
|
+
<section class="flex md:hidden flex-col">
|
|
11
|
+
<BaseText tag="h3" size="md" weight="bold">{{ displayName }}</BaseText>
|
|
12
|
+
<BaseText tag="p" size="xs" weight="normal">{{ clubName }}</BaseText>
|
|
13
|
+
</section>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div class="flex items-center">
|
|
17
|
+
<section class="hidden md:flex">
|
|
18
|
+
<BaseText tag="p" size="sm" weight="normal" class="text-accent">Rating:</BaseText>
|
|
19
|
+
<BaseText tag="p" size="sm" weight="bold" class="text-accent ml-2"> {{ m2Rating }}</BaseText>
|
|
20
|
+
</section>
|
|
21
|
+
<section class="flex md:hidden">
|
|
22
|
+
<BaseText tag="p" size="xs" weight="normal" class="text-accent">Rating:</BaseText>
|
|
23
|
+
<BaseText tag="p" size="xs" weight="bold" class="text-accent ml-2"> {{ m2Rating}}</BaseText>
|
|
24
|
+
</section>
|
|
25
|
+
</div>
|
|
26
|
+
</section>
|
|
27
|
+
|
|
28
|
+
<!-- Loading State -->
|
|
29
|
+
<div v-if="isLoading" class="p-4 bg-secondary rounded-lg flex items-center">
|
|
30
|
+
<FencerCardSkeleton />
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
import BaseText from "../../../Atoms/BaseText/BaseText.vue";
|
|
36
|
+
import defaultPortrait from '../../../../assets/images/portrait1.png'
|
|
37
|
+
import FencerCardSkeleton from "../Skeletons/FencingCardSkeleton.vue";
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
name: 'FencerListCard',
|
|
41
|
+
components: {
|
|
42
|
+
FencerCardSkeleton,
|
|
43
|
+
BaseText,
|
|
44
|
+
},
|
|
45
|
+
props: {
|
|
46
|
+
data: {
|
|
47
|
+
type: Object,
|
|
48
|
+
required: true,
|
|
49
|
+
},
|
|
50
|
+
index: {
|
|
51
|
+
type: Number,
|
|
52
|
+
required: false,
|
|
53
|
+
},
|
|
54
|
+
isLast: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
required: false,
|
|
57
|
+
},
|
|
58
|
+
isLoading: {
|
|
59
|
+
type: Boolean,
|
|
60
|
+
default: false,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
emits: ['grid-card-click'],
|
|
64
|
+
computed: {
|
|
65
|
+
portrait() {
|
|
66
|
+
return this.data.ProfileImage && this.data.ProfileImage.URL
|
|
67
|
+
? this.data.ProfileImage.URL
|
|
68
|
+
: defaultPortrait;
|
|
69
|
+
},
|
|
70
|
+
displayName() {
|
|
71
|
+
return this.data.DisplayName;
|
|
72
|
+
},
|
|
73
|
+
clubName() {
|
|
74
|
+
return this.data.Club.Name;
|
|
75
|
+
},
|
|
76
|
+
m2Rating() {
|
|
77
|
+
return this.data.M2Ratings[0] ? this.data.M2Ratings[0].FormattedRating : 'U';
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
methods: {
|
|
81
|
+
handleCardClicked() {
|
|
82
|
+
this.$emit('grid-card-click', this.data);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import PhotoCard from './PhotoCard.vue';
|
|
2
|
+
import mockAllClubs from "../../../../mocks/getAllClubs.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Organisms/Cards/PhotoCard',
|
|
6
|
+
component: PhotoCard,
|
|
7
|
+
argTypes: {
|
|
8
|
+
data: { control: 'object' },
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Template = (args) => ({
|
|
13
|
+
components: { PhotoCard },
|
|
14
|
+
setup() {
|
|
15
|
+
return { args };
|
|
16
|
+
},
|
|
17
|
+
template: '<PhotoCard v-bind="args" />',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const Default = Template.bind({});
|
|
21
|
+
Default.args = {
|
|
22
|
+
data: mockAllClubs[0].Images[1]
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WithoutTitle = Template.bind({});
|
|
26
|
+
WithoutTitle.args = {
|
|
27
|
+
data: mockAllClubs[0].Images[2]
|
|
28
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-[250px] h-[150px]">
|
|
3
|
+
<img :src="data.URL" :alt="data.AltText" class="object-cover w-full h-full" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
export default {
|
|
9
|
+
name: 'PhotoCard',
|
|
10
|
+
props: {
|
|
11
|
+
data: {
|
|
12
|
+
type: Object,
|
|
13
|
+
required: true,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
</script>
|
|
18
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import SocialMediaLinkCard from './SocialMediaLinkCard.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Cards/SocialMediaLinkCard',
|
|
5
|
+
component: SocialMediaLinkCard,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
components: { SocialMediaLinkCard },
|
|
10
|
+
setup() {
|
|
11
|
+
return { args };
|
|
12
|
+
},
|
|
13
|
+
template: '<SocialMediaLinkCard v-bind="args" />',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const Default = Template.bind({});
|
|
17
|
+
Default.args = {
|
|
18
|
+
socialMedia: [
|
|
19
|
+
{
|
|
20
|
+
Type: 'Discord',
|
|
21
|
+
Link: 'https://discord.com',
|
|
22
|
+
Label: 'Join us on Discord',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
Type: 'Instagram',
|
|
26
|
+
Link: 'https://instagram.com',
|
|
27
|
+
Label: 'Follow us on Instagram',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
Type: 'Facebook',
|
|
31
|
+
Link: 'https://facebook.com',
|
|
32
|
+
Label: 'Like us on Facebook',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
Type: 'Web',
|
|
36
|
+
Link: 'https://www.hemaalliance.com/event-calendar',
|
|
37
|
+
Label: 'Visit our Website',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<aside class="md:w-64 m-2 flex flex-col mb-20">
|
|
3
|
+
<div v-for="(social, index) in socialMedia" :key="index" class="mb-4">
|
|
4
|
+
<BaseButton
|
|
5
|
+
:label="social.Label || social.Type"
|
|
6
|
+
size="md"
|
|
7
|
+
color="secondary"
|
|
8
|
+
border="gradient1"
|
|
9
|
+
weight="normal"
|
|
10
|
+
class="w-full h-16 pl-8"
|
|
11
|
+
:iconName="getIconName(social.Type)"
|
|
12
|
+
iconColor="secondary"
|
|
13
|
+
iconSize="xl"
|
|
14
|
+
:iconType="social.Type === 'Web' ? 'fa-solid' : 'fa-brands'"
|
|
15
|
+
align="between"
|
|
16
|
+
@click="openLink(social.Link)"
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
</aside>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
import BaseButton from '../../../Atoms/BaseButton/BaseButton.vue';
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
name: 'SocialMediaLinkCard',
|
|
27
|
+
components: { BaseButton },
|
|
28
|
+
props: {
|
|
29
|
+
socialMedia: {
|
|
30
|
+
type: Array,
|
|
31
|
+
default: () => ([
|
|
32
|
+
{ "Type": "Discord", "Link": "https://discord.com", "Label": null },
|
|
33
|
+
{ "Type": "Instagram", "Link": "https://instagram.com", "Label": null },
|
|
34
|
+
{ "Type": "Facebook", "Link": "https://facebook.com", "Label": null },
|
|
35
|
+
{ "Type": "Web", "Link": "https://www.hemaalliance.com/event-calendar", "Label": null },
|
|
36
|
+
]),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
methods: {
|
|
40
|
+
getIconName(type) {
|
|
41
|
+
const iconMap = {
|
|
42
|
+
Discord: 'fa-discord',
|
|
43
|
+
Instagram: 'fa-instagram',
|
|
44
|
+
Facebook: 'fa-facebook',
|
|
45
|
+
Web: 'fa-globe',
|
|
46
|
+
};
|
|
47
|
+
return iconMap[type] || 'fa-globe'; // Default to globe icon if no match
|
|
48
|
+
},
|
|
49
|
+
openLink(link) {
|
|
50
|
+
window.open(link, '_blank');
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import TournamentCard from './TournamentCard.vue';
|
|
2
2
|
import mockTournaments from "../../../../mocks/getTournamentsMock.js";
|
|
3
3
|
export default {
|
|
4
|
-
title: 'Organisms/Cards/TournamentCard',
|
|
4
|
+
title: 'Organisms/Cards/Tournament/TournamentCard',
|
|
5
5
|
component: TournamentCard,
|
|
6
6
|
};
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div v-if="isLoading" class="max-w-80 md:w-full mb-8">
|
|
3
3
|
<TournamentCardSkeleton />
|
|
4
4
|
</div>
|
|
5
|
-
<div v-if="!isLoading" class="max-w-80 md:w-full mb-8 border border-secondary hover:border-accent p-2 rounded-lg" @click="onCardClick">
|
|
5
|
+
<div v-if="!isLoading" class="max-w-80 md:w-full mb-8 border border-secondary hover:border-accent hover:cursor-pointer p-2 rounded-lg" @click="onCardClick">
|
|
6
6
|
<!-- Desktop Version -->
|
|
7
7
|
<section class="hidden md:block">
|
|
8
8
|
<img
|
|
@@ -74,6 +74,10 @@ export default {
|
|
|
74
74
|
type: Object,
|
|
75
75
|
required: true,
|
|
76
76
|
},
|
|
77
|
+
index: {
|
|
78
|
+
type: Number,
|
|
79
|
+
required: false,
|
|
80
|
+
},
|
|
77
81
|
isLoading: {
|
|
78
82
|
type: Boolean,
|
|
79
83
|
default: false,
|
|
@@ -84,6 +88,7 @@ export default {
|
|
|
84
88
|
isImageError: false
|
|
85
89
|
};
|
|
86
90
|
},
|
|
91
|
+
emits: ['grid-card-click'],
|
|
87
92
|
computed: {
|
|
88
93
|
image() {
|
|
89
94
|
return !this.isImageError && this.data.ImagesURLs && this.data.ImagesURLs.length > 0
|
|
@@ -123,7 +128,7 @@ export default {
|
|
|
123
128
|
this.isImageError = true;
|
|
124
129
|
},
|
|
125
130
|
onCardClick() {
|
|
126
|
-
this.$emit('card-click', this.data);
|
|
131
|
+
this.$emit('grid-card-click', this.data);
|
|
127
132
|
}
|
|
128
133
|
}
|
|
129
134
|
};
|