@dcrackel/hematournamentui 1.0.707 → 1.0.709
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/AGENTS.md +118 -118
- package/README.md +132 -106
- package/dist/HemaTournamentUI-lib.es.js +7111 -7006
- package/dist/HemaTournamentUI-lib.umd.js +27 -27
- package/dist/hematournamentui-tailwind.css +198 -412
- package/package.json +10 -10
- package/src/index.js +2 -0
- package/src/mocks/getDEBouts-42Fencers.js +4 -4
- package/src/mocks/getDEBouts-TableOf128.js +37 -0
- package/src/mocks/getDEBouts-TableOf64.js +35 -0
- package/src/stories/Atoms/Input/BaseInput.test.js +97 -85
- package/src/stories/Atoms/Input/BaseInput.vue +149 -150
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.stories.js +23 -0
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.vue +35 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.test.js +18 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.vue +3 -2
- package/src/stories/Molecules/Modals/EditBoutModal/EditBoutModal.vue +1 -1
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.stories.js +33 -0
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.test.js +45 -0
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.vue +103 -0
- package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +298 -278
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.stories.js +60 -98
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.test.js +103 -4
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.vue +256 -215
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.stories.js +69 -92
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.vue +80 -128
- package/src/stories/Organisms/Cards/WaitlistFencerCard/WaitlistFencerCard.vue +14 -4
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +31 -20
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.test.js +109 -0
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.vue +192 -133
- package/src/stories/Organisms/Containers/Tableau/Tableau.stories.js +2 -2
- package/src/stories/Organisms/Containers/Tableau/Tableau.test.js +131 -3
- package/src/stories/Organisms/Containers/Tableau/Tableau.vue +287 -89
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.test.js +29 -0
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.vue +46 -0
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.test.js +21 -0
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.vue +39 -0
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.js +145 -0
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.test.js +64 -0
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.js +57 -0
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.test.js +65 -0
- package/src/stories/Organisms/Containers/TableauColumn/TableauColumn.vue +31 -29
- package/src/stories/Templates/EventManagement/Bracket/Bracket.stories.js +146 -18
- package/src/stories/Templates/EventManagement/Bracket/Bracket.test.js +52 -2
- package/src/stories/Templates/EventManagement/Bracket/Bracket.vue +53 -17
- package/src/stories/Templates/EventManagement/Bracket/BracketPlannedSuggestions.js +39 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.js +39 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.test.js +79 -0
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.stories.js +14 -0
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.test.js +39 -0
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.vue +13 -3
- package/src/stories/Templates/PersonManagement/Basic/BasicEdit.vue +170 -172
- package/src/stories/Templates/PersonManagement/PersonManagement.stories.js +156 -103
- package/src/stories/Templates/PersonManagement/PersonManagement.test.js +329 -0
- package/src/stories/Templates/PersonManagement/PersonManagement.vue +329 -213
- package/src/stories/Templates/PersonManagement/PersonManagementDraft.js +42 -0
- package/src/stories/Util/Validations/PersonManagementValidations.js +45 -29
- package/src/stories/Organisms/Cards/TableauBoutCard/SpacingConfig.js +0 -111
- package/src/stories/Organisms/Containers/TableauLines/SpacingConfig.js +0 -162
- package/src/stories/Organisms/Containers/TableauLines/TableauLines.stories.js +0 -21
- package/src/stories/Organisms/Containers/TableauLines/TableauLines.vue +0 -78
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import MissingHemaRatingsId from './MissingHemaRatingsId.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Molecules/Indicators/MissingHemaRatingsId',
|
|
5
|
+
component: MissingHemaRatingsId,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
args: { person: { HemaRatingsId: null } },
|
|
8
|
+
argTypes: {
|
|
9
|
+
person: { control: 'object' }
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const MissingId = {
|
|
14
|
+
args: { person: { HemaRatingsId: null } }
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const UnratedWithId = {
|
|
18
|
+
args: { person: { HemaRatingsId: 10255, HEMARatings: [] } }
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const IdFromRating = {
|
|
22
|
+
args: { person: { HEMARatings: [{ HemaRatingId: 10255, Rating: 1708.8 }] } }
|
|
23
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span
|
|
3
|
+
v-if="!hasHemaRatingsId"
|
|
4
|
+
role="img"
|
|
5
|
+
aria-label="Missing HEMA Ratings ID"
|
|
6
|
+
title="Missing HEMA Ratings ID"
|
|
7
|
+
data-testid="missing-hema-ratings-id"
|
|
8
|
+
class="inline-flex shrink-0 items-center justify-center text-alarm"
|
|
9
|
+
>
|
|
10
|
+
<svg class="h-6 w-6 md:h-7 md:w-7" viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
|
11
|
+
<circle cx="16" cy="16" r="13" stroke="currentColor" stroke-width="2" />
|
|
12
|
+
<text x="16" y="20" text-anchor="middle" fill="currentColor" class="font-bold" font-size="11">HR</text>
|
|
13
|
+
<path d="M7 25 25 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
14
|
+
</svg>
|
|
15
|
+
</span>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script>
|
|
19
|
+
export default {
|
|
20
|
+
name: 'MissingHemaRatingsId',
|
|
21
|
+
props: {
|
|
22
|
+
person: {
|
|
23
|
+
type: Object,
|
|
24
|
+
default: null
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
computed: {
|
|
28
|
+
hasHemaRatingsId() {
|
|
29
|
+
const id = this.person?.HemaRatingsId ?? this.person?.HEMARatings?.[0]?.HemaRatingId;
|
|
30
|
+
const numericId = Number(id);
|
|
31
|
+
return Number.isInteger(numericId) && numericId > 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import DirectorModal from './DirectorModal.vue';
|
|
4
|
+
|
|
5
|
+
describe('DirectorModal backdrop', () => {
|
|
6
|
+
it('keeps the directing screen visible through a 25 percent backdrop', () => {
|
|
7
|
+
const wrapper = shallowMount(DirectorModal, {
|
|
8
|
+
props: {
|
|
9
|
+
show: true,
|
|
10
|
+
bout: { BoutId: 42 },
|
|
11
|
+
eventRules: {},
|
|
12
|
+
hostingClubColors: {}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(wrapper.find('[data-testid="director-modal-backdrop"]').classes()).toContain('bg-secondary/25');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
>
|
|
10
10
|
<div
|
|
11
11
|
v-if="show"
|
|
12
|
-
|
|
12
|
+
data-testid="director-modal-backdrop"
|
|
13
|
+
class="fixed inset-0 z-50 flex items-center justify-center bg-secondary/85"
|
|
13
14
|
@click="close"
|
|
14
15
|
>
|
|
15
|
-
<div class="w-full md:w-1/3 md:min-w-
|
|
16
|
+
<div class="w-full md:w-1/3 md:min-w-120 bg-neutral rounded-lg shadow-lg pb-6 px-2" @click.stop>
|
|
16
17
|
<div class="flex w-full justify-end mt-1">
|
|
17
18
|
<BaseIcon icon-name="fa-circle-xmark" size="lg" color="quaternary" hover="alarm" @click="close" />
|
|
18
19
|
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import BracketDirectorAssignmentCard from './BracketDirectorAssignmentCard.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Cards/BracketDirectorAssignmentCard',
|
|
5
|
+
component: BracketDirectorAssignmentCard,
|
|
6
|
+
args: {
|
|
7
|
+
station: {
|
|
8
|
+
RingId: 1,
|
|
9
|
+
RingName: 'Ring 1',
|
|
10
|
+
Color: '#2563eb',
|
|
11
|
+
Director: {
|
|
12
|
+
PersonId: 1001,
|
|
13
|
+
DisplayName: 'Alex Morgan',
|
|
14
|
+
PortraitUrl: ''
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
variant: 'assigned'
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
station: { control: 'object' },
|
|
21
|
+
variant: { control: 'select', options: ['assigned', 'add'] },
|
|
22
|
+
addLabel: { control: 'text' }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const Assigned = {};
|
|
27
|
+
|
|
28
|
+
export const AddDirector = {
|
|
29
|
+
args: {
|
|
30
|
+
station: null,
|
|
31
|
+
variant: 'add'
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import BracketDirectorAssignmentCard from './BracketDirectorAssignmentCard.vue';
|
|
4
|
+
|
|
5
|
+
const station = {
|
|
6
|
+
RingId: 3,
|
|
7
|
+
RingName: 'Ring 3',
|
|
8
|
+
Color: '#059669',
|
|
9
|
+
Director: { PersonId: 1003, DisplayName: 'Sam Rivera', PortraitUrl: '/portrait.png' }
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe('BracketDirectorAssignmentCard', () => {
|
|
13
|
+
it('renders the ring, portrait, and director name', () => {
|
|
14
|
+
const wrapper = shallowMount(BracketDirectorAssignmentCard, { props: { station } });
|
|
15
|
+
|
|
16
|
+
expect(wrapper.find('img').attributes()).toMatchObject({
|
|
17
|
+
src: '/portrait.png',
|
|
18
|
+
alt: 'Sam Rivera portrait'
|
|
19
|
+
});
|
|
20
|
+
expect(wrapper.findAll('base-text-stub').map(text => text.attributes('text'))).toContain('Sam Rivera');
|
|
21
|
+
expect(wrapper.find('[data-testid="bracket-director-assignment"]').attributes('style')).toBeUndefined();
|
|
22
|
+
expect(wrapper.find('[data-testid="director-color-dot"]').attributes('style')).toContain('#059669');
|
|
23
|
+
expect(wrapper.find('[data-testid="ring-number-icon"]').exists()).toBe(false);
|
|
24
|
+
expect(wrapper.findAll('base-text-stub').map(text => text.attributes('text'))).toContain('Ring 3');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('uses director initials when no portrait is supplied', () => {
|
|
28
|
+
const wrapper = shallowMount(BracketDirectorAssignmentCard, {
|
|
29
|
+
props: { station: { ...station, Director: { ...station.Director, PortraitUrl: '' } } }
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
expect(wrapper.find('img').exists()).toBe(false);
|
|
33
|
+
expect(wrapper.find('[data-testid="director-initials"]').classes()).toContain('rounded-xl');
|
|
34
|
+
expect(wrapper.find('[data-testid="director-initials"] base-text-stub').attributes('text')).toBe('SR');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('emits add intent from the summary card', async () => {
|
|
38
|
+
const wrapper = shallowMount(BracketDirectorAssignmentCard, { props: { variant: 'add' } });
|
|
39
|
+
|
|
40
|
+
await wrapper.find('[data-testid="add-bracket-director"]').trigger('click');
|
|
41
|
+
|
|
42
|
+
expect(wrapper.emitted('action:add')).toEqual([[]]);
|
|
43
|
+
expect(wrapper.find('base-text-stub').attributes('text')).toBe('Click here to add director');
|
|
44
|
+
});
|
|
45
|
+
});
|
package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.vue
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button
|
|
3
|
+
v-if="isAddCard"
|
|
4
|
+
type="button"
|
|
5
|
+
data-testid="add-bracket-director"
|
|
6
|
+
class="flex min-h-20 w-full items-center justify-center gap-3 rounded-lg border-2 border-dashed border-dropdownSelect bg-white px-4 py-3 text-left transition hover:border-bright hover:shadow-md focus-visible:border-bright focus-visible:outline-none"
|
|
7
|
+
@click="$emit('action:add')"
|
|
8
|
+
>
|
|
9
|
+
<span class="flex h-9 w-9 items-center justify-center rounded-full bg-bannerBackground" aria-hidden="true">
|
|
10
|
+
<BaseIcon iconName="fa-plus" color="primaryHighlight" size="sm" />
|
|
11
|
+
</span>
|
|
12
|
+
<BaseText :text="addLabel" color="primaryHighlight" size="sm" weight="bold" />
|
|
13
|
+
</button>
|
|
14
|
+
|
|
15
|
+
<article
|
|
16
|
+
v-else-if="station"
|
|
17
|
+
data-testid="bracket-director-assignment"
|
|
18
|
+
class="flex min-h-16 w-full items-center gap-3 overflow-hidden rounded-md border border-poolSetup bg-white px-3 py-2 shadow-sm hover:border-bright"
|
|
19
|
+
:aria-label="assignmentLabel"
|
|
20
|
+
>
|
|
21
|
+
<div class="relative h-12 w-12 flex-none">
|
|
22
|
+
<img
|
|
23
|
+
v-if="portraitUrl"
|
|
24
|
+
:src="portraitUrl"
|
|
25
|
+
:alt="`${directorName} portrait`"
|
|
26
|
+
class="h-12 w-12 rounded-xl object-cover"
|
|
27
|
+
/>
|
|
28
|
+
<div
|
|
29
|
+
v-else
|
|
30
|
+
data-testid="director-initials"
|
|
31
|
+
class="flex h-12 w-12 items-center justify-center rounded-xl bg-dropdownSelect"
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
>
|
|
34
|
+
<BaseText :text="directorInitials" color="primaryHighlight" size="sm" weight="bold" />
|
|
35
|
+
</div>
|
|
36
|
+
<span
|
|
37
|
+
data-testid="director-color-dot"
|
|
38
|
+
class="absolute -bottom-1 -right-1 h-4 w-4 rounded-full ring-2 ring-white"
|
|
39
|
+
:style="{ backgroundColor: station.Color }"
|
|
40
|
+
aria-hidden="true"
|
|
41
|
+
></span>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="min-w-0 flex-1">
|
|
45
|
+
<BaseText :text="ringLabel" color="quaternary" size="xs" />
|
|
46
|
+
<BaseText class="truncate" :text="directorName" color="primaryHighlight" size="sm" weight="bold" />
|
|
47
|
+
</div>
|
|
48
|
+
</article>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script>
|
|
52
|
+
import BaseIcon from '../../../Atoms/Icon/BaseIcon.vue';
|
|
53
|
+
import BaseText from '../../../Atoms/Text/BaseText.vue';
|
|
54
|
+
|
|
55
|
+
const getInitials = displayName =>
|
|
56
|
+
String(displayName || '')
|
|
57
|
+
.split(/\s+/)
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.slice(0, 2)
|
|
60
|
+
.map(name => name[0].toUpperCase())
|
|
61
|
+
.join('');
|
|
62
|
+
|
|
63
|
+
export default {
|
|
64
|
+
name: 'BracketDirectorAssignmentCard',
|
|
65
|
+
components: { BaseIcon, BaseText },
|
|
66
|
+
emits: ['action:add'],
|
|
67
|
+
props: {
|
|
68
|
+
station: {
|
|
69
|
+
type: Object,
|
|
70
|
+
default: null
|
|
71
|
+
},
|
|
72
|
+
variant: {
|
|
73
|
+
type: String,
|
|
74
|
+
default: 'assigned',
|
|
75
|
+
validator: value => ['assigned', 'add'].includes(value)
|
|
76
|
+
},
|
|
77
|
+
addLabel: {
|
|
78
|
+
type: String,
|
|
79
|
+
default: 'Click here to add director'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
computed: {
|
|
83
|
+
assignmentLabel() {
|
|
84
|
+
return `${this.ringLabel}, Director ${this.directorName}`;
|
|
85
|
+
},
|
|
86
|
+
directorInitials() {
|
|
87
|
+
return getInitials(this.directorName) || '?';
|
|
88
|
+
},
|
|
89
|
+
directorName() {
|
|
90
|
+
return this.station?.Director?.DisplayName || 'Director TBD';
|
|
91
|
+
},
|
|
92
|
+
isAddCard() {
|
|
93
|
+
return this.variant === 'add';
|
|
94
|
+
},
|
|
95
|
+
portraitUrl() {
|
|
96
|
+
return this.station?.Director?.PortraitUrl || '';
|
|
97
|
+
},
|
|
98
|
+
ringLabel() {
|
|
99
|
+
return this.station?.RingName || `Ring ${this.station?.RingId ?? ''}`.trim();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
</script>
|