Better login modal, post layout fixing
This commit is contained in:
		
							parent
							
								
									e6bf6bc8a6
								
							
						
					
					
						commit
						8d23f17f76
					
				
					 9 changed files with 269 additions and 101 deletions
				
			
		
							
								
								
									
										17
									
								
								client-solid/src/Icons.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								client-solid/src/Icons.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | export function Arrow() { | ||||||
|  |   return ( | ||||||
|  |     <svg | ||||||
|  |       xmlns="http://www.w3.org/2000/svg" | ||||||
|  |       fill="none" | ||||||
|  |       viewBox="0 0 24 24" | ||||||
|  |       stroke-width="1.5" | ||||||
|  |       stroke="currentColor" | ||||||
|  |       class="w-6 h-6" | ||||||
|  |     > | ||||||
|  |       <path | ||||||
|  |         stroke-linecap="round" | ||||||
|  |         stroke-linejoin="round" | ||||||
|  |         d="M17.25 8.25L21 12m0 0l-3.75 3.75M21 12H3" /> | ||||||
|  |     </svg> | ||||||
|  |   ); | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								client-solid/src/LoginModal.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								client-solid/src/LoginModal.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | ||||||
|  | import { onCleanup, useContext } from "solid-js"; | ||||||
|  | import { ModalContext } from "./Root"; | ||||||
|  | import { LoginForm } from "./RegLogin/Login"; | ||||||
|  | import { RegisterForm } from "./RegLogin/Register"; | ||||||
|  | 
 | ||||||
|  | export function LoginModal() { | ||||||
|  |   const modal_ctx = useContext(ModalContext); | ||||||
|  | 
 | ||||||
|  |   if (!modal_ctx) { | ||||||
|  |     // Handle the case where ModalContext is not available
 | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const closeModal = () => { | ||||||
|  |     modal_ctx.setLoginModalOpen(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Close the modal when the component is unmounted
 | ||||||
|  |   onCleanup(() => { | ||||||
|  |     modal_ctx.setLoginModalOpen(false); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       {modal_ctx.loginModalOpen() && ( | ||||||
|  |         <dialog class="modal modal-open"> | ||||||
|  |           <div class="modal-box"> | ||||||
|  |             <form method="dialog"> | ||||||
|  |               <button | ||||||
|  |                 onclick={closeModal} | ||||||
|  |                 class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" | ||||||
|  |               > | ||||||
|  |                 ✕ | ||||||
|  |               </button> | ||||||
|  |             </form> | ||||||
|  |             <h3 class="font-bold text-lg mb-2">Welcome!</h3> | ||||||
|  |             <div class="tabs tabs-lifted"> | ||||||
|  |               <input | ||||||
|  |                 type="radio" | ||||||
|  |                 name="login_tabs" | ||||||
|  |                 class="tab" | ||||||
|  |                 aria-label="Login" | ||||||
|  |                 checked | ||||||
|  |               /> | ||||||
|  |               <div class="tab-content bg-base-100 border-base-300 rounded-box p-10"> | ||||||
|  |                 <LoginForm /> | ||||||
|  |               </div> | ||||||
|  | 
 | ||||||
|  |               <input | ||||||
|  |                 type="radio" | ||||||
|  |                 name="login_tabs" | ||||||
|  |                 class="tab" | ||||||
|  |                 aria-label="Register" | ||||||
|  |               /> | ||||||
|  |               <div class="tab-content bg-base-100 border-base-300 rounded-box p-10"> | ||||||
|  |                 <RegisterForm /> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <form method="dialog" class="modal-backdrop"> | ||||||
|  |             <button onclick={closeModal}>close</button> | ||||||
|  |           </form> | ||||||
|  |         </dialog> | ||||||
|  |       )} | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | @ -2,26 +2,23 @@ import { useContext } from "solid-js"; | ||||||
| import { A } from "@solidjs/router"; | import { A } from "@solidjs/router"; | ||||||
| import { LoginContext } from "./Root"; | import { LoginContext } from "./Root"; | ||||||
| import { ModalContext } from "./Root"; | import { ModalContext } from "./Root"; | ||||||
| import { LoginForm } from "./Login"; | 
 | ||||||
|  | function MenuItem(props: { href: string; children: any }) { | ||||||
|  |   return ( | ||||||
|  |     <li> | ||||||
|  |       <A class="justify-center" href={props.href} end> | ||||||
|  |         {props.children} | ||||||
|  |       </A> | ||||||
|  |     </li> | ||||||
|  |   ); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| function Menu() { | function Menu() { | ||||||
|   let login_ctx = useContext(LoginContext); |   let login_ctx = useContext(LoginContext); | ||||||
|   return ( |   return ( | ||||||
|     <ul class="menu menu-horizontal bg-base-100 rounded-box space-x-2"> |     <ul class="menu md:menu-horizontal rounded-box"> | ||||||
|       <li> |       <MenuItem href="/">Home</MenuItem> | ||||||
|         <A href="/" end> |       {login_ctx?.token() != "" && <MenuItem href="/new">New Post</MenuItem>} | ||||||
|           Home |  | ||||||
|         </A> |  | ||||||
|       </li> |  | ||||||
|       {login_ctx?.token() != "" ? ( |  | ||||||
|         <li> |  | ||||||
|           <A href="/new" end> |  | ||||||
|             New |  | ||||||
|           </A> |  | ||||||
|         </li> |  | ||||||
|       ) : ( |  | ||||||
|         <></> |  | ||||||
|       )} |  | ||||||
|     </ul> |     </ul> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | @ -30,61 +27,42 @@ export function Navbar() { | ||||||
|   let modal_ctx = useContext(ModalContext); |   let modal_ctx = useContext(ModalContext); | ||||||
|   let login_ctx = useContext(LoginContext); |   let login_ctx = useContext(LoginContext); | ||||||
| 
 | 
 | ||||||
|  |   const logout = () => { | ||||||
|  |     localStorage.setItem("token", ""); | ||||||
|  |     localStorage.setItem("username", ""); | ||||||
|  |     login_ctx?.setToken(""); | ||||||
|  |     login_ctx?.setUsername(""); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Capitalize the first letter of the username
 | ||||||
|  |   const username = | ||||||
|  |     login_ctx && login_ctx.username() | ||||||
|  |       ? login_ctx.username().charAt(0).toUpperCase() + | ||||||
|  |         login_ctx.username().slice(1) | ||||||
|  |       : "Guest"; | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div class="navbar text-neutral-content max-w-3xl max-w"> |     <div class="navbar text-neutral-content max-w-3xl max-w rounded-box my-4"> | ||||||
|       <div class="flex-1"> |       <div class="flex-1"> | ||||||
|         <A href={"/"} class="btn btn-ghost normal-case text-xl"> |         <A href={"/"} class="btn btn-ghost normal-case text-xl"> | ||||||
|           FrostByte |           FrostByte | ||||||
|         </A> |         </A> | ||||||
|       </div> |       </div> | ||||||
|       <div class="hidden md:flex"> |       <div class="flex"> | ||||||
|         <Menu /> |         <Menu /> | ||||||
|       </div> |       </div> | ||||||
|       <div class="flex-1 justify-end hidden md:flex"> |       <div class="flex-1 justify-end flex"> | ||||||
|         <A |         <A | ||||||
|           href="#" |           href="#" | ||||||
|           class="btn btn-ghost normal-case text-sm" |           class="btn btn-ghost normal-case text-sm" | ||||||
|           onClick={() => { |           onClick={() => { | ||||||
|             if (login_ctx?.token() != "") { |             if (login_ctx?.token() != "") logout(); | ||||||
|               localStorage.setItem("token", ""); |             else modal_ctx?.setLoginModalOpen(true); | ||||||
|               localStorage.setItem("username", ""); |  | ||||||
|               login_ctx?.setToken(""); |  | ||||||
|               login_ctx?.setUsername(""); |  | ||||||
|               return; |  | ||||||
|             } |  | ||||||
|             modal_ctx?.setLoginModalOpen(true); |  | ||||||
|           }} |           }} | ||||||
|         > |         > | ||||||
|           {login_ctx?.token() != "" ? login_ctx?.username() : "Login"} |           {login_ctx?.token() != "" ? username : "Login"} | ||||||
|         </A> |         </A> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // This is a modal
 |  | ||||||
| export function Login() { |  | ||||||
|   const modal_ctx = useContext(ModalContext); |  | ||||||
|   return ( |  | ||||||
|     <dialog id="login_modal" class="modal" open={modal_ctx?.loginModalOpen()}> |  | ||||||
|       <div class="modal-box"> |  | ||||||
|         <h3 class="font-bold text-lg">Hello!</h3> |  | ||||||
|         <p class="py-4">Login to your FrostByte account.</p> |  | ||||||
|         <LoginForm /> |  | ||||||
|       </div> |  | ||||||
|       <form |  | ||||||
|         method="dialog" |  | ||||||
|         // This backdrop renders choppy on my machine. Likely because of the blur filter or misuse of css transisions
 |  | ||||||
|         class="modal-backdrop backdrop-brightness-50 backdrop-blur-sm backdrop-contrast-100 transition-all transition-300" |  | ||||||
|         onsubmit={(e) => { |  | ||||||
|           // This is just needed to set the state to false
 |  | ||||||
|           // The modal will close itself without this code, but without setting the state
 |  | ||||||
|           e.preventDefault(); |  | ||||||
|           modal_ctx?.setLoginModalOpen(false); |  | ||||||
|         }} |  | ||||||
|       > |  | ||||||
|         <button>close</button> |  | ||||||
|       </form> |  | ||||||
|     </dialog> |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ import { createSignal } from "solid-js"; | ||||||
| import { getPosts } from "./api"; | import { getPosts } from "./api"; | ||||||
| import { Post } from "./api"; | import { Post } from "./api"; | ||||||
| import { useNavigate } from "@solidjs/router"; | import { useNavigate } from "@solidjs/router"; | ||||||
|  | import { Arrow } from "./Icons"; | ||||||
| 
 | 
 | ||||||
| export function Posts() { | export function Posts() { | ||||||
|   const [posts, setPosts] = createSignal([] as Post[]); |   const [posts, setPosts] = createSignal([] as Post[]); | ||||||
|  | @ -13,17 +14,15 @@ export function Posts() { | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div class="flex flex-col space-y-2 w-full md:w-96"> |     <> | ||||||
|       {loading() ? ( |       {loading() && ( | ||||||
|         <span class="loading loading-spinner loading-lg self-center"></span> |         <span class="loading loading-spinner loading-lg self-center"></span> | ||||||
|       ) : ( |  | ||||||
|         <></> |  | ||||||
|       )} |       )} | ||||||
|       {posts().map((post) => { |       {posts().map((post) => { | ||||||
|         if (post.content == "") return; // Filtering out empty posts, remove this later
 |         if (post.content == "") return; // Filtering out empty posts, remove this later
 | ||||||
|         return <PostSegment post={post}></PostSegment>; |         return <PostSegment post={post}></PostSegment>; | ||||||
|       })} |       })} | ||||||
|     </div> |     </> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -31,13 +30,17 @@ export function Posts() { | ||||||
| export function PostSegment({ post }: { post: Post }) { | export function PostSegment({ post }: { post: Post }) { | ||||||
|   const nav = useNavigate(); |   const nav = useNavigate(); | ||||||
|   return ( |   return ( | ||||||
|     <div |     <div class="card border-b-2 flex-grow border-b-base-300 bg-base-200 hover:bg-base-300 compact text-base-content w-full"> | ||||||
|       onClick={() => nav("/post/" + post?.id)} |  | ||||||
|       class="card bg-base-200 shadow-lg compact text-base-content w-full" |  | ||||||
|     > |  | ||||||
|       <div class="card-body"> |       <div class="card-body"> | ||||||
|         <p class="text-base-content break-words">{post?.content}</p> |         <p class="text-base-content break-words">{post?.content}</p> | ||||||
|  |         <div class="card-actions justify-end"> | ||||||
|  |           <button onClick={() => nav("/post/" + post?.id)} class="btn btn-xs"> | ||||||
|  |             <Arrow /> | ||||||
|  |           </button> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { createSignal, useContext } from "solid-js"; | import { createSignal, useContext } from "solid-js"; | ||||||
| import { LoginContext, ModalContext } from "./Root"; | import { LoginContext, ModalContext } from "../Root"; | ||||||
| 
 | 
 | ||||||
| export function LoginForm() { | export function LoginForm() { | ||||||
|   const modal_ctx = useContext(ModalContext); |   const modal_ctx = useContext(ModalContext); | ||||||
|  | @ -17,49 +17,49 @@ export function LoginForm() { | ||||||
|     }, 1000); |     }, 1000); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return ( |   async function loginPress(e: Event) { | ||||||
|     <form class="form-control"> |     e.preventDefault(); | ||||||
|       <label class="label"> |  | ||||||
|         <span class="label-text">Username</span> |  | ||||||
|       </label> |  | ||||||
|       <input |  | ||||||
|         type="text" |  | ||||||
|         placeholder="username" |  | ||||||
|         value={username()} |  | ||||||
|         class="input input-bordered" |  | ||||||
|         onChange={(e) => { |  | ||||||
|           setUsername(e.target.value); |  | ||||||
|         }} /> |  | ||||||
|       <label class="label"> |  | ||||||
|         <span class="label-text">Password</span> |  | ||||||
|       </label> |  | ||||||
|       <input |  | ||||||
|         type="password" |  | ||||||
|         placeholder="password" |  | ||||||
|         value={password()} |  | ||||||
|         class="input input-bordered" |  | ||||||
|         onChange={(e) => { |  | ||||||
|           setPassword(e.target.value); |  | ||||||
|         }} /> |  | ||||||
|       <button |  | ||||||
|         class={"btn btn-primary mt-4" + (error() ? " btn-error" : "")} |  | ||||||
|         onClick={(b) => { |  | ||||||
|           b.preventDefault(); |  | ||||||
|     setWaiting(true); |     setWaiting(true); | ||||||
|     submitLogin(username(), password()).then((token) => { |     submitLogin(username(), password()).then((token) => { | ||||||
|       if (token != "") { |       if (token != "") { | ||||||
|         setWaiting(false); |         setWaiting(false); | ||||||
|         setError(false); |         setError(false); | ||||||
|         login_ctx?.setUsername(username()); |         login_ctx?.setUsername(username()); | ||||||
|               setUsername(""); |  | ||||||
|               setPassword(""); |  | ||||||
|         login_ctx?.setToken(token); |         login_ctx?.setToken(token); | ||||||
|         modal_ctx?.setLoginModalOpen(false); |         modal_ctx?.setLoginModalOpen(false); | ||||||
|  |         setUsername(""); | ||||||
|  |         setPassword(""); | ||||||
|       } else { |       } else { | ||||||
|         loginFailed(); |         loginFailed(); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <form class="form-control space-y-2"> | ||||||
|  |       <input | ||||||
|  |         type="text" | ||||||
|  |         placeholder="Username" | ||||||
|  |         value={username()} | ||||||
|  |         class="input input-bordered" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setUsername(e.target.value); | ||||||
|         }} |         }} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <input | ||||||
|  |         type="password" | ||||||
|  |         placeholder="Password" | ||||||
|  |         value={password()} | ||||||
|  |         class="input input-bordered" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setPassword(e.target.value); | ||||||
|  |         }} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <button | ||||||
|  |         class={"btn btn-primary" + (error() ? " btn-error" : "")} | ||||||
|  |         onClick={ loginPress } | ||||||
|       > |       > | ||||||
|         {waiting() ? "Logging in..." : "Login"} |         {waiting() ? "Logging in..." : "Login"} | ||||||
|       </button> |       </button> | ||||||
|  | @ -73,6 +73,7 @@ export async function submitLogin( | ||||||
|   username: string, |   username: string, | ||||||
|   password: string |   password: string | ||||||
| ): Promise<string> { | ): Promise<string> { | ||||||
|  |   if(username == "" || password == "") return ""; | ||||||
|   const response = await fetch("/api/login", { |   const response = await fetch("/api/login", { | ||||||
|     method: "POST", |     method: "POST", | ||||||
|     headers: { "Content-Type": "application/json" }, |     headers: { "Content-Type": "application/json" }, | ||||||
|  | @ -89,4 +90,3 @@ export async function submitLogin( | ||||||
|   } |   } | ||||||
|   return ""; |   return ""; | ||||||
| } | } | ||||||
| 
 |  | ||||||
							
								
								
									
										103
									
								
								client-solid/src/RegLogin/Register.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								client-solid/src/RegLogin/Register.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | ||||||
|  | import { createSignal, useContext } from "solid-js"; | ||||||
|  | import { LoginContext, ModalContext } from "../Root"; | ||||||
|  | 
 | ||||||
|  | export function RegisterForm() { | ||||||
|  |   const modal_ctx = useContext(ModalContext); | ||||||
|  |   const login_ctx = useContext(LoginContext); | ||||||
|  |   const [username, setUsername] = createSignal<string>(""); | ||||||
|  |   const [password, setPassword] = createSignal<string>(""); | ||||||
|  |   const [captcha, setCaptcha] = createSignal<string>(""); | ||||||
|  |   const [waiting, setWaiting] = createSignal(false); | ||||||
|  |   const [error, setError] = createSignal(false); | ||||||
|  | 
 | ||||||
|  |   async function loginFailed() { | ||||||
|  |     setError(true); | ||||||
|  |     setWaiting(false); | ||||||
|  |     setTimeout(() => { | ||||||
|  |       setError(false); | ||||||
|  |     }, 1000); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async function regPress(e: Event) { | ||||||
|  |     e.preventDefault(); | ||||||
|  |     setWaiting(true); | ||||||
|  |     submitRegistration(username(), password(), captcha()).then((token) => { | ||||||
|  |       if (token != "") { | ||||||
|  |         setWaiting(false); | ||||||
|  |         setError(false); | ||||||
|  |         login_ctx?.setUsername(username()); | ||||||
|  |         login_ctx?.setToken(token); | ||||||
|  |         modal_ctx?.setLoginModalOpen(false); | ||||||
|  |         setUsername(""); | ||||||
|  |         setPassword(""); | ||||||
|  |       } else { | ||||||
|  |         loginFailed(); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <form class="form-control space-y-2"> | ||||||
|  |       <input | ||||||
|  |         type="text" | ||||||
|  |         placeholder="Username" | ||||||
|  |         value={username()} | ||||||
|  |         class="input input-bordered" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setUsername(e.target.value); | ||||||
|  |         }} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <input | ||||||
|  |         type="password" | ||||||
|  |         placeholder="Password" | ||||||
|  |         value={password()} | ||||||
|  |         class="input input-bordered" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setPassword(e.target.value); | ||||||
|  |         }} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <input | ||||||
|  |         type="text" | ||||||
|  |         placeholder="Captcha" | ||||||
|  |         value={password()} | ||||||
|  |         class="input input-bordered" | ||||||
|  |         onChange={(e) => { | ||||||
|  |           setCaptcha(e.target.value); | ||||||
|  |         }} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       <button | ||||||
|  |         class={"btn btn-primary" + (error() ? " btn-error" : "")} | ||||||
|  |         onClick={regPress} | ||||||
|  |       > | ||||||
|  |         {waiting() ? "Logging in..." : "Login"} | ||||||
|  |       </button> | ||||||
|  |     </form> | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // This function is responsible for sending the login request to the server
 | ||||||
|  | // and storing the token in localstorage
 | ||||||
|  | export async function submitRegistration( | ||||||
|  |   username: string, | ||||||
|  |   password: string, | ||||||
|  |   captcha: string | ||||||
|  | ): Promise<string> { | ||||||
|  |   const response = await fetch("/api/register", { | ||||||
|  |     method: "POST", | ||||||
|  |     headers: { "Content-Type": "application/json" }, | ||||||
|  |     body: JSON.stringify({ username, password, captcha }), | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   if (response.ok) { | ||||||
|  |     const data = await response.json(); | ||||||
|  |     if (data.token && data.username) { | ||||||
|  |       localStorage.setItem("token", data.token); | ||||||
|  |       localStorage.setItem("username", data.username); | ||||||
|  |       return data.token; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return ""; | ||||||
|  | } | ||||||
|  | @ -5,7 +5,8 @@ import { createPost } from "./api"; | ||||||
| import { NewPost } from "./api"; | import { NewPost } from "./api"; | ||||||
| import { Navbar } from "./Navbar"; | import { Navbar } from "./Navbar"; | ||||||
| import { Primary } from "./Primary"; | import { Primary } from "./Primary"; | ||||||
| import { Login } from "./Navbar"; | // import { Login } from "./Navbar";
 | ||||||
|  | import { LoginModal } from "./LoginModal"; | ||||||
| import { useNavigate } from "@solidjs/router"; | import { useNavigate } from "@solidjs/router"; | ||||||
| 
 | 
 | ||||||
| // Representing the state of varoious modals.
 | // Representing the state of varoious modals.
 | ||||||
|  | @ -44,9 +45,9 @@ function Root() { | ||||||
|         <LoginContext.Provider |         <LoginContext.Provider | ||||||
|           value={{ token, setToken, username, setUsername }} |           value={{ token, setToken, username, setUsername }} | ||||||
|         > |         > | ||||||
|           <div class="flex flex-col items-center my-2"> |           <div class="flex flex-col items-center"> | ||||||
|             <Navbar /> |             <Navbar /> | ||||||
|             <Login /> |             <LoginModal /> | ||||||
|             <div class="flex flex-col items-center md:w-96 space-y-2"> |             <div class="flex flex-col items-center md:w-96 space-y-2"> | ||||||
|               <Primary /> |               <Primary /> | ||||||
|             </div> |             </div> | ||||||
|  | @ -66,10 +67,12 @@ export function NewPostInputArea() { | ||||||
| 
 | 
 | ||||||
|   const sendPost = () => { |   const sendPost = () => { | ||||||
|     setWaiting(true); |     setWaiting(true); | ||||||
|  | 
 | ||||||
|     const response = createPost({ |     const response = createPost({ | ||||||
|       content: content(), |       content: content(), | ||||||
|       token: login_ctx?.token(), |       token: login_ctx?.token(), | ||||||
|     } as NewPost); |     } as NewPost); | ||||||
|  | 
 | ||||||
|     if (response) { |     if (response) { | ||||||
|       response.then(() => { |       response.then(() => { | ||||||
|         setWaiting(false); |         setWaiting(false); | ||||||
|  |  | ||||||
|  | @ -9,11 +9,9 @@ export function SinglePost() { | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Suspense fallback={<div>Some loading message</div>}> |     <Suspense fallback={<div>Some loading message</div>}> | ||||||
|       <div> |  | ||||||
|         <Show when={post()}> |         <Show when={post()}> | ||||||
|           <PostSegment post={post()!}></PostSegment> |           <PostSegment post={post()!}></PostSegment> | ||||||
|         </Show> |         </Show> | ||||||
|       </div> |  | ||||||
|     </Suspense> |     </Suspense> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,7 +29,6 @@ export async function getPost(id: string): Promise<Post> { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function createPost(post: NewPost): Promise<void> { | export async function createPost(post: NewPost): Promise<void> { | ||||||
| //   await fetch(`${API_URL}`, {
 |  | ||||||
|   await fetch("/api/posts", { |   await fetch("/api/posts", { | ||||||
|     method: "POST", |     method: "POST", | ||||||
|     headers: { |     headers: { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Imbus
						Imbus