source: reactapp/src/Pages/Subject.js@ c68150f

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

left: moderation, oAuth, messaging

  • Property mode set to 100644
File size: 8.5 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.17: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 } else {
70 navigate("/login");
71 }
72 };
73
74 const handleModalCloseClick = () => {
75 setTopicModalDisplay("none");
76 };
77
78 const handleTopicSubmit = async (e) => {
79 e.preventDefault();
80
81 if (!topicTitle.length < 1 && !topicContent.length < 1) {
82 const response = await axios(
83 `http://192.168.0.17:8080/secure/subject/${params.subjectId}/addThread`,
84 {
85 method: "post",
86 data: {
87 title: topicTitle,
88 content: topicContent,
89 },
90 withCredentials: true,
91 }
92 );
93 setErrorMessage("");
94 window.location.reload(false);
95 } else {
96 setErrorMessage("Полињата за наслов и содржина не смеат да бидат празни");
97 }
98 };
99
100 const handleContentChange = (e) => {
101 setTopicContent(e.target.value);
102 };
103
104 const handleTitleChange = (e) => {
105 setTopicTitle(e.target.value);
106 };
107
108 return loaded ? (
109 <>
110 <CurrentPageNav>
111 &#187;{" "}
112 <a
113 href={
114 "/university/" +
115 subject.studyProgramme.faculty.university.universityId
116 }
117 >
118 {subject.studyProgramme.faculty.university.universityName}
119 </a>{" "}
120 &#187;{" "}
121 <a href={"/faculty/" + subject.studyProgramme.faculty.facultyId}>
122 {subject.studyProgramme.faculty.facultyName}
123 </a>{" "}
124 &#187; <a href="#">{subject.subjectName}</a>
125 </CurrentPageNav>
126 <ProfessorCard>
127 <ProfessorCardName>{subject.subjectName}</ProfessorCardName>
128 <ProfessorCardSeparator />
129 <div style={{ marginTop: "10px" }}>
130 <ProfessorCardDetails fontSize="20px">
131 {subject.studyProgramme.studyProgrammeName} (
132 {subject.studyProgramme.cycle}
133 {"."}
134 {"циклус"})
135 </ProfessorCardDetails>
136 <ProfessorCardDetails fontSize="20px">
137 {subject.studyProgramme.faculty.facultyName}
138 </ProfessorCardDetails>
139 <ProfessorCardDetails fontSize="15px">
140 {subject.studyProgramme.faculty.university.universityName}
141 </ProfessorCardDetails>
142 </div>
143 </ProfessorCard>
144 <div style={{ height: "20px", marginBottom: "50px" }}>
145 <h3
146 style={{
147 float: "left",
148 }}
149 >
150 {subject.threads.map((thread) => {
151 if (thread.parent === null) {
152 totalTopics++;
153 topics.push(thread);
154 }
155 })}
156 {totalTopics} {totalTopics !== 1 ? "теми" : "тема"}
157 </h3>
158 {auth && (
159 <AddOpinionButton onClick={handleAddTopicButtonClick}>
160 Отвори тема
161 </AddOpinionButton>
162 )}
163 </div>
164 <Modal display={topicModalDisplay}>
165 <ModalContent>
166 <ModalHeader>
167 <ModalClose onClick={handleModalCloseClick}>&times;</ModalClose>
168 <h3 style={{ marginTop: "5px" }}>
169 Тема во врска со {subject.subjectName}
170 </h3>
171 </ModalHeader>
172 <form onSubmit={handleTopicSubmit}>
173 <ModalBody>
174 <label htmlFor="title">
175 <b>Наслов</b>:
176 <ModalInput
177 id="title"
178 value={topicTitle}
179 onChange={handleTitleChange}
180 />
181 </label>
182 <label htmlFor="content">
183 <b>Содржина</b>:
184 <ModalTextarea
185 id="content"
186 rows="8"
187 cols="100"
188 value={topicContent}
189 onChange={handleContentChange}
190 />
191 </label>
192 </ModalBody>
193 <p style={{ color: "red", marginLeft: "15px", marginTop: "10px" }}>
194 {errorMessage}
195 </p>
196 <ModalFooter type="submit">ОБЈАВИ</ModalFooter>
197 </form>
198 </ModalContent>
199 </Modal>
200 <div key={subject.subjectId}>
201 {topics.map((topic) => {
202 var numReplies = topic.children.length;
203 return (
204 <EntityUl key={topic.postId}>
205 <EntityLi bgcolor="cornsilk">
206 <a href={"/topic/" + topic.postId}>{topic.title}</a>
207 <EntityParam right="30px">
208 <span style={{ fontWeight: "normal" }}>
209 отворил:{" "}
210 <a href={"/user/" + topic.author.id}>
211 {topic.author.username}
212 </a>
213 </span>
214 <span style={{ fontStyle: "normal" }}>,</span>{" "}
215 {numReplies !== 1 ? (
216 numReplies !== 0 ? (
217 <span
218 style={{
219 fontWeight: "normal",
220 opacity: numReplies === 0 ? "0.5" : "1",
221 }}
222 >
223 <span
224 style={{
225 fontWeight: "bold",
226 opacity: numReplies === 0 ? "0.5" : "1",
227 }}
228 >
229 {numReplies}
230 </span>{" "}
231 реплики
232 </span>
233 ) : (
234 <span
235 style={{
236 fontWeight: "normal",
237 opacity: numReplies === 0 ? "0.5" : "1",
238 }}
239 >
240 <span
241 style={{
242 fontWeight: "bold",
243 opacity: numReplies === 0 ? "0.5" : "1",
244 }}
245 >
246 {numReplies}
247 </span>{" "}
248 реплики
249 </span>
250 )
251 ) : (
252 <span style={{ fontWeight: "normal" }}>
253 <span style={{ fontWeight: "bold" }}>{numReplies}</span>{" "}
254 реплика
255 </span>
256 )}
257 </EntityParam>
258 </EntityLi>
259 </EntityUl>
260 );
261 })}
262 </div>
263 </>
264 ) : !fetchError ? (
265 <div>
266 <p style={{ marginTop: "140px" }}>се вчитува...</p>
267 <Outlet />
268 </div>
269 ) : (
270 <div style={{ marginTop: "140px" }}>
271 <h1 style={{ textAlign: "center" }}>Страницата не е пронајдена.</h1>
272 </div>
273 );
274};
275
276export default Subject;
Note: See TracBrowser for help on using the repository browser.