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 { 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 { loadSpinner } from "../Util/Icons";
|
||||||
import { getComments, getPost } from "../Util/api";
|
import { getPost } from "../Util/api";
|
||||||
|
import { CommentSection } from "./CommentSection";
|
||||||
import { PostSegment } from "./Posts";
|
import { PostSegment } from "./Posts";
|
||||||
|
import { NewCommentInputArea } from "./NewComment";
|
||||||
|
|
||||||
export function SinglePost(): JSXElement {
|
export function SinglePost(): JSXElement {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [post] = createResource(params.postid, getPost);
|
const [post] = createResource(params.postid, getPost);
|
||||||
const [comments] = createResource(params.postid, () =>
|
|
||||||
getComments(params.postid, 0, 10)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={loadSpinner()}>
|
<Suspense fallback={loadSpinner()}>
|
||||||
<Show when={post()}>
|
<Show when={post()}>
|
||||||
<PostSegment post={post()!} />
|
<PostSegment post={post()!} />
|
||||||
<For each={comments()!}>
|
<NewCommentInputArea parentPostId={parseInt(params.postid)}/>
|
||||||
{(comment) => (
|
<CommentSection postId={params.post_id} />
|
||||||
// TODO: This should be a separate component
|
|
||||||
<div class="comment">
|
|
||||||
<p>{comment.content}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</For>
|
|
||||||
</Show>
|
</Show>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,6 +16,17 @@ export interface Post extends NewPost {
|
||||||
votes: Votes;
|
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
|
// This is what the login and registration responses look like
|
||||||
export interface AuthResponse {
|
export interface AuthResponse {
|
||||||
username: string;
|
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
|
// Gets the comments for a specific post
|
||||||
export async function getComments(
|
export async function getComments(
|
||||||
postId: string,
|
postId: string,
|
||||||
|
|
Loading…
Reference in a new issue