Added main page (show posts)
parent
56ac00655b
commit
c9c2c709a0
@ -0,0 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
type Post = {
|
||||
title: String
|
||||
description: String | null | undefined
|
||||
}
|
||||
|
||||
const props = defineProps<Post>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex w-full flex-col gap-6 bg-secondary p-6">
|
||||
<div class="h-full truncate text-xl font-bold">
|
||||
{{ props.title }}
|
||||
</div>
|
||||
<div class="h-full">
|
||||
{{ props.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -0,0 +1,22 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
const PostValidator = z.object({
|
||||
sequence: z.number(),
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
description: z.string().nullish(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
})
|
||||
|
||||
const parsePost = (data: unknown) => {
|
||||
return PostValidator.parse(data)
|
||||
}
|
||||
|
||||
const PostsValidator = PostValidator.array()
|
||||
|
||||
const parsePosts = (data: unknown[]) => {
|
||||
return PostsValidator.parse(data)
|
||||
}
|
||||
|
||||
export { parsePost, parsePosts, PostsValidator, PostValidator }
|
||||
@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
type Posts = z.infer<typeof PostsValidator>
|
||||
|
||||
const posts = ref<Posts>([])
|
||||
const lastPost = ref<Number>(0)
|
||||
|
||||
const responseValidator = z.object({
|
||||
status: z.number(),
|
||||
data: z.unknown().array(),
|
||||
})
|
||||
|
||||
const getPosts = async () => {
|
||||
const data = await $fetch('http://dev.local:8000/api/posts', {
|
||||
method: 'GET',
|
||||
params: { lastPost: lastPost.value },
|
||||
})
|
||||
|
||||
const response = responseValidator.parse(data)
|
||||
|
||||
posts.value = [...posts.value, ...parsePosts(response.data)]
|
||||
lastPost.value = posts.value[posts.value.length - 1].sequence
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getPosts()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex w-full items-center justify-center">
|
||||
<div class="flex w-1/2 flex-col gap-4 px-4 pb-10 pt-2 2xl:w-1/3">
|
||||
<div v-if="posts" v-for="post in posts">
|
||||
<PostCard :title="post.title" :description="post.description" />
|
||||
</div>
|
||||
<button @click="getPosts()">More {{ lastPost }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Reference in New Issue