source: reactapp/src/Pages/Subject.js@ 3b6962d

main
Last change on this file since 3b6962d was 3b6962d, checked in by unknown <mlviktor23@…>, 20 months ago

moderation/reporting api in spring boot

  • Property mode set to 100644
File size: 8.7 KB
Line 
1import React, { useState, useEffect, useContext } from "react";
2import { useNavigate, useParams } from "react-router-dom";
3import JSOG from "jsog";
4import { Outlet } from "react-router-dom";
5import { CurrentPageNav } from "../Components/Styled/Main.style";
6import {
7 ProfessorCard,
8 ProfessorCardDetails,
9 ProfessorCardName,
10 ProfessorCardSeparator,
11} from "../Components/Styled/ProfessorCard.style";
12import AuthApi from "../api/AuthApi";
13import { AddOpinionButton } from "../Components/Styled/Modal.style";
14import {
15 EntityLi,
16 EntityUl,
17 EntityParam,
18} from "../Components/Styled/EntityList.style";
19import {
20 Modal,
21 ModalBody,
22 ModalClose,
23 ModalContent,
24 ModalFooter,
25 ModalHeader,
26 ModalInput,
27 ModalTextarea,
28} from "../Components/Styled/Modal.style";
29import axios from "../api/axios";
30
31const Subject = () => {
32 let params = useParams();
33 let navigate = useNavigate();
34
35 const { auth, setAuth } = useContext(AuthApi);
36 const [subject, setSubject] = useState(null);
37 const [loaded, setLoaded] = useState(false);
38 const [fetchError, setFetchError] = useState(false);
39 var totalTopics = 0;
40 var topics = [];
41
42 const [topicModalDisplay, setTopicModalDisplay] = useState("none");
43 const [topicTitle, setTopicTitle] = useState("");
44 const [topicContent, setTopicContent] = useState("");
45 const [errorMessage, setErrorMessage] = useState("");
46
47 useEffect(() => {
48 const url = `http://192.168.0.19:8080/public/subject/${params.subjectId}`;
49
50 const fetchData = async () => {
51 try {
52 const response = await fetch(url);
53 let cyclicGraph = await response.json();
54 let jsogStructure = JSOG.encode(cyclicGraph);
55 cyclicGraph = JSOG.decode(jsogStructure);
56 setSubject(cyclicGraph);
57 setLoaded(true);
58 } catch (error) {
59 setFetchError(true);
60 }
61 };
62
63 fetchData();
64 }, [params.subjectId]);
65
66 const handleAddTopicButtonClick = () => {
67 if (auth) {
68 setTopicModalDisplay("block");
69 document.body.style.overflowY = "hidden";
70 } else {
71 navigate("/login");
72 }
73 };
74
75 const handleModalCloseClick = () => {
76 setTopicModalDisplay("none");
77 document.body.style.overflowY = "auto";
78 };
79
80 const handleTopicSubmit = async (e) => {
81 e.preventDefault();
82
83 if (!topicTitle.length < 1 && !topicContent.length < 1) {
84 const response = await axios(
85 `http://192.168.0.19:8080/secure/subject/${params.subjectId}/addThread`,
86 {
87 method: "post",
88 data: {
89 title: topicTitle,
90 content: topicContent,
91 },
92 withCredentials: true,
93 }
94 );
95 setErrorMessage("");
96 window.location.reload(false);
97 } else {
98 setErrorMessage("Полињата за наслов и содржина не смеат да бидат празни");
99 }
100 };
101
102 const handleContentChange = (e) => {
103 setTopicContent(e.target.value);
104 };
105
106 const handleTitleChange = (e) => {
107 setTopicTitle(e.target.value);
108 };
109
110 return loaded ? (
111 <>
112 <CurrentPageNav>
113 &#187;{" "}
114 <a
115 href={
116 "/university/" +
117 subject.studyProgramme.faculty.university.universityId
118 }
119 >
120 {subject.studyProgramme.faculty.university.universityName}
121 </a>{" "}
122 &#187;{" "}
123 <a href={"/faculty/" + subject.studyProgramme.faculty.facultyId}>
124 {subject.studyProgramme.faculty.facultyName}
125 </a>{" "}
126 &#187; <a href="#">{subject.subjectName}</a>
127 </CurrentPageNav>
128 <ProfessorCard>
129 <ProfessorCardName>{subject.subjectName}</ProfessorCardName>
130 <ProfessorCardSeparator />
131 <div style={{ marginTop: "10px" }}>
132 <ProfessorCardDetails fontSize="20px">
133 {subject.studyProgramme.studyProgrammeName} (
134 {subject.studyProgramme.cycle}
135 {"."}
136 {"циклус"})
137 </ProfessorCardDetails>
138 <ProfessorCardDetails fontSize="20px">
139 {subject.studyProgramme.faculty.facultyName}
140 </ProfessorCardDetails>
141 <ProfessorCardDetails fontSize="15px">
142 {subject.studyProgramme.faculty.university.universityName}
143 </ProfessorCardDetails>
144 </div>
145 </ProfessorCard>
146 <div style={{ height: "20px", marginBottom: "50px" }}>
147 <h3
148 style={{
149 float: "left",
150 }}
151 >
152 {subject.threads.map((thread) => {
153 if (thread.parent === null) {
154 totalTopics++;
155 topics.push(thread);
156 }
157 })}
158 {totalTopics} {totalTopics !== 1 ? "теми" : "тема"}
159 </h3>
160 {auth && (
161 <AddOpinionButton onClick={handleAddTopicButtonClick}>
162 Отвори тема
163 </AddOpinionButton>
164 )}
165 </div>
166 <Modal display={topicModalDisplay}>
167 <ModalContent>
168 <ModalHeader>
169 <ModalClose onClick={handleModalCloseClick}>&times;</ModalClose>
170 <h3 style={{ marginTop: "5px" }}>
171 Тема во врска со {subject.subjectName}
172 </h3>
173 </ModalHeader>
174 <form onSubmit={handleTopicSubmit}>
175 <ModalBody>
176 <label htmlFor="title">
177 <b>Наслов</b>:
178 <ModalInput
179 id="title"
180 value={topicTitle}
181 onChange={handleTitleChange}
182 spellCheck={false}
183 />
184 </label>
185 <label htmlFor="content">
186 <b>Содржина</b>:
187 <ModalTextarea
188 id="content"
189 rows="8"
190 cols="100"
191 value={topicContent}
192 onChange={handleContentChange}
193 spellCheck={false}
194 />
195 </label>
196 </ModalBody>
197 <p style={{ color: "red", marginLeft: "15px", marginTop: "10px" }}>
198 {errorMessage}
199 </p>
200 <ModalFooter type="submit">ОБЈАВИ</ModalFooter>
201 </form>
202 </ModalContent>
203 </Modal>
204 <div key={subject.subjectId}>
205 {topics.map((topic) => {
206 var numReplies = topic.children.length;
207 return (
208 <EntityUl key={topic.postId}>
209 <EntityLi bgcolor="cornsilk">
210 <a href={"/topic/" + topic.postId}>{topic.title}</a>
211 <EntityParam right="30px">
212 <span style={{ fontWeight: "normal" }}>
213 отворил:{" "}
214 <a href={"/user/" + topic.author.id}>
215 {topic.author.username}
216 </a>
217 </span>
218 <span style={{ fontStyle: "normal" }}>,</span>{" "}
219 {numReplies !== 1 ? (
220 numReplies !== 0 ? (
221 <span
222 style={{
223 fontWeight: "normal",
224 opacity: numReplies === 0 ? "0.5" : "1",
225 }}
226 >
227 <span
228 style={{
229 fontWeight: "bold",
230 opacity: numReplies === 0 ? "0.5" : "1",
231 }}
232 >
233 {numReplies}
234 </span>{" "}
235 реплики
236 </span>
237 ) : (
238 <span
239 style={{
240 fontWeight: "normal",
241 opacity: numReplies === 0 ? "0.5" : "1",
242 }}
243 >
244 <span
245 style={{
246 fontWeight: "bold",
247 opacity: numReplies === 0 ? "0.5" : "1",
248 }}
249 >
250 {numReplies}
251 </span>{" "}
252 реплики
253 </span>
254 )
255 ) : (
256 <span style={{ fontWeight: "normal" }}>
257 <span style={{ fontWeight: "bold" }}>{numReplies}</span>{" "}
258 реплика
259 </span>
260 )}
261 </EntityParam>
262 </EntityLi>
263 </EntityUl>
264 );
265 })}
266 </div>
267 </>
268 ) : !fetchError ? (
269 <div>
270 <p style={{ marginTop: "140px" }}>се вчитува...</p>
271 <Outlet />
272 </div>
273 ) : (
274 <div style={{ marginTop: "140px" }}>
275 <h1 style={{ textAlign: "center" }}>Страницата не е пронајдена.</h1>
276 </div>
277 );
278};
279
280export default Subject;
Note: See TracBrowser for help on using the repository browser.