Index: backend/backend/settings.py
===================================================================
--- backend/backend/settings.py	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ backend/backend/settings.py	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -57,5 +57,5 @@
 SIMPLE_JWT = {
     'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
-    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
+    'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
     'ROTATE_REFRESH_TOKENS': True,
     'BLACKLIST_AFTER_ROTATION': True,
Index: frontend/package-lock.json
===================================================================
--- frontend/package-lock.json	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/package-lock.json	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -14,5 +14,6 @@
 				"react": "^19.0.0",
 				"react-dom": "^19.0.0",
-				"react-router-dom": "^7.6.0"
+				"react-router-dom": "^7.6.0",
+				"react-toastify": "^11.0.5"
 			},
 			"devDependencies": {
@@ -2058,4 +2059,13 @@
 			"engines": {
 				"node": ">= 6"
+			}
+		},
+		"node_modules/clsx": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+			"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=6"
 			}
 		},
@@ -3833,4 +3843,17 @@
 			}
 		},
+		"node_modules/react-toastify": {
+			"version": "11.0.5",
+			"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
+			"integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==",
+			"license": "MIT",
+			"dependencies": {
+				"clsx": "^2.1.1"
+			},
+			"peerDependencies": {
+				"react": "^18 || ^19",
+				"react-dom": "^18 || ^19"
+			}
+		},
 		"node_modules/read-cache": {
 			"version": "1.0.0",
Index: frontend/package.json
===================================================================
--- frontend/package.json	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/package.json	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -19,5 +19,6 @@
 		"react": "^19.0.0",
 		"react-dom": "^19.0.0",
-		"react-router-dom": "^7.6.0"
+		"react-router-dom": "^7.6.0",
+		"react-toastify": "^11.0.5"
 	},
 	"devDependencies": {
Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/App.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -12,8 +12,23 @@
 import Register from "./pages/Register";
 import SubjectView from "./pages/SubjectView";
+import { ToastContainer } from "react-toastify";
+import "react-toastify/dist/ReactToastify.css";
 
 const Layout = () => (
   <div className="flex flex-col min-h-screen">
     <Navbar />
+    <ToastContainer
+      className="custom-toast-container"
+      position="top-right"
+      autoClose={2000}
+      hideProgressBar={false}
+      newestOnTop={false}
+      closeOnClick
+      rtl={false}
+      pauseOnFocusLoss
+      draggable
+      pauseOnHover
+      theme="light"
+    />
     <main className="flex-grow">
       <Outlet />
Index: frontend/src/components/Footer.tsx
===================================================================
--- frontend/src/components/Footer.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/Footer.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -3,5 +3,5 @@
 const Footer: React.FC = () => {
   return (
-    <footer className="bg-gray-100 text-center text-gray-600 py-4 mt-auto">
+    <footer className="bg-blue-600 text-center text-white py-4 mt-auto">
       <p className="text-sm">&copy; {new Date().getFullYear()} ИзбериИзборен.</p>
     </footer>
Index: frontend/src/components/Navbar.tsx
===================================================================
--- frontend/src/components/Navbar.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/Navbar.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -4,4 +4,5 @@
 import IOimage from "../assets/IOLogo.png";
 import { useAuth } from "../hooks/useAuth";
+import { toast } from "react-toastify";
 
 const Navbar: React.FC = () => {
@@ -14,4 +15,5 @@
     logout();
     navigate("/");
+    toast.success("Успешно сте одјавени!");
   };
 
@@ -32,5 +34,5 @@
 
   return (
-    <nav className="bg-gray-800 text-white p-4">
+    <nav className="bg-blue-600 text-white p-4">
       <div className="flex justify-between items-center">
         <div className="flex items-center space-x-4">
@@ -116,4 +118,9 @@
             </Link>
           )}
+          {isAuthenticated && (
+            <Link to="/recommendations" className="hover:underline">
+              Препораки
+            </Link>
+          )}
           {isAuthenticated ? (
             <button
Index: frontend/src/components/StudentForm/FieldButton.tsx
===================================================================
--- frontend/src/components/StudentForm/FieldButton.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/StudentForm/FieldButton.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -51,5 +51,5 @@
 			className={`px-3 py-2 border rounded-md transition-colors ${
 				isSelected
-					? "bg-yellow-100 border-yellow-300 text-yellow-800"
+					? "bg-green-100 border-green-300 text-green-800"
 					: "bg-white hover:bg-gray-50 border-gray-300"
 			} ${isDisabled ? "opacity-50 cursor-not-allowed" : ""}`}
Index: frontend/src/components/StudentForm/StudentForm.tsx
===================================================================
--- frontend/src/components/StudentForm/StudentForm.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/StudentForm/StudentForm.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -182,6 +182,6 @@
 	const handleSubmit = async (e: React.FormEvent) => {
 		e.preventDefault();
-		let totalCredits = { value: -1 };
-		let creditsByLevel = { value: [0, 0, 0] };
+		const totalCredits = { value: -1 };
+		const creditsByLevel = { value: [0, 0, 0] };
 		const errors = validateForm({
 			index,
@@ -413,5 +413,6 @@
 						</svg>
 						<span className="absolute left-1/2 -translate-x-1/2 mt-2 w-64 bg-gray-800 text-white text-xs rounded px-3 py-2 opacity-0 group-hover:opacity-100 group-focus:opacity-100 pointer-events-none transition-opacity z-10">
-							TODO
+							Ако моментално е јуни/јули/август/септември, за да добиеш препораки одбери дека си твојата година + 1.
+							Пример ако си 2 година и е јуни, избери дека си 3 година.
 						</span>
 					</span>
@@ -471,10 +472,10 @@
 						>
 							<input
-								type="checkbox"
+								type="radio"
 								checked={studyEffort == effort}
 								onChange={() =>
 									setStudyEffort(studyEffort == effort ? "" : effort)
 								}
-								className="form-checkbox h-4 w-5 mr-2 accent-green-600"
+								className="h-4 w-5 mr-2 accent-green-600"
 							/>
 							<span>{effort}</span>
Index: frontend/src/components/SubjectCatalog/SubjectCatalog.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -1,3 +1,3 @@
-import { useEffect, useState } from "react";
+import { useEffect, useState, useMemo } from "react";
 import { Filters, Subject } from "../types";
 import FilterSidebar from "./FilterSidebar";
@@ -61,4 +61,12 @@
 		);
 	}, [subjectData]);
+
+	const subjectIdToNameMap = useMemo(() => {
+		const map = new Map<number, string>();
+		subjectData.forEach((subject) => {
+		  map.set(subject.id, subject.name);
+		});
+		return map;
+	  }, [subjectData]);
 
 	const loadMore = () => {
@@ -162,5 +170,5 @@
 					selectedSubject={selectedSubject}
 					closeModal={closeModal}
-					subjectPrerequisites={getSubjectPrerequisites(selectedSubject)}
+					subjectPrerequisites={getSubjectPrerequisites(selectedSubject, subjectIdToNameMap)}
 				/>
 			)}
Index: frontend/src/components/SubjectCatalog/SubjectList.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -40,5 +40,5 @@
 								<span
 									key={tag}
-									className="bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded"
+									className="bg-green-100 border-green-300 text-green-800 text-xs px-2 py-1 rounded"
 								>
 									{tag}
@@ -52,9 +52,9 @@
 							>
 								<img src="src/assets/eye.svg" className="w-4 h-4 mr-1" />
-								Брз преглед
+								Краток преглед
 							</button>
 							<button
 								onClick={() => openSubjectView(subject)}
-								className="flex items-center px-3 py-2 bg-gray-700 hover:bg-gray-900 text-white text-sm font-medium rounded-md transition-colors"
+								className="flex items-center px-3 py-2 bg-blue-600 hover:bg-blue-900 text-white text-sm font-medium rounded-md transition-colors"
 							>
 								<svg
Index: frontend/src/components/SubjectCatalog/utils.ts
===================================================================
--- frontend/src/components/SubjectCatalog/utils.ts	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/components/SubjectCatalog/utils.ts	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -3,171 +3,171 @@
 
 interface filteredSubjectsParams {
-	subjectData: Subject[];
-	searchTerm: string;
-	professorSearchTerm: string;
-	assistantSearchTerm: string;
-	filters: {
-		season: "W" | "S" | "";
-		semester: number[];
-		level: number[];
-		activated: "activated" | "not_activated" | "";
-		mandatoryFor: StudyTrack[];
-		electiveFor: StudyTrack[];
-		professors: string[];
-		assistants: string[];
-		hasPrerequisites: boolean;
-		tags: string[];
-	};
+  subjectData: Subject[];
+  searchTerm: string;
+  professorSearchTerm: string;
+  assistantSearchTerm: string;
+  filters: {
+    season: "W" | "S" | "";
+    semester: number[];
+    level: number[];
+    activated: "activated" | "not_activated" | "";
+    mandatoryFor: StudyTrack[];
+    electiveFor: StudyTrack[];
+    professors: string[];
+    assistants: string[];
+    hasPrerequisites: boolean;
+    tags: string[];
+  };
 }
 
 export const filterSubjects = ({
-	subjectData,
-	searchTerm,
-	professorSearchTerm,
-	assistantSearchTerm,
-	filters,
+  subjectData,
+  searchTerm,
+  professorSearchTerm,
+  assistantSearchTerm,
+  filters,
 }: filteredSubjectsParams) =>
-	subjectData.filter((subject) => {
-		if (searchTerm !== "") searchTerm = LatinToCyrillic(searchTerm);
-		const searchMatches =
-			searchTerm === "" ||
-			subject.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
-			subject.code.toLowerCase().includes(searchTerm.toLowerCase()) ||
-			subject.abstract?.toLowerCase().includes(searchTerm.toLowerCase());
+  subjectData.filter((subject) => {
+    if (searchTerm !== "") searchTerm = LatinToCyrillic(searchTerm);
+    const searchMatches =
+      searchTerm === "" ||
+      subject.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
+      subject.code.toLowerCase().includes(searchTerm.toLowerCase()) ||
+      subject.abstract?.toLowerCase().includes(searchTerm.toLowerCase());
 
-		const seasonMatches =
-			filters.season === "" || filters.season === subject.subject_info.season;
+    const seasonMatches =
+      filters.season === "" || filters.season === subject.subject_info.season;
 
-		const semesterMatches =
-			filters.semester.length === 0 ||
-			filters.semester.includes(subject.subject_info.semester);
+    const semesterMatches =
+      filters.semester.length === 0 ||
+      filters.semester.includes(subject.subject_info.semester);
 
-		const levelMatches =
-			filters.level.length === 0 ||
-			filters.level.includes(subject.subject_info.level);
+    const levelMatches =
+      filters.level.length === 0 ||
+      filters.level.includes(subject.subject_info.level);
 
-		const activatedMatches =
-			filters.activated == "" ||
-			(filters.activated == "activated" && subject.subject_info.activated) ||
-			(filters.activated == "not_activated" && !subject.subject_info.activated);
+    const activatedMatches =
+      filters.activated == "" ||
+      (filters.activated == "activated" && subject.subject_info.activated) ||
+      (filters.activated == "not_activated" && !subject.subject_info.activated);
 
-		const mandatoryMatches =
-			filters.mandatoryFor.length === 0 ||
-			subject.subject_info.mandatory_for.some((item) =>
-				filters.mandatoryFor.includes(item)
-			);
+    const mandatoryMatches =
+      filters.mandatoryFor.length === 0 ||
+      subject.subject_info.mandatory_for.some((item) =>
+        filters.mandatoryFor.includes(item)
+      );
 
-		const electiveMatches =
-			filters.electiveFor.length === 0 ||
-			subject.subject_info.elective_for.some((item) =>
-				filters.electiveFor.includes(item)
-			);
+    const electiveMatches =
+      filters.electiveFor.length === 0 ||
+      subject.subject_info.elective_for.some((item) =>
+        filters.electiveFor.includes(item)
+      );
 
-		const professorsMatches =
-			professorSearchTerm == "" ||
-			subject.subject_info.professors.some((item) =>
-				item
-					.toLowerCase()
-					.includes(LatinToCyrillic(professorSearchTerm).toLowerCase())
-			);
+    const professorsMatches =
+      professorSearchTerm == "" ||
+      subject.subject_info.professors.some((item) =>
+        item
+          .toLowerCase()
+          .includes(LatinToCyrillic(professorSearchTerm).toLowerCase())
+      );
 
-		const assistantsMatches =
-			assistantSearchTerm == "" ||
-			subject.subject_info.assistants.some((item) =>
-				item
-					.toLowerCase()
-					.includes(LatinToCyrillic(assistantSearchTerm).toLowerCase())
-			);
+    const assistantsMatches =
+      assistantSearchTerm == "" ||
+      subject.subject_info.assistants.some((item) =>
+        item
+          .toLowerCase()
+          .includes(LatinToCyrillic(assistantSearchTerm).toLowerCase())
+      );
 
-		const prerequisitesMatch =
-			!filters.hasPrerequisites || subject.subject_info.prerequisite == null;
+    const prerequisitesMatch =
+      !filters.hasPrerequisites || subject.subject_info.prerequisite == null;
 
-		const tagsMatch =
-			filters.tags.length == 0 ||
-			subject.subject_info.tags.some((item) => filters.tags.includes(item));
-		return (
-			searchMatches &&
-			seasonMatches &&
-			semesterMatches &&
-			levelMatches &&
-			activatedMatches &&
-			mandatoryMatches &&
-			electiveMatches &&
-			professorsMatches &&
-			assistantsMatches &&
-			prerequisitesMatch &&
-			tagsMatch
-		);
-	});
+    const tagsMatch =
+      filters.tags.length == 0 ||
+      subject.subject_info.tags.some((item) => filters.tags.includes(item));
+    return (
+      searchMatches &&
+      seasonMatches &&
+      semesterMatches &&
+      levelMatches &&
+      activatedMatches &&
+      mandatoryMatches &&
+      electiveMatches &&
+      professorsMatches &&
+      assistantsMatches &&
+      prerequisitesMatch &&
+      tagsMatch
+    );
+  });
 
 export const resetFilters = (
-	setSearchTerm: (val: string) => void,
-	setProfessorSearchTerm: (val: string) => void,
-	setAssistantSearchTerm: (val: string) => void,
-	setFilters: (val: (prev: Filters) => Filters) => void
+  setSearchTerm: (val: string) => void,
+  setProfessorSearchTerm: (val: string) => void,
+  setAssistantSearchTerm: (val: string) => void,
+  setFilters: (val: (prev: Filters) => Filters) => void
 ) => {
-	setSearchTerm("");
-	setProfessorSearchTerm("");
-	setAssistantSearchTerm("");
-	setFilters(() => ({
-		season: "",
-		semester: [],
-		level: [],
-		activated: "",
-		mandatoryFor: [],
-		electiveFor: [],
-		professors: [],
-		assistants: [],
-		hasPrerequisites: false,
-		tags: [],
-	}));
+  setSearchTerm("");
+  setProfessorSearchTerm("");
+  setAssistantSearchTerm("");
+  setFilters(() => ({
+    season: "",
+    semester: [],
+    level: [],
+    activated: "",
+    mandatoryFor: [],
+    electiveFor: [],
+    professors: [],
+    assistants: [],
+    hasPrerequisites: false,
+    tags: [],
+  }));
 };
 
 export const getRandomStaff = (
-	subjectData: Subject[],
-	setRandomStaff: ([]: string[]) => void
+  subjectData: Subject[],
+  setRandomStaff: ([]: string[]) => void
 ) => {
-	if (subjectData.length == 0) return;
-	const getRandomProfessor = () => {
-		const randomSubject1 =
-			subjectData[Math.floor(Math.random() * subjectData.length)];
-		return randomSubject1?.subject_info.professors[
-			Math.floor(Math.random() * randomSubject1.subject_info.professors.length)
-		];
-	};
-	const getRandomAssistant = () => {
-		const randomSubject2 =
-			subjectData[Math.floor(Math.random() * subjectData.length)];
-		return randomSubject2?.subject_info.assistants[
-			Math.floor(Math.random() * randomSubject2.subject_info.assistants.length)
-		];
-	};
-	let randomProfessor = "";
-	let randomAssistant = "";
+  if (subjectData.length == 0) return;
+  const getRandomProfessor = () => {
+    const randomSubject1 =
+      subjectData[Math.floor(Math.random() * subjectData.length)];
+    return randomSubject1?.subject_info.professors[
+      Math.floor(Math.random() * randomSubject1.subject_info.professors.length)
+    ];
+  };
+  const getRandomAssistant = () => {
+    const randomSubject2 =
+      subjectData[Math.floor(Math.random() * subjectData.length)];
+    return randomSubject2?.subject_info.assistants[
+      Math.floor(Math.random() * randomSubject2.subject_info.assistants.length)
+    ];
+  };
+  let randomProfessor = "";
+  let randomAssistant = "";
 
-	while (!randomProfessor) randomProfessor = getRandomProfessor();
-	while (!randomAssistant) randomAssistant = getRandomAssistant();
+  while (!randomProfessor) randomProfessor = getRandomProfessor();
+  while (!randomAssistant) randomAssistant = getRandomAssistant();
 
-	setRandomStaff([randomProfessor, randomAssistant]);
+  setRandomStaff([randomProfessor, randomAssistant]);
 };
 
 export const getSubjectPrerequisites = (
-	subject: Subject
+  subject: Subject,
+  subjectMap: Map<number, string>
 ): "Нема предуслов" | number | string => {
-	const prerequisite = subject?.subject_info?.prerequisite;
+  const prerequisite = subject?.subject_info?.prerequisite;
+  if (!prerequisite) return "Нема предуслов";
 
-	if (!prerequisite) return "Нема предуслов";
+  if ("subjects" in prerequisite && Array.isArray(prerequisite.subjects)) {
+    const names = prerequisite.subjects.map(
+      (id) => subjectMap.get(id) || "Непознат предмет"
+    );
+    return names.length > 0 ? names.join(' или ') : "Нема предуслов";
+  }
 
-	if ("subjects" in prerequisite && Array.isArray(prerequisite.subjects)) {
-		return (
-			(subject && subject.subject_info.prerequisite.subjects?.join(" или ")) ||
-			"Нема предуслов"
-		);
-	}
+  if ("credits" in prerequisite && typeof prerequisite.credits === "number") {
+    return prerequisite.credits;
+  }
 
-	if ("credits" in prerequisite && typeof prerequisite.credits === "number") {
-		return prerequisite.credits;
-	}
-
-	return "Нема предуслов";
+  return "Нема предуслов";
 };
Index: frontend/src/context/AuthProvider.tsx
===================================================================
--- frontend/src/context/AuthProvider.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/context/AuthProvider.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -2,4 +2,5 @@
 import AuthContext, { AuthContextType } from "./AuthContext";
 import axiosInstance from "../api/axiosInstance";
+import { toast } from "react-toastify";
 
 export const AuthProvider: React.FC<{ children: ReactNode }> = ({
@@ -7,13 +8,14 @@
 }) => {
   const [accessToken, setAccessToken] = useState<string | null>(
-    localStorage.getItem("access_token")
+    localStorage.getItem("access")
   );
   const [refreshToken, setRefreshToken] = useState<string | null>(
-    localStorage.getItem("refresh_token")
+    localStorage.getItem("refresh")
   );
   const refreshAccessToken = async (): Promise<string | null> => {
-    const refreshToken = localStorage.getItem("refresh_token");
+    const refreshToken = localStorage.getItem("refresh");
     if (!refreshToken) {
       logout();
+      toast.error("Session expired. Please log in again.");
       return null;
     }
@@ -25,10 +27,10 @@
 
       const newAccessToken = response.data.access;
-      localStorage.setItem("access_token", newAccessToken);
+      localStorage.setItem("access", newAccessToken);
       setAccessToken(newAccessToken);
 
       if (response.data.refresh) {
         const newRefreshToken = response.data.refresh;
-        localStorage.setItem("refresh_token", newRefreshToken);
+        localStorage.setItem("refresh", newRefreshToken);
         setRefreshToken(newRefreshToken);
       }
@@ -43,6 +45,6 @@
 
   const login = (newAccessToken: string, newRefreshToken: string) => {
-    localStorage.setItem("access_token", newAccessToken);
-    localStorage.setItem("refresh_token", newRefreshToken);
+    localStorage.setItem("access", newAccessToken);
+    localStorage.setItem("refresh", newRefreshToken);
     setAccessToken(newAccessToken);
     setRefreshToken(newRefreshToken);
@@ -50,6 +52,6 @@
 
   const logout = () => {
-    localStorage.removeItem("access_token");
-    localStorage.removeItem("refresh_token");
+    localStorage.removeItem("access");
+    localStorage.removeItem("refresh");
     setAccessToken(null);
     setRefreshToken(null);
Index: frontend/src/hooks/useAxiosAuth.ts
===================================================================
--- frontend/src/hooks/useAxiosAuth.ts	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/hooks/useAxiosAuth.ts	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -36,5 +36,7 @@
 
             if (newAccessToken) {
-              // The request interceptor will handle adding the new header
+              accessTokenRef.current = newAccessToken;
+              originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
+              // Retry the original request with the new access token
               return axiosInstance(originalRequest);
             } else {
Index: frontend/src/index.css
===================================================================
--- frontend/src/index.css	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/index.css	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -16,2 +16,7 @@
 	}
 }
+
+.custom-toast-container {
+  /* This overrides the default 'top' value from the library */
+  top: 8em !important; 
+}
Index: frontend/src/pages/Account.tsx
===================================================================
--- frontend/src/pages/Account.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/pages/Account.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -4,4 +4,6 @@
 import { StudentData } from "../components/types";
 import useAxiosAuth from "../hooks/useAxiosAuth";
+import { toast } from "react-toastify";
+
 
 const Account = () => {
@@ -13,21 +15,13 @@
 
     useEffect(() => {
-        // This function will run once when the component mounts
         const fetchData = async () => {
             try {
-                // Simply ask for the data.
-                // If the token is expired/missing, the interceptor will
-                // automatically refresh it and retry this request.
-                // This 'await' will just pause until the whole process is complete.
                 const resForm = await axiosAuth.get("/auth/form/");
                 setFormData(resForm.data);
             } catch (error) {
-                // This catch block will only be triggered if the token refresh
-                // fails and the interceptor gives up. In that case, we should
-                // probably navigate the user away.
-                console.error("Could not fetch form data after retries.", error);
-                //navigate("/login");
+                console.error("Error fetching form data:", error);
+                toast.error("Could not fetch form data after retries.");
+                navigate("/login");
             } finally {
-                // This will run whether the request succeeded or failed.
                 setIsLoading(false);
             }
Index: frontend/src/pages/Login.tsx
===================================================================
--- frontend/src/pages/Login.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/pages/Login.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -47,5 +47,5 @@
 				[key: string]: string[] | string;
 			}>;
-			console.log("Error response data:", axiosError.response?.data);
+			console.error("Error response data:", axiosError.response?.data);
 
 			if (axiosError.response && axiosError.response.data) {
Index: frontend/src/pages/Recommendations.tsx
===================================================================
--- frontend/src/pages/Recommendations.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/pages/Recommendations.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -1,220 +1,261 @@
-import { useState } from "react";
+import { useState, useEffect, useMemo } from "react";
 import { useNavigate } from "react-router-dom";
 import { Subject } from "../components/types";
+import SubjectModal from "../components/SubjectCatalog/SubjectModal";
+import { getSubjectPrerequisites } from "../components/SubjectCatalog/utils";
 import useAxiosAuth from "../hooks/useAxiosAuth";
 
 const Recommendations = () => {
-	const axiosAuth = useAxiosAuth();
-	const navigate = useNavigate();
-	const [recommendations, setRecommendations] = useState<Subject[]>([]);
-	const [season_, setSeason] = useState<"winter" | "summer" | "all">("all");
-	const [isLoading, setIsLoading] = useState(false);
-
-	const mapToSeasonInt = (season: "winter" | "summer" | "all") => {
-		if (season == "summer") return 0;
-		if (season == "winter") return 1;
-		return 2;
-	};
-
-	const testAPI = async () => {
-		setIsLoading(true);
-		try {
-			const season = mapToSeasonInt(season_);
-			console.log(season);
-			const response = await axiosAuth.get("/suggestion", {
-				params: { season },
-			});
-			setRecommendations(response.data.data);
-			console.log(response.data.data);
-			console.log(response.data);
-		} catch (error) {
-			console.error("Error fetching recommendations:", error);
-		} finally {
-			setIsLoading(false);
-		}
-	};
-
-	const cycleSeason = () => {
-		if (season_ === "all") setSeason("winter");
-		else if (season_ === "winter") setSeason("summer");
-		else setSeason("all");
-	};
-
-	const openSubjectView = (subject: Subject) => {
-		navigate(`/subjects/${subject.id}`, {
-			state: { from: "/recommendations" },
-		});
-	};
-
-	const openSubjectDetails = (subject: Subject) => {
-		console.log("Opening subject details for:", subject);
-	};
-
-	const getSeasonText = () => {
-		switch (season_) {
-			case "winter":
-				return "Зимски";
-			case "summer":
-				return "Летен";
-			case "all":
-				return "Сите";
-		}
-	};
-
-	return (
-		<div className="flex h-screen bg-gray-50">
-			<div className="w-1/3 bg-white shadow-lg p-8 flex flex-col justify-center items-center space-y-8">
-				<div className="text-center">
-					<h1 className="text-4xl font-bold text-gray-800 mb-2">Препораки</h1>
-					<p className="text-gray-600 text-lg">
-						Откријте ги вашите идеални предмети!
-					</p>
-				</div>
-
-				<div className="bg-blue-50 border border-blue-200 rounded-lg p-6 text-center hover:bg-blue-100 transition-colors duration-200">
-					<p className="text-gray-700 mb-3">Избрана сезона:</p>
-					<p className="text-2xl font-semibold text-gray-800">
-						{getSeasonText()}
-					</p>
-				</div>
-
-				<button
-					onClick={cycleSeason}
-					className="bg-blue-500 hover:bg-blue-600 text-white px-8 py-4 rounded-lg text-lg font-medium hover:scale-105 transition-all duration-200 shadow-md hover:shadow-lg"
-				>
-					Промени сезона
-				</button>
-
-				<button
-					onClick={testAPI}
-					disabled={isLoading}
-					className={`${
-						isLoading
-							? "bg-gray-400 cursor-not-allowed"
-							: "bg-green-500 hover:bg-green-600 hover:scale-105 shadow-md hover:shadow-lg"
-					} text-white px-8 py-4 rounded-lg text-xl font-bold transition-all duration-200 flex items-center space-x-2`}
-				>
-					{isLoading ? (
-						<>
-							<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
-							<span>Се вчитува...</span>
-						</>
-					) : (
-						<span>Вчитај препораки!</span>
-					)}
-				</button>
-			</div>
-
-			<div className="flex-1 p-8 overflow-y-auto">
-				{recommendations.length > 0 ? (
-					<div className="space-y-6">
-						<div className="text-center mb-8">
-							<h2 className="text-3xl font-bold text-gray-800 mb-2">
-								Вашите препораки за {getSeasonText().toLowerCase()} семестар
-							</h2>
-							<div className="w-24 h-1 bg-blue-500 mx-auto rounded-full"></div>
-						</div>
-
-						<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 lg:h-[1100px]">
-							{recommendations.map((subject, index) => (
-								<div
-									key={subject.id}
-									className={`border border-gray-200 rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-200 relative ${
-										index % 2 === 0 ? "self-start" : "self-end"
-									}`}
-									style={{
-										height: "80%",
-										animationDelay: `${index * 100}ms`,
-										animation: "fadeInUp 0.6s ease-out forwards",
-									}}
-								>
-									<div className="p-4 min-h-full flex flex-col gap-1">
-										<div className="flex justify-between items-start mb-2">
-											<div>
-												<h3 className="text-lg font-semibold">
-													{subject.name}
-												</h3>
-												<p className="text-gray-600">{subject.code}</p>
-											</div>
-										</div>
-
-										{subject.subject_info?.tags && (
-											<div className="flex flex-wrap gap-2 mb-4">
-												{subject.subject_info.tags.map((tag) => (
-													<span
-														key={tag}
-														className="bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded"
-													>
-														{tag}
-													</span>
-												))}
-											</div>
-										)}
-
-										<div className="flex justify-between mt-auto gap-3">
-											<button
-												onClick={() => openSubjectDetails(subject)}
-												className="flex items-center text-sm text-gray-600 hover:text-gray-800 transition-colors"
-											>
-												<img
-													src="src/assets/eye.svg"
-													className="w-4 h-4 mr-1"
-												/>
-												Брз преглед
-											</button>
-											<button
-												onClick={() => openSubjectView(subject)}
-												className="flex items-center px-3 py-2 bg-gray-700 hover:bg-gray-900 text-white text-sm font-medium rounded-md transition-colors"
-											>
-												<svg
-													className="w-4 h-4 mr-1"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
-													/>
-												</svg>
-												Отвори предмет
-											</button>
-										</div>
-									</div>
-								</div>
-							))}
-						</div>
-					</div>
-				) : (
-					<div className="flex flex-col items-center justify-center h-full text-center">
-						<div className="text-gray-400 mb-6">
-							<svg
-								className="w-16 h-16 mx-auto"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={1}
-									d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
-								/>
-							</svg>
-						</div>
-						<h3 className="text-2xl font-bold text-gray-600 mb-4">
-							Започнете со пребарување!
-						</h3>
-						<p className="text-gray-500 text-lg max-w-md">
-							Изберете ја саканата сезона и кликнете на "Вчитај препораки" за да
-							ги откриете вашите идеални предмети!
-						</p>
-					</div>
-				)}
-			</div>
-		</div>
-	);
+  const axiosAuth = useAxiosAuth();
+  const navigate = useNavigate();
+  const [subjectData, setSubjectData] = useState<Subject[]>([]);
+  const [recommendations, setRecommendations] = useState<Subject[]>([]);
+  const [season_, setSeason] = useState<"winter" | "summer" | "all">("all");
+  const [isLoading, setIsLoading] = useState(false);
+  const [showModal, setShowModal] = useState(false);
+
+  const mapToSeasonInt = (season: "winter" | "summer" | "all") => {
+    if (season == "summer") return 0;
+    if (season == "winter") return 1;
+    return 2;
+  };
+
+  const fetchRecommendations = async () => {
+    setIsLoading(true);
+    try {
+      const season = mapToSeasonInt(season_);
+      const response = await axiosAuth.get("/suggestion", {
+        params: { season },
+      });
+      setRecommendations(response.data.data);
+    } catch (error) {
+      console.error("Error fetching recommendations:", error);
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  // need to fetch subject data so that we can compare the subject IDs (prerequisites store IDs, but we need names) in the modals for the recommendations
+  useEffect(() => {
+    const fetchData = async () => {
+      const response = await axiosAuth.get("/subjects");
+      setSubjectData(response.data);
+    };
+    fetchData();
+  }, [axiosAuth]);
+
+  const subjectIdToNameMap = useMemo(() => {
+    const map = new Map<number, string>();
+    subjectData.forEach((subject) => {
+      map.set(subject.id, subject.name);
+    });
+	return map;
+  }, [subjectData]);
+
+  const cycleSeason = () => {
+    if (season_ === "all") setSeason("winter");
+    else if (season_ === "winter") setSeason("summer");
+    else setSeason("all");
+  };
+
+  const openSubjectView = (subject: Subject) => {
+    navigate(`/subjects/${subject.id}`, {
+      state: { from: "/recommendations" },
+    });
+  };
+
+  const [selectedSubject, setSelectedSubject] = useState<Subject | null>(null);
+
+  const openSubjectDetails = (subject: Subject) => {
+    setSelectedSubject(
+      subjectData.find((item) => item.id == subject.id) ?? null
+    );
+    setShowModal(true);
+  };
+
+  const closeModal = () => {
+    setSelectedSubject(null);
+    setShowModal(false);
+  };
+
+  const getSeasonText = () => {
+    switch (season_) {
+      case "winter":
+        return "Зимски";
+      case "summer":
+        return "Летен";
+      case "all":
+        return "Двата";
+    }
+  };
+
+  return (
+    <div className="flex h-screen bg-gray-50">
+      <div className="w-1/3 bg-white shadow-lg p-8 flex flex-col justify-center items-center space-y-8">
+        <div className="text-center">
+          <h1 className="text-4xl font-bold text-gray-800 mb-2">Препораки</h1>
+          <p className="text-gray-600 text-lg">
+            Откријте ги вашите идеални предмети!
+          </p>
+        </div>
+
+        <div className="bg-blue-50 border border-blue-200 rounded-lg p-6 text-center hover:bg-blue-100 transition-colors duration-200">
+          <p className="text-gray-700 mb-3">Избран семестар: </p>
+          <p className="text-2xl font-semibold text-gray-800">
+            {getSeasonText()}
+          </p>
+        </div>
+
+        <button
+          onClick={cycleSeason}
+          className="bg-blue-500 hover:bg-blue-600 text-white px-8 py-4 rounded-lg text-lg font-medium hover:scale-105 transition-all duration-200 shadow-md hover:shadow-lg"
+        >
+          Промени семестар
+        </button>
+
+        <button
+          onClick={fetchRecommendations}
+          disabled={isLoading}
+          className={`${
+            isLoading
+              ? "bg-gray-400 cursor-not-allowed"
+              : "bg-green-500 hover:bg-green-600 hover:scale-105 shadow-md hover:shadow-lg"
+          } text-white px-8 py-4 rounded-lg text-xl font-bold transition-all duration-200 flex items-center space-x-2`}
+        >
+          {isLoading ? (
+            <>
+              <div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
+              <span>Се вчитува...</span>
+            </>
+          ) : (
+            <span>Вчитај препораки!</span>
+          )}
+        </button>
+      </div>
+
+      <div className="flex-1 p-8 overflow-y-auto">
+        {recommendations.length > 0 ? (
+          <div className="space-y-6">
+            <div className="text-center mb-8">
+              <h2 className="text-3xl font-bold text-gray-800 mb-2">
+                Вашите препораки за {getSeasonText().toLowerCase()}{" "}
+                {getSeasonText().toLowerCase() === "двата"
+                  ? "семестри"
+                  : "семестар"}
+              </h2>
+              <div className="w-24 h-1 bg-blue-500 mx-auto rounded-full"></div>
+            </div>
+
+            <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 lg:h-[1100px]">
+              {recommendations.map((subject, index) => (
+                <div
+                  key={subject.id}
+                  className={`border border-gray-200 rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow duration-200 relative ${
+                    index % 2 === 0 ? "self-start" : "self-end"
+                  }`}
+                  style={{
+                    height: "80%",
+                    animationDelay: `${index * 100}ms`,
+                    animation: "fadeInUp 0.6s ease-out forwards",
+                  }}
+                >
+                  <div className="p-4 min-h-full flex flex-col gap-1">
+                    <div className="flex justify-between items-start mb-2">
+                      <div>
+                        <h3 className="text-lg font-semibold">
+                          {subject.name}
+                        </h3>
+                        <p className="text-gray-600">{subject.code}</p>
+                      </div>
+                    </div>
+
+                    {subject.subject_info?.tags && (
+                      <div className="flex flex-wrap gap-2 mb-4">
+                        {subject.subject_info.tags.map((tag) => (
+                          <span
+                            key={tag}
+                            className="bg-green-100 border-green-300 text-green-800 text-xs px-2 py-1 rounded"
+                          >
+                            {tag}
+                          </span>
+                        ))}
+                      </div>
+                    )}
+
+                    <div className="flex justify-between mt-auto gap-3">
+                      <button
+                        onClick={() => openSubjectDetails(subject)}
+                        className="flex items-center text-sm text-gray-600 hover:text-gray-800 transition-colors"
+                      >
+                        <img
+                          src="src/assets/eye.svg"
+                          className="w-4 h-4 mr-1"
+                        />
+                        Краток преглед
+                      </button>
+                      <button
+                        onClick={() => openSubjectView(subject)}
+                        className="flex items-center px-3 py-2 bg-blue-600 hover:bg-blue-900 text-white text-sm font-medium rounded-md transition-colors"
+                      >
+                        <svg
+                          className="w-4 h-4 mr-1"
+                          fill="none"
+                          stroke="currentColor"
+                          viewBox="0 0 24 24"
+                        >
+                          <path
+                            strokeLinecap="round"
+                            strokeLinejoin="round"
+                            strokeWidth={2}
+                            d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
+                          />
+                        </svg>
+                        Отвори предмет
+                      </button>
+                    </div>
+                  </div>
+                </div>
+              ))}
+            </div>
+          </div>
+        ) : (
+          <div className="flex flex-col items-center justify-center h-full text-center">
+            <div className="text-gray-400 mb-6">
+              <svg
+                className="w-16 h-16 mx-auto"
+                fill="none"
+                stroke="currentColor"
+                viewBox="0 0 24 24"
+              >
+                <path
+                  strokeLinecap="round"
+                  strokeLinejoin="round"
+                  strokeWidth={1}
+                  d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
+                />
+              </svg>
+            </div>
+            <h3 className="text-2xl font-bold text-gray-600 mb-4">
+              Започнете со пребарување!
+            </h3>
+            <p className="text-gray-500 text-lg max-w-md">
+              Изберете ја саканата сезона и кликнете на "Вчитај препораки" за да
+              ги откриете вашите идеални предмети!
+            </p>
+          </div>
+        )}
+      </div>
+      {showModal && selectedSubject && (
+        <SubjectModal
+          selectedSubject={selectedSubject}
+          closeModal={closeModal}
+          subjectPrerequisites={getSubjectPrerequisites(
+            selectedSubject,
+            subjectIdToNameMap
+          )}
+        />
+      )}
+    </div>
+  );
 };
 
Index: frontend/src/pages/SubjectView.tsx
===================================================================
--- frontend/src/pages/SubjectView.tsx	(revision 0ef57d11142f10639a173589ad4cfb7d05972e1e)
+++ frontend/src/pages/SubjectView.tsx	(revision 8aa983789002e45ac512ac4ef52cc154c24dae6a)
@@ -45,5 +45,5 @@
 			.then((data) => {
 				setSelectedSubject(data);
-				setSubjectPrerequisites(getSubjectPrerequisites(selectedSubject));
+				setSubjectPrerequisites(getSubjectPrerequisites(selectedSubject, data));
 				setIsLoading(false);
 			});
