forked from FoundKeyGang/FoundKey
client: refactor components/tab.vue to composition API
Refactoring this component could be done after changing its method of receiving the list of available tabs by using slots to using an ordinary parameter. This was possible because all uses of this component just provided text as the tab labels. Also removed unused imports of this component. Also removed the use of the click-anime directive.
This commit is contained in:
parent
1592420406
commit
93f54e3258
7 changed files with 67 additions and 49 deletions
|
@ -1,31 +1,29 @@
|
||||||
<script lang="ts">
|
<template>
|
||||||
import { defineComponent, h, resolveDirective, withDirectives } from 'vue';
|
<div class="pxhvhrfw" v-size="{ max: [500] }">
|
||||||
|
<button
|
||||||
|
v-for="option in options"
|
||||||
|
:key="option.value"
|
||||||
|
:class="{ '_button': true, active: modelValue === option.value }"
|
||||||
|
:disabled="modelValue === option.value"
|
||||||
|
@click.stop="emit('update:modelValue', option.value)"
|
||||||
|
>
|
||||||
|
{{ option.label }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
export default defineComponent({
|
<script lang="ts" setup>
|
||||||
props: {
|
const emit = defineEmits<{
|
||||||
modelValue: {
|
(ev: 'update:modelValue', value: string): void;
|
||||||
required: true,
|
}>();
|
||||||
},
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
const options = this.$slots.default();
|
|
||||||
|
|
||||||
return withDirectives(h('div', {
|
const props = defineProps<{
|
||||||
class: 'pxhvhrfw',
|
modelValue: string;
|
||||||
}, options.map(option => withDirectives(h('button', {
|
options: {
|
||||||
class: ['_button', { active: this.modelValue === option.props.value }],
|
value: string;
|
||||||
key: option.key,
|
label: string;
|
||||||
disabled: this.modelValue === option.props.value,
|
};
|
||||||
onClick: () => {
|
}>();
|
||||||
this.$emit('update:modelValue', option.props.value);
|
|
||||||
},
|
|
||||||
}, option.children), [
|
|
||||||
[resolveDirective('click-anime')],
|
|
||||||
]))), [
|
|
||||||
[resolveDirective('size'), { max: [500] }],
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<MkSpacer :content-max="800">
|
<MkSpacer :content-max="800">
|
||||||
<MkTab v-model="tab" style="margin-bottom: var(--margin);">
|
<MkTab v-model="tab" :options="tabs" style="margin-bottom: var(--margin);"/>
|
||||||
<option value="notes">{{ i18n.ts.notes }}</option>
|
|
||||||
<option value="polls">{{ i18n.ts.poll }}</option>
|
|
||||||
</MkTab>
|
|
||||||
<XNotes v-if="tab === 'notes'" :pagination="paginationForNotes"/>
|
<XNotes v-if="tab === 'notes'" :pagination="paginationForNotes"/>
|
||||||
<XNotes v-else-if="tab === 'polls'" :pagination="paginationForPolls"/>
|
<XNotes v-else-if="tab === 'polls'" :pagination="paginationForPolls"/>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
|
@ -14,6 +11,14 @@ import XNotes from '@/components/notes.vue';
|
||||||
import MkTab from '@/components/tab.vue';
|
import MkTab from '@/components/tab.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
|
const tabs = [{
|
||||||
|
value: 'notes',
|
||||||
|
label: i18n.ts.notes,
|
||||||
|
}, {
|
||||||
|
value: 'polls',
|
||||||
|
label: i18n.ts.poll,
|
||||||
|
}];
|
||||||
|
|
||||||
const paginationForNotes = {
|
const paginationForNotes = {
|
||||||
endpoint: 'notes/featured' as const,
|
endpoint: 'notes/featured' as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
|
|
@ -47,7 +47,6 @@ import XUserList from '@/components/user-list.vue';
|
||||||
import MkFolder from '@/components/ui/folder.vue';
|
import MkFolder from '@/components/ui/folder.vue';
|
||||||
import MkInput from '@/components/form/input.vue';
|
import MkInput from '@/components/form/input.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import MkTab from '@/components/tab.vue';
|
|
||||||
import MkPagination from '@/components/ui/pagination.vue';
|
import MkPagination from '@/components/ui/pagination.vue';
|
||||||
import MkGalleryPostPreview from '@/components/gallery-post-preview.vue';
|
import MkGalleryPostPreview from '@/components/gallery-post-preview.vue';
|
||||||
import number from '@/filters/number';
|
import number from '@/filters/number';
|
||||||
|
|
|
@ -45,7 +45,6 @@ import MkPagination from '@/components/ui/pagination.vue';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import MkContainer from '@/components/ui/container.vue';
|
import MkContainer from '@/components/ui/container.vue';
|
||||||
import MkAvatars from '@/components/avatars.vue';
|
import MkAvatars from '@/components/avatars.vue';
|
||||||
import MkTab from '@/components/tab.vue';
|
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="_formRoot">
|
<div class="_formRoot">
|
||||||
<MkTab v-model="tab" style="margin-bottom: var(--margin);">
|
<MkTab v-model="tab" :options="tabs" style="margin-bottom: var(--margin);"/>
|
||||||
<option value="mute">{{ i18n.ts.mutedUsers }}</option>
|
|
||||||
<option value="block">{{ i18n.ts.blockedUsers }}</option>
|
|
||||||
</MkTab>
|
|
||||||
<div v-if="tab === 'mute'">
|
<div v-if="tab === 'mute'">
|
||||||
<MkPagination :pagination="mutingPagination" class="muting">
|
<MkPagination :pagination="mutingPagination" class="muting">
|
||||||
<template #empty><FormInfo>{{ i18n.ts.noUsers }}</FormInfo></template>
|
<template #empty><FormInfo>{{ i18n.ts.noUsers }}</FormInfo></template>
|
||||||
|
@ -39,6 +36,14 @@ import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
|
||||||
let tab = $ref('mute');
|
let tab = $ref('mute');
|
||||||
|
|
||||||
|
const tabs = [{
|
||||||
|
value: 'mute',
|
||||||
|
label: i18n.ts.mutedUsers,
|
||||||
|
}, {
|
||||||
|
value: 'block',
|
||||||
|
label: i18n.ts.blockedUsers,
|
||||||
|
}];
|
||||||
|
|
||||||
const mutingPagination = {
|
const mutingPagination = {
|
||||||
endpoint: 'mute/list' as const,
|
endpoint: 'mute/list' as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="_formRoot">
|
<div class="_formRoot">
|
||||||
<MkTab v-model="tab" class="_formBlock">
|
<MkTab v-model="tab" :options="tabs" class="_formBlock"/>
|
||||||
<option value="soft">{{ i18n.ts._wordMute.soft }}</option>
|
|
||||||
<option value="hard">{{ i18n.ts._wordMute.hard }}</option>
|
|
||||||
</MkTab>
|
|
||||||
<div class="_formBlock">
|
<div class="_formBlock">
|
||||||
<div v-show="tab === 'soft'">
|
<div v-show="tab === 'soft'">
|
||||||
<MkInfo class="_formBlock">{{ i18n.ts._wordMute.softDescription }}</MkInfo>
|
<MkInfo class="_formBlock">{{ i18n.ts._wordMute.softDescription }}</MkInfo>
|
||||||
|
@ -50,6 +47,14 @@ const render = (mutedWords) => mutedWords.map(x => {
|
||||||
}
|
}
|
||||||
}).join('\n');
|
}).join('\n');
|
||||||
|
|
||||||
|
const tabs = [{
|
||||||
|
value: 'soft',
|
||||||
|
label: i18n.ts._wordMute.soft,
|
||||||
|
}, {
|
||||||
|
value: 'hard',
|
||||||
|
label: i18n.ts._wordMute.hard,
|
||||||
|
}];
|
||||||
|
|
||||||
const tab = ref('soft');
|
const tab = ref('soft');
|
||||||
const softMutedWords = ref(render(defaultStore.state.mutedWords));
|
const softMutedWords = ref(render(defaultStore.state.mutedWords));
|
||||||
const hardMutedWords = ref(render($i!.mutedWords));
|
const hardMutedWords = ref(render($i!.mutedWords));
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-sticky-container class="yrzkoczt">
|
<div v-sticky-container class="yrzkoczt">
|
||||||
<MkTab v-model="include" class="tab">
|
<MkTab v-model="include" :options="tabs" class="tab"/>
|
||||||
<option :value="null">{{ i18n.ts.notes }}</option>
|
|
||||||
<option value="replies">{{ i18n.ts.notesAndReplies }}</option>
|
|
||||||
<option value="files">{{ i18n.ts.withFiles }}</option>
|
|
||||||
</MkTab>
|
|
||||||
<XNotes :no-gap="true" :pagination="pagination"/>
|
<XNotes :no-gap="true" :pagination="pagination"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import * as foundkey from 'foundkey-js';
|
import * as foundkey from 'foundkey-js';
|
||||||
import XNotes from '@/components/notes.vue';
|
import XNotes from '@/components/notes.vue';
|
||||||
import MkTab from '@/components/tab.vue';
|
import MkTab from '@/components/tab.vue';
|
||||||
|
@ -21,15 +17,26 @@ const props = defineProps<{
|
||||||
user: foundkey.entities.UserDetailed;
|
user: foundkey.entities.UserDetailed;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const include = ref<string | null>(null);
|
const tabs = [{
|
||||||
|
value: 'notes',
|
||||||
|
label: i18n.ts.notes,
|
||||||
|
}, {
|
||||||
|
value: 'replies',
|
||||||
|
label: i18n.ts.notesAndReplies,
|
||||||
|
}, {
|
||||||
|
value: 'files',
|
||||||
|
label: i18n.ts.withFiles,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let include: string = $ref('notes');
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
endpoint: 'users/notes' as const,
|
endpoint: 'users/notes' as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
params: computed(() => ({
|
params: computed(() => ({
|
||||||
userId: props.user.id,
|
userId: props.user.id,
|
||||||
includeReplies: include.value === 'replies',
|
includeReplies: include === 'replies',
|
||||||
withFiles: include.value === 'files',
|
withFiles: include === 'files',
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue