diff --git a/apps/forum/src/components/App.tsx b/apps/forum/src/components/App.tsx index 7e41f4a0c..e04651147 100644 --- a/apps/forum/src/components/App.tsx +++ b/apps/forum/src/components/App.tsx @@ -11,7 +11,7 @@ import SearchTags from "./SearchTags"; import FeedBackBox from "./FeedBackBox"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { API } from "@aws-amplify/api"; -import { getUserAttr, getIdToken } from "wasedatime-ui"; +import { getUserAttr, getIdToken, LoadingSpinner } from "wasedatime-ui"; const App = () => { return ( @@ -25,6 +25,14 @@ const App = () => { export default App; +const NotFound = () => { + const { theme } = React.useContext(ThemeContext); + const navigate = useNavigate(); + useEffect(() => navigate("/")); + + return ; +}; + const InnerApp = () => { const { t, i18n } = useTranslation(); @@ -108,6 +116,7 @@ const InnerApp = () => { path="forum/:boardSlug" /> } path="forum/:boardSlug/:threadUuid" /> + } path="*" />
diff --git a/apps/forum/src/components/Comment.tsx b/apps/forum/src/components/Comment.tsx index af9e1e7ae..afe2daa8a 100644 --- a/apps/forum/src/components/Comment.tsx +++ b/apps/forum/src/components/Comment.tsx @@ -7,6 +7,7 @@ import { ConfirmModal } from "@app/components/form/ConfirmModal"; import API from "@aws-amplify/api"; import { getIdToken } from "wasedatime-ui"; import ThreadType from "@app/types/thread"; +import { timeFormatter } from "../utils/timeFormatter"; type Props = { comment: CommentType; @@ -18,7 +19,7 @@ type Props = { const convertUrlsToLinks = (text: string) => { if (!text) return null; - const urlRegex = /https?:\/\/[^\s]+/g; + const urlRegex: RegExp = /https?:\/\/[^\s]+/g; const parts = text.split(urlRegex); const matches = text.match(urlRegex); @@ -100,8 +101,6 @@ const Comment = ({ comment, thread, setComments, setThread }: Props) => { } ); - console.log(res); - const action = "update_decr"; await API.patch( "wasedatime-dev", @@ -129,12 +128,15 @@ const Comment = ({ comment, thread, setComments, setThread }: Props) => { } }; + const time = timeFormatter(comment); + console.log(comment); + return (

{convertUrlsToLinks(comment.body)}

-

+

Posted at {time}

{comment.mod === true && (
diff --git a/apps/forum/src/components/CommentForm.tsx b/apps/forum/src/components/CommentForm.tsx index 1871b6011..d470eff1c 100644 --- a/apps/forum/src/components/CommentForm.tsx +++ b/apps/forum/src/components/CommentForm.tsx @@ -66,6 +66,7 @@ const CommentForm: React.FC = ({ ); const newComment: CommentType = response.data; + onNewComment(newComment); setComment(""); @@ -105,12 +106,12 @@ const CommentForm: React.FC = ({ } } catch (error) { console.error("An error occurred:", error); - } finally { } }; return (
+ {/*
Posted at ${time}
*/} = ({ > - {isSignInModalOpen && ( - setSignInModalOpen(false)} - t={t} - /> - )} + setSignInModalOpen(false)} + t={t} + />
); }; diff --git a/apps/forum/src/components/CreateThread.tsx b/apps/forum/src/components/CreateThread.tsx index a2a9c980c..eecad3972 100644 --- a/apps/forum/src/components/CreateThread.tsx +++ b/apps/forum/src/components/CreateThread.tsx @@ -9,6 +9,8 @@ import SchoolFilterForm from "./common/SchoolFilter"; import { Menu, Transition } from "@headlessui/react"; import ThreadType from "@app/types/thread"; import TagType from "@app/types/tag"; +import ImageIcon from "@mui/icons-material/Image"; +import threadPayload from "@app/types/threadPayload"; interface CreateThreadProps { onNewThread: (newThread: ThreadType) => void; @@ -29,6 +31,9 @@ const CreateThread = ({ onNewThread }: CreateThreadProps) => { const [selectedBoard, setSelectedBoard] = useState(""); const [selectedTag, setSelectedTag] = useState(null); const [selectedSchool, setSelectedSchool] = useState(""); + const [fileName, setFileName] = useState(null); + const [selectedFile, setSelectedFile] = useState(null); + const [fileType, setFileType] = useState(null); // Tags and Group buttons might be best moved to their respective components but this is how I will leave it for now. const { boardSlug } = useParams(); @@ -81,6 +86,20 @@ const CreateThread = ({ onNewThread }: CreateThreadProps) => { setSelectedTag(tag); }; + const handleImageChange = (e: ChangeEvent) => { + const file = e.target.files ? e.target.files[0] : null; + if (file) { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onloadend = () => { + const base64data = reader.result as string; + setSelectedFile(base64data); // Store the base64-encoded image + setFileType(file.type); // Store the MIME type of the file + }; + setFileName(file.name); // Store the name of the selected file + } + }; + const handleSubmit = async () => { // Require a Board // If current board isn't chosen, then output this @@ -125,18 +144,26 @@ const CreateThread = ({ onNewThread }: CreateThreadProps) => { } try { + const payload: threadPayload = { + body: textContent, + title: "default", + tag_id: "default", + group_id: selectedSchool, + univ_id: "1", + board_id: selectedBoard, + }; + + if (selectedFile) { + payload.image = selectedFile; + payload.contentType = fileType || ""; + payload.fileName = fileName || "image"; + } const response = await API.post( "wasedatime-dev", `/forum/${selectedBoard}`, { body: { - data: { - body: textContent, - title: "default", - tag_id: "default", - group_id: selectedSchool, - univ_id: "1", - }, + data: payload, }, headers: { "Content-Type": "application/json", @@ -158,6 +185,10 @@ const CreateThread = ({ onNewThread }: CreateThreadProps) => { setTitleContent(""); setTextContent(""); setSelectedBoard(""); + setSelectedSchool(""); + setSelectedFile(null); + setFileType(null); + setFileName(null); setSelectedTag(null); } catch (error) { console.log(error); @@ -308,6 +339,22 @@ const CreateThread = ({ onNewThread }: CreateThreadProps) => { ) : null}

{selectedSchool ? selectedSchool : "School"}

+
+ + +