@dcrackel/hematournamentui 1.0.39 → 1.0.42
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/{.eslintrc.js → .eslintrc.ts} +3 -4
- package/dist/HemaTouranmentUI-lib.es.js +6764 -6352
- package/dist/HemaTouranmentUI-lib.umd.js +27 -27
- package/dist/style.css +1 -1
- package/package.json +63 -58
- package/src/index.js +5 -5
- package/src/mocks/locationMock.js +44 -0
- package/src/mocks/personsMock.js +46 -0
- package/src/mocks/tournamentMock.js +98 -24
- package/src/stories/Atoms/Icon/BaseIcon.stories.js +26 -1
- package/src/stories/Atoms/Icon/BaseIcon.vue +9 -1
- package/src/stories/Atoms/Input/BaseInput.vue +1 -1
- package/src/stories/Molecules/Buttons/BaseButton/BaseButton.stories.js +7 -1
- package/src/stories/Molecules/Cards/Detail/TournamentCardDetail.vue +26 -8
- package/src/stories/Molecules/Cards/Header/TournamentCardHeader.vue +4 -0
- package/src/stories/Molecules/CombinationInputs/TitledInput/TitledInput.stories.js +75 -0
- package/src/stories/Molecules/CombinationInputs/TitledInput/TitledInput.test.js +81 -0
- package/src/stories/Molecules/CombinationInputs/TitledInput/TitledInput.vue +42 -0
- package/src/stories/Molecules/Filters/FilterAndSortBar/FilterAndSortBar.vue +1 -1
- package/src/stories/Molecules/Filters/FilterUpcomingPast/FilterUpcomingPast.vue +1 -1
- package/src/stories/Molecules/Menus/EditTournamentMenu/EditTournamentMenu.stories.js +13 -1
- package/src/stories/Molecules/Menus/EditTournamentMenu/EditTournamentMenu.vue +6 -4
- package/src/stories/Molecules/Modals/BaseModal/BaseModal.stories.js +39 -18
- package/src/stories/Molecules/Modals/BaseModal/BaseModal.vue +22 -9
- package/src/stories/Organisms/Cards/TournamentCard/TournamentCard.vue +20 -8
- package/src/stories/Organisms/ComplexInputs/AddressAutocomplete/AddressAutocomplete.stories.js +13 -0
- package/src/stories/Organisms/{Inputs → ComplexInputs}/AddressAutocomplete/AddressAutocomplete.vue +9 -11
- package/src/stories/Organisms/{Inputs → ComplexInputs}/DatePicker/DatePicker.stories.js +1 -1
- package/src/stories/Organisms/ComplexInputs/DropDown/DropDownMenu.stories.js +20 -0
- package/src/stories/Organisms/ComplexInputs/FindLocation/FindLocation.stories.js +30 -0
- package/src/stories/Organisms/ComplexInputs/FindLocation/FindLocation.vue +125 -0
- package/src/stories/Organisms/ComplexInputs/FindPerson/FindPerson.stories.js +30 -0
- package/src/stories/Organisms/ComplexInputs/FindPerson/FindPerson.vue +113 -0
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +20 -0
- package/src/stories/Organisms/{Inputs → ComplexInputs}/ImageCropper/ImageCropper.vue +4 -6
- package/src/stories/Organisms/ComplexInputs/TextBoxEditor/TextBoxEditor.stories.js +17 -0
- package/src/stories/Organisms/Containers/Container.stories.js +13 -0
- package/src/stories/Organisms/Containers/Container.vue +6 -0
- package/src/stories/Organisms/Forms/EditTournamentForm1.stories.js +26 -0
- package/src/stories/Organisms/Forms/EditTournamentForm1.vue +66 -0
- package/src/stories/Organisms/Grids/GridContainer.stories.js +28 -1
- package/src/stories/Organisms/Grids/GridContainer.vue +3 -3
- package/src/stories/Templates/TournamentManagement/AddTournament/PageOne/AddTournamentPageOne.stories.js +17 -13
- package/src/stories/Templates/TournamentManagement/AddTournament/PageOne/AddTournamentPageOne.vue +30 -25
- package/src/stories/Templates/TournamentManagement/AddTournament/PageTwo/AddTournamentPageTwo.vue +0 -2
- package/tailwind.config.js +2 -1
- package/src/stories/Organisms/Inputs/AddressAutocomplete/AddressAutocomplete.stories.js +0 -25
- package/src/stories/Organisms/Inputs/DropDown/DropDownMenu.stories.js +0 -34
- package/src/stories/Organisms/Inputs/ImageCropper/ImageCropper.stories.js +0 -28
- package/src/stories/Organisms/Inputs/TextBoxEditor/TextBoxEditor.stories.js +0 -28
- /package/src/stories/Organisms/{Inputs → ComplexInputs}/DatePicker/DatePicker.vue +0 -0
- /package/src/stories/Organisms/{Inputs → ComplexInputs}/DropDown/DropDownMenu.vue +0 -0
- /package/src/stories/Organisms/{Inputs → ComplexInputs}/TextBoxEditor/TextBoxEditor.vue +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import TitledInput from './TitledInput.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Molecules/CombinationInputs/TitledInput',
|
|
5
|
+
component: TitledInput,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
args: {
|
|
8
|
+
title: 'Your Title',
|
|
9
|
+
invalid: false,
|
|
10
|
+
inputValue: '',
|
|
11
|
+
placeholder: 'Enter text'
|
|
12
|
+
},
|
|
13
|
+
argTypes: {
|
|
14
|
+
title: {
|
|
15
|
+
control: {
|
|
16
|
+
type: 'text'
|
|
17
|
+
},
|
|
18
|
+
defaultValue: 'Your Title'
|
|
19
|
+
},
|
|
20
|
+
invalid: {
|
|
21
|
+
control: {
|
|
22
|
+
type: 'boolean'
|
|
23
|
+
},
|
|
24
|
+
defaultValue: false
|
|
25
|
+
},
|
|
26
|
+
inputValue: {
|
|
27
|
+
control: {
|
|
28
|
+
type: 'text'
|
|
29
|
+
},
|
|
30
|
+
defaultValue: ''
|
|
31
|
+
},
|
|
32
|
+
placeholder: {
|
|
33
|
+
control: {
|
|
34
|
+
type: 'text'
|
|
35
|
+
},
|
|
36
|
+
defaultValue: 'Enter text'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const DefaultTitledInput = {
|
|
42
|
+
args: {
|
|
43
|
+
title: 'Default Title',
|
|
44
|
+
invalid: false,
|
|
45
|
+
inputValue: '',
|
|
46
|
+
placeholder: 'Enter text'
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const TitledInputWithError = {
|
|
51
|
+
args: {
|
|
52
|
+
title: 'Error Title',
|
|
53
|
+
invalid: true,
|
|
54
|
+
inputValue: '',
|
|
55
|
+
placeholder: 'Enter text'
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const TitledInputWithInitialValue = {
|
|
60
|
+
args: {
|
|
61
|
+
title: 'Initial Value Title',
|
|
62
|
+
invalid: false,
|
|
63
|
+
inputValue: 'Initial Value',
|
|
64
|
+
placeholder: 'Enter text'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const TitledInputCustomPlaceholder = {
|
|
69
|
+
args: {
|
|
70
|
+
title: 'Custom Placeholder Title',
|
|
71
|
+
invalid: false,
|
|
72
|
+
inputValue: '',
|
|
73
|
+
placeholder: 'Custom Placeholder'
|
|
74
|
+
}
|
|
75
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {mount} from '@vue/test-utils';
|
|
2
|
+
import TitledInput from './TitledInput.vue';
|
|
3
|
+
import BaseInput from "../../../Atoms/Input/BaseInput.vue";
|
|
4
|
+
import {describe, expect, it} from "vitest";
|
|
5
|
+
|
|
6
|
+
describe('TitledInput', () => {
|
|
7
|
+
it('renders correctly with all props', () => {
|
|
8
|
+
const wrapper = mount(TitledInput, {
|
|
9
|
+
props: {
|
|
10
|
+
title: 'Test Title',
|
|
11
|
+
invalid: false,
|
|
12
|
+
inputValue: 'Test Input',
|
|
13
|
+
placeholder: 'Enter something'
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
expect(wrapper.text()).toContain('Test Title');
|
|
18
|
+
const input = wrapper.find('input');
|
|
19
|
+
expect(input.element.placeholder).toBe('Enter something');
|
|
20
|
+
expect(input.element.value).toBe('Test Input');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('shows invalid state', async () => {
|
|
24
|
+
const wrapper = mount(TitledInput, {
|
|
25
|
+
props: {
|
|
26
|
+
title: 'Test Title',
|
|
27
|
+
invalid: true,
|
|
28
|
+
inputValue: 'Test Input',
|
|
29
|
+
placeholder: 'Enter something'
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Wait for the next DOM update cycle
|
|
34
|
+
await wrapper.vm.$nextTick();
|
|
35
|
+
|
|
36
|
+
// Find the BaseText component and check if it has the 'text-alarm' class
|
|
37
|
+
const baseTextComponent = wrapper.findComponent({name: 'BaseText'});
|
|
38
|
+
expect(baseTextComponent.classes()).toContain('text-alarm');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('BaseInput emits update:value correctly', async () => {
|
|
42
|
+
const wrapper = mount(BaseInput, {
|
|
43
|
+
props: {
|
|
44
|
+
value: 'Initial Value'
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Simulate input
|
|
49
|
+
const inputElement = wrapper.find('input');
|
|
50
|
+
await inputElement.setValue('New Value');
|
|
51
|
+
|
|
52
|
+
// Wait for debounce timeout
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, 350)); // Slightly more than 300ms for safety
|
|
54
|
+
|
|
55
|
+
// Assertions
|
|
56
|
+
expect(wrapper.emitted()).toHaveProperty('update:value');
|
|
57
|
+
expect(wrapper.emitted()['update:value'][0]).toEqual(['New Value']);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('emits update event when input value changes', async () => {
|
|
61
|
+
const wrapper = mount(TitledInput, {
|
|
62
|
+
props: {
|
|
63
|
+
title: 'Test Title',
|
|
64
|
+
invalid: false,
|
|
65
|
+
inputValue: 'Test Input',
|
|
66
|
+
placeholder: 'Enter something'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Find the input element within BaseInput
|
|
71
|
+
const inputElement = wrapper.find('input');
|
|
72
|
+
await inputElement.setValue('New Value');
|
|
73
|
+
|
|
74
|
+
// Wait for the debounce timeout (300 ms) in BaseInput
|
|
75
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
76
|
+
|
|
77
|
+
// Check if the update:value event was emitted
|
|
78
|
+
expect(wrapper.emitted()).toHaveProperty('update:value');
|
|
79
|
+
expect(wrapper.emitted()['update:value'][0]).toEqual(['New Value']);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col mb-3">
|
|
3
|
+
<BaseText :invalid=invalid :text=title class="mb-1 ml-1" color="primary"
|
|
4
|
+
size="sm" weight="normal"/>
|
|
5
|
+
<BaseInput :addBorder="true" :invalid=invalid :placeholder=placeholder :value=inputValue
|
|
6
|
+
@update:value="handleUpdateValue"/>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
import BaseIcon from "../../../Atoms/Icon/BaseIcon.vue";
|
|
12
|
+
import BaseInput from "../../../Atoms/Input/BaseInput.vue";
|
|
13
|
+
import BaseText from "../../../Atoms/Text/BaseText.vue";
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'TitledInput',
|
|
17
|
+
components: {BaseIcon, BaseInput, BaseText},
|
|
18
|
+
props: {
|
|
19
|
+
title: {
|
|
20
|
+
type: String,
|
|
21
|
+
required: true
|
|
22
|
+
},
|
|
23
|
+
invalid: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false
|
|
26
|
+
},
|
|
27
|
+
inputValue: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: true
|
|
30
|
+
},
|
|
31
|
+
placeholder: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: ''
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
methods: {
|
|
37
|
+
handleUpdateValue(value) {
|
|
38
|
+
this.$emit('update:value', value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
<script>
|
|
14
14
|
import BaseInput from "../../../Atoms/Input/BaseInput.vue";
|
|
15
|
-
import DropDownMenu from "../../../Organisms/
|
|
15
|
+
import DropDownMenu from "../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue";
|
|
16
16
|
|
|
17
17
|
export default {
|
|
18
18
|
name: 'FilterAndSortBar',
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
15
|
import BaseInput from "../../../Atoms/Input/BaseInput.vue";
|
|
16
|
-
import DropDownMenu from "../../../Organisms/
|
|
16
|
+
import DropDownMenu from "../../../Organisms/ComplexInputs/DropDown/DropDownMenu.vue";
|
|
17
17
|
import BaseButton from "../../../Molecules/Buttons/BaseButton/BaseButton.vue";
|
|
18
18
|
import BaseText from "../../../Atoms/Text/BaseText.vue";
|
|
19
19
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import EditTournamentMenu from './EditTournamentMenu.vue';
|
|
2
|
+
import {action} from "@storybook/addon-actions";
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
title: 'Molecules/Menus/EditTournamentMenu/EditTournamentMenu',
|
|
@@ -12,7 +13,18 @@ export default {
|
|
|
12
13
|
|
|
13
14
|
export const Primary = {
|
|
14
15
|
args: {
|
|
15
|
-
|
|
16
|
+
items: [
|
|
17
|
+
{text: 'Details', link: ''},
|
|
18
|
+
{text: 'Events', link: ''},
|
|
19
|
+
{text: 'Payments', link: ''},
|
|
20
|
+
{text: 'Staff', link: ''}
|
|
21
|
+
],
|
|
22
|
+
selectedItem: {text: 'Details', link: ''},
|
|
23
|
+
props: {
|
|
24
|
+
onLinkClick: {
|
|
25
|
+
default: () => action('link-clicked')
|
|
26
|
+
}
|
|
27
|
+
},
|
|
16
28
|
selected: true
|
|
17
29
|
}
|
|
18
30
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<nav class="flex flex-row w-full">
|
|
3
|
-
<
|
|
3
|
+
<div v-for="(item, index) in items" :key="index" class="flex flex-row">
|
|
4
|
+
<BaseText :text="item.text" class="mx-3" color="secondary"/>
|
|
5
|
+
</div>
|
|
4
6
|
</nav>
|
|
5
7
|
</template>
|
|
6
8
|
|
|
@@ -11,9 +13,9 @@ export default {
|
|
|
11
13
|
name: 'edit-tournament-menu',
|
|
12
14
|
components: {BaseText},
|
|
13
15
|
props: {
|
|
14
|
-
|
|
15
|
-
type:
|
|
16
|
-
default:
|
|
16
|
+
items: {
|
|
17
|
+
type: Array,
|
|
18
|
+
default: () => []
|
|
17
19
|
},
|
|
18
20
|
selected: {
|
|
19
21
|
type: Boolean,
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
1
2
|
import BaseModal from './BaseModal.vue';
|
|
3
|
+
import AddressAutocomplete from "../../../Organisms/ComplexInputs/AddressAutocomplete/AddressAutocomplete.vue";
|
|
4
|
+
import BaseText from "../../../Atoms/Text/BaseText.vue";
|
|
5
|
+
import BaseButton from "../../Buttons/BaseButton/BaseButton.vue";
|
|
6
|
+
import BaseInput from "../../../Atoms/Input/BaseInput.vue";
|
|
2
7
|
|
|
3
8
|
export default {
|
|
9
|
+
components: {AddressAutocomplete, BaseText},
|
|
4
10
|
title: 'Molecules/Modals/BaseModal',
|
|
5
11
|
component: BaseModal,
|
|
6
12
|
tags: ['autodocs'],
|
|
13
|
+
args: {},
|
|
7
14
|
argTypes: {
|
|
8
15
|
show: {
|
|
9
16
|
control: 'boolean',
|
|
@@ -40,24 +47,38 @@ export default {
|
|
|
40
47
|
}
|
|
41
48
|
};
|
|
42
49
|
|
|
43
|
-
const
|
|
44
|
-
|
|
50
|
+
export const Default = {
|
|
51
|
+
args: {
|
|
52
|
+
show: true,
|
|
53
|
+
iconName: 'fa-check-circle',
|
|
54
|
+
iconColor: 'accepted',
|
|
55
|
+
iconBackgroundColor: 'acceptedHighlight',
|
|
56
|
+
iconBorderColor: 'acceptedBorder',
|
|
57
|
+
headerText: 'Congratulations!',
|
|
58
|
+
bodyText: "Your tournament's been created. Now you can start editing events, setup up staff and start inviting members.",
|
|
59
|
+
buttonText: "Get Started!"
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
export const WithCustomForm = () => ({
|
|
63
|
+
components: {
|
|
64
|
+
BaseModal,
|
|
65
|
+
BaseText,
|
|
66
|
+
BaseInput,
|
|
67
|
+
AddressAutocomplete,
|
|
68
|
+
BaseButton
|
|
69
|
+
},
|
|
45
70
|
setup() {
|
|
46
|
-
|
|
71
|
+
const show = ref(true);
|
|
72
|
+
return { show };
|
|
47
73
|
},
|
|
48
|
-
template:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
iconName: 'fa-check-circle',
|
|
55
|
-
iconColor: 'accepted',
|
|
56
|
-
iconBackgroundColor: 'acceptedHighlight',
|
|
57
|
-
iconBorderColor: 'acceptedBorder',
|
|
58
|
-
headerText: 'Congratulations!',
|
|
59
|
-
bodyText: "Your tournament's been created. Now you can start editing events, setup up staff and start inviting members.",
|
|
60
|
-
buttonText: "Get Started!"
|
|
61
|
-
};
|
|
62
|
-
|
|
74
|
+
template: `
|
|
75
|
+
<BaseModal :show="show">
|
|
76
|
+
<template #modal-content>
|
|
77
|
+
<p>This is custom content</p>
|
|
78
|
+
<BaseInput :addBorder="true" :invalid="false" :value="locationName" class="pb-2" placeholder="Enter Location Name" type="formInput" @update:value="value => locationName = value"/>
|
|
79
|
+
<AddressAutocomplete :address="address" :invalid="validAddress" @update:address="handleAddressUpdate" class="text-lg" />
|
|
63
80
|
|
|
81
|
+
</template>
|
|
82
|
+
</BaseModal>
|
|
83
|
+
`,
|
|
84
|
+
});
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="show" class="fixed inset-0 bg-secondary bg-opacity-50 overflow-y-auto h-full w-full" @click="close">
|
|
3
|
-
<div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-neutral">
|
|
2
|
+
<div v-if="show" class="fixed inset-0 bg-secondary bg-opacity-50 overflow-y-auto h-full w-full z-20" @click="close">
|
|
3
|
+
<div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-neutral" @click.stop>
|
|
4
|
+
|
|
5
|
+
<!-- Close icon wrapper with absolute positioning -->
|
|
6
|
+
<div class="absolute top-3 right-3">
|
|
7
|
+
<BaseIcon icon-name="fa-circle-xmark" size="lg" color="quaternary" hover="alarm" @click="close" />
|
|
8
|
+
</div>
|
|
9
|
+
|
|
4
10
|
<div class="mt-3 text-center w-full">
|
|
5
|
-
<div class="w-full flex flex-row justify-center">
|
|
11
|
+
<div class="w-full flex flex-row justify-center mb-8">
|
|
6
12
|
<p :class="['bg-' + iconBackgroundColor, 'flex flex-row justify-center h-20 w-20 rounded-full', 'border border-' + iconBorderColor]">
|
|
7
13
|
<BaseIcon :icon-name="iconName" iconStyle="fa-solid" size="4xl" :color="iconColor" class="mb-3 mt-5" data-testid="base-icon" />
|
|
8
14
|
</p>
|
|
9
15
|
</div>
|
|
10
|
-
|
|
11
|
-
<
|
|
16
|
+
|
|
17
|
+
<slot name="modal-content">
|
|
18
|
+
<BaseText :text="headerText" size="2xl" weight="bold" color="secondary" class="m-3" data-testid="text-title"/>
|
|
19
|
+
<BaseText :text="bodyText" size="sm" weight="normal" color="primaryHighlight" class="mb-3" data-testid="text-title"/>
|
|
20
|
+
</slot>
|
|
21
|
+
|
|
12
22
|
<div class="mt-4">
|
|
13
|
-
<BaseButton :label="buttonText" size="sm" type="secondary" :selected="true" @click="
|
|
23
|
+
<BaseButton :label="buttonText" size="sm" type="secondary" :selected="true" @click="submit" color="neutral" class="w-full" data-testid="base-button"/>
|
|
14
24
|
</div>
|
|
15
25
|
</div>
|
|
16
26
|
</div>
|
|
17
27
|
</div>
|
|
18
28
|
</template>
|
|
19
29
|
|
|
20
|
-
|
|
21
30
|
<script>
|
|
22
31
|
import BaseText from "../../../Atoms/Text/BaseText.vue";
|
|
23
32
|
import BaseIcon from "../../../Atoms/Icon/BaseIcon.vue";
|
|
@@ -60,11 +69,15 @@ export default {
|
|
|
60
69
|
default: 'Button Text'
|
|
61
70
|
}
|
|
62
71
|
},
|
|
63
|
-
emits: ['update:show'],
|
|
72
|
+
emits: ['update:show', 'submit-modal'],
|
|
64
73
|
methods: {
|
|
65
74
|
close() {
|
|
66
75
|
this.$emit('update:show', false)
|
|
67
|
-
}
|
|
76
|
+
},
|
|
77
|
+
submit() {
|
|
78
|
+
this.$emit('submit-modal');
|
|
79
|
+
this.close();
|
|
80
|
+
},
|
|
68
81
|
}
|
|
69
82
|
};
|
|
70
83
|
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="rounded-xl w-72 shadow">
|
|
3
|
-
<TournamentHeader :artwork="detail.
|
|
3
|
+
<TournamentHeader :artwork="detail.images && detail.images.length > 0 ? detail.images[0].URL : ''" :tags="detail.tags" />
|
|
4
4
|
<TournamentDetail :detail="detail" />
|
|
5
5
|
</div>
|
|
6
6
|
</template>
|
|
@@ -20,13 +20,25 @@ export default {
|
|
|
20
20
|
type: Object,
|
|
21
21
|
required: true,
|
|
22
22
|
default: () => ({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
TournamentId: null,
|
|
24
|
+
Name: '',
|
|
25
|
+
StartDate: '',
|
|
26
|
+
EndDate: '',
|
|
27
|
+
Description: '',
|
|
28
|
+
ClubId: null,
|
|
29
|
+
AddressId: null,
|
|
30
|
+
'Club.Name': '',
|
|
31
|
+
Address: [{
|
|
32
|
+
Name: '',
|
|
33
|
+
Address1: '',
|
|
34
|
+
City: '',
|
|
35
|
+
State: '',
|
|
36
|
+
Zip: null,
|
|
37
|
+
Coordinates: ''
|
|
38
|
+
}],
|
|
39
|
+
SocialMedia: [],
|
|
40
|
+
images: [],
|
|
41
|
+
tags: []
|
|
30
42
|
})
|
|
31
43
|
}
|
|
32
44
|
},
|
package/src/stories/Organisms/ComplexInputs/AddressAutocomplete/AddressAutocomplete.stories.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import AddressAutocomplete from './AddressAutocomplete.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/ComplexInputs/AddressAutocomplete',
|
|
5
|
+
component: AddressAutocomplete,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
args: {},
|
|
8
|
+
argTypes: {}
|
|
9
|
+
};
|
|
10
|
+
export const Default = {
|
|
11
|
+
args: {
|
|
12
|
+
}
|
|
13
|
+
};
|
package/src/stories/Organisms/{Inputs → ComplexInputs}/AddressAutocomplete/AddressAutocomplete.vue
RENAMED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/>
|
|
12
|
-
|
|
2
|
+
<vue-google-autocomplete
|
|
3
|
+
class="border rounded-lg text-secondary text-sm p-2 w-full appearance-none focus:outline-none"
|
|
4
|
+
:class="invalid ? 'border-alarm' : 'border-dropdownSelect'"
|
|
5
|
+
id="map"
|
|
6
|
+
ref="address"
|
|
7
|
+
v-model="address"
|
|
8
|
+
placeholder="Venue Address"
|
|
9
|
+
@placechanged="getAddressData"
|
|
10
|
+
/>
|
|
13
11
|
</template>
|
|
14
12
|
|
|
15
13
|
<script>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import DropDownMenu from './DropDownMenu.vue';
|
|
2
|
+
export default {
|
|
3
|
+
title: 'Organisms/ComplexInputs/DropDownMenu',
|
|
4
|
+
component: DropDownMenu,
|
|
5
|
+
tags: ['autodocs'],
|
|
6
|
+
args: {},
|
|
7
|
+
argTypes: {}
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const Default = {
|
|
11
|
+
args: {
|
|
12
|
+
label: 'Sort By',
|
|
13
|
+
items: [
|
|
14
|
+
{text: 'Text1', link: '/link1'},
|
|
15
|
+
{text: 'Text2', link: '/link2'},
|
|
16
|
+
{text: 'Text3', link: '/link3'}
|
|
17
|
+
],
|
|
18
|
+
selectedItem: {text: 'Text1', link: '/link1'}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import FindLocation from './FindLocation.vue';
|
|
2
|
+
import mockLocation from '../../../../mocks/locationMock.js';
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/ComplexInputs/FindLocation',
|
|
5
|
+
component: FindLocation,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
args: {
|
|
8
|
+
locations: mockLocation,
|
|
9
|
+
addNewText: "Add New Location"
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
locations: {
|
|
13
|
+
control: {
|
|
14
|
+
type: 'object'
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
addNewText: {
|
|
18
|
+
control: {
|
|
19
|
+
type: 'text'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Default = {
|
|
26
|
+
args: {
|
|
27
|
+
locations: mockLocation,
|
|
28
|
+
addNewText: "Add New Location"
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section>
|
|
3
|
+
<div v-if="!showNewLocation" class="relative">
|
|
4
|
+
<BaseInput
|
|
5
|
+
:addBorder="addBorder"
|
|
6
|
+
:value="inputValue"
|
|
7
|
+
@input="updateInput"
|
|
8
|
+
placeholder="Enter Location Name"
|
|
9
|
+
/>
|
|
10
|
+
<div v-if="showDropdown" class="absolute z-10 w-full bg-white border border-gray-300 rounded-md mt-1">
|
|
11
|
+
<ul>
|
|
12
|
+
<li v-for="(item, index) in filteredLocations" :key="index" @click="selectItem(item)" class="p-2 hover:bg-gray-100 cursor-pointer">
|
|
13
|
+
{{ item.Name }}
|
|
14
|
+
</li>
|
|
15
|
+
</ul>
|
|
16
|
+
<div @click="addNewItem" class="p-2 hover:bg-gray-100 cursor-pointer">
|
|
17
|
+
<base-button
|
|
18
|
+
type="secondary"
|
|
19
|
+
label="Add New Location"
|
|
20
|
+
iconName="fa-location-dot"
|
|
21
|
+
v-on:click="showNewLocation = true"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div v-if="showNewLocation" >
|
|
27
|
+
<BaseModal :show="showNewLocation" iconName="fa-location-plus" buttonText="Add Location" @submit-modal="handleSubmit" @update:show="showNewLocation = false">
|
|
28
|
+
<template #modal-content>
|
|
29
|
+
<BaseInput :addBorder="true" :value="locationName" :invalid="false" @update:value="handleLocationName" class="pb-2" placeholder="Enter Location Name" type="formInput" />
|
|
30
|
+
<AddressAutocomplete v-model="formData.address" :invalid="validAddress" @update:address="handleAddressUpdate" class="text-lg" />
|
|
31
|
+
</template>
|
|
32
|
+
</BaseModal>
|
|
33
|
+
</div>
|
|
34
|
+
</section>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
import BaseInput from '../../../Atoms/Input/BaseInput.vue';
|
|
39
|
+
import BaseIcon from "../../../Atoms/Icon/BaseIcon.vue";
|
|
40
|
+
import BaseButton from "../../../Molecules/Buttons/BaseButton/BaseButton.vue";
|
|
41
|
+
import AddressAutocomplete from "../AddressAutocomplete/AddressAutocomplete.vue";
|
|
42
|
+
import BaseModal from "../../../Molecules/Modals/BaseModal/BaseModal.vue";
|
|
43
|
+
import BaseText from "../../../Atoms/Text/BaseText.vue";
|
|
44
|
+
|
|
45
|
+
export default {
|
|
46
|
+
name: 'FindLocation',
|
|
47
|
+
components: {BaseText, BaseModal, AddressAutocomplete, BaseButton, BaseIcon, BaseInput },
|
|
48
|
+
props: {
|
|
49
|
+
locations: {
|
|
50
|
+
type: Array,
|
|
51
|
+
required: true
|
|
52
|
+
},
|
|
53
|
+
addBorder: {
|
|
54
|
+
type: Boolean,
|
|
55
|
+
default: false
|
|
56
|
+
},
|
|
57
|
+
addNewText: {
|
|
58
|
+
type: String,
|
|
59
|
+
default: 'Add New'
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
data() {
|
|
63
|
+
return {
|
|
64
|
+
formData: {
|
|
65
|
+
locationName: '',
|
|
66
|
+
address: '',
|
|
67
|
+
coordinates: ''
|
|
68
|
+
},
|
|
69
|
+
locationName: '',
|
|
70
|
+
validAddress: false,
|
|
71
|
+
showNewLocation: false,
|
|
72
|
+
filteredLocations: this.locations,
|
|
73
|
+
inputValue: '',
|
|
74
|
+
showDropdown: false,
|
|
75
|
+
showAddNew: false,
|
|
76
|
+
debouncedTimeout: null
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
watch: {
|
|
80
|
+
inputValue(newValue) {
|
|
81
|
+
this.showDropdown = newValue.length > 0;
|
|
82
|
+
this.showAddNew = newValue.length > 0 && this.filteredLocations.length === 0;
|
|
83
|
+
this.debounceSearch();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
methods: {
|
|
87
|
+
updateInput(event) {
|
|
88
|
+
this.inputValue = event.target.value;
|
|
89
|
+
},
|
|
90
|
+
selectItem(item) {
|
|
91
|
+
this.showDropdown = false;
|
|
92
|
+
this.inputValue = item.Name;
|
|
93
|
+
this.$emit('update-location', item);
|
|
94
|
+
this.$nextTick(() => {
|
|
95
|
+
this.showDropdown = false;
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
addNewItem() {
|
|
99
|
+
this.$emit('add-new', this.inputValue);
|
|
100
|
+
this.showDropdown = false;
|
|
101
|
+
},
|
|
102
|
+
onInputChanged(value) {
|
|
103
|
+
if (!this.showDropdown) return;
|
|
104
|
+
this.filteredLocations = this.locations.filter(item => item.Name.toLowerCase().includes(value.toLowerCase()));
|
|
105
|
+
},
|
|
106
|
+
debounceSearch() {
|
|
107
|
+
clearTimeout(this.debouncedTimeout);
|
|
108
|
+
this.debouncedTimeout = setTimeout(() => {
|
|
109
|
+
this.onInputChanged(this.inputValue)
|
|
110
|
+
}, 500);
|
|
111
|
+
},
|
|
112
|
+
handleLocationName(newName) {
|
|
113
|
+
this.formData.locationName = newName
|
|
114
|
+
},
|
|
115
|
+
handleAddressUpdate(newAddress) {
|
|
116
|
+
this.formData.address = newAddress.address
|
|
117
|
+
this.formData.coordinates = newAddress.coordinates
|
|
118
|
+
},
|
|
119
|
+
handleSubmit(formData) {
|
|
120
|
+
this.$emit('update-location', formData);
|
|
121
|
+
this.showNewLocation = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
</script>
|