diff --git a/src/app/posts/[id]/edit/page.tsx b/src/app/posts/[id]/edit/page.tsx
index a1c6ed7..1c091e3 100644
--- a/src/app/posts/[id]/edit/page.tsx
+++ b/src/app/posts/[id]/edit/page.tsx
@@ -1,69 +1,14 @@
-'use client';
+import EditPostForm from '@/components/EditPostForm';
+import { Metadata } from 'next';
-import Editor, { SubmitActionParams } from '@/components/Editor';
-import SpinningLoader from '@/components/SpinningLoader';
-import { useRouter } from '@/hooks';
-import { useUser } from '@clerk/nextjs';
-import { useMutation, useQuery } from 'convex/react';
-import { api } from '../../../../../convex/_generated/api';
-import { Id } from '../../../../../convex/_generated/dataModel';
+export const metadata: Metadata = {
+ title: 'conveX | Edit post',
+};
export default function EditPostPage({ params }: { params: { id: string } }) {
- const user = useUser();
- const post = useQuery(api.posts.getPostById, {
- id: params.id as Id<'posts'>,
- });
- const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
- const router = useRouter();
-
- if (user.isSignedIn === false) {
- router.push('/login');
- return;
- }
-
- if (post === 'POST_NOT_FOUND' || post === 'USER_FOR_POST_NOT_FOUND') {
- // TODO: Return actual not found component
- return
Not Found
;
- }
-
- async function submitAction({
- clerkUserId,
- parentPostId,
- post,
- currentDoc,
- }: SubmitActionParams) {
- const result = await createOrUpdatePost({
- parentPostId: parentPostId,
- id: post?._id,
- clerkUserId: clerkUserId,
- content: currentDoc,
- });
-
- switch (result) {
- case 'USER_NOT_FOUND':
- case 'USER_NOT_AUTHORIZED':
- case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
- throw Error('Unable to update post');
- default:
- router.push(`/posts/${post?._id}`);
- return;
- }
- }
-
return (
- {user.isLoaded && post !== undefined ? (
-
- ) : (
-
-
- Loading...
-
- )}
+
);
}
diff --git a/src/app/posts/[id]/page.tsx b/src/app/posts/[id]/page.tsx
index b5452cb..d6050ce 100644
--- a/src/app/posts/[id]/page.tsx
+++ b/src/app/posts/[id]/page.tsx
@@ -1,16 +1,9 @@
-'use client';
+import DisplayPost from '@/components/DisplayPost';
+import { Metadata } from 'next';
-import Editor, { SubmitActionParams } from '@/components/Editor';
-import Post from '@/components/Post';
-import PostReplies from '@/components/PostReplies';
-import SpinningLoader from '@/components/SpinningLoader';
-import { useRouter } from '@/hooks';
-import { useUser } from '@clerk/nextjs';
-import { useMutation, useQuery } from 'convex/react';
-import Image from 'next/image';
-import { useEffect, useRef } from 'react';
-import { api } from '../../../../convex/_generated/api';
-import { Id } from '../../../../convex/_generated/dataModel';
+export const metadata: Metadata = {
+ title: 'conveX | Post',
+};
export default function PostPage({
params,
@@ -19,90 +12,13 @@ export default function PostPage({
params: { id: string };
searchParams: { [key: string]: string | string[] | undefined };
}) {
- const replyRef = useRef
(null);
- const user = useUser();
- const router = useRouter();
- const post = useQuery(api.posts.getPostById, {
- id: params.id as Id<'posts'>,
- });
- const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
- const isReply = searchParams.reply === 'true';
-
- useEffect(() => {
- if (replyRef.current !== null && isReply) {
- replyRef.current.scrollIntoView();
- }
- }, [isReply, user]);
-
- async function submitAction({
- clerkUserId,
- parentPostId,
- post,
- currentDoc,
- }: SubmitActionParams) {
- const result = await createOrUpdatePost({
- parentPostId: parentPostId,
- id: post?._id,
- clerkUserId: clerkUserId,
- content: currentDoc,
- });
-
- switch (result) {
- case 'USER_NOT_FOUND':
- case 'USER_NOT_AUTHORIZED':
- case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
- throw Error('Unable to create post');
- default:
- return;
- }
- }
-
- if (user.isSignedIn === false) {
- router.push('/login');
- return;
- }
-
- if (post === 'POST_NOT_FOUND' || post === 'USER_FOR_POST_NOT_FOUND') {
- // TODO: Return actual not found component
- return Not Found
;
- }
-
return (
- {post !== undefined && user.isLoaded ? (
- <>
-
-
-
- >
- ) : (
-
- Loading post...
-
- )}
+
);
diff --git a/src/app/posts/add/page.tsx b/src/app/posts/add/page.tsx
index dfd1a01..f05ae6d 100644
--- a/src/app/posts/add/page.tsx
+++ b/src/app/posts/add/page.tsx
@@ -1,57 +1,14 @@
-'use client';
+import AddPostForm from '@/components/AddPostForm';
+import { Metadata } from 'next';
-import Editor, { SubmitActionParams } from '@/components/Editor';
-import SpinningLoader from '@/components/SpinningLoader';
-import { useRouter } from '@/hooks';
-import { useUser } from '@clerk/nextjs';
-import { useMutation } from 'convex/react';
-import { api } from '../../../../convex/_generated/api';
+export const metadata: Metadata = {
+ title: 'conveX | Add post',
+};
export default function AddPost() {
- const user = useUser();
- const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
- const router = useRouter();
-
- async function submitAction({
- clerkUserId,
- parentPostId,
- post,
- currentDoc,
- }: SubmitActionParams) {
- const result = await createOrUpdatePost({
- parentPostId: parentPostId,
- id: post?._id,
- clerkUserId: clerkUserId,
- content: currentDoc,
- });
-
- switch (result) {
- case 'USER_NOT_FOUND':
- case 'USER_NOT_AUTHORIZED':
- case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
- throw Error('Unable to create post');
- default:
- 'use server';
- router.push('/');
- return;
- }
- }
-
- if (user.isSignedIn === false) {
- router.push('/login');
- return;
- }
-
return (
- {user.isLoaded ? (
-
- ) : (
-
-
- Loading...
-
- )}
+
);
}
diff --git a/src/app/profile/[id]/page.tsx b/src/app/profile/[id]/page.tsx
index a9be135..8636556 100644
--- a/src/app/profile/[id]/page.tsx
+++ b/src/app/profile/[id]/page.tsx
@@ -1,8 +1,13 @@
import UserPosts from '@/components/UserPosts';
import UserProfile from '@/components/UserProfile';
import { getConvexClient } from '@/lib/convex';
+import { Metadata } from 'next';
import { api } from '../../../../convex/_generated/api';
+export const metadata: Metadata = {
+ title: 'conveX | Profile',
+};
+
export default async function UserProfilePage({
params,
}: {
diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx
index 899eaeb..5b9d05f 100644
--- a/src/app/search/page.tsx
+++ b/src/app/search/page.tsx
@@ -1,4 +1,9 @@
import SearchResults from '@/components/SearchResults';
+import { Metadata } from 'next';
+
+export const metadata: Metadata = {
+ title: 'conveX | Search',
+};
export default function SearchPage({
searchParams,
diff --git a/src/app/signup/[[...signup]]/page.tsx b/src/app/signup/[[...signup]]/page.tsx
index 67b7c29..0c1f7f0 100644
--- a/src/app/signup/[[...signup]]/page.tsx
+++ b/src/app/signup/[[...signup]]/page.tsx
@@ -1,25 +1,14 @@
-'use client';
+import SignUpForm from '@/components/SignUpForm';
+import { Metadata } from 'next';
-import { SignUp } from '@clerk/nextjs';
+export const metadata: Metadata = {
+ title: 'conveX | Sign up',
+};
export default function SignUpPage() {
return (
-
+
);
}
diff --git a/src/app/types/index.ts b/src/app/types/index.ts
index 4a6b278..8606582 100644
--- a/src/app/types/index.ts
+++ b/src/app/types/index.ts
@@ -8,6 +8,8 @@ export type UserDto = {
clerkUserId: string;
};
-export type PostWithUserDto = Omit, 'contentText'> & {
+export type PostDto = Omit, 'contentText'>;
+
+export type PostWithUserDto = PostDto & {
user: UserDto;
};
diff --git a/src/components/AccountForm.tsx b/src/components/AccountForm.tsx
new file mode 100644
index 0000000..a0dbf0f
--- /dev/null
+++ b/src/components/AccountForm.tsx
@@ -0,0 +1,20 @@
+'use client';
+
+import { UserProfile } from '@clerk/nextjs';
+
+export default function AccountForm() {
+ return (
+
+ );
+}
diff --git a/src/components/AddPostForm.tsx b/src/components/AddPostForm.tsx
new file mode 100644
index 0000000..1d4408f
--- /dev/null
+++ b/src/components/AddPostForm.tsx
@@ -0,0 +1,55 @@
+'use client';
+
+import { useUser } from '@clerk/nextjs';
+import { useMutation } from 'convex/react';
+import { useRouter } from '@/hooks';
+import { api } from '../../convex/_generated/api';
+import Editor, { SubmitActionParams } from './Editor';
+import SpinningLoader from './SpinningLoader';
+
+export default function AddPostForm() {
+ const user = useUser();
+ const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
+ const router = useRouter();
+
+ async function submitAction({
+ clerkUserId,
+ parentPostId,
+ post,
+ currentDoc,
+ }: SubmitActionParams) {
+ const result = await createOrUpdatePost({
+ parentPostId: parentPostId,
+ id: post?._id,
+ clerkUserId: clerkUserId,
+ content: currentDoc,
+ });
+
+ switch (result) {
+ case 'USER_NOT_FOUND':
+ case 'USER_NOT_AUTHORIZED':
+ case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
+ throw Error('Unable to create post');
+ default:
+ 'use server';
+ router.push('/');
+ return;
+ }
+ }
+
+ if (user.isSignedIn === false) {
+ router.push('/login');
+ return;
+ }
+
+ if (user.isLoaded) {
+ return ;
+ }
+
+ return (
+
+
+ Loading...
+
+ );
+}
diff --git a/src/components/DisplayPost.tsx b/src/components/DisplayPost.tsx
new file mode 100644
index 0000000..d638976
--- /dev/null
+++ b/src/components/DisplayPost.tsx
@@ -0,0 +1,106 @@
+'use client';
+
+import { useUser } from '@clerk/nextjs';
+import { useMutation, useQuery } from 'convex/react';
+import Image from 'next/image';
+import { useRouter } from '@/hooks';
+import { useEffect, useRef } from 'react';
+import { api } from '../../convex/_generated/api';
+import { Id } from '../../convex/_generated/dataModel';
+import Editor, { SubmitActionParams } from './Editor';
+import Post from './Post';
+import PostReplies from './PostReplies';
+import SpinningLoader from './SpinningLoader';
+
+export default function DisplayPost({
+ postId,
+ isReply,
+}: {
+ postId: string;
+ isReply: boolean;
+}) {
+ const replyRef = useRef(null);
+ const user = useUser();
+ const router = useRouter();
+ const post = useQuery(api.posts.getPostById, {
+ id: postId as Id<'posts'>,
+ });
+ const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
+
+ useEffect(() => {
+ if (replyRef.current !== null && isReply) {
+ replyRef.current.scrollIntoView();
+ }
+ }, [isReply, user]);
+
+ async function submitAction({
+ clerkUserId,
+ parentPostId,
+ post,
+ currentDoc,
+ }: SubmitActionParams) {
+ const result = await createOrUpdatePost({
+ parentPostId: parentPostId,
+ id: post?._id,
+ clerkUserId: clerkUserId,
+ content: currentDoc,
+ });
+
+ switch (result) {
+ case 'USER_NOT_FOUND':
+ case 'USER_NOT_AUTHORIZED':
+ case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
+ throw Error('Unable to create post');
+ default:
+ return;
+ }
+ }
+
+ if (user.isSignedIn === false) {
+ router.push('/login');
+ return;
+ }
+
+ if (post === 'POST_NOT_FOUND' || post === 'USER_FOR_POST_NOT_FOUND') {
+ // TODO: Return actual not found component
+ return Not Found
;
+ }
+
+ if (post !== undefined && user.isLoaded) {
+ return (
+ <>
+
+
+
+ >
+ );
+ }
+
+ return (
+
+ Loading post...
+
+ );
+}
diff --git a/src/components/EditPostForm.tsx b/src/components/EditPostForm.tsx
new file mode 100644
index 0000000..8929c48
--- /dev/null
+++ b/src/components/EditPostForm.tsx
@@ -0,0 +1,69 @@
+'use client';
+
+import { useRouter } from '@/hooks';
+import { useUser } from '@clerk/nextjs';
+import { useMutation, useQuery } from 'convex/react';
+import { api } from '../../convex/_generated/api';
+import { Id } from '../../convex/_generated/dataModel';
+import Editor, { SubmitActionParams } from './Editor';
+import SpinningLoader from './SpinningLoader';
+
+export default function EditPostForm({ postId }: { postId: string }) {
+ const user = useUser();
+ const post = useQuery(api.posts.getPostById, {
+ id: postId as Id<'posts'>,
+ });
+ const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
+ const router = useRouter();
+
+ if (user.isSignedIn === false) {
+ router.push('/login');
+ return;
+ }
+
+ if (post === 'POST_NOT_FOUND' || post === 'USER_FOR_POST_NOT_FOUND') {
+ // TODO: Return actual not found component
+ return Not Found
;
+ }
+
+ async function submitAction({
+ clerkUserId,
+ parentPostId,
+ post,
+ currentDoc,
+ }: SubmitActionParams) {
+ const result = await createOrUpdatePost({
+ parentPostId: parentPostId,
+ id: post?._id,
+ clerkUserId: clerkUserId,
+ content: currentDoc,
+ });
+
+ switch (result) {
+ case 'USER_NOT_FOUND':
+ case 'USER_NOT_AUTHORIZED':
+ case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
+ throw Error('Unable to update post');
+ default:
+ router.push(`/posts/${post?._id}`);
+ return;
+ }
+ }
+
+ if (user.isLoaded && post !== undefined) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+ Loading...
+
+ );
+}
diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx
index 7e4e1ff..3844b20 100644
--- a/src/components/Editor.tsx
+++ b/src/components/Editor.tsx
@@ -1,5 +1,6 @@
'use client';
+import { PostDto } from '@/app/types';
import { useCodeMirror, useRouter } from '@/hooks';
import { basicDark } from '@/lib/codemirror';
import { indentWithTab } from '@codemirror/commands';
@@ -9,13 +10,13 @@ import { Compartment, EditorState, Text } from '@codemirror/state';
import { EditorView, keymap } from '@codemirror/view';
import { basicSetup } from 'codemirror';
import { FormEvent, useEffect, useState } from 'react';
-import { Doc, Id } from '../../convex/_generated/dataModel';
+import { Id } from '../../convex/_generated/dataModel';
import PostContent from './PostContent';
export type SubmitActionParams = {
clerkUserId: string;
parentPostId?: Id<'posts'>;
- post?: Doc<'posts'>;
+ post?: PostDto;
currentDoc: string[];
};
@@ -28,7 +29,7 @@ export default function Editor({
}: {
clerkUserId: string;
parentPostId?: Id<'posts'>;
- post?: Doc<'posts'>;
+ post?: PostDto;
submitAction: ({
clerkUserId,
parentPostId,
diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx
new file mode 100644
index 0000000..3b78e13
--- /dev/null
+++ b/src/components/LoginForm.tsx
@@ -0,0 +1,23 @@
+'use client';
+
+import { SignIn } from '@clerk/nextjs';
+
+export default function LoginForm() {
+ return (
+
+ );
+}
diff --git a/src/components/SignUpForm.tsx b/src/components/SignUpForm.tsx
new file mode 100644
index 0000000..220b807
--- /dev/null
+++ b/src/components/SignUpForm.tsx
@@ -0,0 +1,23 @@
+'use client';
+
+import { SignUp } from '@clerk/nextjs';
+
+export default function SignUpForm() {
+ return (
+
+ );
+}