Skip to content

Commit 3358e75

Browse files
authored
Refactor Home page to Vue3 (#798)
Bug: T353869
1 parent 03163fe commit 3358e75

File tree

2 files changed

+50
-78
lines changed

2 files changed

+50
-78
lines changed

resources/js/Pages/Home.vue

Lines changed: 40 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,15 @@
9898
</div>
9999
</template>
100100

101-
<script lang="ts">
102-
import { Head as InertiaHead } from '@inertiajs/inertia-vue3';
103-
import { mapState } from 'pinia';
101+
<script setup lang="ts">
102+
import { Head as InertiaHead, usePage } from '@inertiajs/inertia-vue3';
104103
import { useStore } from '../store';
105104
import { CdxDialog, CdxButton, CdxIcon, CdxMessage } from "@wikimedia/codex";
106-
import ItemIdSearchTextarea from '../Components/ItemIdSearchTextarea.vue';
107105
import { cdxIconDie, cdxIconInfo } from '@wikimedia/codex-icons';
108-
import { defineComponent, ref } from 'vue';
109-
import ValidationError from '../types/ValidationError';
110-
111-
interface HomeState {
112-
validationError: null|ValidationError,
113-
faqDialog: boolean
114-
}
106+
import ItemIdSearchTextarea from '../Components/ItemIdSearchTextarea.vue';
107+
import { ref, computed } from 'vue';
108+
import type { Ref } from 'vue';
109+
import { Inertia } from '@inertiajs/inertia';
115110
116111
interface ErrorMessages {
117112
[ key : string ] : string
@@ -121,63 +116,41 @@
121116
errors : { [ key : string ] : string }
122117
}
123118
124-
export default defineComponent({
125-
components: {
126-
CdxDialog,
127-
CdxButton,
128-
CdxIcon,
129-
CdxMessage,
130-
ItemIdSearchTextarea,
131-
InertiaHead
132-
},
133-
setup() {
134-
const store = useStore();
135-
const textareaInputValue = ref(store.lastSearchedIds);
136-
137-
return {
138-
cdxIconDie,
139-
cdxIconInfo,
140-
textareaInputValue
141-
};
142-
},
143-
methods: {
144-
send(): void {
145-
(this.$refs.textarea as InstanceType<typeof ItemIdSearchTextarea>).validate();
146-
147-
if((this.$refs.textarea as InstanceType<typeof ItemIdSearchTextarea>).validationError) {
148-
return;
149-
}
150-
const store = useStore();
151-
store.saveSearchedIds( this.textareaInputValue );
152-
this.$inertia.get( '/results',
153-
{ ids: (this.$refs.textarea as InstanceType<typeof ItemIdSearchTextarea>).serializeInput() }
154-
);
155-
},
156-
showRandom(): void {
157-
this.$inertia.get( '/random' );
158-
},
159-
},
160-
computed: {
161-
serversideValidationError() {
162-
const errors = this.$page.props.errors as ErrorMessages;
163-
return errors && Object.keys(errors).length > 0;
164-
},
165-
unexpectedError() {
166-
const flashMessages = this.$page.props.flash as FlashMessages;
167-
return (flashMessages.errors && flashMessages.errors.unexpected);
168-
},
169-
// spread to combine with local computed props
170-
// only mapping 'loading' and not 'lastSearchedIds' because computed
171-
//properties are not available when data is processed in vue's lifecycle
172-
...mapState(useStore, ['loading']),
173-
},
174-
data(): HomeState {
175-
return {
176-
validationError: null,
177-
faqDialog: false
178-
}
179-
}
119+
const textarea = ref<InstanceType<typeof ItemIdSearchTextarea> | null>(null);
120+
const store = useStore();
121+
const page = usePage();
122+
const textareaInputValue: Ref<string> = ref(store.lastSearchedIds);
123+
124+
const faqDialog = ref(false);
125+
const serversideValidationError = computed<boolean>(() => {
126+
const errors = page.props.value.errors as ErrorMessages;
127+
return errors && Object.keys(errors).length > 0;
128+
});
129+
130+
const unexpectedError = computed<string>(() => {
131+
const flashMessages = page.props.value.flash as FlashMessages;
132+
return (flashMessages.errors && flashMessages.errors.unexpected);
180133
});
134+
135+
const loading = computed<boolean>(() => {
136+
return (store.loading);
137+
});
138+
139+
function send(): void{
140+
(textarea as InstanceType<typeof ItemIdSearchTextarea>).value.validate();
141+
142+
if((textarea as InstanceType<typeof ItemIdSearchTextarea>).value.validationError) {
143+
return;
144+
}
145+
store.saveSearchedIds( textareaInputValue.value );
146+
Inertia.get( '/results',
147+
{ ids: (textarea as InstanceType<typeof ItemIdSearchTextarea>).value.serializeInput() }
148+
);
149+
}
150+
151+
function showRandom(): void{
152+
Inertia.get( '/random' );
153+
}
181154
</script>
182155

183156
<style lang="scss">

tests/Vue/Pages/Home.spec.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@ import { createI18n } from 'vue-banana-i18n';
55

66
// Stub the inertia vue components module entirely so that we don't run into
77
// issues with the Head component.
8-
jest.mock('@inertiajs/inertia-vue3', () => ({}));
8+
jest.mock('@inertiajs/inertia-vue3', () => ({
9+
usePage: () => ({
10+
props: {
11+
value: {
12+
flash: {},
13+
errors: { 'somekey' : 'someError'},
14+
},
15+
},
16+
})
17+
}));
918

1019
const i18n = createI18n({
1120
messages: {},
@@ -15,20 +24,12 @@ const i18n = createI18n({
1524

1625
describe('Home.vue', () => {
1726

18-
const mocks = {
19-
$i18n: key => key,
20-
$page: {
21-
props: { flash: {} }
22-
},
23-
}
24-
2527
it('shows dialog after clicking the more info button', async () => {
2628

2729
const wrapper = mount(Home, {
2830
attachTo: document.body,
2931
global:
3032
{
31-
mocks,
3233
plugins: [createTestingPinia(),i18n],
3334
stubs: {
3435
teleport: true,
@@ -41,9 +42,7 @@ describe('Home.vue', () => {
4142
});
4243

4344
it('shows error message upon serverside validation errors', async () => {
44-
mocks.$page.props.errors = { 'someKey' : 'someError'}
4545
const wrapper = mount(Home, { global: {
46-
mocks,
4746
plugins: [createTestingPinia(), i18n]
4847
}});
4948
const errorMessage = wrapper.find('#message-section .cdx-message--error');

0 commit comments

Comments
 (0)