From 04b8a91e8043ebbcdca59eb6d1a26c0ed0697b94 Mon Sep 17 00:00:00 2001
From: Izan Gil <66965250+SrIzan10@users.noreply.github.com>
Date: Mon, 6 Jan 2025 22:31:26 +0100
Subject: [PATCH] feat: post browser infinite scroll
---
src/app/(public)/api/posts/route.ts | 22 ++++++
src/app/(public)/page.tsx | 25 +------
.../app/PostBrowser/PostBrowser.tsx | 64 +++++++++++++++++
src/components/ui/infinite-scroll.tsx | 68 +++++++++++++++++++
src/instrumentation.ts | 2 +-
5 files changed, 158 insertions(+), 23 deletions(-)
create mode 100644 src/app/(public)/api/posts/route.ts
create mode 100644 src/components/app/PostBrowser/PostBrowser.tsx
create mode 100644 src/components/ui/infinite-scroll.tsx
diff --git a/src/app/(public)/api/posts/route.ts b/src/app/(public)/api/posts/route.ts
new file mode 100644
index 0000000..7855818
--- /dev/null
+++ b/src/app/(public)/api/posts/route.ts
@@ -0,0 +1,22 @@
+import prisma from '@/lib/db';
+import { type NextRequest } from 'next/server';
+
+export async function GET(request: NextRequest) {
+ const searchParams = request.nextUrl.searchParams;
+ const page = parseInt(searchParams.get('page')!);
+ if (page && isNaN(page)) {
+ return new Response('Invalid page number', { status: 400 });
+ }
+
+ const queryPosts = await prisma.post.findMany({
+ take: 30,
+ skip: page * 30,
+ orderBy: { createdAt: 'desc' },
+ });
+
+ return new Response(JSON.stringify(queryPosts), {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+}
diff --git a/src/app/(public)/page.tsx b/src/app/(public)/page.tsx
index 101a6da..f2a5dae 100644
--- a/src/app/(public)/page.tsx
+++ b/src/app/(public)/page.tsx
@@ -1,3 +1,4 @@
+import PostBrowser from '@/components/app/PostBrowser/PostBrowser';
import prisma from '@/lib/db';
import Image from 'next/image';
import Link from 'next/link';
@@ -13,30 +14,10 @@ export default async function Home() {
{Boolean(process.env.SAFEBOORU_PULL) && (
- Development instance is pulling the first 30 safebooru images it finds for demonstration
- purposes.
+ This development instance pulls some safebooru images for testing.
)}
-
- {posts.map((post) => (
-
-
-
-
- ))}
-
+
);
}
diff --git a/src/components/app/PostBrowser/PostBrowser.tsx b/src/components/app/PostBrowser/PostBrowser.tsx
new file mode 100644
index 0000000..f6105dd
--- /dev/null
+++ b/src/components/app/PostBrowser/PostBrowser.tsx
@@ -0,0 +1,64 @@
+'use client';
+
+import React from 'react';
+import InfiniteScroll from '@/components/ui/infinite-scroll';
+import { Skeleton } from '@/components/ui/skeleton';
+import { Post } from '@prisma/client';
+import Image from 'next/image';
+import Link from 'next/link';
+
+export default function PostBrowser() {
+ const [page, setPage] = React.useState(0);
+ const [loading, setLoading] = React.useState(false);
+ const [hasMore, setHasMore] = React.useState(true);
+ const [posts, setPosts] = React.useState([]);
+
+ const next = async () => {
+ setLoading(true);
+ const res = await fetch(`/api/posts?page=${page}`);
+ const newImages = await res.json();
+ if (!newImages.length) {
+ setHasMore(false);
+ setLoading(false);
+ return;
+ }
+ setPosts((prev) => [...prev, ...newImages]);
+ setPage((prev) => prev + 1);
+ setLoading(false);
+ };
+
+ return (
+
+