| 1 | import React, { useState, useEffect } from "react";
|
|---|
| 2 | import axios from "axios";
|
|---|
| 3 | import styles from "./AdminPanelNedelniAktivnosti.module.css";
|
|---|
| 4 | import Navbar from "../../../components/nav/Navbar.jsx";
|
|---|
| 5 | import { Link } from "react-router-dom";
|
|---|
| 6 |
|
|---|
| 7 | const AdminPanelNedelniAktivnosti = () => {
|
|---|
| 8 | const [nedelniPlanovi, setNedelniPlanovi] = useState([]);
|
|---|
| 9 | const [siteAktivnosti, setSiteAktivnosti] = useState([]);
|
|---|
| 10 | const [allClasses, setAllClasses] = useState([]);
|
|---|
| 11 | const [loading, setLoading] = useState(true);
|
|---|
| 12 | const [predmeti, setPredmeti] = useState([]);
|
|---|
| 13 |
|
|---|
| 14 | const [showAktModal, setShowAktModal] = useState(false);
|
|---|
| 15 | const [showPlanModal, setShowPlanModal] = useState(false);
|
|---|
| 16 | const [showAddToPlanModal, setShowAddToPlanModal] = useState(false);
|
|---|
| 17 |
|
|---|
| 18 | const [selectedPlanId, setSelectedPlanId] = useState(null);
|
|---|
| 19 | const [selectedAktivnostId, setSelectedAktivnostId] = useState("");
|
|---|
| 20 |
|
|---|
| 21 | const [planFormData, setPlanFormData] = useState({
|
|---|
| 22 | datumOd: "",
|
|---|
| 23 | datumDo: "",
|
|---|
| 24 | sledenOdKlasId: null,
|
|---|
| 25 | });
|
|---|
| 26 | const [aktFormData, setAktFormData] = useState({
|
|---|
| 27 | naslov: "",
|
|---|
| 28 | opis: "",
|
|---|
| 29 | denVoNedelata: "",
|
|---|
| 30 | predmet_id: "",
|
|---|
| 31 | });
|
|---|
| 32 |
|
|---|
| 33 | const fetchData = async () => {
|
|---|
| 34 | try {
|
|---|
| 35 | setLoading(true);
|
|---|
| 36 | const [resPlanovi, resSiteAktivnosti, resClasses] = await Promise.all([
|
|---|
| 37 | axios.get("http://localhost:8080/api/nedelenPlan", {
|
|---|
| 38 | withCredentials: true,
|
|---|
| 39 | }),
|
|---|
| 40 | axios.get("http://localhost:8080/api/nedelnaAktivnost", {
|
|---|
| 41 | withCredentials: true,
|
|---|
| 42 | }),
|
|---|
| 43 | axios.get("http://localhost:8080/api/klas", { withCredentials: true }),
|
|---|
| 44 | ]);
|
|---|
| 45 |
|
|---|
| 46 | const enrichedPlanovi = await Promise.all(
|
|---|
| 47 | resPlanovi.data.map(async (plan) => {
|
|---|
| 48 | const [resKlas, resAktivnosti, resPredmeti] = await Promise.all([
|
|---|
| 49 | axios.get(`http://localhost:8080/api/klas/${plan.sledenOdKlasId}`, {
|
|---|
| 50 | withCredentials: true,
|
|---|
| 51 | }),
|
|---|
| 52 | axios.get(
|
|---|
| 53 | `http://localhost:8080/api/nedelenPlan/${plan.id}/aktivnosti`,
|
|---|
| 54 | { withCredentials: true }
|
|---|
| 55 | ),
|
|---|
| 56 | axios.get(`http://localhost:8080/api/predmeti`, {
|
|---|
| 57 | withCredentials: true,
|
|---|
| 58 | }),
|
|---|
| 59 | ]);
|
|---|
| 60 | setPredmeti(resPredmeti.data);
|
|---|
| 61 | return {
|
|---|
| 62 | ...plan,
|
|---|
| 63 | klasIme: `${resKlas.data.oddelenie}-${resKlas.data.paralelka}`,
|
|---|
| 64 | aktivnosti: resAktivnosti.data,
|
|---|
| 65 | };
|
|---|
| 66 | })
|
|---|
| 67 | );
|
|---|
| 68 |
|
|---|
| 69 | setNedelniPlanovi(enrichedPlanovi);
|
|---|
| 70 | setSiteAktivnosti(resSiteAktivnosti.data);
|
|---|
| 71 | setAllClasses(resClasses.data);
|
|---|
| 72 | } catch (err) {
|
|---|
| 73 | console.error("Грешка:", err);
|
|---|
| 74 | } finally {
|
|---|
| 75 | setLoading(false);
|
|---|
| 76 | }
|
|---|
| 77 | };
|
|---|
| 78 |
|
|---|
| 79 | useEffect(() => {
|
|---|
| 80 | fetchData();
|
|---|
| 81 | }, []);
|
|---|
| 82 |
|
|---|
| 83 | const handleSubmitPlan = async (e) => {
|
|---|
| 84 | e.preventDefault();
|
|---|
| 85 | try {
|
|---|
| 86 | await axios.post("http://localhost:8080/api/nedelenPlan", planFormData, {
|
|---|
| 87 | withCredentials: true,
|
|---|
| 88 | });
|
|---|
| 89 | setShowPlanModal(false);
|
|---|
| 90 | setPlanFormData({ datumOd: "", datumDo: "", sledenOdKlasId: "" });
|
|---|
| 91 | fetchData();
|
|---|
| 92 | } catch (err) {
|
|---|
| 93 | alert("Грешка при креирање план.");
|
|---|
| 94 | }
|
|---|
| 95 | };
|
|---|
| 96 |
|
|---|
| 97 | const handleSubmitAktivnost = async (e) => {
|
|---|
| 98 | e.preventDefault();
|
|---|
| 99 | try {
|
|---|
| 100 | await axios.post(
|
|---|
| 101 | "http://localhost:8080/api/nedelnaAktivnost",
|
|---|
| 102 | aktFormData,
|
|---|
| 103 | { withCredentials: true }
|
|---|
| 104 | );
|
|---|
| 105 | setShowAktModal(false);
|
|---|
| 106 | setAktFormData({ naslov: "", opis: "", denVoNedelata: "" });
|
|---|
| 107 | fetchData();
|
|---|
| 108 | } catch (err) {
|
|---|
| 109 | alert("Грешка при креирање активност.");
|
|---|
| 110 | }
|
|---|
| 111 | };
|
|---|
| 112 |
|
|---|
| 113 | if (loading)
|
|---|
| 114 | return (
|
|---|
| 115 | <div className={styles.adminWrapper}>
|
|---|
| 116 | <Navbar />
|
|---|
| 117 | <h2 style={{ textAlign: "center", marginTop: "50px" }}>Вчитување...</h2>
|
|---|
| 118 | </div>
|
|---|
| 119 | );
|
|---|
| 120 |
|
|---|
| 121 | return (
|
|---|
| 122 | <div className={styles.adminWrapper}>
|
|---|
| 123 | {console.log("predmeti vo telo")}
|
|---|
| 124 | {console.log(predmeti)}
|
|---|
| 125 | <Navbar />
|
|---|
| 126 |
|
|---|
| 127 | <div className={styles.mainContainer}>
|
|---|
| 128 | <div className={styles.toolbar}>
|
|---|
| 129 | <button
|
|---|
| 130 | className={styles.mainBtn}
|
|---|
| 131 | onClick={() => setShowAktModal(true)}
|
|---|
| 132 | >
|
|---|
| 133 | Креирај неделна активност
|
|---|
| 134 | </button>
|
|---|
| 135 | <button
|
|---|
| 136 | className={styles.mainBtn}
|
|---|
| 137 | onClick={() => setShowPlanModal(true)}
|
|---|
| 138 | >
|
|---|
| 139 | Креирај неделен план
|
|---|
| 140 | </button>
|
|---|
| 141 | </div>
|
|---|
| 142 | <div
|
|---|
| 143 | className="d-flex flex-row justify-content-center align-items-center p-2"
|
|---|
| 144 | style={{ backgroundColor: "#147176" }}
|
|---|
| 145 | >
|
|---|
| 146 | <Link
|
|---|
| 147 | to="/adminDashboard/users"
|
|---|
| 148 | className="mx-3 text-white text-decoration-none fs-6 opacity-100-hover"
|
|---|
| 149 | >
|
|---|
| 150 | Корисници
|
|---|
| 151 | </Link>
|
|---|
| 152 |
|
|---|
| 153 | <Link
|
|---|
| 154 | to="/adminDashboard/classes"
|
|---|
| 155 | className="mx-3 text-white text-decoration-none fs-6"
|
|---|
| 156 | >
|
|---|
| 157 | Класови
|
|---|
| 158 | </Link>
|
|---|
| 159 |
|
|---|
| 160 | <Link
|
|---|
| 161 | to="/adminDashboard/subjects"
|
|---|
| 162 | className="mx-3 text-white text-decoration-none fs-6"
|
|---|
| 163 | >
|
|---|
| 164 | Предмети
|
|---|
| 165 | </Link>
|
|---|
| 166 |
|
|---|
| 167 | <Link
|
|---|
| 168 | to="/adminDashboard/schedules"
|
|---|
| 169 | className="mx-3 text-white text-decoration-none fs-6"
|
|---|
| 170 | >
|
|---|
| 171 | Распореди
|
|---|
| 172 | </Link>
|
|---|
| 173 |
|
|---|
| 174 | <Link
|
|---|
| 175 | to="/adminDashboard/weeklyPlans"
|
|---|
| 176 | className="mx-3 text-white text-decoration-none fs-6"
|
|---|
| 177 | >
|
|---|
| 178 | Неделни планови
|
|---|
| 179 | </Link>
|
|---|
| 180 | <Link
|
|---|
| 181 | to="/adminDashboard/paymentAnnoucements"
|
|---|
| 182 | className="mx-3 text-white text-decoration-none fs-6"
|
|---|
| 183 | >
|
|---|
| 184 | Соопштенија за плаќање
|
|---|
| 185 | </Link>
|
|---|
| 186 | </div>
|
|---|
| 187 | <div className={styles.contentSplit}>
|
|---|
| 188 | <div className={styles.columnSection}>
|
|---|
| 189 | <h2 className={styles.columnTitle}>НЕДЕЛНИ ПЛАНОВИ</h2>
|
|---|
| 190 | {nedelniPlanovi.map((plan) => (
|
|---|
| 191 | <div key={plan.id} className={styles.planCard}>
|
|---|
| 192 | <div className={styles.planHeader}>
|
|---|
| 193 | <span>
|
|---|
| 194 | <strong>Клас:</strong> {plan.klasIme}
|
|---|
| 195 | </span>
|
|---|
| 196 | <span>
|
|---|
| 197 | {plan.datumOd} / {plan.datumDo}
|
|---|
| 198 | </span>
|
|---|
| 199 | </div>
|
|---|
| 200 | <div className={styles.planActivitiesList}>
|
|---|
| 201 | {plan.aktivnosti.map((akt) => (
|
|---|
| 202 | <div key={akt.id} className={styles.miniActivity}>
|
|---|
| 203 | <strong>{akt.denVo_Nedelata}:</strong> {akt.naslov}
|
|---|
| 204 | </div>
|
|---|
| 205 | ))}
|
|---|
| 206 | </div>
|
|---|
| 207 | </div>
|
|---|
| 208 | ))}
|
|---|
| 209 | </div>
|
|---|
| 210 |
|
|---|
| 211 | <div className={styles.columnSection}>
|
|---|
| 212 | <h2 className={styles.columnTitle}>СИТЕ ДОСТАПНИ АКТИВНОСТИ</h2>
|
|---|
| 213 | <div className={styles.activitiesScrollContainer}>
|
|---|
| 214 | {siteAktivnosti.map((akt) => (
|
|---|
| 215 | <div key={akt.id} className={styles.libraryCard}>
|
|---|
| 216 | <div className={styles.libraryTopRow}>
|
|---|
| 217 | <span className={styles.libraryTitle}>{akt.naslov}</span>
|
|---|
| 218 | <span className={styles.dayBadge}>
|
|---|
| 219 | {akt.denVo_Nedelata}
|
|---|
| 220 | </span>
|
|---|
| 221 | </div>
|
|---|
| 222 | <p className={styles.libraryDesc}>{akt.opis}</p>
|
|---|
| 223 | </div>
|
|---|
| 224 | ))}
|
|---|
| 225 | </div>
|
|---|
| 226 | </div>
|
|---|
| 227 | </div>
|
|---|
| 228 | </div>
|
|---|
| 229 |
|
|---|
| 230 | {showAktModal && (
|
|---|
| 231 | <div className={styles.modalOverlay}>
|
|---|
| 232 | <div className={styles.modalContent}>
|
|---|
| 233 | <h2 className={styles.modalTitle}>Нова Активност</h2>
|
|---|
| 234 | <form onSubmit={handleSubmitAktivnost}>
|
|---|
| 235 | <div className={styles.inputGroup}>
|
|---|
| 236 | <label>Наслов:</label>
|
|---|
| 237 | <input
|
|---|
| 238 | type="text"
|
|---|
| 239 | maxLength="30"
|
|---|
| 240 | required
|
|---|
| 241 | value={aktFormData.naslov}
|
|---|
| 242 | onChange={(e) =>
|
|---|
| 243 | setAktFormData({ ...aktFormData, naslov: e.target.value })
|
|---|
| 244 | }
|
|---|
| 245 | />
|
|---|
| 246 | </div>
|
|---|
| 247 | <div className={styles.inputGroup}>
|
|---|
| 248 | <label>Опис:</label>
|
|---|
| 249 | <textarea
|
|---|
| 250 | maxLength="80"
|
|---|
| 251 | required
|
|---|
| 252 | value={aktFormData.opis}
|
|---|
| 253 | onChange={(e) =>
|
|---|
| 254 | setAktFormData({ ...aktFormData, opis: e.target.value })
|
|---|
| 255 | }
|
|---|
| 256 | />
|
|---|
| 257 | </div>
|
|---|
| 258 | <div className={styles.inputGroup}>
|
|---|
| 259 | <label>Ден:</label>
|
|---|
| 260 | <select
|
|---|
| 261 | required
|
|---|
| 262 | value={aktFormData.denVoNedelata}
|
|---|
| 263 | onChange={(e) =>
|
|---|
| 264 | setAktFormData({
|
|---|
| 265 | ...aktFormData,
|
|---|
| 266 | denVoNedelata: e.target.value,
|
|---|
| 267 | })
|
|---|
| 268 | }
|
|---|
| 269 | >
|
|---|
| 270 | <option value="">Избери ден</option>
|
|---|
| 271 | <option value="Ponedelnik">Понеделник</option>
|
|---|
| 272 | <option value="Vtornik">Вторник</option>
|
|---|
| 273 | <option value="Sreda">Среда</option>
|
|---|
| 274 | <option value="Cetvrtok">Четврток</option>
|
|---|
| 275 | <option value="Petok">Петок</option>
|
|---|
| 276 | <option value="Sabota">Сабота</option>
|
|---|
| 277 | </select>
|
|---|
| 278 | </div>
|
|---|
| 279 | <div className={styles.inputGroup}>
|
|---|
| 280 | <label>Избери предмет:</label>
|
|---|
| 281 | <select
|
|---|
| 282 | required
|
|---|
| 283 | value={aktFormData.predmet_id}
|
|---|
| 284 | onChange={(e) =>
|
|---|
| 285 | setAktFormData({
|
|---|
| 286 | ...aktFormData,
|
|---|
| 287 | predmet_id: e.target.value,
|
|---|
| 288 | })
|
|---|
| 289 | }
|
|---|
| 290 | >
|
|---|
| 291 | <option value="">-- Предмети --</option>
|
|---|
| 292 | {predmeti.map((p) => (
|
|---|
| 293 | <option key={p.id} value={p.id}>
|
|---|
| 294 | {p.ime}-{p.fond_casovi}
|
|---|
| 295 | </option>
|
|---|
| 296 | ))}
|
|---|
| 297 | </select>
|
|---|
| 298 | </div>
|
|---|
| 299 | <div className={styles.modalActions}>
|
|---|
| 300 | <button
|
|---|
| 301 | type="button"
|
|---|
| 302 | className={styles.cancelBtn}
|
|---|
| 303 | onClick={() => setShowAktModal(false)}
|
|---|
| 304 | >
|
|---|
| 305 | Откажи
|
|---|
| 306 | </button>
|
|---|
| 307 | <button type="submit" className={styles.saveBtn}>
|
|---|
| 308 | Зачувај
|
|---|
| 309 | </button>
|
|---|
| 310 | </div>
|
|---|
| 311 | </form>
|
|---|
| 312 | </div>
|
|---|
| 313 | </div>
|
|---|
| 314 | )}
|
|---|
| 315 |
|
|---|
| 316 | {showPlanModal && (
|
|---|
| 317 | <div className={styles.modalOverlay}>
|
|---|
| 318 | <div className={styles.modalContent}>
|
|---|
| 319 | <h2 className={styles.modalTitle}>Нов Неделен План</h2>
|
|---|
| 320 | <form onSubmit={handleSubmitPlan}>
|
|---|
| 321 | <div className={styles.inputGroup}>
|
|---|
| 322 | <label>Датум од:</label>
|
|---|
| 323 | <input
|
|---|
| 324 | type="date"
|
|---|
| 325 | required
|
|---|
| 326 | value={planFormData.datumOd}
|
|---|
| 327 | onChange={(e) =>
|
|---|
| 328 | setPlanFormData({
|
|---|
| 329 | ...planFormData,
|
|---|
| 330 | datumOd: e.target.value,
|
|---|
| 331 | })
|
|---|
| 332 | }
|
|---|
| 333 | />
|
|---|
| 334 | </div>
|
|---|
| 335 | <div className={styles.inputGroup}>
|
|---|
| 336 | <label>Датум до:</label>
|
|---|
| 337 | <input
|
|---|
| 338 | type="date"
|
|---|
| 339 | required
|
|---|
| 340 | value={planFormData.datumDo}
|
|---|
| 341 | onChange={(e) =>
|
|---|
| 342 | setPlanFormData({
|
|---|
| 343 | ...planFormData,
|
|---|
| 344 | datumDo: e.target.value,
|
|---|
| 345 | })
|
|---|
| 346 | }
|
|---|
| 347 | />
|
|---|
| 348 | </div>
|
|---|
| 349 | <div className={styles.inputGroup}>
|
|---|
| 350 | <label>Клас:</label>
|
|---|
| 351 | <select
|
|---|
| 352 | required
|
|---|
| 353 | value={planFormData.sledenOdKlasId}
|
|---|
| 354 | onChange={(e) =>
|
|---|
| 355 | setPlanFormData({
|
|---|
| 356 | ...planFormData,
|
|---|
| 357 | sledenOdKlasId: e.target.value,
|
|---|
| 358 | })
|
|---|
| 359 | }
|
|---|
| 360 | >
|
|---|
| 361 | <option value="">-- Избери клас --</option>
|
|---|
| 362 | {allClasses.map((k) => (
|
|---|
| 363 | <option key={k.id} value={k.id}>
|
|---|
| 364 | {k.oddelenie}-{k.paralelka}
|
|---|
| 365 | </option>
|
|---|
| 366 | ))}
|
|---|
| 367 | </select>
|
|---|
| 368 | </div>
|
|---|
| 369 | <div className={styles.modalActions}>
|
|---|
| 370 | <button
|
|---|
| 371 | type="button"
|
|---|
| 372 | className={styles.cancelBtn}
|
|---|
| 373 | onClick={() => setShowPlanModal(false)}
|
|---|
| 374 | >
|
|---|
| 375 | Откажи
|
|---|
| 376 | </button>
|
|---|
| 377 | <button type="submit" className={styles.saveBtn}>
|
|---|
| 378 | Креирај
|
|---|
| 379 | </button>
|
|---|
| 380 | </div>
|
|---|
| 381 | </form>
|
|---|
| 382 | </div>
|
|---|
| 383 | </div>
|
|---|
| 384 | )}
|
|---|
| 385 |
|
|---|
| 386 | {showAddToPlanModal && (
|
|---|
| 387 | <div className={styles.modalOverlay}>
|
|---|
| 388 | <div className={styles.modalContent}>
|
|---|
| 389 | <h2 className={styles.modalTitle}>Додади во План</h2>
|
|---|
| 390 | <form onSubmit={handleAddAktivnostToPlan}>
|
|---|
| 391 | <div className={styles.inputGroup}>
|
|---|
| 392 | <label>Избери активност:</label>
|
|---|
| 393 | <select
|
|---|
| 394 | required
|
|---|
| 395 | value={selectedAktivnostId}
|
|---|
| 396 | onChange={(e) => setSelectedAktivnostId(e.target.value)}
|
|---|
| 397 | >
|
|---|
| 398 | <option value="">-- Избери активност --</option>
|
|---|
| 399 | {siteAktivnosti.map((akt) => (
|
|---|
| 400 | <option key={akt.id} value={akt.id}>
|
|---|
| 401 | {akt.denVo_Nedelata}: {akt.naslov}
|
|---|
| 402 | </option>
|
|---|
| 403 | ))}
|
|---|
| 404 | </select>
|
|---|
| 405 | </div>
|
|---|
| 406 | <div className={styles.modalActions}>
|
|---|
| 407 | <button
|
|---|
| 408 | type="button"
|
|---|
| 409 | className={styles.cancelBtn}
|
|---|
| 410 | onClick={() => setShowAddToPlanModal(false)}
|
|---|
| 411 | >
|
|---|
| 412 | Откажи
|
|---|
| 413 | </button>
|
|---|
| 414 |
|
|---|
| 415 | <button type="submit" className={styles.saveBtn}>
|
|---|
| 416 | Додади
|
|---|
| 417 | </button>
|
|---|
| 418 | </div>
|
|---|
| 419 | </form>
|
|---|
| 420 | </div>
|
|---|
| 421 | </div>
|
|---|
| 422 | )}
|
|---|
| 423 | </div>
|
|---|
| 424 | );
|
|---|
| 425 | };
|
|---|
| 426 |
|
|---|
| 427 | export default AdminPanelNedelniAktivnosti;
|
|---|