| 1 | import React, { useState, useEffect } from "react";
|
|---|
| 2 | import axios from "axios";
|
|---|
| 3 |
|
|---|
| 4 | import NavbarKlasen from "../../../components/navbarKlasen/NavbarKlasen.jsx";
|
|---|
| 5 | import { Link, useParams } from "react-router-dom";
|
|---|
| 6 |
|
|---|
| 7 | const PredmetenNastavnikSoopstenijaView = () => {
|
|---|
| 8 | const [klasovi, setKlasovi] = useState([]);
|
|---|
| 9 | const [roditeli, setRoditeli] = useState([]);
|
|---|
| 10 | const [klasen, setKlasen] = useState(null);
|
|---|
| 11 | const [students, setStudents] = useState([]);
|
|---|
| 12 | const [soopstenija, setSoopstenija] = useState([]);
|
|---|
| 13 | const [error, setError] = useState("");
|
|---|
| 14 | const [loading, setLoading] = useState(false);
|
|---|
| 15 | const [classInfo, setClassInfo] = useState(null);
|
|---|
| 16 | const { klasId } = useParams();
|
|---|
| 17 | const [predmetenNastavnik, setPredmetenNastavnik] = useState(null);
|
|---|
| 18 |
|
|---|
| 19 | useEffect(() => {
|
|---|
| 20 | axios
|
|---|
| 21 | .get("http://localhost:8080/api/auth/me", { withCredentials: true })
|
|---|
| 22 | .then((res) => setPredmetenNastavnik(res.data))
|
|---|
| 23 | .catch((err) => console.log(err));
|
|---|
| 24 | }, []);
|
|---|
| 25 |
|
|---|
| 26 | useEffect(() => {
|
|---|
| 27 | if (!predmetenNastavnik?.id) return;
|
|---|
| 28 |
|
|---|
| 29 | const fetchData = async () => {
|
|---|
| 30 | try {
|
|---|
| 31 | setLoading(true);
|
|---|
| 32 | const [resKlasovi] = await Promise.all([
|
|---|
| 33 | axios.get(
|
|---|
| 34 | `http://localhost:8080/api/users/nastavnici/predmetniNastavnici/${predmetenNastavnik.id}/classes`,
|
|---|
| 35 | { withCredentials: true }
|
|---|
| 36 | ),
|
|---|
| 37 | ]);
|
|---|
| 38 | setKlasovi(resKlasovi.data);
|
|---|
| 39 | const resStudents = await axios.get(
|
|---|
| 40 | `http://localhost:8080/api/klas/${klasId}/students`,
|
|---|
| 41 | {
|
|---|
| 42 | withCredentials: true,
|
|---|
| 43 | }
|
|---|
| 44 | );
|
|---|
| 45 | const studentsData = resStudents.data;
|
|---|
| 46 | setStudents(studentsData);
|
|---|
| 47 |
|
|---|
| 48 | const parentIds = [
|
|---|
| 49 | ...new Set(studentsData.map((s) => s.staratelId).filter((id) => id)),
|
|---|
| 50 | ];
|
|---|
| 51 |
|
|---|
| 52 | const parentRequests = parentIds.map((id) =>
|
|---|
| 53 | axios.get(`http://localhost:8080/api/users/roditeli/${id}`, {
|
|---|
| 54 | withCredentials: true,
|
|---|
| 55 | })
|
|---|
| 56 | );
|
|---|
| 57 |
|
|---|
| 58 | const parentResponses = await Promise.all(parentRequests);
|
|---|
| 59 | const parentsData = parentResponses.map((res) => res.data);
|
|---|
| 60 |
|
|---|
| 61 | setRoditeli(parentsData);
|
|---|
| 62 |
|
|---|
| 63 | const [resClass, resKlasen, resSoopstenija] = await Promise.all([
|
|---|
| 64 | axios.get(`http://localhost:8080/api/klas/${klasId}`, {
|
|---|
| 65 | withCredentials: true,
|
|---|
| 66 | }),
|
|---|
| 67 | axios.get(
|
|---|
| 68 | `http://localhost:8080/api/klas/${klasId}/klasenRakovoditel`,
|
|---|
| 69 | {
|
|---|
| 70 | withCredentials: true,
|
|---|
| 71 | }
|
|---|
| 72 | ),
|
|---|
| 73 |
|
|---|
| 74 | axios.get(`http://localhost:8080/api/klas/${klasId}/soopstenija`, {
|
|---|
| 75 | withCredentials: true,
|
|---|
| 76 | }),
|
|---|
| 77 | ]);
|
|---|
| 78 |
|
|---|
| 79 | setClassInfo(resClass.data);
|
|---|
| 80 | setKlasen(resKlasen.data);
|
|---|
| 81 | setStudents(resStudents.data);
|
|---|
| 82 | setSoopstenija(resSoopstenija.data);
|
|---|
| 83 | } catch (err) {
|
|---|
| 84 | console.log(err);
|
|---|
| 85 | } finally {
|
|---|
| 86 | setLoading(false);
|
|---|
| 87 | }
|
|---|
| 88 | };
|
|---|
| 89 |
|
|---|
| 90 | fetchData();
|
|---|
| 91 | }, [predmetenNastavnik?.id, klasId]);
|
|---|
| 92 | const formatDate = (dateString) => {
|
|---|
| 93 | if (!dateString) return "";
|
|---|
| 94 | const date = new Date(dateString);
|
|---|
| 95 | return date.toLocaleDateString("mk-MK", {
|
|---|
| 96 | day: "2-digit",
|
|---|
| 97 | month: "2-digit",
|
|---|
| 98 | year: "numeric",
|
|---|
| 99 | });
|
|---|
| 100 | };
|
|---|
| 101 | return (
|
|---|
| 102 | <>
|
|---|
| 103 | <div>
|
|---|
| 104 | <NavbarKlasen />
|
|---|
| 105 | <div className=" mh-100 ">
|
|---|
| 106 | <div className="container-fluid">
|
|---|
| 107 | <div className="row ">
|
|---|
| 108 | <div className="d-flex flex-row m-3 align-items-left gap-3">
|
|---|
| 109 | <h1>
|
|---|
| 110 | Клас: {classInfo?.oddelenie} {classInfo?.paralelka}
|
|---|
| 111 | </h1>
|
|---|
| 112 | <div className="dropdown mt-2">
|
|---|
| 113 | <button
|
|---|
| 114 | className="btn btn-secondary dropdown-toggle"
|
|---|
| 115 | type="button"
|
|---|
| 116 | id="dropdownMenuButton"
|
|---|
| 117 | data-bs-toggle="dropdown"
|
|---|
| 118 | aria-haspopup="true"
|
|---|
| 119 | aria-expanded="false"
|
|---|
| 120 | >
|
|---|
| 121 | Мои класови
|
|---|
| 122 | </button>
|
|---|
| 123 | <div
|
|---|
| 124 | className="dropdown-menu"
|
|---|
| 125 | aria-labelledby="dropdownMenuButton"
|
|---|
| 126 | >
|
|---|
| 127 | {loading ? (
|
|---|
| 128 | <div className="dropdown-item">Вчитување...</div>
|
|---|
| 129 | ) : klasovi.length > 0 ? (
|
|---|
| 130 | klasovi.map((k) => (
|
|---|
| 131 | <Link
|
|---|
| 132 | key={k.id}
|
|---|
| 133 | className="dropdown-item"
|
|---|
| 134 | to={`/predmetenNastavnikDashboard/klas/${k.id}/soopstenija`}
|
|---|
| 135 | >
|
|---|
| 136 | {k.oddelenie}-{k.paralelka}
|
|---|
| 137 | </Link>
|
|---|
| 138 | ))
|
|---|
| 139 | ) : (
|
|---|
| 140 | <div className="dropdown-item">Нема класови</div>
|
|---|
| 141 | )}
|
|---|
| 142 | </div>
|
|---|
| 143 | </div>
|
|---|
| 144 | </div>
|
|---|
| 145 | <div className="navbar navbar-expand-lg bg-secondary justify-content-start ">
|
|---|
| 146 | <ul className="navbar-nav">
|
|---|
| 147 | <li className="nav-item active">
|
|---|
| 148 | <Link className="nav-link text-white fs-4">
|
|---|
| 149 | {" "}
|
|---|
| 150 | Соопштенија за класот{" "}
|
|---|
| 151 | </Link>
|
|---|
| 152 | </li>
|
|---|
| 153 |
|
|---|
| 154 | <li className="nav-item">
|
|---|
| 155 | <Link
|
|---|
| 156 | className="nav-link text-white fs-4"
|
|---|
| 157 | to={`/predmetenNastavnikDashboard/klas/${klasId}/weeklyPlan`}
|
|---|
| 158 | >
|
|---|
| 159 | {" "}
|
|---|
| 160 | Неделни активности
|
|---|
| 161 | </Link>
|
|---|
| 162 | </li>
|
|---|
| 163 | <li className="nav-item">
|
|---|
| 164 | <Link
|
|---|
| 165 | className="nav-link text-white fs-4"
|
|---|
| 166 | to={`/predmetenNastavnikDashboard/klas/${klasId}/schedule`}
|
|---|
| 167 | >
|
|---|
| 168 | {" "}
|
|---|
| 169 | Распоред
|
|---|
| 170 | </Link>
|
|---|
| 171 | </li>
|
|---|
| 172 | <li className="nav-item">
|
|---|
| 173 | <Link
|
|---|
| 174 | className="nav-link text-white fs-4"
|
|---|
| 175 | to={`/predmetenNastavnikDashboard/klas/${klasId}/students`}
|
|---|
| 176 | >
|
|---|
| 177 | {" "}
|
|---|
| 178 | Студенти
|
|---|
| 179 | </Link>
|
|---|
| 180 | </li>
|
|---|
| 181 | <li className="nav-item">
|
|---|
| 182 | <Link
|
|---|
| 183 | className="nav-link text-white fs-4"
|
|---|
| 184 | to={`/predmetenNastavnikDashboard/klas/${klasId}/subjects`}
|
|---|
| 185 | >
|
|---|
| 186 | {" "}
|
|---|
| 187 | Види слушани предмети
|
|---|
| 188 | </Link>
|
|---|
| 189 | </li>
|
|---|
| 190 | </ul>
|
|---|
| 191 | </div>
|
|---|
| 192 | </div>
|
|---|
| 193 | </div>
|
|---|
| 194 |
|
|---|
| 195 | <div className="row container-fluid w-100 m-3">
|
|---|
| 196 | <div className="col-8">
|
|---|
| 197 | <div className="d-flex flex-column gap-3">
|
|---|
| 198 | {console.log(soopstenija)}
|
|---|
| 199 | {soopstenija.length > 0 ? (
|
|---|
| 200 | soopstenija.map((s) => (
|
|---|
| 201 | <div key={s.id} className="card shadow-sm">
|
|---|
| 202 | <div className="card-body">
|
|---|
| 203 | <div className="d-flex align-items-center mb-3">
|
|---|
| 204 | <div
|
|---|
| 205 | className="rounded-circle bg-secondary me-3"
|
|---|
| 206 | style={{
|
|---|
| 207 | width: "50px",
|
|---|
| 208 | height: "50px",
|
|---|
| 209 | flexShrink: 0,
|
|---|
| 210 | }}
|
|---|
| 211 | />
|
|---|
| 212 | <div>
|
|---|
| 213 | <span className="fw-bold d-block">
|
|---|
| 214 | {klasen?.ime} {klasen?.prezime}
|
|---|
| 215 | </span>
|
|---|
| 216 | <small className="text-muted">
|
|---|
| 217 | {formatDate(s.kreiranoNa)}
|
|---|
| 218 | </small>
|
|---|
| 219 | </div>
|
|---|
| 220 | </div>
|
|---|
| 221 | <h5 className="card-title">{s.naslov}</h5>
|
|---|
| 222 | <p className="card-text">{s.sodrzina}</p>
|
|---|
| 223 | </div>
|
|---|
| 224 | </div>
|
|---|
| 225 | ))
|
|---|
| 226 | ) : (
|
|---|
| 227 | <p className="text-muted text-center">
|
|---|
| 228 | Нема активни соопштенија.
|
|---|
| 229 | </p>
|
|---|
| 230 | )}
|
|---|
| 231 | </div>
|
|---|
| 232 | </div>
|
|---|
| 233 | <div className="col-4">
|
|---|
| 234 | <div>
|
|---|
| 235 | <h2 className="mt-0 fw-semibold">Информации за класот</h2>
|
|---|
| 236 |
|
|---|
| 237 | <div>
|
|---|
| 238 | <h4>Класен раководител</h4>
|
|---|
| 239 | <p>
|
|---|
| 240 | {klasen
|
|---|
| 241 | ? `${klasen.ime} ${klasen.prezime}`
|
|---|
| 242 | : "Не е назначен"}
|
|---|
| 243 | </p>
|
|---|
| 244 | </div>
|
|---|
| 245 |
|
|---|
| 246 | <div>
|
|---|
| 247 | <h4>Ученици {students.length}</h4>
|
|---|
| 248 | <ul>
|
|---|
| 249 | {students.map((student) => (
|
|---|
| 250 | <li key={student.id}>
|
|---|
| 251 | {student.ime} {student.prezime}
|
|---|
| 252 | </li>
|
|---|
| 253 | ))}
|
|---|
| 254 | {students.length === 0 && <li>Нема запишани ученици</li>}
|
|---|
| 255 | </ul>
|
|---|
| 256 | </div>
|
|---|
| 257 | <div>
|
|---|
| 258 | <h4>Родители {roditeli.length}</h4>
|
|---|
| 259 | <ul>
|
|---|
| 260 | {roditeli.map((parent) => (
|
|---|
| 261 | <li key={parent.id}>
|
|---|
| 262 | {parent.ime} {parent.prezime}
|
|---|
| 263 | </li>
|
|---|
| 264 | ))}
|
|---|
| 265 | {roditeli.length === 0 && (
|
|---|
| 266 | <li>Нема податоци за родители</li>
|
|---|
| 267 | )}
|
|---|
| 268 | </ul>
|
|---|
| 269 | </div>
|
|---|
| 270 | </div>
|
|---|
| 271 | </div>
|
|---|
| 272 | </div>
|
|---|
| 273 | </div>
|
|---|
| 274 | </div>
|
|---|
| 275 | </>
|
|---|
| 276 | );
|
|---|
| 277 | };
|
|---|
| 278 |
|
|---|
| 279 | export default PredmetenNastavnikSoopstenijaView;
|
|---|