page.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. "use client";
  2. import { useState } from "react";
  3. import Head from "next/head";
  4. import Alert from "../ui/components/Alert";
  5. import { useRouter } from "next/navigation";
  6. export default function AuthPage() {
  7. const router = useRouter();
  8. const [isLogin, setIsLogin] = useState(true);
  9. const [username, setUsername] = useState("");
  10. const [password, setPassword] = useState("");
  11. const [alert, setAlert] = useState(null);
  12. const handleSubmit = async (e) => {
  13. e.preventDefault();
  14. const values = { username, password };
  15. try {
  16. const endpoint = isLogin ? "/api/auth/login" : "/api/auth/register";
  17. const response = await fetch(endpoint, {
  18. method: "POST",
  19. headers: {
  20. "Content-Type": "application/json",
  21. },
  22. body: JSON.stringify(values),
  23. });
  24. const res = await response.json();
  25. if (res.success) {
  26. if (isLogin) {
  27. console.log("登录成功", res.user);
  28. setAlert({ type: "success", message: "登录成功" });
  29. localStorage.setItem("currentUser", JSON.stringify(res.user));
  30. setTimeout(() => {
  31. router.push("/");
  32. }, 1000);
  33. } else {
  34. setAlert({ type: "success", message: "注册成功" });
  35. setIsLogin(true);
  36. }
  37. } else {
  38. setAlert({ type: "error", message: res.error });
  39. if (isLogin) {
  40. setTimeout(() => {
  41. router.push("/login");
  42. }, 2000);
  43. }
  44. }
  45. } catch (error) {
  46. console.error(
  47. "Error during " + (isLogin ? "login" : "registration") + ":",
  48. error
  49. );
  50. setAlert({ type: "error", message: "操作失败,请重试" });
  51. }
  52. };
  53. return (
  54. <div className="min-h-screen bg-gray-100 flex flex-col justify-center px-4 sm:px-6 lg:px-8">
  55. <Head>
  56. <title>{isLogin ? "登录" : "注册"}</title>
  57. <meta name="viewport" content="width=device-width, initial-scale=1" />
  58. </Head>
  59. <div className="w-full max-w-md mx-auto">
  60. <h2 className="mt-6 text-center text-2xl sm:text-3xl font-extrabold text-gray-900">
  61. {isLogin ? "登录您的账户" : "创建新账户"}
  62. </h2>
  63. </div>
  64. <div className="mt-8 w-full max-w-md mx-auto">
  65. <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
  66. <form className="space-y-6" onSubmit={handleSubmit}>
  67. <div>
  68. <label
  69. htmlFor="phone"
  70. className="block text-sm font-medium text-gray-700"
  71. >
  72. 用户名
  73. </label>
  74. <div className="mt-1">
  75. <input
  76. id="phone"
  77. name="phone"
  78. type="tel"
  79. autoComplete="tel"
  80. required
  81. className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 text-base"
  82. value={username}
  83. onChange={(e) => setUsername(e.target.value)}
  84. />
  85. </div>
  86. </div>
  87. <div>
  88. <label
  89. htmlFor="password"
  90. className="block text-sm font-medium text-gray-700"
  91. >
  92. 密码
  93. </label>
  94. <div className="mt-1">
  95. <input
  96. id="password"
  97. name="password"
  98. type="password"
  99. autoComplete="current-password"
  100. required
  101. className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 text-base"
  102. value={password}
  103. onChange={(e) => setPassword(e.target.value)}
  104. />
  105. </div>
  106. </div>
  107. <div>
  108. <button
  109. type="submit"
  110. className="w-full flex justify-center py-3 px-4 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
  111. >
  112. {isLogin ? "登录" : "注册"}
  113. </button>
  114. </div>
  115. </form>
  116. <div className="mt-6">
  117. <div className="relative">
  118. <div className="absolute inset-0 flex items-center">
  119. <div className="w-full border-t border-gray-300" />
  120. </div>
  121. <div className="relative flex justify-center text-sm">
  122. <span className="px-2 bg-white text-gray-500">
  123. {isLogin ? "还没有账户?" : "已经有账户?"}
  124. </span>
  125. </div>
  126. </div>
  127. <div className="mt-6">
  128. <button
  129. onClick={() => setIsLogin(!isLogin)}
  130. className="w-full flex justify-center py-3 px-4 border border-transparent rounded-md shadow-sm text-base font-medium text-indigo-600 bg-white hover:bg-gray-50"
  131. >
  132. {isLogin ? "创建新账户" : "登录已有账户"}
  133. </button>
  134. </div>
  135. </div>
  136. </div>
  137. </div>
  138. {alert && (
  139. <Alert
  140. message={alert.message}
  141. type={alert.type}
  142. onClose={() => setAlert(null)}
  143. />
  144. )}
  145. </div>
  146. );
  147. }