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…
	
	Add table
		Add a link
		
	
		Reference in a new issue