diff --git a/src/app/(pages)/home/page.tsx b/src/app/(pages)/home/page.tsx index 39556c8..def28f9 100644 --- a/src/app/(pages)/home/page.tsx +++ b/src/app/(pages)/home/page.tsx @@ -1,94 +1,18 @@ -import { getArticlesPaginated } from '@/lib/feature/article/article.external'; -import { ArticleCard } from '@/ui/components/internal/article-card'; -import { ArticleListPagination } from '@/ui/components/internal/article-list-pagination'; -import { FileTextIcon } from 'lucide-react'; +import { ArticleList } from '@/ui/components/internal/article/article-list'; +import { ArticleListSkeleton } from '@/ui/components/internal/article/article-list-skeleton'; import { Suspense } from 'react'; -const PAGE_SIZE = 9; -const ArticleCardSkeleton = () => ( -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-); -const ArticleListSkeleton = () => ( - <> -
-
- {Array.from({ length: PAGE_SIZE }).map((_, i) => ( - - ))} -
- -); -type ArticleListProps = { - searchParams: Promise<{ page?: string; pageSize?: string }>; -}; -const ArticleList = async ({ searchParams }: ArticleListProps) => { - const { page: pageParam, pageSize: pageSizeParam } = await searchParams; - const page = Math.max(1, Number(pageParam) || 1); - const pageSize = Number(pageSizeParam) || PAGE_SIZE; - const paginationResult = await getArticlesPaginated(page, pageSize); - if (!paginationResult.ok) throw paginationResult.error; - const { data: articles, totalPages, total } = paginationResult.value; - return ( - <> -

- {total === 0 - ? 'No articles published yet.' - : `${total} article${total === 1 ? '' : 's'} published`} -

- {articles.length === 0 ? ( -
- -

- No articles yet. Check back soon! -

-
- ) : ( -
- {articles.map((article) => ( - - ))} -
- )} - {totalPages > 1 && ( -
-

- Page {page} of {totalPages} -

- -
- )} - - ); -}; + + +const PAGE_SIZE = 4; type HomeProps = { searchParams: Promise<{ page?: string; pageSize?: string }>; @@ -105,8 +29,13 @@ const Home = async ({ searchParams }: HomeProps) => { Latest Articles
- }> - + } + > +
); diff --git a/src/lib/feature/article/article.external.ts b/src/lib/feature/article/article.external.ts index fb377f6..83d6c57 100644 --- a/src/lib/feature/article/article.external.ts +++ b/src/lib/feature/article/article.external.ts @@ -39,6 +39,8 @@ export const getArticlesPaginated: ( page: number = 1, pageSize: number = 10 ): Promise => { + // await new Promise((r) => setTimeout(r, 1000)); + const result = await service.getArticlesPaginated(page, pageSize); if (!result.ok) throw result.error; return result.value; diff --git a/src/lib/storage/storage.adapter.ts b/src/lib/storage/storage.adapter.ts index 5ddc916..d4cca79 100644 --- a/src/lib/storage/storage.adapter.ts +++ b/src/lib/storage/storage.adapter.ts @@ -3,7 +3,6 @@ import { TypedResult, wrap } from '@/utils/types/results'; import { DeleteObjectCommand, HeadObjectCommand, - ObjectCannedACL, PutObjectCommand, S3Client, } from '@aws-sdk/client-s3'; diff --git a/src/lib/storage/storage.external.ts b/src/lib/storage/storage.external.ts index 2454490..81d4638 100644 --- a/src/lib/storage/storage.external.ts +++ b/src/lib/storage/storage.external.ts @@ -14,10 +14,6 @@ export const getPublicUrl = async ( if (!storageProvider) { storageProvider = storage; } - const session = await getSessionData(); - if (!session || !session?.user || session?.user.role !== 'admin') { - throw new Error('Unauthorized: Only admin users can delete articles.'); - } return await storageProvider.get(key); }; diff --git a/src/proxy.ts b/src/proxy.ts index daeadd5..426efa0 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -2,9 +2,15 @@ import { getSessionData } from '@/lib/session/session-storage'; import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'; import { NextResponse } from 'next/server'; + + + + + const isPublic = createRouteMatcher([ '/home(.*)?', '/about(.*)?', + '/article(.*)?', '/api/user(.*)?', ]); diff --git a/src/ui/components/internal/article/article-list-skeleton.tsx b/src/ui/components/internal/article/article-list-skeleton.tsx new file mode 100644 index 0000000..e9a74d0 --- /dev/null +++ b/src/ui/components/internal/article/article-list-skeleton.tsx @@ -0,0 +1,33 @@ +export const ArticleCardSkeleton = () => ( +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+); + +export const ArticleListSkeleton = ({ + skeletonSize, +}: { + skeletonSize: number; +}) => ( + <> +
+
+ {Array.from({ length: skeletonSize }).map((_, i) => ( + + ))} +
+ +); diff --git a/src/ui/components/internal/article/article-list.tsx b/src/ui/components/internal/article/article-list.tsx new file mode 100644 index 0000000..1ede796 --- /dev/null +++ b/src/ui/components/internal/article/article-list.tsx @@ -0,0 +1,87 @@ +// 'use client'; +import { getArticlesPaginated } from '@/lib/feature/article/article.external'; +import { ArticleCard } from '@/ui/components/internal/article-card'; +import { ArticleListPagination } from '@/ui/components/internal/article-list-pagination'; +import { FileTextIcon } from 'lucide-react'; + + + + + + + + + + + + + + + +type ArticleListProps = { + searchParams: Promise<{ page?: string; pageSize?: string }>; + defaultPageSize: number; +}; + +export const ArticleList = async ({ + searchParams, + defaultPageSize, +}: ArticleListProps) => { + const { page: pageParam, pageSize: pageSizeParam } = await searchParams; + const page = Math.max(1, Number(pageParam) || 1); + const pageSize = Number(pageSizeParam) || defaultPageSize; + + const paginationResult = await getArticlesPaginated(page, pageSize); + + if (!paginationResult.ok) { + return ( +
+ +

+ Failed to load articles. Please try again later. +

+
+ ); + } + const { data: articles, totalPages, total } = paginationResult.value; + + return ( + <> +

+ {total === 0 + ? 'No articles published yet.' + : `${total} article${total === 1 ? '' : 's'} published`} +

+ + {articles.length === 0 ? ( +
+ +

+ No articles yet. Check back soon! +

+
+ ) : ( +
+ {articles.map((article) => ( + + ))} +
+ )} + + {totalPages > 1 && ( +
+

+ Page {page} of {totalPages} +

+ +
+ )} + + ); +};