From 26cc67aa44e82a48aa887d5fa05398e05b27f7e5 Mon Sep 17 00:00:00 2001 From: NiallJoeMaher Date: Tue, 9 Dec 2025 07:31:37 +0000 Subject: [PATCH 1/8] feat: Upgrade to Next.js 16, React 19, and modernize dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Upgrade Next.js from 14.2.21 to 16.0.7 - Upgrade React/React-DOM from 18.3.1 to 19.2.1 - Upgrade next-auth from 4.x to 5.0.0-beta.30 (Auth.js) - Upgrade tRPC from v10 to v11.7.2 - Upgrade TanStack React Query from v4 to v5.90.12 - Upgrade Zod from 3.x to 4.1.13 - Upgrade Sentry from 8.x to 10.29.0 - Upgrade Framer Motion from 11.x to 12.23.25 Breaking changes addressed: - Convert all page params to async (Next.js 16 requirement) - Migrate headers() to async function calls - Update next-auth to new Auth.js v5 API with handlers export - Replace 'loading' status with 'pending' (React Query v5) - Migrate ESLint from .eslintrc to flat config (eslint.config.mjs) - Update Zod error API (error.errors → error.issues) - Fix React 19 type changes (ChildNode → React.ReactNode) - Update TRPCReactProvider to accept serialized headers object --- .eslintrc | 23 - .gitignore | 3 + .mcp.json | 27 + app/(app)/[username]/page.tsx | 16 +- .../alpha/additional-details/_actions.ts | 6 +- app/(app)/alpha/layout.tsx | 3 +- .../alpha/new/[[...postIdArr]]/_client.tsx | 7 +- app/(app)/articles/[slug]/page.tsx | 12 +- app/(app)/articles/_client.tsx | 4 +- app/(app)/company/[slug]/page.tsx | 5 +- app/(app)/draft/[id]/page.tsx | 10 +- app/(app)/jobs/create/_client.tsx | 10 +- app/(app)/my-posts/_client.tsx | 4 +- app/(app)/notifications/_client.tsx | 4 +- app/(app)/saved/_client.tsx | 2 +- app/(app)/settings/_client.tsx | 6 +- .../create/[[...paramsArr]]/_client.tsx | 22 +- app/(standalone)/newsletter/actions.ts | 7 +- app/api/auth/[...nextauth]/route.ts | 8 +- app/layout.tsx | 18 +- app/verify-email/_client.tsx | 6 +- auth.ts | 101 + components/ArticleMenu/ArticleMenu.tsx | 4 +- components/ArticlePreview/ArticlePreview.tsx | 4 +- components/Comments/CommentsArea.tsx | 10 +- components/PromptService/PromptContext.tsx | 13 +- components/SideBar/SideBarSavedPosts.tsx | 2 +- .../editor/components/image-resizer.tsx | 9 +- .../disable-heading-text-style-shortcuts.tsx | 3 +- .../editor/editor/plugins/upload-images.tsx | 14 +- components/editor/editor/props.ts | 4 +- components/editor/primitives/leaflet.tsx | 2 +- .../markdocNodes/CodeSandbox/CodeSandbox.tsx | 4 +- components/markdocNodes/Media/Media.tsx | 2 +- components/markdocNodes/Youtube/Youtube.tsx | 4 +- e2e/articles.spec.ts | 3 +- e2e/constants/constants.ts | 5 + e2e/setup.ts | 38 +- e2e/utils/utils.ts | 8 +- eslint.config.mjs | 53 + hooks/useCreatePage.ts | 32 +- markdoc/editor/hotkeys/hotkeys.markdoc.ts | 4 +- markdoc/editor/shortcuts/shortcuts.markdoc.ts | 3 +- markdoc/nodes/customLink.markdoc.ts | 7 +- next-env.d.ts | 3 +- next.config.js | 28 +- package-lock.json | 5786 +++++++++-------- package.json | 50 +- server/auth.ts | 115 +- server/trpc/react.tsx | 6 +- server/trpc/server.ts | 7 +- tsconfig.json | 25 +- types/next-auth.d.ts | 10 +- types/types.ts | 2 +- utils/trpc.ts | 3 +- 55 files changed, 3607 insertions(+), 2960 deletions(-) delete mode 100644 .eslintrc create mode 100644 .mcp.json create mode 100644 auth.ts create mode 100644 eslint.config.mjs diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 57efadbf..00000000 --- a/.eslintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json" - }, - "plugins": ["@typescript-eslint", "jsx-a11y"], - "extends": [ - "next/core-web-vitals", - "plugin:@typescript-eslint/recommended", - "prettier", - "plugin:jsx-a11y/recommended", - "plugin:playwright/recommended" - ], - "rules": { - "@typescript-eslint/consistent-type-imports": "warn", - "@typescript-eslint/ban-ts-comment": "warn", - "@next/next/no-img-element": "off", - "no-unused-vars": "warn", - "@typescript-eslint/no-unused-vars": "warn", - "no-console": "warn" - }, - "ignorePatterns": ["next.config.js", "*/lambdas/**/*.js"] -} diff --git a/.gitignore b/.gitignore index d3f19f80..2951c3a5 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,6 @@ ssmSetup.zsh # open-next .open-next + +# Snyk Security Extension - AI Rules (auto-generated) +.github/instructions/snyk_rules.instructions.md diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 00000000..a86d7c2c --- /dev/null +++ b/.mcp.json @@ -0,0 +1,27 @@ +{ + "mcpServers": { + "context7": { + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"], + "env": { + "CONTEXT7_API_KEY": "ctx7sk-1d829fe1-62b2-4697-b7f4-673ae5047efd" + } + }, + "puppeteer": { + "command": "npx", + "args": ["-y", "puppeteer-mcp-server"], + "env": {} + }, + "next-devtools": { + "command": "npx", + "args": ["-y", "next-devtools-mcp@latest"] + }, + "sequential-thinking": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"] + }, + "Sentry": { + "url": "https://mcp.sentry.dev/mcp/assemble-pro/javascript-nextjs" + } + } +} diff --git a/app/(app)/[username]/page.tsx b/app/(app)/[username]/page.tsx index 75462db6..90938289 100644 --- a/app/(app)/[username]/page.tsx +++ b/app/(app)/[username]/page.tsx @@ -5,9 +5,10 @@ import { getServerAuthSession } from "@/server/auth"; import { type Metadata } from "next"; import { db } from "@/server/db"; -type Props = { params: { username: string } }; +type Props = { params: Promise<{ username: string }> }; -export async function generateMetadata({ params }: Props): Promise { +export async function generateMetadata(props: Props): Promise { + const params = await props.params; const username = params.username; const profile = await db.query.user.findFirst({ @@ -52,11 +53,12 @@ export async function generateMetadata({ params }: Props): Promise { }; } -export default async function Page({ - params, -}: { - params: { username: string }; -}) { +export default async function Page( + props: { + params: Promise<{ username: string }>; + } +) { + const params = await props.params; const username = params?.username; if (!username) { diff --git a/app/(app)/alpha/additional-details/_actions.ts b/app/(app)/alpha/additional-details/_actions.ts index ed4eaad0..dc133a64 100644 --- a/app/(app)/alpha/additional-details/_actions.ts +++ b/app/(app)/alpha/additional-details/_actions.ts @@ -37,7 +37,7 @@ export async function slideOneSubmitAction(dataInput: TypeSlideOneSchema) { return true; } catch (error) { if (error instanceof z.ZodError) { - console.error("Validation error:", error.errors); + console.error("Validation error:", error.issues); } else { console.error("Error updating the User model:", error); } @@ -65,7 +65,7 @@ export async function slideTwoSubmitAction(dataInput: TypeSlideTwoSchema) { return true; } catch (error) { if (error instanceof z.ZodError) { - console.error("Validation error:", error.errors); + console.error("Validation error:", error.issues); } else { console.error("Error updating the User model:", error); } @@ -97,7 +97,7 @@ export async function slideThreeSubmitAction(dataInput: TypeSlideThreeSchema) { return true; } catch (error) { if (error instanceof z.ZodError) { - console.error("Validation error:", error.errors); + console.error("Validation error:", error.issues); } else { console.error("Error updating the User model:", error); } diff --git a/app/(app)/alpha/layout.tsx b/app/(app)/alpha/layout.tsx index 642edf85..0c56d862 100644 --- a/app/(app)/alpha/layout.tsx +++ b/app/(app)/alpha/layout.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { notFound } from "next/navigation"; export const metadata = { @@ -8,7 +9,7 @@ export const metadata = { }, }; -export default function Alpha({ children }: { children: ChildNode }) { +export default function Alpha({ children }: { children: React.ReactNode }) { if (process.env.ALPHA || process.env.NODE_ENV === "development") { return <>{children}; } diff --git a/app/(app)/alpha/new/[[...postIdArr]]/_client.tsx b/app/(app)/alpha/new/[[...postIdArr]]/_client.tsx index 69074792..c9b0cdc2 100644 --- a/app/(app)/alpha/new/[[...postIdArr]]/_client.tsx +++ b/app/(app)/alpha/new/[[...postIdArr]]/_client.tsx @@ -47,7 +47,8 @@ const Create = () => { useEffect(() => { _setUnsaved(hasUnsavedChanges); - }, [hasUnsavedChanges, _setUnsaved]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hasUnsavedChanges]); return ( <> @@ -197,7 +198,7 @@ const Create = () => { - {dataStatus === "loading" && postId && ( + {dataStatus === "pending" && postId && (
@@ -236,7 +237,7 @@ const Create = () => {
- {saveStatus === "loading" && ( + {saveStatus === "pending" && (

Auto-saving...

)} {saveStatus === "error" && savedTime && ( diff --git a/app/(app)/articles/[slug]/page.tsx b/app/(app)/articles/[slug]/page.tsx index 614e9f6e..605920d0 100644 --- a/app/(app)/articles/[slug]/page.tsx +++ b/app/(app)/articles/[slug]/page.tsx @@ -20,9 +20,10 @@ import DOMPurify from "isomorphic-dompurify"; import type { JSONContent } from "@tiptap/core"; import NotFound from "@/components/NotFound/NotFound"; -type Props = { params: { slug: string } }; +type Props = { params: Promise<{ slug: string }> }; -export async function generateMetadata({ params }: Props): Promise { +export async function generateMetadata(props: Props): Promise { + const params = await props.params; const slug = params.slug; const post = await getPost({ slug }); @@ -32,7 +33,7 @@ export async function generateMetadata({ params }: Props): Promise { const tags = post?.tags.map((tag) => tag.tag.title); if (!post) return {}; - const host = headers().get("host") || ""; + const host = (await headers()).get("host") || ""; return { title: `${post.title} | by ${post.user.name} | Codú`, authors: { @@ -77,11 +78,12 @@ const renderSanitizedTiptapContent = (jsonContent: JSONContent) => { return DOMPurify.sanitize(rawHtml); }; -const ArticlePage = async ({ params }: Props) => { +const ArticlePage = async (props: Props) => { + const params = await props.params; const session = await getServerAuthSession(); const { slug } = params; - const host = headers().get("host") || ""; + const host = (await headers()).get("host") || ""; const post = await getPost({ slug }); diff --git a/app/(app)/articles/_client.tsx b/app/(app)/articles/_client.tsx index 6ad05d83..73e21cd0 100644 --- a/app/(app)/articles/_client.tsx +++ b/app/(app)/articles/_client.tsx @@ -104,7 +104,7 @@ const ArticlesPage = () => { Something went wrong... Please refresh your page.
)} - {status === "loading" && + {status === "pending" && Children.toArray( Array.from({ length: 7 }, () => { return ; @@ -164,7 +164,7 @@ const ArticlesPage = () => { Popular topics
- {tagsStatus === "loading" && } + {tagsStatus === "pending" && } {tagsStatus === "success" && tagsData.data.map(({ title }) => ( }; -export default async function Page({ params }: Props) { +export default async function Page(props: Props) { + const params = await props.params; const { slug } = params; const company = companies.find((item) => item.slug === slug.toLowerCase()); diff --git a/app/(app)/draft/[id]/page.tsx b/app/(app)/draft/[id]/page.tsx index d132565f..ff6c0944 100644 --- a/app/(app)/draft/[id]/page.tsx +++ b/app/(app)/draft/[id]/page.tsx @@ -11,15 +11,16 @@ import { type Metadata } from "next"; import { getPostPreview } from "@/server/lib/posts"; import { getCamelCaseFromLower } from "@/utils/utils"; -type Props = { params: { id: string } }; +type Props = { params: Promise<{ id: string }> }; -export async function generateMetadata({ params }: Props): Promise { +export async function generateMetadata(props: Props): Promise { + const params = await props.params; const { id } = params; const post = await getPostPreview({ id }); if (!post) return {}; - const host = headers().get("host") || ""; + const host = (await headers()).get("host") || ""; return { title: `Draft: ${post.title} | by ${post.user.name} | Codú`, authors: { @@ -34,7 +35,8 @@ export async function generateMetadata({ params }: Props): Promise { }; } -const PreviewPage = async ({ params }: Props) => { +const PreviewPage = async (props: Props) => { + const params = await props.params; const { id } = params; const post = await getPostPreview({ id }); diff --git a/app/(app)/jobs/create/_client.tsx b/app/(app)/jobs/create/_client.tsx index dcbb7acf..7b49f23f 100644 --- a/app/(app)/jobs/create/_client.tsx +++ b/app/(app)/jobs/create/_client.tsx @@ -59,7 +59,7 @@ export default function Content() { const fileInputRef = useRef(null); const [imgUrl, setImgUrl] = useState(null); const [uploadStatus, setUploadStatus] = useState< - "idle" | "loading" | "success" | "error" + "idle" | "pending" | "success" | "error" >("idle"); const onSubmit: SubmitHandler = (values) => { const formData = { @@ -70,12 +70,12 @@ export default function Content() { }; const handleLogoUpload = async (e: React.ChangeEvent) => { - if (uploadStatus === "loading") { + if (uploadStatus === "pending") { return toast.info("Upload in progress, please wait..."); } if (e.target.files && e.target.files.length > 0) { - setUploadStatus("loading"); + setUploadStatus("pending"); const file = e.target.files[0]; const { size, type } = file; @@ -155,9 +155,9 @@ export default function Content() { onClick={() => { fileInputRef.current?.click(); }} - disabled={uploadStatus === "loading"} + disabled={uploadStatus === "pending"} > - {uploadStatus === "loading" ? "Uploading..." : "Change Logo"} + {uploadStatus === "pending" ? "Uploading..." : "Change Logo"} { title="Delete article" subTitle="Are you sure you want to delete this article?" content="All of the data will be permanently removed from our servers forever. This action cannot be undone." - confirmText={deleteStatus === "loading" ? "Deleting..." : "Delete"} + confirmText={deleteStatus === "pending" ? "Deleting..." : "Delete"} cancelText="Cancel" /> )} @@ -113,7 +113,7 @@ const MyPosts = () => {
- {selectedTabData.status === "loading" && ( + {selectedTabData.status === "pending" && (

Fetching your posts...

)} {selectedTabData.status === "error" && ( diff --git a/app/(app)/notifications/_client.tsx b/app/(app)/notifications/_client.tsx index 7cc8ca4e..ad24277b 100644 --- a/app/(app)/notifications/_client.tsx +++ b/app/(app)/notifications/_client.tsx @@ -89,13 +89,13 @@ const Notifications = () => { {status === "error" && (
Something went wrong... Please refresh your page.
)} - {status === "loading" && + {status === "pending" && Children.toArray( Array.from({ length: 7 }, () => { return ; }), )} - {status !== "loading" && noNotifications && ( + {status !== "pending" && noNotifications && (

No new notifications. ✅{" "}

diff --git a/app/(app)/saved/_client.tsx b/app/(app)/saved/_client.tsx index f6e0c4ec..042a2a32 100644 --- a/app/(app)/saved/_client.tsx +++ b/app/(app)/saved/_client.tsx @@ -32,7 +32,7 @@ const SavedPosts = () => {
Saved items
- {bookmarkStatus === "loading" && + {bookmarkStatus === "pending" && Children.toArray( Array.from({ length: 7 }, () => { return ; diff --git a/app/(app)/settings/_client.tsx b/app/(app)/settings/_client.tsx index 04d02cce..b39f45ca 100644 --- a/app/(app)/settings/_client.tsx +++ b/app/(app)/settings/_client.tsx @@ -41,7 +41,7 @@ type User = Pick< >; type ProfilePhoto = { - status: "success" | "error" | "loading" | "idle"; + status: "pending" | "error" | "success" | "idle"; url: string; }; @@ -105,7 +105,7 @@ const Settings = ({ profile }: { profile: User }) => { }; const uploadToUrl = async (signedUrl: string, file: File) => { - setProfilePhoto({ status: "loading", url: "" }); + setProfilePhoto({ status: "pending", url: "" }); if (!file) { setProfilePhoto({ status: "error", url: "" }); @@ -204,7 +204,7 @@ const Settings = ({ profile }: { profile: User }) => { square src={ profilePhoto.status === "error" || - profilePhoto.status === "loading" + profilePhoto.status === "pending" ? undefined : `${profilePhoto.url}` } diff --git a/app/(editor)/create/[[...paramsArr]]/_client.tsx b/app/(editor)/create/[[...paramsArr]]/_client.tsx index b0d7bf30..85ea64d7 100644 --- a/app/(editor)/create/[[...paramsArr]]/_client.tsx +++ b/app/(editor)/create/[[...paramsArr]]/_client.tsx @@ -57,7 +57,7 @@ const Create = ({ session }: { session: Session | null }) => { const [copied, setCopied] = useState(false); const [uploadUrl, setUploadUrl] = useState(null); const [uploadStatus, setUploadStatus] = useState< - "loading" | "error" | "success" | "default" + "pending" | "error" | "success" | "default" >("default"); const [postStatus, setPostStatus] = useState(null); @@ -65,16 +65,16 @@ const Create = ({ session }: { session: Session | null }) => { usePrompt(); useEffect(() => { - _setUnsaved(); + _setUnsaved(unsavedChanges); }, [unsavedChanges, _setUnsaved]); const handleUpload = async (e: React.ChangeEvent) => { - if (uploadStatus === "loading") { + if (uploadStatus === "pending") { return toast.info("Upload in progress, please wait..."); } if (e.target.files && e.target.files.length > 0) { setUploadUrl(null); - setUploadStatus("loading"); + setUploadStatus("pending"); const file = e.target.files[0]; const { size, type } = file; @@ -240,9 +240,9 @@ const Create = ({ session }: { session: Session | null }) => { }; const hasLoadingState = - publishStatus === "loading" || - saveStatus === "loading" || - dataStatus === "loading"; + publishStatus === "pending" || + saveStatus === "pending" || + dataStatus === "pending"; const currentPostStatus = data?.published ? getPostStatus(new Date(data.published)) @@ -624,7 +624,7 @@ const Create = ({ session }: { session: Session | null }) => {
- {dataStatus === "loading" && postId && ( + {dataStatus === "pending" && postId && (
@@ -700,9 +700,9 @@ const Create = ({ session }: { session: Session | null }) => {
- {status === "loading" && ( + {status === "pending" && (

diff --git a/auth.ts b/auth.ts new file mode 100644 index 00000000..2c878d4d --- /dev/null +++ b/auth.ts @@ -0,0 +1,101 @@ +import NextAuth from "next-auth"; +import GitHub from "next-auth/providers/github"; +import GitLab from "next-auth/providers/gitlab"; +import Nodemailer from "next-auth/providers/nodemailer"; +import { DrizzleAdapter } from "@auth/drizzle-adapter"; +import { db } from "@/server/db"; +import { user } from "@/server/db/schema"; +import { createWelcomeEmailTemplate } from "@/utils/createEmailTemplate"; +import { createPasswordLessEmailTemplate } from "@/utils/createPasswordLessEmailTemplate"; +import { manageNewsletterSubscription } from "@/server/lib/newsletter"; +import sendEmail, { nodemailerSesTransporter } from "@/utils/sendEmail"; +import * as Sentry from "@sentry/nextjs"; + +export const { handlers, auth, signIn, signOut } = NextAuth({ + // @ts-expect-error - DrizzleAdapter type mismatch with next-auth internal types + adapter: DrizzleAdapter(db, { + // @ts-expect-error - Custom user table + usersTable: user, + }), + providers: [ + GitHub({ + clientId: process.env.GITHUB_ID!, + clientSecret: process.env.GITHUB_SECRET!, + }), + GitLab({ + clientId: process.env.GITLAB_ID!, + clientSecret: process.env.GITLAB_SECRET!, + }), + Nodemailer({ + server: { + // Using custom sendVerificationRequest, so this is not used + host: "", + port: 0, + auth: { user: "", pass: "" }, + }, + from: process.env.ADMIN_EMAIL, + async sendVerificationRequest({ identifier, url }) { + try { + if (!process.env.ADMIN_EMAIL) { + throw new Error("ADMIN_EMAIL not set"); + } + await nodemailerSesTransporter.sendMail({ + to: `Niall (Codú) ${identifier}`, + from: process.env.ADMIN_EMAIL, + subject: `Sign in to Codú 🚀`, + text: `Sign in to Codú 🚀\n\n`, + html: createPasswordLessEmailTemplate(url), + }); + } catch (error) { + Sentry.captureException(error); + throw new Error(`Sign in email could not be sent`); + } + }, + }), + ], + pages: { + signIn: "/get-started", + newUser: "/settings", + verifyRequest: "/auth", + error: "/auth/error", + }, + callbacks: { + session({ session, user }) { + if (session.user) { + session.user.id = user.id; + session.user.role = user.role; + } + return session; + }, + async signIn({ user }) { + const userIsBanned = await db.query.banned_users.findFirst({ + where: (banned_users, { eq }) => eq(banned_users.userId, user.id), + }); + return !userIsBanned; + }, + }, + events: { + async createUser({ user }) { + const { email } = user; + + if (!email) { + console.error("Missing email so cannot send welcome email"); + Sentry.captureMessage("Missing 'email' so cannot send welcome email"); + return; + } + const htmlMessage = createWelcomeEmailTemplate(user?.name || undefined); + try { + await manageNewsletterSubscription(email, "subscribe"); + await sendEmail({ + recipient: email, + htmlMessage, + subject: + "Thanks for Joining Codú 🎉 + Your Excluisve Community Invite.", + }); + } catch (error) { + console.log("Error in createUser event:", error); + Sentry.captureException(error); + } + }, + }, +}); diff --git a/components/ArticleMenu/ArticleMenu.tsx b/components/ArticleMenu/ArticleMenu.tsx index 1c97ec37..5bfe6ff3 100644 --- a/components/ArticleMenu/ArticleMenu.tsx +++ b/components/ArticleMenu/ArticleMenu.tsx @@ -77,7 +77,7 @@ const ArticleMenu = ({ }); const likePost = async (postId: string, setLiked = true) => { - if (likeStatus === "loading") return; + if (likeStatus === "pending") return; try { await like({ postId, setLiked }); } catch (err) { @@ -87,7 +87,7 @@ const ArticleMenu = ({ }; const bookmarkPost = async (postId: string, setBookmarked = true) => { - if (bookmarkStatus === "loading") return; + if (bookmarkStatus === "pending") return; try { await bookmark({ postId, setBookmarked }); } catch (err) { diff --git a/components/ArticlePreview/ArticlePreview.tsx b/components/ArticlePreview/ArticlePreview.tsx index 3b545377..2ac0108e 100644 --- a/components/ArticlePreview/ArticlePreview.tsx +++ b/components/ArticlePreview/ArticlePreview.tsx @@ -39,7 +39,7 @@ type Props = { menuOptions?: Array; showBookmark?: boolean; bookmarkedInitialState?: boolean; - likes: number; + likes?: number; }; const ArticlePreview: NextPage = ({ @@ -86,7 +86,7 @@ const ArticlePreview: NextPage = ({ }); const bookmarkPost = async (postId: string, setBookmarked = true) => { - if (bookmarkStatus === "loading") return; + if (bookmarkStatus === "pending") return; try { if (!session) { signIn(); diff --git a/components/Comments/CommentsArea.tsx b/components/Comments/CommentsArea.tsx index 6e9e621e..24db1d4c 100644 --- a/components/Comments/CommentsArea.tsx +++ b/components/Comments/CommentsArea.tsx @@ -86,7 +86,7 @@ const CommentsArea = ({ postId, postOwnerId }: Props) => { const likeComment = async (commentId: number) => { if (!session) return signIn(); - if (likeStatus === "loading") return; + if (likeStatus === "pending") return; try { await like({ commentId }); } catch (err) { @@ -357,7 +357,7 @@ const CommentsArea = ({ postId, postOwnerId }: Props) => { resetField("reply"); setShowCommentBoxId(null); }} - loading={createCommentStatus === "loading"} + loading={createCommentStatus === "pending"} />

)} @@ -370,7 +370,7 @@ const CommentsArea = ({ postId, postOwnerId }: Props) => { name="edit" id={id} editMode - loading={editStatus === "loading"} + loading={editStatus === "pending"} onCancel={() => setEditCommentBoxId(null)} /> )} @@ -449,14 +449,14 @@ const CommentsArea = ({ postId, postOwnerId }: Props) => { )}