Compare commits

...

4 Commits

@ -21,7 +21,4 @@ RUN apt-get update \
php8.2-memcached php8.2-pcov php8.2-xdebug \ php8.2-memcached php8.2-pcov php8.2-xdebug \
&& curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer
EXPOSE 8080
CMD ["/bin/bash", "-c", "php artisan migrate && php artisan serve --host=0.0.0.0"] CMD ["/bin/bash", "-c", "php artisan migrate && php artisan serve --host=0.0.0.0"]

@ -14,15 +14,25 @@ class PostController extends Controller
$request->validate( $request->validate(
[ [
'lastPost' => 'required|integer', 'lastPost' => 'required|integer',
'firstPost' => 'required|integer',
'order' => 'required|string|in:new,old',
] ]
); );
$lastPost = $request->lastPost; $lastPost = $request->lastPost;
$firstPost = $request->firstPost;
$posts = Post::query() $postsQuery = Post::query()->with('user')->orderByDesc(column: 'sequence');
->where(column: 'sequence', operator: '>', value: $lastPost)
->take(10) if ($request->order == 'new') {
->get(); $postsQuery->where(column: 'sequence', operator: '>', value: $firstPost);
}
if ($request->order == 'old' && $lastPost != 0) {
$postsQuery->where(column: 'sequence', operator: '<', value: $lastPost);
}
$posts = $postsQuery->take(10)->get();
return response( return response(
[ [

@ -5,10 +5,16 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model class Post extends Model
{ {
use HasFactory, HasUuids; use HasFactory, HasUuids;
protected $fillable = ['title', 'description']; protected $fillable = ['title', 'description'];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
} }

@ -15,7 +15,7 @@ services:
context: ./backend context: ./backend
dockerfile: Dockerfile dockerfile: Dockerfile
volumes: [./backend:/var/www/html:Z] volumes: [./backend:/var/www/html:Z]
ports: [8080:8080] ports: [8000:8000]
networks: [twitter] networks: [twitter]
depends_on: [mysql] depends_on: [mysql]
mysql: mysql:

@ -0,0 +1 @@
LARAVEL_API=http://localhost:8000

@ -1,7 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
type Post = { type Post = {
user: {
name: String
}
title: String title: String
description: String description: String
created_at: string
} }
const props = defineProps<Post>() const props = defineProps<Post>()
@ -10,6 +14,15 @@ const props = defineProps<Post>()
<template> <template>
<div> <div>
<div class="flex w-full flex-col gap-6 rounded-md border border-lightgray bg-secondary p-6"> <div class="flex w-full flex-col gap-6 rounded-md border border-lightgray bg-secondary p-6">
<div class="flex justify-between">
<div class="flex h-full gap-4">
<Icon name="user" />
{{ props.user.name }}
</div>
<div>
{{ new Date(props.created_at).toLocaleString() }}
</div>
</div>
<div class="h-full truncate text-xl font-bold"> <div class="h-full truncate text-xl font-bold">
{{ props.title }} {{ props.title }}
</div> </div>

@ -1,5 +1,7 @@
import type { UseFetchOptions } from 'nuxt/app' import type { UseFetchOptions } from 'nuxt/app'
const config = useRuntimeConfig()
const useCustomFetch = async <T>( const useCustomFetch = async <T>(
path: string, path: string,
options: UseFetchOptions<T> = {} options: UseFetchOptions<T> = {}
@ -11,7 +13,7 @@ const useCustomFetch = async <T>(
headers['X-XSRF-TOKEN'] = token.value as string headers['X-XSRF-TOKEN'] = token.value as string
} }
return useFetch('http://localhost:8080' + path, { return useFetch(config.public.laravelApi + path, {
credentials: 'include', credentials: 'include',
watch: false, watch: false,
...options, ...options,

@ -5,8 +5,11 @@ const PostValidator = z.object({
id: z.string(), id: z.string(),
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
created_at: z.string(), created_at: z.string().datetime(),
updated_at: z.string(), updated_at: z.string(),
user: z.object({
name: z.string(),
}),
}) })
const newPostValidator = z.object({ const newPostValidator = z.object({
@ -33,12 +36,12 @@ const createNewPost = async (data: unknown) => {
if (!parsedNewPost.success) return if (!parsedNewPost.success) return
const { data: post } = await useCustomFetch('/api/posts', { await useCustomFetch('/api/posts', {
method: 'POST', method: 'POST',
body: parsedNewPost.data, body: parsedNewPost.data,
}) })
await fetchPosts() await fetchPosts('new')
} }
const responseValidator = z.object({ const responseValidator = z.object({
@ -46,23 +49,31 @@ const responseValidator = z.object({
data: z.unknown().array(), data: z.unknown().array(),
}) })
const fetchPosts = async (refresh: Boolean = false) => { const fetchPosts = async (
order: 'new' | 'old' = 'old',
refresh: Boolean = false
) => {
const posts = usePosts() const posts = usePosts()
const lastPost = refresh const lastPost = refresh
? 0 ? 0
: posts.value.length : posts.value.length
? posts.value[posts.value.length - 1].sequence ? posts.value[posts.value.length - 1].sequence
: 0 : 0
const firstPost = posts.value.length ? posts.value[0].sequence : 0
const { data } = await useCustomFetch('/api/posts', { const { data } = await useCustomFetch('/api/posts', {
params: { lastPost: lastPost }, params: { lastPost: lastPost, firstPost: firstPost, order: order },
}) })
const response = responseValidator.safeParse(data.value) const response = responseValidator.safeParse(data.value)
if (!response.success) return if (!response.success) return
posts.value = [...posts.value, ...parsePosts(response.data.data)] if (order == 'old') {
posts.value = [...posts.value, ...parsePosts(response.data.data)]
} else {
posts.value = [...parsePosts(response.data.data), ...posts.value]
}
} }
export { export {

@ -9,8 +9,7 @@ export default defineNuxtConfig({
}, },
runtimeConfig: { runtimeConfig: {
public: { public: {
api: 'http://dev.local:8000/api', laravelApi: process.env.LARAVEL_API || 'http://localhost:8000',
url: 'http://dev.local:8000',
}, },
}, },
ssr: false, ssr: false,

@ -27,9 +27,10 @@ onMounted(() => {
<div> <div>
<Header /> <Header />
<div class="mt-16 flex w-full items-center justify-center"> <div class="mt-16 flex w-full items-center justify-center">
<div class="flex w-full max-w-2xl flex-col gap-4 px-4 pb-10 pt-4"> <div class="flex w-full max-w-2xl flex-col gap-4 px-4 pb-16 pt-4">
<div v-if="posts" v-for="post in posts"> <div v-if="posts" v-for="post in posts">
<PostCard :title="post.title" :description="post.description" /> <PostCard :title="post.title" :description="post.description" :created_at="post.created_at"
:user="post.user" />
</div> </div>
<button @click="getPosts()"> More </button> <button @click="getPosts()"> More </button>
</div> </div>

Loading…
Cancel
Save