@dcrackel/hematournamentui 1.0.710 → 1.0.712

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 (23) hide show
  1. package/README.md +152 -148
  2. package/dist/HemaTournamentUI-lib.es.js +4172 -4046
  3. package/dist/HemaTournamentUI-lib.umd.js +27 -27
  4. package/dist/hematournamentui-tailwind.css +11 -0
  5. package/package.json +1 -1
  6. package/src/stories/Molecules/Indicators/RegistrationStatus/RegistrationStatus.vue +30 -0
  7. package/src/stories/Organisms/Cards/EventCard/EventCard.stories.js +41 -1
  8. package/src/stories/Organisms/Cards/EventCard/EventCard.test.js +106 -0
  9. package/src/stories/Organisms/Cards/EventCard/EventCard.vue +62 -30
  10. package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +1 -1
  11. package/src/stories/Organisms/Headers/AttendanceSummary/AttendanceSummary.vue +12 -5
  12. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.stories.js +4 -0
  13. package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.vue +249 -227
  14. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.stories.js +4 -0
  15. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.test.js +221 -191
  16. package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.vue +372 -366
  17. package/src/stories/Organisms/Wizards/EditEventWizard/RuleSerialization.test.js +29 -0
  18. package/src/stories/Templates/EventManagement/EventAttendance/EventAttendance.stories.js +31 -1
  19. package/src/stories/Templates/TournamentManagement/ListEvents/ListEvents.stories.js +58 -45
  20. package/src/stories/Templates/TournamentManagement/TournamentManagement.test.js +27 -2
  21. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.stories.js +1 -1
  22. package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.vue +17 -2
  23. package/src/stories/Util/registrationStatus.js +11 -0
@@ -530,6 +530,9 @@
530
530
  .ml-5 {
531
531
  margin-left: calc(var(--spacing) * 5);
532
532
  }
533
+ .ml-6 {
534
+ margin-left: calc(var(--spacing) * 6);
535
+ }
533
536
  .ml-9 {
534
537
  margin-left: calc(var(--spacing) * 9);
535
538
  }
@@ -1049,6 +1052,9 @@
1049
1052
  margin-inline-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)));
1050
1053
  }
1051
1054
  }
1055
+ .gap-y-1 {
1056
+ row-gap: calc(var(--spacing) * 1);
1057
+ }
1052
1058
  .self-end {
1053
1059
  align-self: flex-end;
1054
1060
  }
@@ -2396,6 +2402,11 @@
2396
2402
  flex-wrap: nowrap;
2397
2403
  }
2398
2404
  }
2405
+ .md\:items-stretch {
2406
+ @media (width >= 48rem) {
2407
+ align-items: stretch;
2408
+ }
2409
+ }
2399
2410
  .md\:justify-start {
2400
2411
  @media (width >= 48rem) {
2401
2412
  justify-content: flex-start;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dcrackel/hematournamentui",
3
3
  "private": false,
4
- "version": "1.0.710",
4
+ "version": "1.0.712",
5
5
  "type": "module",
6
6
  "main": "dist/HemaTournamentUI-lib.umd.js",
7
7
  "module": "dist/HemaTournamentUI-lib.es.js",
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <div v-if="statusLabel" class="inline-flex items-center gap-2 whitespace-nowrap">
3
+ <span class="sr-only">Registration status:</span>
4
+ <BaseIcon icon-name="fa-info-circle" size="xs" color="quaternary" aria-hidden="true" />
5
+ <BaseText :text="statusLabel" size="xs" color="quaternary" />
6
+ </div>
7
+ </template>
8
+
9
+ <script>
10
+ import BaseIcon from '../../../Atoms/Icon/BaseIcon.vue';
11
+ import BaseText from '../../../Atoms/Text/BaseText.vue';
12
+
13
+ import { getRegistrationStatusLabel } from '../../../Util/registrationStatus.js';
14
+
15
+ export default {
16
+ name: 'RegistrationStatus',
17
+ components: { BaseIcon, BaseText },
18
+ props: {
19
+ status: {
20
+ type: String,
21
+ default: ''
22
+ }
23
+ },
24
+ computed: {
25
+ statusLabel() {
26
+ return getRegistrationStatusLabel(this.status);
27
+ }
28
+ }
29
+ };
30
+ </script>
@@ -5,6 +5,14 @@ export default {
5
5
  title: 'Organisms/Cards/EventCard',
6
6
  component: EventCard,
7
7
  tags: ['autodocs'],
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component:
12
+ 'RegistrationStatus accepts open, waitlist, full, or closed from the consuming app. The icon tray displays a status icon and the current state using existing theme colors. These values are also supported in Status when RegistrationStatus is absent. Missing or unknown values hide the status indicator. Lifecycle Status values such as live and completed continue to control existing behavior.'
13
+ }
14
+ }
15
+ },
8
16
  args: {
9
17
  event: singleEventMock
10
18
  },
@@ -12,5 +20,37 @@ export default {
12
20
  };
13
21
 
14
22
  export const Default = {
15
- event: singleEventMock
23
+ args: { event: singleEventMock }
24
+ };
25
+
26
+ export const Open = {
27
+ args: { event: { ...singleEventMock, Status: 'registration', RegistrationStatus: 'open' } }
28
+ };
29
+
30
+ export const Waitlist = {
31
+ args: { event: { ...singleEventMock, Status: 'registration', RegistrationStatus: 'waitlist' } }
32
+ };
33
+
34
+ export const Full = {
35
+ args: { event: { ...singleEventMock, Status: 'registration', RegistrationStatus: 'full' } }
36
+ };
37
+
38
+ export const Closed = {
39
+ args: { event: { ...singleEventMock, RegistrationStatus: 'closed' } }
40
+ };
41
+
42
+ export const MissingSettings = {
43
+ args: { event: { ...singleEventMock, EventRules: [] } }
44
+ };
45
+
46
+ export const InvalidSavedLimit = {
47
+ args: {
48
+ event: {
49
+ ...singleEventMock,
50
+ EventRules: [
51
+ ...singleEventMock.EventRules.filter(rule => rule.RuleId !== 14),
52
+ { RuleId: 14, RuleValue: 'function link() { [native code] }', Rules: { RuleName: 'CutOffNumber' } }
53
+ ]
54
+ }
55
+ }
16
56
  };
@@ -0,0 +1,106 @@
1
+ import { afterEach, expect, it } from 'vitest';
2
+ import { shallowMount } from '@vue/test-utils';
3
+ import EventCard from './EventCard.vue';
4
+
5
+ const wrappers = [];
6
+ afterEach(() => wrappers.splice(0).forEach(wrapper => wrapper.unmount()));
7
+ const nativeFunction = 'function link() { [native code] }';
8
+
9
+ function rule(RuleName, RuleValue) {
10
+ return { Rules: { RuleName }, RuleValue };
11
+ }
12
+
13
+ function mountCard(overrides = {}) {
14
+ const wrapper = shallowMount(EventCard, {
15
+ props: {
16
+ event: {
17
+ EventName: 'Example Event',
18
+ Date: '2026-10-17',
19
+ StartTime: '12:00',
20
+ Present: '8',
21
+ Absent: '0',
22
+ EventRules: [],
23
+ ...overrides
24
+ }
25
+ },
26
+ global: { stubs: { BaseText: { props: ['text'], template: '<span>{{ text }}</span>' } } }
27
+ });
28
+ wrappers.push(wrapper);
29
+ return wrapper;
30
+ }
31
+
32
+ it.each([
33
+ [32, '32'],
34
+ ['32', '32'],
35
+ [0, 'Unlimited'],
36
+ ['0', 'Unlimited'],
37
+ [null, 'Unlimited'],
38
+ ['', 'Unlimited'],
39
+ [nativeFunction, 'Not set']
40
+ ])('renders the fencer limit %j as %s', (value, expected) => {
41
+ const wrapper = mountCard({ EventRules: [rule('CutOffNumber', value)] });
42
+ expect(wrapper.vm.getMaxFencers).toBe(expected);
43
+ expect(wrapper.text()).not.toContain('[native code]');
44
+ });
45
+
46
+ it('handles missing rules without crashing or inventing an elimination format', () => {
47
+ const wrapper = mountCard({ EventRules: undefined });
48
+ expect(wrapper.vm.getMaxFencers).toBe('Unlimited');
49
+ expect(wrapper.vm.eventSummary).toBe('Event settings not available');
50
+ expect(wrapper.vm.getCombinedNumberOfFencers).toBe('8 / Unlimited');
51
+ });
52
+
53
+ it('keeps the phase, time, point and fencer summaries for nested and flat API rules', () => {
54
+ const EventRules = [
55
+ rule('PoolTime', '90'),
56
+ rule('DETime', '180'),
57
+ rule('PoolMaxPoints', '7'),
58
+ rule('DEMaxPoints', '12'),
59
+ rule('DEType', 'single'),
60
+ rule('DE3rdFenceOff', true),
61
+ rule('CutOffNumber', '32')
62
+ ];
63
+ for (const event of [
64
+ { EventRules },
65
+ {
66
+ EventRules: undefined,
67
+ rules: EventRules.map(item => ({ RuleName: item.Rules.RuleName, RuleValue: item.RuleValue }))
68
+ }
69
+ ]) {
70
+ const wrapper = mountCard(event);
71
+ expect(wrapper.vm.eventSummary).toBe('Pools -> Single Elim -> 3rd Place Fence off');
72
+ expect(wrapper.vm.getMaxPoolPoints).toBe('7');
73
+ expect(wrapper.vm.getMaxDEPoints).toBe('12');
74
+ expect(wrapper.vm.getCombinedNumberOfFencers).toBe('8 / 32');
75
+ expect(wrapper.text().match(/1:30/g)).toHaveLength(2);
76
+ expect(wrapper.text().match(/3:00/g)).toHaveLength(2);
77
+ }
78
+ });
79
+
80
+ it('renders pass-based pools and double elimination correctly', () => {
81
+ const wrapper = mountCard({
82
+ EventRules: [
83
+ rule('PoolNumOfPasses', '5'),
84
+ rule('DENumOfPasses', '7'),
85
+ rule('DEType', 'double'),
86
+ rule('DE3rdFenceOff', 'false')
87
+ ]
88
+ });
89
+ expect(wrapper.vm.eventSummary).toBe('Pools -> Double Elim -> Tie for 3rd Place');
90
+ expect(wrapper.vm.getPoolBoutTimeOrPasses).toBe('5');
91
+ expect(wrapper.vm.getDEBoutTimeOrPasses).toBe('7');
92
+ });
93
+
94
+ it('marks corrupted stored values as unset instead of displaying function text or guessing a format', () => {
95
+ const wrapper = mountCard({
96
+ EventRules: ['CutOffNumber', 'PoolTime', 'PoolMaxPoints', 'DETime', 'DEMaxPoints', 'DEType'].map(name =>
97
+ rule(name, nativeFunction)
98
+ )
99
+ });
100
+ expect(wrapper.text()).not.toContain('[native code]');
101
+ expect(wrapper.text()).not.toContain('NaN');
102
+ expect(wrapper.vm.eventSummary).toContain('DE format not set');
103
+ expect(wrapper.vm.getMaxFencers).toBe('Not set');
104
+ expect(wrapper.vm.getPoolBoutTimeOrPasses).toBe('Not set');
105
+ expect(wrapper.vm.getMaxDEPoints).toBe('Not set');
106
+ });
@@ -6,7 +6,7 @@
6
6
  <div class="w-full flex flex-col md:flex-row justify-between">
7
7
  <section class="flex flex-row px-1 justify-start w-full">
8
8
  <div class="flex flex-col w-full">
9
- <div class="hidden md:flex mb-1">
9
+ <div class="hidden md:flex flex-wrap items-center gap-y-1 mb-1">
10
10
  <div class="flex">
11
11
  <BaseIcon icon-name="fa-calendar" size="xs" color="quaternary" class="mr-2" />
12
12
  <BaseText :text="event.Date" size="xs" color="quinary" class="text-left" />
@@ -19,6 +19,7 @@
19
19
  <BaseIcon icon-name="fa-users" size="xs" color="quaternary" class="mx-2" />
20
20
  <BaseText :text="getMaxFencers" size="xs" color="quinary" class="text-right" />
21
21
  </div>
22
+ <RegistrationStatus :status="event.RegistrationStatus ?? event.Status" class="ml-6" />
22
23
  </div>
23
24
 
24
25
  <BaseText
@@ -31,12 +32,17 @@
31
32
  <BaseText :text="eventSummary" size="xs" color="quaternary" class="text-left" />
32
33
 
33
34
  <div class="flex flex-col md:hidden pt-2">
34
- <div class="flex">
35
- <BaseIcon icon-name="fa-calendar" size="xs" color="quaternary" class="mr-2" />
36
- <BaseText :text="event.Date" size="xs" color="quinary" class="text-left" />
37
- <BaseText :text="formatStartTime(event.StartTime)" size="xs" color="quinary" class="text-left ml-1" />
38
- <BaseIcon icon-name="fa-users" size="xs" color="quaternary" class="mr-2 ml-4" />
39
- <BaseText :text="getCombinedNumberOfFencers" size="xs" color="quinary" class="text-right" />
35
+ <div class="flex flex-wrap items-center gap-x-4 gap-y-1">
36
+ <div class="flex items-center whitespace-nowrap">
37
+ <BaseIcon icon-name="fa-calendar" size="xs" color="quaternary" class="mr-2" />
38
+ <BaseText :text="event.Date" size="xs" color="quinary" class="text-left" />
39
+ <BaseText :text="formatStartTime(event.StartTime)" size="xs" color="quinary" class="text-left ml-1" />
40
+ </div>
41
+ <div class="flex items-center whitespace-nowrap">
42
+ <BaseIcon icon-name="fa-users" size="xs" color="quaternary" class="mr-2" />
43
+ <BaseText :text="getCombinedNumberOfFencers" size="xs" color="quinary" class="text-right" />
44
+ </div>
45
+ <RegistrationStatus :status="event.RegistrationStatus ?? event.Status" />
40
46
  </div>
41
47
 
42
48
  <div class="flex flex-row mt-3 w-full">
@@ -49,7 +55,7 @@
49
55
  </div>
50
56
  <div class="flex w-full">
51
57
  <BaseIcon icon-name="fa-clock-desk" size="xs" color="quaternary" class="mr-2" />
52
- <BaseText :text="getDEBoutTimeOrPasses" size="xs" color="quinary" class="text-right" />
58
+ <BaseText :text="getPoolBoutTimeOrPasses" size="xs" color="quinary" class="text-right" />
53
59
  </div>
54
60
  </div>
55
61
  </div>
@@ -151,10 +157,11 @@ import BaseButton from '../../../Molecules/Buttons/BaseButton/BaseButton.vue';
151
157
  import EventStatusBox from '../../../Molecules/Boxes/EventStatusBox/EventStatusBox.vue';
152
158
  import BaseIcon from '../../../Atoms/Icon/BaseIcon.vue';
153
159
  import BaseModal from '../../../Molecules/Modals/BaseModal/BaseModal.vue';
160
+ import RegistrationStatus from '../../../Molecules/Indicators/RegistrationStatus/RegistrationStatus.vue';
154
161
 
155
162
  export default {
156
163
  name: 'EventCard',
157
- components: { BaseModal, BaseIcon, EventStatusBox, BaseButton, BaseText },
164
+ components: { RegistrationStatus, BaseModal, BaseIcon, EventStatusBox, BaseButton, BaseText },
158
165
  emits: ['manage', 'edit', 'delete'],
159
166
  props: {
160
167
  event: {
@@ -168,54 +175,72 @@ export default {
168
175
  };
169
176
  },
170
177
  computed: {
178
+ eventRules() {
179
+ const rules = this.event.EventRules ?? this.event.rules;
180
+ return Array.isArray(rules) ? rules.filter(rule => rule && typeof rule === 'object') : [];
181
+ },
171
182
  eventSummary() {
172
- const rules = this.event.EventRules;
183
+ const rules = this.eventRules;
184
+ if (rules.length === 0) return 'Event settings not available';
173
185
 
174
- const poolRule = rules.find(rule => rule.Rules.RuleName === 'PoolTime');
175
- const deType = rules.find(rule => rule.Rules.RuleName === 'DEType');
176
- const deThirdFenceOff = rules.find(rule => rule.Rules.RuleName === 'DE3rdFenceOff');
186
+ const poolRule = rules.find(rule =>
187
+ ['PoolTime', 'PoolNumOfPasses', 'PoolMaxPoints', 'PoolSeeding'].includes(rule.Rules?.RuleName ?? rule.RuleName)
188
+ );
189
+ const deType = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'DEType');
190
+ const deThirdFenceOff = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'DE3rdFenceOff');
177
191
 
178
192
  const poolSummary = poolRule ? 'Pools' : '';
179
- const deSummary = deType?.RuleValue === 'single' ? 'Single Elim' : 'Double Elim';
193
+ const deSummary =
194
+ new Map([
195
+ ['single', 'Single Elim'],
196
+ ['double', 'Double Elim']
197
+ ]).get(deType?.RuleValue) ?? 'DE format not set';
180
198
  const thirdPlaceSummary =
181
- deThirdFenceOff && deThirdFenceOff.RuleValue === 'true' ? '3rd Place Fence off' : 'Tie for 3rd Place';
199
+ new Map([
200
+ ['true', '3rd Place Fence off'],
201
+ ['false', 'Tie for 3rd Place']
202
+ ]).get(String(deThirdFenceOff?.RuleValue)) ?? '';
182
203
 
183
204
  return [poolSummary, deSummary, thirdPlaceSummary].filter(Boolean).join(' -> ');
184
205
  },
185
206
  getMaxFencers() {
186
- const maxRule = this.event.EventRules.find(rule => rule.Rules.RuleName === 'CutOffNumber');
187
- return maxRule.RuleValue === 0 ? 'Unlimited' : maxRule.RuleValue;
207
+ const maxRule = this.eventRules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'CutOffNumber');
208
+ const value = maxRule?.RuleValue;
209
+ if (value == null || value === '') return 'Unlimited';
210
+ const limit = Number(value);
211
+ if (!Number.isSafeInteger(limit) || limit < 0) return 'Not set';
212
+ return limit === 0 ? 'Unlimited' : String(limit);
188
213
  },
189
214
  getCombinedNumberOfFencers() {
190
- const combined = this.event.Present + this.event.Absent;
215
+ const combined = Number(this.event.Present ?? 0) + Number(this.event.Absent ?? 0);
191
216
  return combined + ' / ' + this.getMaxFencers;
192
217
  },
193
218
  getMaxPoolPoints() {
194
- const maxRule = this.event.EventRules.find(rule => rule.Rules.RuleName === 'PoolMaxPoints');
195
- return maxRule ? maxRule.RuleValue : '';
219
+ const maxRule = this.eventRules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'PoolMaxPoints');
220
+ return maxRule ? this.formatRuleNumber(maxRule.RuleValue) : '';
196
221
  },
197
222
  getMaxDEPoints() {
198
- const maxRule = this.event.EventRules.find(rule => rule.Rules.RuleName === 'DEMaxPoints');
199
- return maxRule ? maxRule.RuleValue : '';
223
+ const maxRule = this.eventRules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'DEMaxPoints');
224
+ return maxRule ? this.formatRuleNumber(maxRule.RuleValue) : '';
200
225
  },
201
226
  getPoolBoutTimeOrPasses() {
202
- const rules = this.event.EventRules;
227
+ const rules = this.eventRules;
203
228
 
204
- const poolTimeRule = rules.find(rule => rule.Rules.RuleName === 'PoolTime');
205
- const passesRule = rules.find(rule => rule.Rules.RuleName === 'PoolNumOfPasses');
229
+ const poolTimeRule = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'PoolTime');
230
+ const passesRule = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'PoolNumOfPasses');
206
231
 
207
232
  if (poolTimeRule) return this.formatTime(poolTimeRule.RuleValue);
208
- if (passesRule) return passesRule.RuleValue;
233
+ if (passesRule) return this.formatRuleNumber(passesRule.RuleValue);
209
234
  return '';
210
235
  },
211
236
  getDEBoutTimeOrPasses() {
212
- const rules = this.event.EventRules;
237
+ const rules = this.eventRules;
213
238
 
214
- const DETimeRule = rules.find(rule => rule.Rules.RuleName === 'DETime');
215
- const passesRule = rules.find(rule => rule.Rules.RuleName === 'DENumOfPasses');
239
+ const DETimeRule = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'DETime');
240
+ const passesRule = rules.find(rule => (rule.Rules?.RuleName ?? rule.RuleName) === 'DENumOfPasses');
216
241
 
217
242
  if (DETimeRule) return this.formatTime(DETimeRule.RuleValue);
218
- if (passesRule) return passesRule.RuleValue;
243
+ if (passesRule) return this.formatRuleNumber(passesRule.RuleValue);
219
244
  return '';
220
245
  }
221
246
  },
@@ -234,7 +259,14 @@ export default {
234
259
  handleSubmit() {
235
260
  this.$emit('delete', this.event);
236
261
  },
262
+ formatRuleNumber(value) {
263
+ if (value == null || value === '') return '';
264
+ const number = Number(value);
265
+ return Number.isFinite(number) && number >= 0 ? String(number) : 'Not set';
266
+ },
237
267
  formatTime(seconds) {
268
+ if (seconds == null || seconds === '' || !Number.isFinite(Number(seconds)) || Number(seconds) < 0)
269
+ return 'Not set';
238
270
  const minutes = Math.floor(seconds / 60);
239
271
  const remainingSeconds = seconds % 60;
240
272
  return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
@@ -57,7 +57,7 @@
57
57
  </div>
58
58
 
59
59
  <div class="hidden md:block mr-4">
60
- <div v-if="!portraitURL" class="w-14 h-14 r ounded-xl bg-dropdownSelect flex items-center justify-center">
60
+ <div v-if="!portraitURL" class="w-14 h-14 rounded-xl bg-dropdownSelect flex items-center justify-center">
61
61
  <BaseText text="" size="sm" color="neutral" weight="bold" />
62
62
  </div>
63
63
  <img v-if="portraitURL" :src="portraitURL" alt="Portrait" class="w-14 h-14 rounded-xl" />
@@ -7,11 +7,10 @@
7
7
  <BaseText :text="event.RuleSummary" size="" color="quinary" weight="normal" class="text-xs md:text-md" />
8
8
  <span class="hidden md:h-8"></span>
9
9
  </section>
10
- <section class="hidden md:flex flex-col">
11
- <div class="flex justify-center items-center">
12
- <BaseText text="Fencer Counts" size="sm" color="quinary" />
13
- </div>
14
- <div class="flex flex-row flex-nowrap">
10
+ <section class="flex flex-col items-start md:items-stretch">
11
+ <BaseText :text="fencerCountHeading" size="sm" color="quinary" class="hidden md:block text-center" />
12
+ <BaseText :text="registrationStatusLabel" size="xs" color="quaternary" class="md:hidden" />
13
+ <div class="hidden md:flex flex-row flex-nowrap">
15
14
  <EventStatusBox :status-count="absent" status-label="ABSENT" box-color="bg-eventBoxBlue" />
16
15
  <EventStatusBox :status-count="present" status-label="PRESENT" box-color="bg-eventBoxGreen" />
17
16
  <EventStatusBox
@@ -35,6 +34,7 @@
35
34
  import EventStatusBox from '../../../Molecules/Boxes/EventStatusBox/EventStatusBox.vue';
36
35
  import CounterBox from '../../../Molecules/Boxes/CounterBox/CounterBox.vue';
37
36
  import BaseText from '../../../Atoms/Text/BaseText.vue';
37
+ import { getRegistrationStatusLabel } from '../../../Util/registrationStatus.js';
38
38
 
39
39
  export default {
40
40
  name: 'AttendanceSummary',
@@ -69,6 +69,13 @@ export default {
69
69
  }
70
70
  },
71
71
  computed: {
72
+ registrationStatusLabel() {
73
+ return getRegistrationStatusLabel(this.event.RegistrationStatus ?? this.event.Status);
74
+ },
75
+ fencerCountHeading() {
76
+ if (!this.registrationStatusLabel) return 'Fencing Count';
77
+ return `Fencing Count - ${this.registrationStatusLabel}`;
78
+ },
72
79
  showRosterCounts() {
73
80
  return this.activeCount !== '' || this.waitlistCount !== '';
74
81
  },
@@ -46,3 +46,7 @@ export const InvalidPrice = {
46
46
  }
47
47
  }
48
48
  };
49
+
50
+ export const WaitlistDisabled = {
51
+ args: { ...Default.args, eventConfig: { ...eventConfig, CutOffNumber: 32, WaitlistEnabled: false } }
52
+ };