@dcrackel/hematournamentui 1.0.701 → 1.0.702

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.
@@ -1,7 +1,13 @@
1
1
  <template>
2
2
  <section>
3
3
  <EditEventsTopMenu :currentTab="'Checkin'" :tabs="tabs(role, isMobile)" @tabMenuClick="handleTabMenuClick"/>
4
- <AttendanceSummary :event="event" :absent="absent" :present="present"/>
4
+ <AttendanceSummary
5
+ :event="event"
6
+ :absent="absent"
7
+ :present="present"
8
+ :activeCount="activeRosterCount"
9
+ :waitlistCount="waitlistCount"
10
+ :capacity="eventCapacity"/>
5
11
  <div class="w-full flex flex-row justify-center mt-1 md:mt-3">
6
12
  <section class="w-full">
7
13
  <div class="w-full flex flex-col justify-center items-center" style="text-align: center">
@@ -30,20 +36,38 @@
30
36
  </div>
31
37
  </section>
32
38
  <section v-if="!loading" class="w-full">
33
- <div v-for="(person, index) in sortedPersons" :key="person.PersonId || person.Person?.PersonId || index">
39
+ <div v-if="activeRosterCount > 0" class="mb-2 flex items-center justify-between">
40
+ <BaseText text="Active Roster" size="md" color="quaternary" weight="bold"/>
41
+ <BaseText :text="activeRosterSummary" size="sm" color="quinary"/>
42
+ </div>
43
+ <div v-for="(person, index) in sortedActivePersons" :key="person.PersonId || person.Person?.PersonId || index">
34
44
  <FencerCard :person="person" class="mb-4"
35
- :isLast="index === sortedPersons.length - 1"
45
+ :isLast="index === sortedActivePersons.length - 1"
36
46
  :isEdit="event.Status === 'planning' || event.Status === 'preparation'"
37
- @forward:toProfile="handleForwardToProfile"
38
- @update:status="handleStatus"
47
+ @forward:toProfile="handleForwardToProfile"
48
+ @update:status="handleStatus"
39
49
  @remove:fencer="handleRemoveFencer"
40
50
  @update:moveUp="handleMoveUp"
41
51
  @update:moveDown="handleMoveDown"
42
52
  @request:weaver-sign="openWeaverModal"
43
53
  />
44
54
  </div>
55
+ <section v-if="waitlistCount > 0" class="mt-6 w-full">
56
+ <div class="mb-2 flex items-center justify-between">
57
+ <BaseText text="Waitlist" size="md" color="quaternary" weight="bold"/>
58
+ <BaseText :text="waitlistSummary" size="sm" color="quinary"/>
59
+ </div>
60
+ <div v-for="(person, index) in sortedWaitlistedPersons" :key="person.PersonId || person.Person?.PersonId || index" class="mb-3">
61
+ <WaitlistFencerCard
62
+ :person="person"
63
+ :queuePosition="index + 1"
64
+ @forward:toProfile="handleForwardToProfile"
65
+ @move:active="handleMoveWaitlistToActive"
66
+ @remove:fencer="handleRemoveWaitlistFencer"/>
67
+ </div>
68
+ </section>
45
69
  </section>
46
- <div v-if="!loading && personsInTournament.length === 0" class="mb-10">
70
+ <div v-if="!loading && personsInTournament.length === 0" class="mb-10">
47
71
  <div class="flex items-center border border-dropdownSelect rounded-lg shadow-lg bg-poolBox">
48
72
  <BaseText text="Remember to assign staff to your event!" size="lg" color="quaternary" weight="bold" class="w-full text-center py-2 px-8"/>
49
73
  </div>
@@ -74,7 +98,8 @@
74
98
  <script>
75
99
  import BaseText from "../../../Atoms/Text/BaseText.vue";
76
100
  import emptyDesertIcon from '../../../../assets/empty_desert_icon.png';
77
- import FencerCard from "../../../Organisms/Cards/FencerCard/FencerCard.vue";
101
+ import FencerCard from "../../../Organisms/Cards/FencerCard/FencerCard.vue";
102
+ import WaitlistFencerCard from "../../../Organisms/Cards/WaitlistFencerCard/WaitlistFencerCard.vue";
78
103
  import EditEventsTopMenu from "../../Menus/EditEventsTopMenu/EditEventsTopMenu.vue";
79
104
  import DropDownMenu from "../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue";
80
105
  import FindOrAddPerson from "../../../Organisms/ComplexInputs/FindOrAddPerson/FindOrAddPerson.vue";
@@ -98,10 +123,27 @@ const personSorters = {
98
123
  }
99
124
  };
100
125
 
126
+ const waitlistStatuses = new Set(['waitlist', 'waitlisted', 'waitinglist']);
127
+
128
+ const normalizeStatus = (status) => String(status || '').toLocaleLowerCase().replace(/[\s_-]/g, '');
129
+
130
+ const isWaitlistedPerson = (person) => waitlistStatuses.has(normalizeStatus(person?.Status));
131
+
132
+ const getEventRuleValue = (event, ruleName) => {
133
+ const rule = event?.EventRules?.find(eventRule => eventRule?.Rules?.RuleName === ruleName);
134
+ return rule?.RuleValue;
135
+ };
136
+
137
+ const getWaitlistOrderValue = (person) => {
138
+ const order = person?.WaitlistPosition ?? person?.WaitlistOrder ?? person?.CreatedAt ?? person?.Seed ?? person?.PoolPosition ?? 0;
139
+ return Number.isNaN(Number(order)) ? order : Number(order);
140
+ };
141
+
101
142
  export default {
102
- emits: ['add:existing-person', 'add:person', 'forward:toProfile', 'remove:fencer', 'tab:menu-click', 'update:moveDown', 'update:moveUp', 'update:person', 'weaver:sign'],
103
- components: {
104
- FencerCardSkeleton,
143
+ emits: ['add:existing-person', 'add:person', 'forward:toProfile', 'move:waitlist-to-active', 'remove:fencer', 'remove:waitlist-fencer', 'tab:menu-click', 'update:moveDown', 'update:moveUp', 'update:person', 'weaver:sign'],
144
+ components: {
145
+ WaitlistFencerCard,
146
+ FencerCardSkeleton,
105
147
  AttendanceSummary,
106
148
  FindOrAddPerson,
107
149
  DropDownMenu,
@@ -166,15 +208,28 @@ export default {
166
208
  isMobile() {
167
209
  return this.windowWidth <= 748;
168
210
  },
169
- sortedPersons() {
170
- if (!Array.isArray(this.personsInTournament) || this.personsInTournament.length === 0) {
171
- console.warn("personsInTournament is empty or not an array");
172
- return [];
173
- }
174
-
175
- let sortedArray = [...this.personsInTournament]; // Clone array to prevent modifying props
176
-
177
- sortedArray.sort((a, b) => {
211
+ activePersons() {
212
+ if (!Array.isArray(this.personsInTournament) || this.personsInTournament.length === 0) {
213
+ return [];
214
+ }
215
+
216
+ return this.personsInTournament.filter(person => !isWaitlistedPerson(person));
217
+ },
218
+ waitlistedPersons() {
219
+ if (!Array.isArray(this.personsInTournament) || this.personsInTournament.length === 0) {
220
+ return [];
221
+ }
222
+
223
+ return this.personsInTournament.filter(isWaitlistedPerson);
224
+ },
225
+ sortedActivePersons() {
226
+ if (this.activePersons.length === 0) {
227
+ return [];
228
+ }
229
+
230
+ let sortedArray = [...this.activePersons]; // Clone array to prevent modifying props
231
+
232
+ sortedArray.sort((a, b) => {
178
233
  if (!a || !b || !a.Person || !b.Person) {
179
234
  console.warn("Undefined person object detected:", a, b);
180
235
  return 0;
@@ -186,14 +241,50 @@ export default {
186
241
  console.warn("Unknown sorting key:", this.localSelectedItem.link);
187
242
  return 0;
188
243
  });
189
- return sortedArray;
190
- },
191
- absent() {
192
- return this.personsInTournament.filter(person => person.Status === 'Absent').length;
193
- },
194
- present() {
195
- return this.personsInTournament.filter(person => person.Status === 'Present').length;
196
- },
244
+ return sortedArray;
245
+ },
246
+ sortedWaitlistedPersons() {
247
+ return [...this.waitlistedPersons].sort((a, b) => {
248
+ const orderA = getWaitlistOrderValue(a);
249
+ const orderB = getWaitlistOrderValue(b);
250
+
251
+ if (typeof orderA === 'number' && typeof orderB === 'number') {
252
+ return orderA - orderB;
253
+ }
254
+
255
+ return String(orderA).localeCompare(String(orderB));
256
+ });
257
+ },
258
+ activeRosterCount() {
259
+ return this.activePersons.length;
260
+ },
261
+ waitlistCount() {
262
+ return this.waitlistedPersons.length;
263
+ },
264
+ eventCapacity() {
265
+ const capacity = this.event?.CutOffNumber ?? this.event?.MaxFencers ?? getEventRuleValue(this.event, 'CutOffNumber');
266
+ if (capacity === 0 || capacity === '0') {
267
+ return 'Unlimited';
268
+ }
269
+
270
+ return capacity || '';
271
+ },
272
+ activeRosterSummary() {
273
+ if (!this.eventCapacity) {
274
+ return `${this.activeRosterCount} active`;
275
+ }
276
+
277
+ return `${this.activeRosterCount} / ${this.eventCapacity}`;
278
+ },
279
+ waitlistSummary() {
280
+ return `${this.waitlistCount} waiting`;
281
+ },
282
+ absent() {
283
+ return this.activePersons.filter(person => person.Status === 'Absent').length;
284
+ },
285
+ present() {
286
+ return this.activePersons.filter(person => person.Status === 'Present').length;
287
+ },
197
288
  },
198
289
  methods: {
199
290
  openWeaverModal(person) {
@@ -226,6 +317,12 @@ export default {
226
317
  handleRemoveFencer(value) {
227
318
  this.$emit('remove:fencer', value);
228
319
  },
320
+ handleMoveWaitlistToActive(person) {
321
+ this.$emit('move:waitlist-to-active', person);
322
+ },
323
+ handleRemoveWaitlistFencer(person) {
324
+ this.$emit('remove:waitlist-fencer', person);
325
+ },
229
326
  handleMoveUp(person){
230
327
  this.$emit('update:moveUp', person);
231
328
  },
@@ -5,9 +5,10 @@
5
5
  :displays="localDisplays"
6
6
  :eventDropDown="eventDropDown"
7
7
  :staffDropDown="staffDropDown"
8
- :userRole="role"
9
- @remove:kiosk="handleRemove"
10
- @update:ringChange="handleRingChange"
8
+ :userRole="role"
9
+ @remove:kiosk="handleRemove"
10
+ @test:scoreboard="handleScoreboardTest"
11
+ @update:ringChange="handleRingChange"
11
12
  @update:selectedStaff="handleAssignmentStaff"
12
13
  @update:selectedEvent="handleAssignmentEvent"
13
14
  @update:selectedType="handleSelectedType"
@@ -30,7 +31,7 @@ export default {
30
31
  EditEventsTopMenu
31
32
 
32
33
  },
33
- emits: ['remove:kiosk', 'update:selectedStaff', 'update:selectedEvent', 'update:selectedType', 'update:ringChange', 'submit:kiosk', 'update:assignToMe','tab:menu-click'],
34
+ emits: ['remove:kiosk', 'test:scoreboard', 'update:selectedStaff', 'update:selectedEvent', 'update:selectedType', 'update:ringChange', 'submit:kiosk', 'update:assignToMe','tab:menu-click'],
34
35
  props: {
35
36
  displays: {
36
37
  type: Array,
@@ -75,8 +76,11 @@ export default {
75
76
  return this.windowWidth <= 748;
76
77
  },
77
78
  },
78
- methods: {
79
- handleTabMenuClick(value) {
79
+ methods: {
80
+ handleScoreboardTest(display) {
81
+ this.$emit('test:scoreboard', display);
82
+ },
83
+ handleTabMenuClick(value) {
80
84
  this.$emit('tab:menu-click', value);
81
85
  },
82
86
  handleRingChange(item){