141 lines
3.1 KiB
Vue
141 lines
3.1 KiB
Vue
<template>
|
|
<div class="index-page">
|
|
<div class="index-page__search">
|
|
<UInput
|
|
:model-value="search"
|
|
size="xl"
|
|
class="w-full"
|
|
placeholder="Поиск..."
|
|
:loading="postsIsLoading || usersIsLoading"
|
|
@update:model-value="updateSearch"
|
|
/>
|
|
</div>
|
|
|
|
<UiTable :table-data="tableData" :columns="columns" />
|
|
|
|
<UserModal v-model:model-value="open" :selected-user="selectedUser" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { UiTableShortText } from '#components'
|
|
import {
|
|
createColumnHelper,
|
|
} from '@tanstack/vue-table'
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
import { useGetPosts, useGetUsers } from '~/api/queries'
|
|
import UserModal from '~/components/modals/UserModal.vue'
|
|
import UiTable from '~/components/UiTable.vue'
|
|
|
|
const open = ref(false)
|
|
const selectedUser = ref<User | null>(null)
|
|
const search = ref('')
|
|
const updateSearch = useDebounceFn((value: string) => {
|
|
search.value = value
|
|
}, 500)
|
|
const { data: posts, isLoading: postsIsLoading } = useGetPosts(search)
|
|
const { data: users, isLoading: usersIsLoading } = useGetUsers()
|
|
|
|
const tableData = computed(() => (posts?.value ?? []).map(post => ({
|
|
userId: post?.userId,
|
|
userEmail: users?.value?.find(user => user?.id === post?.userId)?.email,
|
|
id: post?.id,
|
|
title: post?.title,
|
|
body: post?.body,
|
|
})))
|
|
|
|
const columnHelper = createColumnHelper<Posts>()
|
|
const columns = [
|
|
columnHelper.accessor('id', {
|
|
header: 'ID',
|
|
footer: props => props?.column?.id,
|
|
meta: {
|
|
style: {
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
},
|
|
size: 50,
|
|
}),
|
|
columnHelper.accessor('title', {
|
|
header: 'Заголовок',
|
|
cell: info => h(UiTableShortText, {
|
|
text: info.getValue(),
|
|
maxLength: 10,
|
|
}),
|
|
size: 150,
|
|
}),
|
|
columnHelper.accessor('userEmail', {
|
|
header: 'Автор',
|
|
cell: info =>
|
|
h(UiTableShortText, {
|
|
text: info.getValue(),
|
|
hideIcon: true,
|
|
class: 'title-cell',
|
|
onClick: () => openPost(info.row.original),
|
|
}),
|
|
meta: {
|
|
style: {
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
},
|
|
size: 170,
|
|
}),
|
|
columnHelper.accessor('body', {
|
|
header: 'Контент',
|
|
cell: info => h(UiTableShortText, {
|
|
text: info.getValue(),
|
|
maxLength: 18,
|
|
}),
|
|
size: 230,
|
|
}),
|
|
]
|
|
|
|
function openPost(post: Post) {
|
|
selectedUser.value = users?.value?.find(user => user?.id === post?.userId)
|
|
open.value = true
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.index-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
max-width: 600px;
|
|
margin-inline: auto;
|
|
padding-bottom: 40px;
|
|
position: relative;
|
|
|
|
&__search {
|
|
position: fixed;
|
|
top: 48px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
max-width: 600px;
|
|
width: 100%;
|
|
|
|
z-index: 1000;
|
|
background: var(--ui-bg-base);
|
|
|
|
@include mobile {
|
|
padding-inline: 10px;
|
|
}
|
|
}
|
|
}
|
|
|
|
//userEmail
|
|
.title-cell {
|
|
cursor: pointer;
|
|
text-decoration: underline;
|
|
color: var(--ui-primary);
|
|
}
|
|
|
|
.title-cell:hover {
|
|
color: var(--ui-primary-hover);
|
|
}
|
|
</style>
|