LoginFrame.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { useEffect, useState } from "preact/hooks";
  2. import Input from "../components/form/Input.tsx";
  3. import Button from "../components/form/Button.tsx";
  4. import ThemeToggle from "./ThemeToggle.tsx";
  5. interface LoginFrameProps {
  6. mode: "login" | "register";
  7. }
  8. export default function LoginFrame(props: LoginFrameProps) {
  9. const [email, setEmail] = useState("");
  10. const [password, setPassword] = useState("");
  11. const [confirmPassword, setConfirmPassword] = useState("");
  12. const [emailError, setEmailError] = useState(false);
  13. const [passwordError, setPasswordError] = useState(false);
  14. const [confirmPasswordError, setConfirmPasswordError] = useState(false);
  15. const checkUserLogin = async () => {
  16. const resp = await fetch("/api/user/login");
  17. const respJson = await resp.json();
  18. if (respJson.success) {
  19. // Redirect to main page if valid
  20. location.href = "/";
  21. return true;
  22. }
  23. return false;
  24. };
  25. const doUserLogin = async () => {
  26. const resp = await fetch("/api/user/login", {
  27. method: "POST",
  28. headers: { "Content-Type": "application/json" },
  29. body: JSON.stringify({
  30. email,
  31. password,
  32. }),
  33. });
  34. const respJson = await resp.json();
  35. if (respJson.success) {
  36. location.href = "/";
  37. return true;
  38. }
  39. return false;
  40. };
  41. const doUserRegister = async () => {
  42. const resp = await fetch("/api/user/register", {
  43. method: "POST",
  44. headers: { "Content-Type": "application/json" },
  45. body: JSON.stringify({
  46. email,
  47. password,
  48. }),
  49. });
  50. const respJson = await resp.json();
  51. if (respJson.success) {
  52. location.href = "/login";
  53. return true;
  54. }
  55. return false;
  56. };
  57. useEffect(() => {
  58. props.mode === "login" && checkUserLogin();
  59. }, []);
  60. const onSubmit = async () => {
  61. globalThis.$loading?.show();
  62. // Do request
  63. if (email && password && props.mode === "login") {
  64. await doUserLogin();
  65. } else if (
  66. email &&
  67. password &&
  68. confirmPassword &&
  69. props.mode === "register"
  70. ) {
  71. if (password !== confirmPassword) {
  72. setConfirmPasswordError(true);
  73. } else {
  74. await doUserRegister();
  75. }
  76. }
  77. // Set error
  78. if (!email) {
  79. setEmailError(true);
  80. }
  81. if (!password) {
  82. setPasswordError(true);
  83. }
  84. if (!confirmPassword && props.mode === "register") {
  85. setConfirmPasswordError(true);
  86. }
  87. globalThis.$loading?.hide();
  88. };
  89. return (
  90. <div className="flex items-center justify-center flex-col w-full h-full relative">
  91. <div className="absolute top-0 right-0">
  92. <ThemeToggle />
  93. </div>
  94. <h2>
  95. {props.mode === "register"
  96. ? "Register to Postdown"
  97. : "Sign in to Postdown"}
  98. </h2>
  99. <div className="w-[375px] mt-4 box-border p-4 text-gray-800 dark:text-gray-100 flex flex-col">
  100. <Input
  101. label="Email"
  102. error={emailError}
  103. type="text"
  104. placeholder="Your email"
  105. value={email}
  106. onInput={(e) => {
  107. setEmailError(false);
  108. setEmail((e.target as HTMLInputElement).value);
  109. }}
  110. />
  111. <Input
  112. label="Password"
  113. error={passwordError}
  114. type="password"
  115. placeholder="Your password"
  116. value={password}
  117. onInput={(e) => {
  118. setPasswordError(false);
  119. setPassword((e.target as HTMLInputElement).value);
  120. }}
  121. onKeyDown={(e) => {
  122. if (e.key === "Enter") {
  123. onSubmit();
  124. }
  125. }}
  126. />
  127. {props.mode === "register"
  128. ? (
  129. <Input
  130. label="Confirm Password"
  131. error={confirmPasswordError}
  132. type="password"
  133. placeholder="Confirm your password"
  134. value={confirmPassword}
  135. onInput={(e) => {
  136. setConfirmPasswordError(false);
  137. setConfirmPassword((e.target as HTMLInputElement).value);
  138. }}
  139. onKeyDown={(e) => {
  140. if (e.key === "Enter") {
  141. onSubmit();
  142. }
  143. }}
  144. />
  145. )
  146. : null}
  147. <Button
  148. variant="primary"
  149. className="h-[38px] mt-2 mb-2"
  150. type="button"
  151. onClick={onSubmit}
  152. >
  153. {props.mode === "register" ? "Register" : "Sign in"}
  154. </Button>
  155. <Button
  156. type="button"
  157. onClick={() => {
  158. location.href = props.mode === "register" ? "/login" : "/register";
  159. }}
  160. >
  161. {props.mode === "register" ? "Go Login" : "Go Register"}
  162. </Button>
  163. </div>
  164. </div>
  165. );
  166. }