HomeBar.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import Input from "../components/form/Input.tsx";
  2. import Button from "../components/form/Button.tsx";
  3. import FileInput from "../components/form/FileInput.tsx";
  4. import ThemeToggle from "./ThemeToggle.tsx";
  5. interface HomeBarProps {
  6. name: string;
  7. }
  8. const settingsData: { [key: string]: string } = {};
  9. const newPostData: { [key: string]: string } = {};
  10. export default function HomeBar(props: HomeBarProps) {
  11. const doCreatePost = async () => {
  12. globalThis.$loading?.show();
  13. const resp = await fetch("/api/post", {
  14. method: "POST",
  15. headers: { "Content-Type": "application/json" },
  16. body: JSON.stringify({
  17. title: newPostData["title"] || "",
  18. content: newPostData["content"] || "",
  19. }),
  20. });
  21. const respJson = await resp.json();
  22. if (respJson.success) {
  23. location.href = `/${respJson.data}`;
  24. return true;
  25. }
  26. return false;
  27. };
  28. const showNewPost = () => {
  29. newPostData["title"] = "";
  30. newPostData["content"] = "";
  31. globalThis.$modal?.show(
  32. "New Post",
  33. <div>
  34. <FileInput
  35. label="Import file (optional)"
  36. accept=".md,.txt"
  37. onInput={(e) => {
  38. const file = (e.target as HTMLInputElement).files?.[0];
  39. if (!file) {
  40. newPostData["title"] = "";
  41. newPostData["content"] = "";
  42. return;
  43. }
  44. newPostData["title"] = file.name.replace(/\.(md|txt)$/, "");
  45. const reader = new FileReader();
  46. reader.onload = () => {
  47. newPostData["content"] = reader.result as string;
  48. };
  49. reader.readAsText(file);
  50. }}
  51. />
  52. </div>,
  53. [
  54. {
  55. text: "Create",
  56. onClick: async () => {
  57. await doCreatePost();
  58. },
  59. },
  60. {
  61. text: "Cancel",
  62. },
  63. ],
  64. );
  65. };
  66. const doLogout = async () => {
  67. const resp = await fetch("/api/user/logout");
  68. const respJson = await resp.json();
  69. if (respJson.success) {
  70. location.href = "/login";
  71. return true;
  72. }
  73. return false;
  74. };
  75. const showReset = () => {
  76. settingsData["old"] = "";
  77. settingsData["new"] = "";
  78. settingsData["repeat"] = "";
  79. globalThis.$modal?.show(
  80. "Reset password",
  81. <div>
  82. <Input
  83. label="Old password"
  84. type="password"
  85. placeholder="Old password"
  86. value={settingsData["old"]}
  87. onInput={(e) => {
  88. settingsData["old"] = (e.target as HTMLInputElement).value;
  89. }}
  90. />
  91. <Input
  92. label="New password"
  93. type="password"
  94. placeholder="New password"
  95. value={settingsData["new"]}
  96. onInput={(e) => {
  97. settingsData["new"] = (e.target as HTMLInputElement).value;
  98. }}
  99. />
  100. <Input
  101. label="Repeat new password"
  102. type="password"
  103. placeholder="Repeat new password"
  104. value={settingsData["repeat"]}
  105. onInput={(e) => {
  106. settingsData["repeat"] = (e.target as HTMLInputElement).value;
  107. }}
  108. />
  109. </div>,
  110. [
  111. {
  112. text: "Confirm",
  113. onClick: async () => {
  114. if (
  115. settingsData["old"] && settingsData["new"] &&
  116. settingsData["repeat"] &&
  117. settingsData["new"] === settingsData["repeat"]
  118. ) {
  119. const resp = await fetch("/api/user/reset", {
  120. method: "POST",
  121. headers: { "Content-Type": "application/json" },
  122. body: JSON.stringify({
  123. old: settingsData["old"],
  124. new: settingsData["new"],
  125. }),
  126. });
  127. const respJson = await resp.json();
  128. if (respJson.success) {
  129. globalThis.$modal?.hide();
  130. }
  131. }
  132. },
  133. },
  134. ],
  135. );
  136. };
  137. return (
  138. <div className="flex items-center justify-between">
  139. <Button
  140. type="button"
  141. onClick={showNewPost}
  142. >
  143. New Post
  144. </Button>
  145. <div className="flex items-center">
  146. <span>{props.name}</span>
  147. <Button
  148. type="button"
  149. className="ml-2"
  150. onClick={showReset}
  151. >
  152. Password
  153. </Button>
  154. <Button
  155. type="button"
  156. className="ml-2"
  157. onClick={doLogout}
  158. >
  159. Logout
  160. </Button>
  161. <span className="ml-3">
  162. <ThemeToggle />
  163. </span>
  164. </div>
  165. </div>
  166. );
  167. }