Initial draft of comments
This commit is contained in:
parent
5916a21bd5
commit
edb7ef2fc4
5 changed files with 164 additions and 13 deletions
47
client-solid/src/Components/Comment.tsx
Normal file
47
client-solid/src/Components/Comment.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { useNavigate } from "@solidjs/router";
|
||||
import { For, JSXElement, Show, createSignal } from "solid-js";
|
||||
|
||||
import { CheckMark, loadSpinner } from "../Util/Icons";
|
||||
import { PublicComment, getComments } from "../Util/api";
|
||||
|
||||
//exported into primary as a Route
|
||||
export function Comment({ postId }: { postId: string }): JSXElement {
|
||||
const [comments, setComments] = createSignal([] as PublicComment[]);
|
||||
const [loading, setLoading] = createSignal(true);
|
||||
|
||||
getComments(postId, 10, 0).then((comment) => {
|
||||
setComments(comment);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return (
|
||||
<Show when={!loading()} fallback={loadSpinner()}>
|
||||
<For each={comments()}>
|
||||
{(comment): JSXElement => <CommentSegment comment={comment} />}
|
||||
</For>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
export function CommentSegment(props: { comment: PublicComment }): JSXElement {
|
||||
const nav = useNavigate();
|
||||
return (
|
||||
<div class="card compact w-full flex-grow border-b-2 border-b-base-300 bg-base-200 text-base-content transition-all hover:bg-base-300">
|
||||
<div class="card-body">
|
||||
<p class="break-words text-base-content md:px-6 md:pt-2">
|
||||
{props.comment?.content}
|
||||
</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button
|
||||
onClick={(): void =>
|
||||
nav("/comments?post_id" + props.comment?.parent_comment_id)
|
||||
}
|
||||
class="btn btn-xs"
|
||||
>
|
||||
<CheckMark />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
21
client-solid/src/Components/CommentSection.tsx
Normal file
21
client-solid/src/Components/CommentSection.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import {
|
||||
For,
|
||||
JSXElement,
|
||||
Show,
|
||||
createResource,
|
||||
createSignal,
|
||||
useContext,
|
||||
} from "solid-js";
|
||||
|
||||
import { getComments } from "../Util/api";
|
||||
import { CommentSegment } from "./Comment";
|
||||
|
||||
export function CommentSection({ postId }: { postId: string }): JSXElement {
|
||||
const [comments] = createResource(postId, () => getComments(postId, 0, 10));
|
||||
|
||||
return (
|
||||
<For each={comments()!}>
|
||||
{(comment) => <CommentSegment comment={comment} />}
|
||||
</For>
|
||||
);
|
||||
}
|
69
client-solid/src/Components/NewComment.tsx
Normal file
69
client-solid/src/Components/NewComment.tsx
Normal file
|
@ -0,0 +1,69 @@
|
|||
import { useNavigate } from "@solidjs/router";
|
||||
import { JSXElement, Show, createSignal, onMount, useContext } from "solid-js";
|
||||
|
||||
import { LoginContext } from "../Context/GlobalState";
|
||||
import { NewComment, createComment } from "../Util/api";
|
||||
|
||||
export function NewCommentInputArea({
|
||||
parentPostId,
|
||||
}: {
|
||||
parentPostId: number;
|
||||
}): JSXElement {
|
||||
const [content, setContent] = createSignal("");
|
||||
const [waiting, setWaiting] = createSignal(false);
|
||||
|
||||
// We assumte this context is always available
|
||||
const login_ctx = useContext(LoginContext)!;
|
||||
|
||||
const nav = useNavigate();
|
||||
|
||||
const sendComment = (): void => {
|
||||
setWaiting(true);
|
||||
|
||||
const response = createComment({
|
||||
content: content(),
|
||||
user_token: login_ctx.token(),
|
||||
parent_post_id: parentPostId,
|
||||
} as NewComment);
|
||||
|
||||
if (response) {
|
||||
response.then(() => {
|
||||
setWaiting(false);
|
||||
setContent("");
|
||||
nav("/");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Bail out if not logged in
|
||||
onMount(() => {
|
||||
if (!login_ctx.loggedIn()) nav("/");
|
||||
});
|
||||
|
||||
return (
|
||||
<Show
|
||||
when={!waiting()}
|
||||
fallback={<span class="loading loading-spinner loading-lg self-center" />}
|
||||
>
|
||||
<div class="flex w-full flex-col space-y-2">
|
||||
<textarea
|
||||
class="textarea textarea-bordered h-32"
|
||||
placeholder="Reply to post..."
|
||||
maxLength={500}
|
||||
onInput={(input): void => {
|
||||
setContent(input.target.value);
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
class={
|
||||
"btn btn-primary btn-sm self-end" +
|
||||
(content() == "" ? " btn-disabled" : "")
|
||||
}
|
||||
onClick={sendComment}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
}
|
|
@ -1,29 +1,22 @@
|
|||
import { useParams } from "@solidjs/router";
|
||||
import { For, JSXElement, Show, Suspense, createResource } from "solid-js";
|
||||
import { JSXElement, Show, Suspense, createResource } from "solid-js";
|
||||
|
||||
import { loadSpinner } from "../Util/Icons";
|
||||
import { getComments, getPost } from "../Util/api";
|
||||
import { getPost } from "../Util/api";
|
||||
import { CommentSection } from "./CommentSection";
|
||||
import { PostSegment } from "./Posts";
|
||||
import { NewCommentInputArea } from "./NewComment";
|
||||
|
||||
export function SinglePost(): JSXElement {
|
||||
const params = useParams();
|
||||
const [post] = createResource(params.postid, getPost);
|
||||
const [comments] = createResource(params.postid, () =>
|
||||
getComments(params.postid, 0, 10)
|
||||
);
|
||||
|
||||
return (
|
||||
<Suspense fallback={loadSpinner()}>
|
||||
<Show when={post()}>
|
||||
<PostSegment post={post()!} />
|
||||
<For each={comments()!}>
|
||||
{(comment) => (
|
||||
// TODO: This should be a separate component
|
||||
<div class="comment">
|
||||
<p>{comment.content}</p>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
<NewCommentInputArea parentPostId={parseInt(params.postid)}/>
|
||||
<CommentSection postId={params.post_id} />
|
||||
</Show>
|
||||
</Suspense>
|
||||
);
|
||||
|
|
|
@ -16,6 +16,17 @@ export interface Post extends NewPost {
|
|||
votes: Votes;
|
||||
}
|
||||
|
||||
export interface NewComment {
|
||||
content: string;
|
||||
user_token: string;
|
||||
parent_post_id: number;
|
||||
}
|
||||
|
||||
export interface Comment extends NewComment {
|
||||
content: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
// This is what the login and registration responses look like
|
||||
export interface AuthResponse {
|
||||
username: string;
|
||||
|
@ -56,6 +67,16 @@ export async function createPost(post: NewPost): Promise<void> {
|
|||
});
|
||||
}
|
||||
|
||||
export async function createComment(comment: NewComment): Promise<void> {
|
||||
await fetch("/api/comments", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(comment),
|
||||
});
|
||||
}
|
||||
|
||||
// Gets the comments for a specific post
|
||||
export async function getComments(
|
||||
postId: string,
|
||||
|
|
Loading…
Reference in a new issue