@dcrackel/hematournamentui 1.0.708 → 1.0.710

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.
Files changed (38) hide show
  1. package/README.md +148 -106
  2. package/dist/HemaTournamentUI-lib.es.js +6678 -6196
  3. package/dist/HemaTournamentUI-lib.umd.js +27 -27
  4. package/dist/hematournamentui-tailwind.css +16 -6
  5. package/package.json +1 -1
  6. package/src/stories/Atoms/Input/BaseInput.test.js +97 -85
  7. package/src/stories/Atoms/Input/BaseInput.vue +149 -150
  8. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +31 -20
  9. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.test.js +109 -0
  10. package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.vue +192 -133
  11. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.stories.js +48 -41
  12. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.vue +227 -206
  13. package/src/stories/Organisms/Wizards/EditEventWizard/DirectElimination/DirectElimination.vue +226 -225
  14. package/src/stories/Organisms/Wizards/EditEventWizard/DirectEliminationPromotion/DirectEliminationPromotion.vue +204 -204
  15. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.stories.js +133 -91
  16. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.test.js +191 -0
  17. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.vue +366 -309
  18. package/src/stories/Organisms/Wizards/EditEventWizard/EventCustomization/EventCustomization.vue +172 -171
  19. package/src/stories/Organisms/Wizards/EditEventWizard/PoolConfiguration/PoolConfiguration.vue +216 -215
  20. package/src/stories/Organisms/Wizards/EditEventWizard/PriceFields.test.js +79 -0
  21. package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.stories.js +93 -52
  22. package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.vue +91 -75
  23. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.stories.js +14 -0
  24. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.test.js +39 -0
  25. package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.vue +13 -3
  26. package/src/stories/Templates/PersonManagement/Basic/BasicEdit.vue +170 -172
  27. package/src/stories/Templates/PersonManagement/PersonManagement.stories.js +156 -103
  28. package/src/stories/Templates/PersonManagement/PersonManagement.test.js +329 -0
  29. package/src/stories/Templates/PersonManagement/PersonManagement.vue +329 -213
  30. package/src/stories/Templates/PersonManagement/PersonManagementDraft.js +42 -0
  31. package/src/stories/Templates/TournamentManagement/TournamentManagement.stories.js +84 -83
  32. package/src/stories/Templates/TournamentManagement/TournamentManagement.test.js +89 -0
  33. package/src/stories/Templates/TournamentManagement/TournamentManagement.vue +363 -360
  34. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.stories.js +116 -113
  35. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.vue +292 -280
  36. package/src/stories/Util/Validations/PersonManagementValidations.js +45 -29
  37. package/src/stories/Util/Validations/PriceValidation.js +6 -0
  38. package/src/stories/Util/Validations/TournamentFieldsValidations.js +4 -0
@@ -1,75 +1,91 @@
1
- <template>
2
- <section>
3
- <EditEventsTopMenu :currentTab="'Edit'" :tabs="tabs(userLevel, isMobile)" @tabMenuClick="handleTabMenuClick" />
4
-
5
- <div class="w-full flex flex-row justify-center mt-3">
6
- <EditEventWizard
7
- :event="event"
8
- :rules="rules"
9
- :weapons="weapons"
10
- :userLevel="userLevel"
11
- @update:submit="handleSubmit"
12
- />
13
- </div>
14
- </section>
15
- </template>
16
-
17
- <script>
18
- import EditEventsTopMenu from '../../Menus/EditEventsTopMenu/EditEventsTopMenu.vue';
19
- import EditEventWizard from '../../../Organisms/Wizards/EditEventWizard/EditEventWizard.vue';
20
- import { tabs } from '../../../Util/tabs.js';
21
-
22
- export default {
23
- emits: ['tab:menu-click', 'update:submit'],
24
- components: {
25
- EditEventWizard,
26
- EditEventsTopMenu
27
- },
28
- props: {
29
- event: {
30
- type: Object,
31
- required: true
32
- },
33
- weapons: {
34
- type: Array,
35
- required: true
36
- },
37
- rules: {
38
- type: Array,
39
- required: true
40
- },
41
- userLevel: {
42
- type: String,
43
- default: 'Club'
44
- }
45
- },
46
- data() {
47
- return {
48
- tabs,
49
- windowWidth: window.innerWidth
50
- };
51
- },
52
- mounted() {
53
- window.addEventListener('resize', this.handleResize);
54
- },
55
- beforeUnmount() {
56
- window.removeEventListener('resize', this.handleResize);
57
- },
58
- computed: {
59
- isMobile() {
60
- return this.windowWidth <= 748;
61
- }
62
- },
63
- methods: {
64
- handleTabMenuClick(value) {
65
- this.$emit('tab:menu-click', value);
66
- },
67
- handleSubmit(value) {
68
- this.$emit('update:submit', value);
69
- },
70
- handleResize() {
71
- this.windowWidth = window.innerWidth;
72
- }
73
- }
74
- };
75
- </script>
1
+ <template>
2
+ <section>
3
+ <EditEventsTopMenu :currentTab="'Edit'" :tabs="tabs(userLevel, isMobile)" @tabMenuClick="handleTabMenuClick" />
4
+
5
+ <div class="w-full flex flex-row justify-center mt-3">
6
+ <EditEventWizard
7
+ :event="event"
8
+ :rules="rules"
9
+ :weapons="weapons"
10
+ :userLevel="userLevel"
11
+ :editMode="editMode"
12
+ :step="step"
13
+ :saving="saving"
14
+ :saveError="saveError"
15
+ :saveNotice="saveNotice"
16
+ @save:step="$emit('save:step', $event)"
17
+ @navigate:step="$emit('navigate:step', $event)"
18
+ @update:dirty="$emit('update:dirty', $event)"
19
+ @update:cancel="$emit('update:cancel')"
20
+ @update:submit="handleSubmit"
21
+ />
22
+ </div>
23
+ </section>
24
+ </template>
25
+
26
+ <script>
27
+ import EditEventsTopMenu from '../../Menus/EditEventsTopMenu/EditEventsTopMenu.vue';
28
+ import EditEventWizard from '../../../Organisms/Wizards/EditEventWizard/EditEventWizard.vue';
29
+ import { tabs } from '../../../Util/tabs.js';
30
+
31
+ export default {
32
+ emits: ['tab:menu-click', 'update:submit', 'save:step', 'navigate:step', 'update:dirty', 'update:cancel'],
33
+ components: {
34
+ EditEventWizard,
35
+ EditEventsTopMenu
36
+ },
37
+ props: {
38
+ editMode: { type: Boolean, default: false },
39
+ step: { type: Number, default: 1 },
40
+ saving: { type: Boolean, default: false },
41
+ saveError: { type: String, default: '' },
42
+ saveNotice: { type: String, default: '' },
43
+
44
+ event: {
45
+ type: Object,
46
+ required: true
47
+ },
48
+ weapons: {
49
+ type: Array,
50
+ required: true
51
+ },
52
+ rules: {
53
+ type: Array,
54
+ required: true
55
+ },
56
+ userLevel: {
57
+ type: String,
58
+ default: 'Club'
59
+ }
60
+ },
61
+ data() {
62
+ return {
63
+ tabs,
64
+ windowWidth: window.innerWidth
65
+ };
66
+ },
67
+ mounted() {
68
+ window.addEventListener('resize', this.handleResize);
69
+ },
70
+ beforeUnmount() {
71
+ window.removeEventListener('resize', this.handleResize);
72
+ },
73
+ computed: {
74
+ isMobile() {
75
+ return this.windowWidth <= 748;
76
+ }
77
+ },
78
+ methods: {
79
+ handleTabMenuClick(value) {
80
+ if (this.saving) return;
81
+ this.$emit('tab:menu-click', value);
82
+ },
83
+ handleSubmit(value) {
84
+ this.$emit('update:submit', value);
85
+ },
86
+ handleResize() {
87
+ this.windowWidth = window.innerWidth;
88
+ }
89
+ }
90
+ };
91
+ </script>
@@ -65,3 +65,17 @@ export const EmptyAccessLevel = {
65
65
  userLevel: 'Club'
66
66
  }
67
67
  };
68
+
69
+ export const ClearedHemaRatingId = {
70
+ args: {
71
+ person: { ...personsMock[1], HemaRatingsId: null, HEMARatings: [{ HemaRatingId: 123 }] },
72
+ userLevel: 'Admin'
73
+ }
74
+ };
75
+
76
+ export const InvalidHemaRatingId = {
77
+ args: {
78
+ person: { ...personsMock[1], HemaRatingsId: '1.5' },
79
+ userLevel: 'Admin'
80
+ }
81
+ };
@@ -0,0 +1,39 @@
1
+ import { afterEach, describe, expect, it } from 'vitest';
2
+ import { enableAutoUnmount, mount } from '@vue/test-utils';
3
+ import Administration from './Administration.vue';
4
+ import TitledInput from '../../../../Molecules/CombinationInputs/TitledInput/TitledInput.vue';
5
+
6
+ enableAutoUnmount(afterEach);
7
+
8
+ function mountAdministration(id) {
9
+ return mount(Administration, {
10
+ props: {
11
+ person: { PersonId: 1, HemaRatingsId: id, HEMARatings: [{ HemaRatingId: 123 }], AccessLevel: 'User' },
12
+ userLevel: 'Admin'
13
+ },
14
+ global: { stubs: { DropDownMenu: true } }
15
+ });
16
+ }
17
+
18
+ const findHemaInput = wrapper => wrapper.findAllComponents(TitledInput)[1].find('input');
19
+
20
+ describe('Administration HR ID draft', () => {
21
+ it.each([null, ''])('keeps the explicitly cleared ID %j blank', id => {
22
+ const wrapper = mountAdministration(id);
23
+ expect(findHemaInput(wrapper).element.value).toBe('');
24
+ expect(findHemaInput(wrapper).attributes('aria-invalid')).toBe('false');
25
+ });
26
+
27
+ it('falls back to legacy ratings only when the canonical ID is undefined', () => {
28
+ const wrapper = mountAdministration(undefined);
29
+ expect(findHemaInput(wrapper).element.value).toBe('123');
30
+ });
31
+
32
+ it('shows invalid-ID feedback and preserves invalid input for correction', async () => {
33
+ const wrapper = mountAdministration(0);
34
+ expect(wrapper.text()).toContain('positive whole-number ID');
35
+ expect(findHemaInput(wrapper).attributes('aria-invalid')).toBe('true');
36
+ await findHemaInput(wrapper).setValue('-5');
37
+ expect(wrapper.emitted('update:person')).toEqual([[{ field: 'HemaRatingsId', value: '-5' }]]);
38
+ });
39
+ });
@@ -14,9 +14,10 @@
14
14
  <div class="flex flex-col mb-4">
15
15
  <TitledInput
16
16
  :inputValue="hemaRatingId"
17
- :inputType="'number'"
17
+ inputType="text"
18
18
  placeholder="HEMA Rating ID"
19
- title="HEMA Rating ID"
19
+ :invalid="hemaRatingValidation.invalid"
20
+ :title="hemaRatingLabel"
20
21
  @update:value="emitUpdate('HemaRatingsId', $event)"
21
22
  />
22
23
  </div>
@@ -41,6 +42,8 @@
41
42
  import TitledInput from '../../../../Molecules/CombinationInputs/TitledInput/TitledInput.vue';
42
43
  import BaseText from '../../../../Atoms/Text/BaseText.vue';
43
44
  import DropDownMenu from '../../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue';
45
+ import { getDraftHemaRatingsId } from '../../PersonManagementDraft.js';
46
+ import { validateField } from '../../../../Util/Validations/PersonManagementValidations.js';
44
47
 
45
48
  const STANDARD_ACCESS_LEVELS = [
46
49
  { text: 'User', link: 'User' },
@@ -63,7 +66,14 @@ export default {
63
66
  return this.person?.PersonId ?? '';
64
67
  },
65
68
  hemaRatingId() {
66
- return this.person?.HemaRatingsId ?? this.person?.HEMARatings?.[0]?.HemaRatingId ?? '';
69
+ return getDraftHemaRatingsId(this.person);
70
+ },
71
+ hemaRatingValidation() {
72
+ return validateField('HemaRatingsId', this.hemaRatingId);
73
+ },
74
+ hemaRatingLabel() {
75
+ if (this.hemaRatingValidation.invalid) return `HEMA Rating ID - ${this.hemaRatingValidation.message}`;
76
+ return 'HEMA Rating ID';
67
77
  },
68
78
  accessLevels() {
69
79
  if (this.userLevel === 'Admin') {
@@ -1,172 +1,170 @@
1
- <template>
2
- <section class="mt-2 min-h-80">
3
- <div>
4
- <div class="flex flex-col mb-4">
5
- <TitledInput
6
- :inputValue="person.DisplayName || ''"
7
- placeholder="Enter Display Name"
8
- :invalid="validation.DisplayName.invalid"
9
- :title="
10
- validation.DisplayName.invalid ? `DisplayName Name - ${validation.DisplayName.message}` : 'Display Name'
11
- "
12
- @update:value="emitUpdate('DisplayName', $event)"
13
- />
14
- </div>
15
-
16
- <div class="flex flex-col mb-4">
17
- <TitledInput
18
- :inputValue="getLegalName"
19
- placeholder="Enter Your Legal Name"
20
- :invalid="validation.LegalName.invalid"
21
- :title="
22
- validation.LegalName.invalid
23
- ? `Legal Name - ${validation.LegalName.message}`
24
- : 'Legal Name (not shown on site)'
25
- "
26
- @update:value="emitUpdate('LegalName', $event)"
27
- />
28
- </div>
29
-
30
- <div class="flex flex-col mb-4">
31
- <BaseText text="Club Name" size="sm" color="quaternary" />
32
- <DropDownMenu
33
- :label="formattedClubs.length < 2 ? 'Select Club' : ''"
34
- :items="formattedClubs"
35
- :selectedItem="getClubName"
36
- class="pb-2"
37
- @update:selectedItem="emitUpdate('Club', { Name: $event.text, ClubId: $event.link })"
38
- width="w-full"
39
- dropDownWidth="w-full"
40
- />
41
- </div>
42
-
43
- <div class="flex flex-col mb-4">
44
- <BaseText text="Preferred Pronouns" size="sm" color="quaternary" />
45
- <DropDownMenu
46
- :label="getPronounLabel"
47
- :items="pronouns"
48
- class="pb-2"
49
- :selectedItem="getSelectedPronouns"
50
- @update:selectedItem="emitUpdate('Pronouns', $event.text)"
51
- width="w-full"
52
- dropDownWidth="w-full"
53
- />
54
- </div>
55
-
56
- <div class="flex flex-col mb-4">
57
- <TitledInput
58
- :inputValue="getEmail || ''"
59
- placeholder="Enter Your Email"
60
- :invalid="validation.EmailAddress.invalid"
61
- :title="
62
- validation.EmailAddress.invalid ? `Email Address - ${validation.EmailAddress.message}` : 'Email Address'
63
- "
64
- @update:value="emitUpdate('EmailAddress', $event)"
65
- />
66
- </div>
67
-
68
- <div class="border-b border-dropdownSelect mt-6">
69
- <BaseText color="quinary" size="sm" text="PROFILE USE" weight="normal" data-testid="text-registration" />
70
- </div>
71
-
72
- <div class="my-4 w-full">
73
- <BaseText
74
- color="quinary"
75
- size="sm"
76
- text="Your information belongs to you..."
77
- weight="normal"
78
- data-testid="text-registration"
79
- class="mb-4"
80
- />
81
-
82
- <Toggle
83
- :checked="person.ShowData"
84
- label="Allow your name and profile image to be displayed on M² Website?"
85
- :labelLeft="false"
86
- @update:checked="emitUpdate('ShowData', $event)"
87
- />
88
-
89
- <Toggle
90
- :checked="person.ShareData"
91
- label="Share information with 3rd Parties? (like: Hema Ratings)"
92
- :labelLeft="false"
93
- @update:checked="emitUpdate('ShareData', $event)"
94
- />
95
- </div>
96
- </div>
97
- </section>
98
- </template>
99
-
100
- <script>
101
- import TitledInput from '../../../Molecules/CombinationInputs/TitledInput/TitledInput.vue';
102
- import BaseText from '../../../Atoms/Text/BaseText.vue';
103
- import DropDownMenu from '../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue';
104
- import Toggle from '../../../Molecules/Inputs/Toggle/Toggle.vue';
105
-
106
- export default {
107
- name: 'BasicEdit',
108
- emits: ['update:person'], // Generic emit event
109
- components: { Toggle, DropDownMenu, BaseText, TitledInput },
110
- props: {
111
- person: {
112
- type: Object,
113
- required: true
114
- },
115
- fencingClubs: {
116
- type: Array,
117
- default: () => []
118
- },
119
- validation: {
120
- type: Object,
121
- required: true
122
- }
123
- },
124
- data() {
125
- return {
126
- pronouns: [
127
- { text: 'He/Him', link: 'He/Him' },
128
- { text: 'She/Her', link: 'She/Her' },
129
- { text: 'They/Them', link: 'They/Them' },
130
- { text: 'Other', link: 'Other' }
131
- ]
132
- };
133
- },
134
- computed: {
135
- formattedClubs() {
136
- return this.fencingClubs.map(club => ({
137
- text: club.Name,
138
- link: club.ClubId.toString()
139
- }));
140
- },
141
- getLegalName() {
142
- if (!this.person.FirstName && !this.person.LastName) {
143
- return ``;
144
- }
145
- return `${this.person.FirstName} ${this.person.LastName}`;
146
- },
147
- getClubName() {
148
- return this.person?.Club
149
- ? { text: this.person.Club.Name, link: this.person.Club.ClubId }
150
- : { text: 'No Club', link: null };
151
- },
152
- getSelectedPronouns() {
153
- if (!this.person.Pronouns) {
154
- return { text: 'He/Him', link: 'He/Him' };
155
- }
156
- return { text: this.person.Pronouns, link: this.person.Pronouns };
157
- },
158
- getEmail() {
159
- const primaryEmail = this.person.PersonEmails?.find(e => e.IsPrimary === true);
160
- return primaryEmail ? primaryEmail.EmailAddress : '';
161
- },
162
- getPronounLabel() {
163
- return this.person.Pronouns ? '' : 'Please select your preferred pronouns';
164
- }
165
- },
166
- methods: {
167
- emitUpdate(field, value) {
168
- this.$emit('update:person', { field, value });
169
- }
170
- }
171
- };
172
- </script>
1
+ <template>
2
+ <section class="mt-2 min-h-80">
3
+ <div>
4
+ <div class="flex flex-col mb-4">
5
+ <TitledInput
6
+ :inputValue="person.DisplayName || ''"
7
+ placeholder="Enter Display Name"
8
+ :invalid="validation.DisplayName.invalid"
9
+ :title="
10
+ validation.DisplayName.invalid ? `DisplayName Name - ${validation.DisplayName.message}` : 'Display Name'
11
+ "
12
+ @update:value="emitUpdate('DisplayName', $event)"
13
+ />
14
+ </div>
15
+
16
+ <div class="flex flex-col mb-4">
17
+ <TitledInput
18
+ :inputValue="getLegalName"
19
+ placeholder="Enter Your Legal Name"
20
+ :invalid="validation.LegalName.invalid"
21
+ :title="
22
+ validation.LegalName.invalid
23
+ ? `Legal Name - ${validation.LegalName.message}`
24
+ : 'Legal Name (not shown on site)'
25
+ "
26
+ @update:value="emitUpdate('LegalName', $event)"
27
+ />
28
+ </div>
29
+
30
+ <div class="flex flex-col mb-4">
31
+ <BaseText text="Club Name" size="sm" color="quaternary" />
32
+ <DropDownMenu
33
+ :label="formattedClubs.length < 2 ? 'Select Club' : ''"
34
+ :items="formattedClubs"
35
+ :selectedItem="getClubName"
36
+ class="pb-2"
37
+ @update:selectedItem="emitUpdate('Club', { Name: $event.text, ClubId: $event.link })"
38
+ width="w-full"
39
+ dropDownWidth="w-full"
40
+ />
41
+ </div>
42
+
43
+ <div class="flex flex-col mb-4">
44
+ <BaseText text="Preferred Pronouns" size="sm" color="quaternary" />
45
+ <DropDownMenu
46
+ :label="getPronounLabel"
47
+ :items="pronouns"
48
+ class="pb-2"
49
+ :selectedItem="getSelectedPronouns"
50
+ @update:selectedItem="emitUpdate('Pronouns', $event.text)"
51
+ width="w-full"
52
+ dropDownWidth="w-full"
53
+ />
54
+ </div>
55
+
56
+ <div class="flex flex-col mb-4">
57
+ <TitledInput
58
+ :inputValue="getEmail || ''"
59
+ inputType="email"
60
+ placeholder="Enter Your Email"
61
+ :invalid="validation.EmailAddress.invalid"
62
+ :title="
63
+ validation.EmailAddress.invalid ? `Email Address - ${validation.EmailAddress.message}` : 'Email Address'
64
+ "
65
+ @update:value="emitUpdate('EmailAddress', $event)"
66
+ />
67
+ </div>
68
+
69
+ <div class="border-b border-dropdownSelect mt-6">
70
+ <BaseText color="quinary" size="sm" text="PROFILE USE" weight="normal" data-testid="text-registration" />
71
+ </div>
72
+
73
+ <div class="my-4 w-full">
74
+ <BaseText
75
+ color="quinary"
76
+ size="sm"
77
+ text="Your information belongs to you..."
78
+ weight="normal"
79
+ data-testid="text-registration"
80
+ class="mb-4"
81
+ />
82
+
83
+ <Toggle
84
+ :checked="person.ShowData"
85
+ label="Allow your name and profile image to be displayed on M² Website?"
86
+ :labelLeft="false"
87
+ @update:checked="emitUpdate('ShowData', $event)"
88
+ />
89
+
90
+ <Toggle
91
+ :checked="person.ShareData"
92
+ label="Share information with 3rd Parties? (like: Hema Ratings)"
93
+ :labelLeft="false"
94
+ @update:checked="emitUpdate('ShareData', $event)"
95
+ />
96
+ </div>
97
+ </div>
98
+ </section>
99
+ </template>
100
+
101
+ <script>
102
+ import TitledInput from '../../../Molecules/CombinationInputs/TitledInput/TitledInput.vue';
103
+ import BaseText from '../../../Atoms/Text/BaseText.vue';
104
+ import DropDownMenu from '../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue';
105
+ import Toggle from '../../../Molecules/Inputs/Toggle/Toggle.vue';
106
+ import { getDraftEmailAddress, getDraftLegalName } from '../PersonManagementDraft.js';
107
+
108
+ export default {
109
+ name: 'BasicEdit',
110
+ emits: ['update:person'], // Generic emit event
111
+ components: { Toggle, DropDownMenu, BaseText, TitledInput },
112
+ props: {
113
+ person: {
114
+ type: Object,
115
+ required: true
116
+ },
117
+ fencingClubs: {
118
+ type: Array,
119
+ default: () => []
120
+ },
121
+ validation: {
122
+ type: Object,
123
+ required: true
124
+ }
125
+ },
126
+ data() {
127
+ return {
128
+ pronouns: [
129
+ { text: 'He/Him', link: 'He/Him' },
130
+ { text: 'She/Her', link: 'She/Her' },
131
+ { text: 'They/Them', link: 'They/Them' },
132
+ { text: 'Other', link: 'Other' }
133
+ ]
134
+ };
135
+ },
136
+ computed: {
137
+ formattedClubs() {
138
+ return this.fencingClubs.map(club => ({
139
+ text: club.Name,
140
+ link: club.ClubId.toString()
141
+ }));
142
+ },
143
+ getLegalName() {
144
+ return getDraftLegalName(this.person);
145
+ },
146
+ getClubName() {
147
+ return this.person?.Club
148
+ ? { text: this.person.Club.Name, link: this.person.Club.ClubId }
149
+ : { text: 'No Club', link: null };
150
+ },
151
+ getSelectedPronouns() {
152
+ if (!this.person.Pronouns) {
153
+ return { text: 'He/Him', link: 'He/Him' };
154
+ }
155
+ return { text: this.person.Pronouns, link: this.person.Pronouns };
156
+ },
157
+ getEmail() {
158
+ return getDraftEmailAddress(this.person);
159
+ },
160
+ getPronounLabel() {
161
+ return this.person.Pronouns ? '' : 'Please select your preferred pronouns';
162
+ }
163
+ },
164
+ methods: {
165
+ emitUpdate(field, value) {
166
+ this.$emit('update:person', { field, value });
167
+ }
168
+ }
169
+ };
170
+ </script>