@dcrackel/hematournamentui 1.0.707 → 1.0.708

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 (46) hide show
  1. package/AGENTS.md +118 -118
  2. package/dist/HemaTournamentUI-lib.es.js +4483 -4618
  3. package/dist/HemaTournamentUI-lib.umd.js +27 -27
  4. package/dist/hematournamentui-tailwind.css +185 -406
  5. package/package.json +10 -10
  6. package/src/index.js +2 -0
  7. package/src/mocks/getDEBouts-42Fencers.js +4 -4
  8. package/src/mocks/getDEBouts-TableOf128.js +37 -0
  9. package/src/mocks/getDEBouts-TableOf64.js +35 -0
  10. package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.stories.js +23 -0
  11. package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.vue +35 -0
  12. package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.test.js +18 -0
  13. package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.vue +3 -2
  14. package/src/stories/Molecules/Modals/EditBoutModal/EditBoutModal.vue +1 -1
  15. package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.stories.js +33 -0
  16. package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.test.js +45 -0
  17. package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.vue +103 -0
  18. package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +298 -278
  19. package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.stories.js +60 -98
  20. package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.test.js +103 -4
  21. package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.vue +256 -215
  22. package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.stories.js +69 -92
  23. package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.vue +80 -128
  24. package/src/stories/Organisms/Cards/WaitlistFencerCard/WaitlistFencerCard.vue +14 -4
  25. package/src/stories/Organisms/Containers/Tableau/Tableau.stories.js +2 -2
  26. package/src/stories/Organisms/Containers/Tableau/Tableau.test.js +131 -3
  27. package/src/stories/Organisms/Containers/Tableau/Tableau.vue +287 -89
  28. package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.test.js +29 -0
  29. package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.vue +46 -0
  30. package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.test.js +21 -0
  31. package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.vue +39 -0
  32. package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.js +145 -0
  33. package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.test.js +64 -0
  34. package/src/stories/Organisms/Containers/Tableau/plannedAssignments.js +57 -0
  35. package/src/stories/Organisms/Containers/Tableau/plannedAssignments.test.js +65 -0
  36. package/src/stories/Organisms/Containers/TableauColumn/TableauColumn.vue +31 -29
  37. package/src/stories/Templates/EventManagement/Bracket/Bracket.stories.js +146 -18
  38. package/src/stories/Templates/EventManagement/Bracket/Bracket.test.js +52 -2
  39. package/src/stories/Templates/EventManagement/Bracket/Bracket.vue +53 -17
  40. package/src/stories/Templates/EventManagement/Bracket/BracketPlannedSuggestions.js +39 -0
  41. package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.js +39 -0
  42. package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.test.js +79 -0
  43. package/src/stories/Organisms/Cards/TableauBoutCard/SpacingConfig.js +0 -111
  44. package/src/stories/Organisms/Containers/TableauLines/SpacingConfig.js +0 -162
  45. package/src/stories/Organisms/Containers/TableauLines/TableauLines.stories.js +0 -21
  46. package/src/stories/Organisms/Containers/TableauLines/TableauLines.vue +0 -78
@@ -1,215 +1,256 @@
1
- <template>
2
- <section :class="getTopSpace">
3
- <div
4
- v-if="roundName === 'Third Place'"
5
- class="flex justify-center border-b mb-4 mt-8"
6
- :class="large ? 'w-72' : 'w-40'"
7
- >
8
- <BaseText :text="roundName" size="sm" color="quaternary" />
9
- </div>
10
- <div v-if="roundName === 'Final'" class="flex justify-center border-b mb-4 mt-0" :class="large ? 'w-72' : 'w-40'">
11
- <BaseText :text="roundName" size="sm" color="quaternary" />
12
- </div>
13
- <div v-if="showGrandFinal" class="flex justify-center border-b mb-4 mt-0" :class="large ? 'w-72' : 'w-40'">
14
- <BaseText :text="roundName" size="sm" color="quaternary" />
15
- </div>
16
- <!-- Replacement headers for finals -->
17
- <div v-if="roundName !== 'Grand Final' || showGrandFinal">
18
- <section @click="handleBoutClick(bout)">
19
- <TableauFencerCard
20
- :fencer="person1Display"
21
- :score="score1"
22
- :position="dePosition1"
23
- :color="hostingClubColors.Color1"
24
- :scoreColor="getScoreColor(true)"
25
- :large="large"
26
- :highLight="highlight"
27
- :isCountingBackwardsMaxScore="isCountingBackwardsMaxScore"
28
- :faded="shouldFade(bout, true)"
29
- @action:highLight="handleHighlight"
30
- />
31
- </section>
32
- <!-- Card break -->
33
- <div :class="getCardSpace"></div>
34
- <!-- Card break -->
35
- <section @click="handleBoutClick(bout)">
36
- <TableauFencerCard
37
- :fencer="person2Display"
38
- :score="score2"
39
- :position="dePosition2"
40
- :color="hostingClubColors.Color2"
41
- :scoreColor="getScoreColor(false)"
42
- :large="large"
43
- :highLight="highlight"
44
- :isCountingBackwardsMaxScore="isCountingBackwardsMaxScore"
45
- :faded="shouldFade(bout, false)"
46
- @action:highLight="handleHighlight"
47
- />
48
- </section>
49
- </div>
50
- </section>
51
- </template>
52
-
53
- <script>
54
- import BaseText from '../../../Atoms/Text/BaseText.vue';
55
- import TableauFencerCard from '../TableauFencerCard/TableauFencerCard.vue';
56
- import { spacingConfig } from './SpacingConfig';
57
-
58
- const scoreColorRulesByFencer = {
59
- true: [
60
- {
61
- matches: bout => bout.Person1.DisplayName !== 'BYE' && bout.Person2.DisplayName === 'BYE',
62
- color: 'bg-winGreen'
63
- },
64
- { matches: bout => bout.Score1 > bout.Score2, color: 'bg-winGreen' },
65
- {
66
- matches: bout => bout.Score1 < bout.Score2 && bout.Status === 'Active',
67
- color: 'bg-lossRed'
68
- }
69
- ],
70
- false: [
71
- {
72
- matches: bout => bout.Person2.DisplayName !== 'BYE' && bout.Person1.DisplayName === 'BYE',
73
- color: 'bg-winGreen'
74
- },
75
- { matches: bout => bout.Score2 > bout.Score1, color: 'bg-winGreen' },
76
- {
77
- matches: bout => bout.Score2 < bout.Score1 && bout.Status === 'Active',
78
- color: 'bg-lossRed'
79
- }
80
- ]
81
- };
82
-
83
- const getMatchingScoreColor = (bout, isPerson1) => {
84
- const matchingRule = scoreColorRulesByFencer[String(isPerson1)].find(rule => rule.matches(bout));
85
- return matchingRule?.color || 'bg-dropdownSelect';
86
- };
87
-
88
- export default {
89
- name: 'TableauBoutCard',
90
- emits: ['action:directingBout', 'action:editBout'],
91
- components: { BaseText, TableauFencerCard },
92
- props: {
93
- bout: {
94
- type: Object,
95
- required: true
96
- },
97
- hostingClubColors: {
98
- type: Object,
99
- required: true
100
- },
101
- large: {
102
- type: Boolean,
103
- default: true
104
- },
105
- roundName: {
106
- type: String,
107
- required: true
108
- },
109
- bracketSize: {
110
- type: String,
111
- required: true
112
- },
113
- isCountingBackwardsMaxScore: {
114
- type: Number,
115
- default: 0
116
- }
117
- },
118
- data() {
119
- return {
120
- highlight: false,
121
- currentConfig: {}
122
- };
123
- },
124
- mounted() {
125
- this.updateConfig();
126
- },
127
- watch: {
128
- large(newVal, oldVal) {
129
- if (newVal !== oldVal) {
130
- this.updateConfig();
131
- }
132
- },
133
- bracketSize(newVal, oldVal) {
134
- if (newVal !== oldVal) {
135
- this.updateConfig();
136
- }
137
- }
138
- },
139
- methods: {
140
- updateConfig() {
141
- const size = this.large ? 'large' : 'small';
142
- this.currentConfig = spacingConfig[this.bracketSize]?.[size]?.[this.roundName] || {};
143
- },
144
- handleBoutClick(bout) {
145
- if (bout.Status === 'Completed') {
146
- this.$emit('action:editBout', bout);
147
- return;
148
- }
149
- this.$emit('action:directingBout', bout);
150
- },
151
- getScoreColor(isPerson1) {
152
- return getMatchingScoreColor(this.bout, isPerson1);
153
- },
154
- handleHighlight(value) {
155
- if (this.bout.Person1.DisplayName.length < 1 || this.bout.Person2.DisplayName.length < 1) return;
156
- if (this.bout.Person1.DisplayName === 'BYE' || this.bout.Person2.DisplayName === 'BYE') return;
157
- this.highlight = value;
158
- },
159
- shouldFade(bout, person1) {
160
- if (this.bout.Person1.DisplayName === 'BYE' && this.bout.Person2.DisplayName === 'BYE') return false;
161
-
162
- if (person1) {
163
- if (bout.Person1.DisplayName === 'BYE') return true;
164
- if (parseInt(bout.Score1) < parseInt(bout.Score2)) return true;
165
- }
166
-
167
- if (!person1) {
168
- if (bout.Person2.DisplayName === 'BYE') return true;
169
- if (parseInt(bout.Score2) < parseInt(bout.Score1)) return true;
170
- }
171
-
172
- return false;
173
- }
174
- },
175
- computed: {
176
- dePosition1() {
177
- return this.bout.Person1?.EventPersons?.[0]?.DEPosition ?? '';
178
- },
179
- score1() {
180
- return `${this.bout.Score1}`;
181
- },
182
- dePosition2() {
183
- return this.bout.Person2?.EventPersons?.[0]?.DEPosition ?? '';
184
- },
185
- score2() {
186
- return `${this.bout.Score2}`;
187
- },
188
- getTopSpace() {
189
- return this.currentConfig?.getTopSpace || '';
190
- },
191
- getCardSpace() {
192
- return this.currentConfig?.getCardSpace || '';
193
- },
194
- person1Display() {
195
- if (this.bout.Status === 'Scheduled' && this.bout.Person1.DisplayName === 'BYE') {
196
- return { ...this.bout.Person1, DisplayName: '', Club: { Name: '' } };
197
- }
198
- return this.bout.Person1;
199
- },
200
- person2Display() {
201
- if (this.bout.Status === 'Scheduled' && this.bout.Person2.DisplayName === 'BYE') {
202
- return { ...this.bout.Person2, DisplayName: '', Club: { Name: '' } };
203
- }
204
- return this.bout.Person2;
205
- },
206
- showGrandFinal() {
207
- return (
208
- this.roundName === 'Grand Final' &&
209
- this.bout.Person1.DisplayName !== 'BYE' &&
210
- this.bout.Person2.DisplayName !== 'BYE'
211
- );
212
- }
213
- }
214
- };
215
- </script>
1
+ <template>
2
+ <section v-if="showBout" class="relative w-40">
3
+ <div
4
+ v-if="showRingLabel"
5
+ data-testid="active-ring"
6
+ class="pointer-events-none absolute -top-4 left-0 z-20 flex h-4 w-40 items-center rounded-t bg-primary px-2"
7
+ >
8
+ <BaseText :text="ringName" size="xs" color="neutral" weight="bold" class="truncate uppercase" />
9
+ </div>
10
+
11
+ <div class="relative w-40 text-left" :class="{ 'opacity-70': !isSelectable }">
12
+ <TableauFencerCard
13
+ :fencer="person1Display"
14
+ :score="score1"
15
+ :position="dePosition1"
16
+ :color="hostingClubColors.Color1"
17
+ :scoreColor="getScoreColor('person1')"
18
+ :showScore="showScore1"
19
+ :isCountingBackwardsMaxScore="isCountingBackwardsMaxScore"
20
+ corners="top"
21
+ />
22
+
23
+ <div class="relative h-px bg-dropdownSelect">
24
+ <span
25
+ :ref="element => registerAnchor('input', element)"
26
+ class="pointer-events-none absolute left-0 top-1/2 h-px w-px -translate-y-1/2 opacity-0"
27
+ ></span>
28
+ <span
29
+ :ref="element => registerAnchor('output', element)"
30
+ class="pointer-events-none absolute right-0 top-1/2 h-px w-px -translate-y-1/2 opacity-0"
31
+ ></span>
32
+ </div>
33
+
34
+ <TableauFencerCard
35
+ :fencer="person2Display"
36
+ :score="score2"
37
+ :position="dePosition2"
38
+ :color="hostingClubColors.Color2"
39
+ :scoreColor="getScoreColor('person2')"
40
+ :showScore="showScore2"
41
+ :isCountingBackwardsMaxScore="isCountingBackwardsMaxScore"
42
+ corners="bottom"
43
+ />
44
+ <button
45
+ type="button"
46
+ data-testid="tableau-bout"
47
+ class="absolute inset-0 z-10 w-40 rounded text-left shadow-md outline-none ring-1 ring-transparent transition hover:shadow-lg hover:ring-2 hover:ring-bright focus-visible:ring-2 focus-visible:ring-bright disabled:cursor-default"
48
+ :disabled="!isSelectable"
49
+ :aria-label="boutLabel"
50
+ @click="handleBoutClick"
51
+ ></button>
52
+ </div>
53
+
54
+ <div
55
+ v-if="showActiveChrome"
56
+ data-testid="active-time"
57
+ class="pointer-events-none absolute left-full top-1/2 z-20 flex h-[57px] w-10 -translate-y-1/2 items-center justify-center rounded-r-md bg-primary px-1"
58
+ >
59
+ <BaseText :text="displayTime" size="xs" color="neutral" weight="bold" class="font-sourceCodePro" />
60
+ </div>
61
+ </section>
62
+ </template>
63
+
64
+ <script>
65
+ import BaseText from '../../../Atoms/Text/BaseText.vue';
66
+ import TableauFencerCard from '../TableauFencerCard/TableauFencerCard.vue';
67
+
68
+ const EMPTY_FENCER = { DisplayName: '', Club: { Name: '' }, EventPersons: [] };
69
+
70
+ const getFencerName = fencer => String(fencer?.DisplayName || '');
71
+ const isByeName = fencer => getFencerName(fencer).toUpperCase() === 'BYE';
72
+ const isMissingFencer = fencer => !fencer?.PersonId || Number(fencer.PersonId) === 0;
73
+ const isUnavailableFencer = fencer => isMissingFencer(fencer) || isByeName(fencer);
74
+ const isCompletedBout = bout => String(bout?.Status || '').toLowerCase() === 'completed';
75
+ const getNumericScore = score => Number(score ?? 0);
76
+ const normalizeSeconds = value => Math.max(0, Number(value) || 0);
77
+ const formatSeconds = value => {
78
+ const seconds = normalizeSeconds(value);
79
+ return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, '0')}`;
80
+ };
81
+ const isRunningActiveBout = bout =>
82
+ String(bout?.Status || '').toLowerCase() === 'active' && String(bout?.TimerStatus || '').toLowerCase() === 'running';
83
+
84
+ const scoreColorRules = {
85
+ person1: [
86
+ { matches: bout => !isByeName(bout.Person1) && isByeName(bout.Person2), color: 'bg-winGreen' },
87
+ { matches: bout => getNumericScore(bout.Score1) > getNumericScore(bout.Score2), color: 'bg-winGreen' },
88
+ {
89
+ matches: bout =>
90
+ getNumericScore(bout.Score1) < getNumericScore(bout.Score2) && String(bout.Status).toLowerCase() === 'active',
91
+ color: 'bg-lossRed'
92
+ }
93
+ ],
94
+ person2: [
95
+ { matches: bout => !isByeName(bout.Person2) && isByeName(bout.Person1), color: 'bg-winGreen' },
96
+ { matches: bout => getNumericScore(bout.Score2) > getNumericScore(bout.Score1), color: 'bg-winGreen' },
97
+ {
98
+ matches: bout =>
99
+ getNumericScore(bout.Score2) < getNumericScore(bout.Score1) && String(bout.Status).toLowerCase() === 'active',
100
+ color: 'bg-lossRed'
101
+ }
102
+ ]
103
+ };
104
+
105
+ const getMatchingScoreColor = (bout, fencerKey) =>
106
+ scoreColorRules[fencerKey].find(rule => rule.matches(bout))?.color || 'bg-dropdownSelect';
107
+
108
+ const getDisplayFencer = (bout, fencer) => {
109
+ if (!fencer) return EMPTY_FENCER;
110
+ if (String(bout.Status).toLowerCase() !== 'scheduled' || !isByeName(fencer)) return fencer;
111
+ return { ...fencer, DisplayName: '', Club: { Name: '' } };
112
+ };
113
+
114
+ export default {
115
+ name: 'TableauBoutCard',
116
+ components: { BaseText, TableauFencerCard },
117
+ emits: ['action:directingBout', 'action:editBout', 'register-node-anchor'],
118
+ props: {
119
+ bout: {
120
+ type: Object,
121
+ required: true
122
+ },
123
+ hostingClubColors: {
124
+ type: Object,
125
+ required: true
126
+ },
127
+ roundName: {
128
+ type: String,
129
+ required: true
130
+ },
131
+ bracketSize: {
132
+ type: String,
133
+ required: true
134
+ },
135
+ isCountingBackwardsMaxScore: {
136
+ type: Number,
137
+ default: 0
138
+ }
139
+ },
140
+ data() {
141
+ return {
142
+ remainingTime: normalizeSeconds(this.bout.TimeLeft),
143
+ timerInterval: null
144
+ };
145
+ },
146
+ computed: {
147
+ boutNodeId() {
148
+ return this.bout.DEBoutId ?? this.bout.BoutId;
149
+ },
150
+ boutLabel() {
151
+ return `${this.person1Display.DisplayName || 'Unassigned'} versus ${
152
+ this.person2Display.DisplayName || 'Unassigned'
153
+ }`;
154
+ },
155
+ dePosition1() {
156
+ return this.bout.Person1?.EventPersons?.[0]?.DEPosition ?? '';
157
+ },
158
+ dePosition2() {
159
+ return this.bout.Person2?.EventPersons?.[0]?.DEPosition ?? '';
160
+ },
161
+ displayTime() {
162
+ return formatSeconds(this.remainingTime);
163
+ },
164
+ isActiveBout() {
165
+ return String(this.bout.Status || '').toLowerCase() === 'active';
166
+ },
167
+ isDirectable() {
168
+ return !isUnavailableFencer(this.bout.Person1) && !isUnavailableFencer(this.bout.Person2);
169
+ },
170
+ isSelectable() {
171
+ return isCompletedBout(this.bout) || this.isDirectable;
172
+ },
173
+ person1Display() {
174
+ return getDisplayFencer(this.bout, this.bout.Person1);
175
+ },
176
+ person2Display() {
177
+ return getDisplayFencer(this.bout, this.bout.Person2);
178
+ },
179
+ ringName() {
180
+ return String(this.bout.RingName || '');
181
+ },
182
+ score1() {
183
+ return String(this.bout.Score1 ?? 0);
184
+ },
185
+ score2() {
186
+ return String(this.bout.Score2 ?? 0);
187
+ },
188
+ showBout() {
189
+ if (this.roundName !== 'Grand Final') return true;
190
+ return !isUnavailableFencer(this.bout.Person1) && !isUnavailableFencer(this.bout.Person2);
191
+ },
192
+ showActiveChrome() {
193
+ return this.isActiveBout && (this.ringName.length > 0 || this.remainingTime > 0 || this.shouldTickTimer);
194
+ },
195
+ showScore1() {
196
+ return !isUnavailableFencer(this.bout.Person1);
197
+ },
198
+ showScore2() {
199
+ return !isUnavailableFencer(this.bout.Person2);
200
+ },
201
+ showRingLabel() {
202
+ return this.isActiveBout && this.ringName.length > 0;
203
+ },
204
+ shouldTickTimer() {
205
+ return isRunningActiveBout(this.bout) && this.remainingTime > 0;
206
+ }
207
+ },
208
+ watch: {
209
+ 'bout.TimeLeft'(value) {
210
+ this.remainingTime = normalizeSeconds(value);
211
+ this.restartTimer();
212
+ },
213
+ 'bout.TimerStatus'() {
214
+ this.restartTimer();
215
+ },
216
+ 'bout.Status'() {
217
+ this.restartTimer();
218
+ }
219
+ },
220
+ mounted() {
221
+ this.restartTimer();
222
+ },
223
+ beforeUnmount() {
224
+ this.stopTimer();
225
+ },
226
+ methods: {
227
+ getScoreColor(fencerKey) {
228
+ return getMatchingScoreColor(this.bout, fencerKey);
229
+ },
230
+ handleBoutClick() {
231
+ if (isCompletedBout(this.bout)) {
232
+ this.$emit('action:editBout', this.bout);
233
+ return;
234
+ }
235
+ if (this.isDirectable) this.$emit('action:directingBout', this.bout);
236
+ },
237
+ restartTimer() {
238
+ this.stopTimer();
239
+ if (!this.shouldTickTimer) return;
240
+ this.timerInterval = setInterval(this.tickTimer, 1000);
241
+ },
242
+ registerAnchor(kind, element) {
243
+ if (this.boutNodeId === null || this.boutNodeId === undefined) return;
244
+ this.$emit('register-node-anchor', { id: this.boutNodeId, kind, el: element });
245
+ },
246
+ stopTimer() {
247
+ if (this.timerInterval) clearInterval(this.timerInterval);
248
+ this.timerInterval = null;
249
+ },
250
+ tickTimer() {
251
+ this.remainingTime = Math.max(0, this.remainingTime - 1);
252
+ if (this.remainingTime === 0) this.stopTimer();
253
+ }
254
+ }
255
+ };
256
+ </script>
@@ -1,92 +1,69 @@
1
- import TableauFencerCard from './TableauFencerCard.vue';
2
-
3
- export default {
4
- title: 'Organisms/Cards/TableauFencerCard',
5
- component: TableauFencerCard,
6
- args: {
7
- fencer: {
8
- DisplayName: 'John Doe',
9
- Club: {
10
- Name: 'Fencing Club'
11
- },
12
- Images: [
13
- {
14
- URL: 'https://randomuser.me/api/portraits/men/91.jpg'
15
- }
16
- ]
17
- },
18
- score: '15',
19
- position: '1',
20
- color: 'blue',
21
- scoreColor: 'bg-winGreen',
22
- large: true
23
- },
24
- argTypes: {
25
- fencer: {
26
- control: 'object',
27
- description: 'Object containing fencer details including name, club, and images'
28
- },
29
- score: {
30
- control: 'text',
31
- description: 'Score of the fencer'
32
- },
33
- position: {
34
- control: 'text',
35
- description: 'Position of the fencer in the bracket'
36
- },
37
- color: {
38
- control: 'color',
39
- description: 'Color for the position background'
40
- },
41
- scoreColor: {
42
- control: 'color',
43
- description: 'Color for the score background'
44
- },
45
- large: {
46
- control: 'boolean',
47
- description: 'Boolean to determine the size of the card'
48
- }
49
- }
50
- };
51
-
52
- export const Default = {
53
- args: {
54
- fencer: {
55
- DisplayName: 'John Doe',
56
- Club: {
57
- Name: 'Fencing Club'
58
- },
59
- Images: [
60
- {
61
- URL: 'https://randomuser.me/api/portraits/men/50.jpg'
62
- }
63
- ]
64
- },
65
- score: '15',
66
- position: '1',
67
- color: 'blue',
68
- scoreColor: 'bg-winGreen',
69
- large: true
70
- }
71
- };
72
-
73
- export const Small = {
74
- args: {
75
- fencer: {
76
- DisplayName: 'Jane Doe',
77
- Club: {
78
- Name: 'Fencing Club'
79
- },
80
- Images: [
81
- {
82
- URL: 'https://via.placeholder.com/40'
83
- }
84
- ]
85
- },
86
- score: '12',
87
- position: '2',
88
- color: 'red',
89
- scoreColor: 'bg-lossRed',
90
- large: false
91
- }
92
- };
1
+ import TableauFencerCard from './TableauFencerCard.vue';
2
+
3
+ export default {
4
+ title: 'Organisms/Cards/TableauFencerCard',
5
+ component: TableauFencerCard,
6
+ tags: ['autodocs'],
7
+ args: {
8
+ fencer: { DisplayName: 'John Doe' },
9
+ score: '15',
10
+ position: '1',
11
+ color: 'blue',
12
+ scoreColor: 'bg-winGreen',
13
+ showScore: true,
14
+ corners: 'top'
15
+ },
16
+ argTypes: {
17
+ fencer: {
18
+ control: 'object',
19
+ description: 'Fencer displayed in the bracket row'
20
+ },
21
+ score: {
22
+ control: 'text',
23
+ description: 'Displayed bout score'
24
+ },
25
+ position: {
26
+ control: 'text',
27
+ description: 'Seed or direct-elimination position'
28
+ },
29
+ color: {
30
+ control: 'text',
31
+ description: 'Tailwind theme color used for the seed strip'
32
+ },
33
+ scoreColor: {
34
+ control: 'text',
35
+ description: 'Tailwind background class used for the score cell'
36
+ },
37
+ showScore: {
38
+ control: 'boolean',
39
+ description: 'Whether the score cell displays a value'
40
+ },
41
+ corners: {
42
+ control: 'select',
43
+ options: ['none', 'top', 'bottom'],
44
+ description: 'Rounds the outside corners when used as the top or bottom bout row'
45
+ }
46
+ }
47
+ };
48
+
49
+ export const Default = {};
50
+
51
+ export const LosingScore = {
52
+ args: {
53
+ fencer: { DisplayName: 'Jane Doe' },
54
+ score: '12',
55
+ position: '2',
56
+ color: 'red',
57
+ scoreColor: 'bg-lossRed',
58
+ corners: 'bottom'
59
+ }
60
+ };
61
+
62
+ export const PendingFencer = {
63
+ args: {
64
+ fencer: { DisplayName: '' },
65
+ score: '0',
66
+ position: '',
67
+ showScore: false
68
+ }
69
+ };