From d52330d191cad00b5d5f1e837a2db1548ebbf302 Mon Sep 17 00:00:00 2001 From: Aidan Date: Thu, 30 Jan 2025 19:59:24 -0500 Subject: [PATCH] migrate all strings to strings.json, reorganize strings.json, bump packages, add todo, rm unnecessary import, minor error fixes --- README.md | 1 + app/admin/layout.tsx | 11 +- app/admin/page.tsx | 42 +++---- app/admin/posts/new/page.tsx | 6 +- app/admin/posts/page.tsx | 24 ++-- app/admin/users/new/page.tsx | 6 +- app/admin/users/page.tsx | 22 ++-- app/categories/page.tsx | 4 +- app/category/[slug]/page.tsx | 39 ++++--- app/page.tsx | 10 +- app/posts/[slug]/page.tsx | 27 ++--- bun.lockb | Bin 251965 -> 253969 bytes components/login-form.tsx | 41 +++---- components/navigation/Navbar.tsx | 4 +- components/navigation/Sidebar.tsx | 28 ++--- .../navigation/sidebar/AdminSidebar.tsx | 14 +-- .../navigation/sidebar/MobileAdminSidebar.tsx | 13 ++- .../navigation/sidebar/MobileSidebar.tsx | 12 +- package.json | 14 +-- strings.json | 110 +++++++++++++++++- 20 files changed, 265 insertions(+), 163 deletions(-) diff --git a/README.md b/README.md index a08e159..710077f 100644 --- a/README.md +++ b/README.md @@ -85,3 +85,4 @@ A simple blogging platform built with Next.js, shadcn/ui and Tailwind CSS. - [ ] Implement a logout animation on `/admin/logout` - [ ] Add a post list w/ management options on `/admin/posts` - [ ] Add a user list w/ management options in `/admin/users` +- [ ] Better error handling in `server/index.js` diff --git a/app/admin/layout.tsx b/app/admin/layout.tsx index d09df91..7132229 100644 --- a/app/admin/layout.tsx +++ b/app/admin/layout.tsx @@ -2,6 +2,7 @@ export const dynamic = 'force-dynamic'; import { useState, useEffect } from 'react'; +import strings from "@/strings.json" export default function AdminLayout({ children }: { children: React.ReactNode }) { const [loading, setLoading] = useState(true); @@ -9,7 +10,7 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) useEffect(() => { if (window.location.pathname.startsWith('/admin/login')) { - console.log("[i] Detected login page, skipping validation"); + console.log(strings.logsDetectedLoginPage); setAuthorized(true); setLoading(false); return; @@ -24,7 +25,7 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) const validate = async () => { const key = cookies.key; if (!key) { - console.log("[!] No key found, clearing cookies and redirecting to login"); + console.log(strings.errorsNoKeyFoundFancy); document.cookie.split(';').forEach((cookie) => { const [name] = cookie.split('='); document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`; @@ -41,16 +42,16 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) }); if (!response.ok) { - console.log('[!] Failed to check key, skipping validation and clearing cookie'); + console.log(strings.errorsFailedKeyCheckFancy); document.cookie = 'key=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'; window.location.href = '/admin/login'; } else { const data = await response.json() if (data.success) { - console.log("[✓] Key is valid"); + console.log(strings.logsKeyIsValid); setAuthorized(true); } else { - console.log("[✖] Key is invalid, clearing cookie and redirecting to login"); + console.log(strings.errorsKeyInvalidFancy); document.cookie = 'key=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'; window.location.href = '/admin/login'; } diff --git a/app/admin/page.tsx b/app/admin/page.tsx index c8c108f..7cbe72b 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -15,7 +15,7 @@ export default function Home() { const [userCtCardLoading, setUserCtCardLoading] = useState(true); useEffect(() => { - console.log("[i] Calculating post count..."); + console.log(strings.logsCalculatingPostCt); (async () => { try { const username = document.cookie.split('; ').find(row => row.startsWith('username='))?.split('=')[1] || ''; @@ -34,9 +34,9 @@ export default function Home() { }); if (!res.ok) { - alert('Failed to fetch total post count'); + alert(strings.errorsFetchTotalPostCtErr); setPostCardError(true); - throw new Error(`Failed to fetch total post count: ${res.status}`); + throw new Error(`${strings.errorsFetchTotalPostCtErr}: ${res.status}`); } const data = await res.json(); @@ -47,25 +47,25 @@ export default function Home() { setPostCardLoading(false); throw new Error(data.message); } else { - alert('Unknown error occurred'); + alert(strings.errorsUnknownError); setPostCardError(true); setPostCardLoading(false); - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else if (data.count) { - console.log("[✓] Total posts:", data.count); + console.log(strings.logsTotalPosts, data.count); setTotalPosts(data.count); setPostCardLoading(false); } } catch (error) { - alert('Error fetching total post count'); + alert(strings.errorsFetchTotalPostCtErr); setPostCardError(true); setPostCardLoading(false); - console.error('[!] Failed to fetch total post count:', error); + console.error(strings.errorsFetchTotalPostCtErrFancy, error); } })(); - console.log("[i] Calculating user count..."); + console.log(strings.logsCalculatingUserCt); (async () => { try { const username = document.cookie.split('; ').find(row => row.startsWith('username='))?.split('=')[1] || ''; @@ -84,9 +84,9 @@ export default function Home() { }); if (!res.ok) { - alert('Failed to fetch total user count'); + alert(strings.errorsFetchTotalUserCtErr); setUserCtCardError(true); - throw new Error(`Failed to fetch total user count: ${res.status}`); + throw new Error(`${strings.errorsFetchTotalUserCtErr}: ${res.status}`); } const data = await res.json(); @@ -97,21 +97,21 @@ export default function Home() { setUserCtCardLoading(false); throw new Error(data.message); } else { - alert('Unknown error occurred'); + alert(strings.errorsUnknownError); setUserCtCardError(true); setUserCtCardLoading(false); - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else if (data.count) { - console.log("[✓] Total users:", data.count); + console.log(strings.logsTotalUsers, data.count); setTotalUsers(data.count); setUserCtCardLoading(false); } } catch (error) { - alert('Error fetching total user count'); + alert(strings.errorsFetchTotalUserCtErr); setUserCtCardError(true); setUserCtCardLoading(false); - console.error('[!] Failed to fetch total user count:', error); + console.error(strings.errorsFetchTotalUserCtErrFancy, error); } })(); }, []); @@ -130,7 +130,7 @@ export default function Home() { ) : userCtCardError ? (
-

Error

+

{strings.errorsSuperGeneric}

) : ( totalUsers @@ -149,7 +149,7 @@ export default function Home() { ) : postCardError ? (
-

Error

+

{strings.errorsSuperGeneric}

) : ( totalPosts @@ -162,19 +162,19 @@ export default function Home() {
- Quick Actions + {strings.adminQuickActionsCardTitle} diff --git a/app/admin/posts/new/page.tsx b/app/admin/posts/new/page.tsx index e878fa1..08bc2a6 100644 --- a/app/admin/posts/new/page.tsx +++ b/app/admin/posts/new/page.tsx @@ -43,13 +43,13 @@ export default function CreatePost() { }); if (!response.ok) { - throw new Error('Failed to create post'); + throw new Error(strings.errorsCreatePostFail); } const data = await response.json(); - console.log('Success:', data); + console.log(`${strings.successSuperGeneric}: ${data}`); } catch (error) { - console.error('Error:', error); + console.error(`${strings.errorsSuperGeneric}: ${error}`); } console.log({ title, description, category, slug, content, date }) } diff --git a/app/admin/posts/page.tsx b/app/admin/posts/page.tsx index 295d433..a0bff07 100644 --- a/app/admin/posts/page.tsx +++ b/app/admin/posts/page.tsx @@ -12,7 +12,7 @@ export default function Posts() { const [postCardLoading, setPostCardLoading] = useState(true); useEffect(() => { - console.log("[i] Calculating post count..."); + console.log(strings.logsCalculatingPostCt); (async () => { try { const username = document.cookie.split('; ').find(row => row.startsWith('username='))?.split('=')[1] || ''; @@ -31,9 +31,9 @@ export default function Posts() { }); if (!res.ok) { - alert('Failed to fetch total post count'); + alert(strings.errorsFetchTotalPostCtErr); setPostCardError(true); - throw new Error(`Failed to fetch total post count: ${res.status}`); + throw new Error(`${strings.errorsFetchTotalPostCtErr}: ${res.status}`); } const data = await res.json(); @@ -44,38 +44,38 @@ export default function Posts() { setPostCardLoading(false); throw new Error(data.message); } else { - alert('Unknown error occurred'); + alert(strings.errorsUnknownError); setPostCardError(true); setPostCardLoading(false); - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else if (data.count) { - console.log("[✓] Total posts:", data.count); + console.log(strings.logsTotalPosts, data.count); setTotalPosts(data.count); setPostCardLoading(false); } } catch (error) { - alert('Error fetching total post count'); + alert(strings.errorsFetchTotalPostCtErr); setPostCardError(true); setPostCardLoading(false); - console.error('[!] Failed to fetch total post count:', error); + console.error(strings.errorsFetchTotalPostCtErrFancy, error); } })(); }, []); return (
-

Posts

+

{strings.postsHeader}

- Quick Actions + {strings.adminQuickActionsCardTitle} @@ -90,7 +90,7 @@ export default function Posts() { ) : postCardError ? (
-

Error

+

{strings.errorsSuperGeneric}

) : ( totalPosts diff --git a/app/admin/users/new/page.tsx b/app/admin/users/new/page.tsx index 347d946..eee7625 100644 --- a/app/admin/users/new/page.tsx +++ b/app/admin/users/new/page.tsx @@ -24,13 +24,13 @@ export default function CreateUser() { }); if (!response.ok) { - throw new Error('Failed to create user'); + throw new Error(strings.errorsCreateUserFail); } const data = await response.json(); - console.log('Success:', data); + console.log(`${strings.successSuperGeneric}: ${data}`); } catch (error) { - console.error('Error:', error); + console.error(`${strings.errorsSuperGeneric}: ${error}`); } console.log({ username, email, password }) } diff --git a/app/admin/users/page.tsx b/app/admin/users/page.tsx index 2995340..17e61ac 100644 --- a/app/admin/users/page.tsx +++ b/app/admin/users/page.tsx @@ -12,7 +12,7 @@ export default function Users() { const [userCtCardLoading, setUserCtCardLoading] = useState(true); useEffect(() => { - console.log("[i] Calculating user count..."); + console.log(strings.logsCalculatingUserCt); (async () => { try { const username = document.cookie.split('; ').find(row => row.startsWith('username='))?.split('=')[1] || ''; @@ -31,9 +31,9 @@ export default function Users() { }); if (!res.ok) { - alert('Failed to fetch total user count'); + alert(strings.errorsFetchTotalUserCtErr); setUserCtCardError(true); - throw new Error(`Failed to fetch total user count: ${res.status}`); + throw new Error(`${strings.errorsFetchTotalUserCtErr}: ${res.status}`); } const data = await res.json(); @@ -44,21 +44,21 @@ export default function Users() { setUserCtCardLoading(false); throw new Error(data.message); } else { - alert('Unknown error occurred'); + alert(strings.errorsUnknownError); setUserCtCardError(true); setUserCtCardLoading(false); - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else if (data.count) { - console.log("[✓] Total users:", data.count); + console.log(strings.logsTotalUsers, data.count); setTotalUsers(data.count); setUserCtCardLoading(false); } } catch (error) { - alert('Error fetching total user count'); + alert(strings.errorsFetchTotalUserCtErr); setUserCtCardError(true); setUserCtCardLoading(false); - console.error('[!] Failed to fetch total user count:', error); + console.error(strings.errorsFetchTotalUserCtErrFancy, error); } })(); }, []); @@ -69,13 +69,13 @@ export default function Users() {
- Quick Actions + {strings.adminQuickActionsCardTitle} @@ -90,7 +90,7 @@ export default function Users() { ) : userCtCardError ? (
-

Error

+

{strings.errorsSuperGeneric}

) : ( totalUsers diff --git a/app/categories/page.tsx b/app/categories/page.tsx index d95da03..513a7d0 100644 --- a/app/categories/page.tsx +++ b/app/categories/page.tsx @@ -36,8 +36,8 @@ export default function Home() { setLoading(false) }) .catch((error) => { - console.error("[!] Error fetching data:", error) - setError("Failed to fetch data") + console.error(strings.errorsFetchDataErrCtxFancy, error) + setError(strings.errorsFetchDataFail) setLoading(false) }) }, []) diff --git a/app/category/[slug]/page.tsx b/app/category/[slug]/page.tsx index 4cc0b02..00ba658 100644 --- a/app/category/[slug]/page.tsx +++ b/app/category/[slug]/page.tsx @@ -2,11 +2,18 @@ import { useEffect, useState } from 'react'; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" -import { Badge } from "@/components/ui/badge" import Link from "next/link" import strings from "@/strings.json" import { formatDistanceToNow, format } from 'date-fns' +type Post = { + id: string; + title: string; + description: string; + date: number; + slug: string; +}; + export default function CategorySlug() { const [posts, setPosts] = useState([]); const [error, setError] = useState(''); @@ -14,7 +21,7 @@ export default function CategorySlug() { const [loading, setLoading] = useState(true); useEffect(() => { - console.log("[i] Fetching post list..."); + console.log(strings.logsFetchPostList); (async () => { try { const catReq = await fetch(`http://localhost:3001/api/categories/fetchList`, { @@ -26,49 +33,53 @@ export default function CategorySlug() { }); if (!catReq.ok) { - throw new Error(`Failed to fetch category list: ${catReq.status}`); + throw new Error(`${strings.errorsFetchCategoryListFailCtx} ${catReq.status}`); } if (!postReq.ok) { - throw new Error(`Failed to fetch post list: ${postReq.status}`); + throw new Error(`${strings.errorsFetchPostListFailCtx} ${postReq.status}`); } const catData = await catReq.json(); const postData = await postReq.json(); if (!catData) { - setError('Failed to fetch category list'); + setError(strings.errorsFetchCategoryListFail); } else { - console.log("[✓] Fetched categories"); + console.log(strings.logsOnFetchedCategory); const slug = window.location.pathname.split('/').slice(-1)[0]; const category = catData.categories.find((cat: { slug: string }) => cat.slug === slug); if (category) { - console.log(`[✓] Found category: ${category.name}`); + console.log(`${strings.logsOnFoundCategory} ${category.name}`); setCategory(category.name); if (postData.success === false) { if (postData.message) { throw new Error(postData.message); } else { - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else { - const sortedPosts = postData.posts.sort((a, b) => b.date - a.date); + const sortedPosts = postData.posts.sort((a: Post, b: Post) => b.date - a.date); setPosts(sortedPosts); } } else { - setError('Could not find requested category'); - throw new Error(`Category with slug "${slug}" not found`); + setError(strings.errorsFetchCategoryNotFound); + throw new Error(strings.errorsFetchCategoryNotFound); } } } catch (error) { - console.error('[!] Error fetching post list:', error); - setError('Failed to fetch post list. Please try again later.'); + console.error(strings.errorsFetchPostListErrCtxFancy, error); + setError(strings.errorsFetchPostListErr); } finally { setLoading(false); } })(); }, []); - const formatDate = (timestamp) => { + interface FormatDate { + (timestamp: number): string; + } + + const formatDate: FormatDate = (timestamp) => { const date = new Date(timestamp * 1000); const now = new Date(); if (date.getFullYear() !== now.getFullYear()) { diff --git a/app/page.tsx b/app/page.tsx index 6431e6f..6ba374a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -22,7 +22,7 @@ export default function Home() { const [loading, setLoading] = useState(true); useEffect(() => { - console.log("[i] Fetching post list..."); + console.log(strings.logsFetchPostList); (async () => { try { const res = await fetch(`http://localhost:3001/api/posts/fetchList`, { @@ -30,7 +30,7 @@ export default function Home() { }); if (!res.ok) { - throw new Error(`Failed to fetch post list: ${res.status}`); + throw new Error(`${strings.errorsFetchPostListFailCtx} ${res.status}`); } const data = await res.json(); @@ -38,15 +38,15 @@ export default function Home() { if (data.message) { throw new Error(data.message); } else { - throw new Error('Unknown error occurred'); + throw new Error(strings.errorsUnknownError); } } else { const sortedPosts: Post[] = data.posts.sort((a: Post, b: Post) => b.date - a.date); setPosts(sortedPosts); } } catch (error) { - console.error('[!] Error fetching post list:', error); - setError('Failed to fetch post list. Please try again later.'); + console.error(strings.errorsFetchPostListErrCtx, error); + setError(strings.errorsFetchPostListErr); } finally { setLoading(false); } diff --git a/app/posts/[slug]/page.tsx b/app/posts/[slug]/page.tsx index f0c8e5d..cbbe883 100644 --- a/app/posts/[slug]/page.tsx +++ b/app/posts/[slug]/page.tsx @@ -5,6 +5,7 @@ import remarkGfm from 'remark-gfm'; import { useParams } from 'next/navigation'; import Image from 'next/image'; import { Tag } from 'lucide-react'; +import strings from "@/strings.json" export default function PostPage() { const [markdown, setMarkdown] = useState(''); @@ -24,18 +25,14 @@ export default function PostPage() { } function setPostData(postData: PostData) { - setPostTitle(postData.title || 'Untitled Post'); + setPostTitle(postData.title || strings.blankPostTitlePlaceholder); if (postData.date) { - console.log("[i] Date:", postData.date); const date = new Date(Number(postData.date) * 1000) - console.log("[i] Date object:", date); const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' }; - console.log("[i] Date options:", options); - console.log("[i] Formatted date:", date.toLocaleDateString(undefined, options)); setPostDate(date.toLocaleDateString(undefined, options)); } else { - setPostDate('an unknown date'); + setPostDate(strings.blankPostDatePlaceholder); } if (postData.category) { @@ -43,11 +40,11 @@ export default function PostPage() { } else if (postData.message) { setPostCategory(postData.message); } else { - setPostCategory("Error"); + setPostCategory(strings.errorsSuperGeneric); } } - console.log("[i] Navigated to slug: ", slug); + console.log(strings.logsOnSlugNavigate, slug); (async () => { try { const res = await fetch(`http://localhost:3001/api/posts/get/${slug}`, { @@ -64,8 +61,8 @@ export default function PostPage() { throw new Error(data.message); } else { setLoading(false); - setError('Unknown error occurred'); - throw new Error('Unknown error occurred'); + setError(strings.errorsUnknownError); + throw new Error(strings.errorsUnknownError); } } } else { @@ -81,7 +78,7 @@ export default function PostPage() { if (postData.message) { setPostData(postData); } else { - setPostCategory("Error"); + setPostCategory(strings.errorsSuperGeneric); } } @@ -89,9 +86,9 @@ export default function PostPage() { setLoading(false); } } catch (error) { - console.error('Error fetching post:', error); - setError('Could not load the post.'); - setMarkdown('# Error\n\nCould not load the post.'); + console.error(strings.errorsFetchPostErr, ':', error); + setError(strings.errorsFetchPostErr); + setMarkdown(strings.errorsFetchPostErrMd); } })(); }, [slug]); @@ -113,7 +110,7 @@ export default function PostPage() { return (

{postTitle}

-

Published on {postDate}

+

{strings.postPublishedOnLabel} {postDate}

{postCategory} diff --git a/bun.lockb b/bun.lockb index 329fef5b088282a9f75df2cd5bdcaf3effb9ceb8..94d963f5e3ef5aa21d417c37d5b3186f862b0af5 100755 GIT binary patch delta 5345 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 delta 4702 zcmeHKX;c+Q7VfSV;UW8?EP{Ya&9@A%eKVQ%gmo z;}XOKP#E)6M4tf_+))!8LnKZXl|(oa^~l>etdPms=8J8*6n`X zm2$(DBZiw@#^`yr=Nm`vD886g@$AQn)Xlr)AvY^*tAi{i-P`%${<8&jT>{6h$jYb@ zWOc~VWfOHJl^Gmo%5lXmnH)C+Tn9D)+k%b2BCt7lM;6D4z)vxL7+78B*O<-l9w#mN(+yrJWPKM9r{f zC@ffs+VXcjx!t*37nj+ec z7Snkt^VJ6{L1Tqvb6lFnIu0vNV-3YA&Qe%xM+q9M@+~isDN13oW@Ip|5RFy+2kRlM z*^0hOCoj!LSgT;oL?0p<aoj@9JP9miHrdElSYetz)8)!+@>29k10;GC2hqNa}K#kvx0 zNVf^c4FY$A*~OUM$~`LmYn9HJjk^!#!4JT!t5?N8fZ4nsRrV9`VAwx{4ZvEgQ^l;Q zBXAPMgdwmnhSLXYfla_{fVoN^#tdAH*}@iJCRyVT3%~))=8pp7DZ)8}@t<>Le^ku+ z-C*m0C#&?yLX+Eth1v$p=Me0avEJaOUz;cYKQSyZ`hQ4F)AD;;VttxM9+mgUf1hIa z&-XsQ)>7s#DRH3nxv?jI(5~1$YNf5D$8Pnq6UT$ojf)QIm!$0c_7_P=(|ebmoqDdH z>(D(RPOm1|n>Y12@X-3skGjQuQ#SRl5XMZ~BnxcJXwfPdS=D^=(8ctj9}T+WJm#tR znfSnEJ*-m=^)z*c=FhZbl zZMJSNzRRzEE61+)Lf%i~{66)@nef~z!&l%$`U~6k#2BozfW?tS6C)u!U_uL9IGH|V zJJ}w~C;P0;o4}ur%evNR-0ROTJoT=r+n6GkB~jBn?~MLe+i!-`x0)PndAoD8#OCHS zi^qLMXNT-K7v+8G^`6(+k&Q3fx-QeH3wR5k!8v>9mi(GnHj~SE?^w=;RGSu)`ZrpR zpQ`_Uan#G?hTJfnR_mUzo1SfPX#MSqU$1-J=+pPQE^Ti3C}&>G*TSurbn61X-6#BX zTU5BKPeNnLkVburjpGag?fsV;H72i*U%%wqa}Q@eNxRSglZQd8__bVMU3A~kcC)HC zDyk0N*6ZavJ`UI`+a1R{h0?rwJ}7t&yR}uxANsd}2Yp^x1#%-k->NI3a~=sp%J zXT-+PxH#fKzlk6RB}K`VW=W#gZCcw>*Xo#JV{wjgAKF%um7&2WRlIsyK2(H*g_R zx(Jv7L;*=a0uT?x0SkaRKsYcBm=1`6Fd!5N0epdATDh1Evzd+NEZ|$L69}FOyvB6` zb^x_mOh)Jj4UlFr$=Y5$f;m>V)yx(RrAJeVspWh$=K<=yvMx3yl{vI>rm3X>_y`6@5g^Q-d@z6i)@;G-6F} zr4chr^-z{ImZcPcxeHTF@nzkM0QF}7TVm5xQ&Yj}1S=D2|DW8j)!0gkbD;K1$S}mt zGBlozRxkMPr^rrFy%1Z3ouG0N*_I{5OxJ|fMg(f(L5{L+?2Kiz3dkLQ>U|oa8_~qG z#F8IL-#J4pssB}C#ZRSAPD6^IJy(b&Nl&Lot`ajXcevR|6R)D@Fm+~hjv8VB-$h&4 z@JF-~79DklSkXaka3jzLrDy&+x&x`99F#_D&JcGu^*4?Bm7nl&<6ZC%&j5VQu#brM zzbcX>SRTEJ9yb?Hm+{m`PSS>}zlqwaUC;HG=!{nMy1RJcT_=-XZYOTUHgj7Cu^=v) z)T)Eb(4B;LaZk9b%cLnCBu+V-Dp-M(bL5hUuF5U zs2y2Q@j##3T8YPi?WfR_Z4i`Ipg4Y7cvf?Gcf(10Q2R5)24#ohSp7dQ!dsolS0QS7U?u+5 zqWja`scr;%`I;ti%D}1zBwke(0}`#u)1Tj9syj;&l;X}(WXc^wAo@jqWWI22nZdRkV`I1rs`cgJ4GATr22PgL1*lF)KScKQ%KiCowxU(K#h` z(W2yx?Bv9xT<7fM^vwKZ=bWVM%q2_clRUvj*1bvi2cbq%A%ywUqs); if (cookies.key) { - console.log('[i] Key found in browser cookies, checking validity'); + console.log(strings.logsFoundKey); try { const response = await fetch('http://localhost:3001/api/admin/validate', { method: 'POST', @@ -41,17 +36,17 @@ export function LoginForm({ }) if (!response.ok) { - console.log('[!] Failed to check key, skipping validation and clearing cookie'); + console.log(strings.errorsFailedKeyCheckFancy); document.cookie = 'key=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'; } else { const data = await response.json() if (data.valid) { // key exists and is valid, user has no reason to use login - console.log("[✓] Key is valid, redirecting to admin panel"); + console.log(strings.logsAdminLoginKeyIsValid); window.location.href = '/admin'; } else { // key exists, but the server reports its not the latest key - console.log("[!] Key is invalid, clearing cookie and redirecting to login"); + console.log(strings.errorsFailedKeyCheckFancy); document.cookie.split(";").forEach((cookie) => { document.cookie = cookie .replace(/^ +/, "") @@ -61,8 +56,8 @@ export function LoginForm({ } } } catch (error) { - console.error('[!]', error) - setError('Failed to connect to the server. Please try again later.') + console.error('[!]', error); + setError(strings.errorsConnectionFail); } } }; @@ -85,12 +80,12 @@ export function LoginForm({ }) if (!response.ok) { - console.log('[!] Failed to login'); - setError('An unknown error occurred. Please try again later.') + console.log(strings.errorsLoginFailFancy); + setError(strings.errorsUnknownErrorLong) } else { const data = await response.json() if (data.success && data.key) { - console.log("[✓] Login successful, redirecting to admin panel"); + console.log(strings.logsAdminLoginSuccessful); document.cookie = `key=${data.key}; path=/; secure; samesite=strict`; document.cookie = `username=${username}; path=/; secure; samesite=strict`; document.location.href = '/admin'; @@ -98,13 +93,13 @@ export function LoginForm({ if (!data.success && data.message) { setError(data.message) } else { - setError('An unknown error occurred. Please try again later.') + setError(strings.errorsUnknownErrorLong) } } } } catch (error) { console.error('[i]', error) - setError('Failed to connect to the server. Please try again later.') + setError(strings.errorsConnectionFail) } } @@ -112,9 +107,9 @@ export function LoginForm({
- Administration Panel + {strings.adminLoginCardTitle} - Please authenticate with your credentials. + {strings.adminLoginCardDescription} @@ -122,7 +117,7 @@ export function LoginForm({
- +
- +
diff --git a/components/navigation/Navbar.tsx b/components/navigation/Navbar.tsx index c51c2aa..ddcc3a6 100644 --- a/components/navigation/Navbar.tsx +++ b/components/navigation/Navbar.tsx @@ -48,11 +48,11 @@ export function Navbar() {
- +
diff --git a/components/navigation/Sidebar.tsx b/components/navigation/Sidebar.tsx index b48f548..3619b36 100644 --- a/components/navigation/Sidebar.tsx +++ b/components/navigation/Sidebar.tsx @@ -22,31 +22,31 @@ export function Sidebar() { const [uniqueCategories, setUniqueCategories] = useState<{ name: string; slug: string }[]>([]); useEffect(() => { - console.log("[i] Fetching post list..."); + console.log(strings.logsFetchPostList); fetch('http://localhost:3001/api/posts/fetchList') .then(response => response.json()) .then(data => { if (!data.posts) { - throw new Error('[!] Failed to fetch posts'); + throw new Error(strings.errorsFetchPostsFailFancy); } - console.log("[✓] Fetched posts"); + console.log(strings.logsOnFetchedPosts); setPosts(data.posts); setLoadingPosts(false); }) .catch(error => { console.error(error); - setError(`[!] Error fetching posts: ${error.message}`); + setError(`${strings.errorsFetchPostsFailFancy}: ${error.message}`); setLoadingPosts(false); }); - console.log("[i] Fetching category list..."); + console.log(strings.logsFetchCategoryList); fetch('http://localhost:3001/api/categories/fetchList') .then(response => response.json()) .then(data => { if (!data.categories) { - throw new Error('Failed to fetch categories'); + throw new Error(strings.errorsFetchCategoryListFail); } - console.log("[✓] Fetched categories"); + console.log(strings.logsOnFetchedCategory); const categories = data.categories.map((cat: { name: string, slug: string }) => ({ name: cat.name, slug: cat.slug, @@ -56,7 +56,7 @@ export function Sidebar() { }) .catch(error => { console.error(error); - setError(`[!] Error fetching categories: ${error.message}`); + setError(`${strings.errorsFetchCategoriesErrCtxFancy} ${error.message}`); setLoadingCategories(false); }); }, []); @@ -64,12 +64,12 @@ export function Sidebar() { return (