Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision ff9e2e0b894acd6b30ee578a2ca46b95813ccdeb)
+++ frontend/src/App.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -1,4 +1,4 @@
 import { createBrowserRouter, RouterProvider } from "react-router-dom";
-import CourseCatalog from "./components/SubjectCatalog";
+import CourseCatalog from "./components/SubjectCatalog/SubjectCatalog";
 import "./index.css";
 import Home from "./pages/Home";
Index: ontend/src/components/SubjectCatalog.tsx
===================================================================
--- frontend/src/components/SubjectCatalog.tsx	(revision ff9e2e0b894acd6b30ee578a2ca46b95813ccdeb)
+++ 	(revision )
@@ -1,611 +1,0 @@
-import { useEffect, useState } from "react";
-import { PROGRAMS } from "../constants/subjects";
-import { Programs, Subject } from "../types";
-import SubjectModal from "./SubjectModal";
-const SubjectCatalog = () => {
-	const [visibleCourses, setVisibleCourses] = useState<number>(10);
-	const [searchTerm, setSearchTerm] = useState<string>("");
-	const [professorSearchTerm, setProfessorSearchTerm] = useState<string>("");
-	const [assistantSearchTerm, setAssistantSearchTerm] = useState<string>("");
-	const [selectedSubject, setSelectedSubject] = useState<Subject | null>(null);
-	const [subjectData, setSubjectData] = useState<Subject[]>([]);
-	const [isLoaded, setIsLoaded] = useState(false);
-	const [randomStaff, setRandomStaff] = useState(["", ""]);
-	const [showModal, setShowModal] = useState(false);
-	const [filters, setFilters] = useState({
-		season: "" as "W" | "S" | "",
-		semester: [] as number[],
-		level: [] as number[],
-		activated: "" as "activated" | "not_activated" | "",
-		mandatoryFor: [] as Programs[],
-		electiveFor: [] as Programs[],
-		professors: [] as string[],
-		assistants: [] as string[],
-		hasPrerequisites: false as boolean,
-	});
-
-	const filteredSubjects = subjectData.filter((subject) => {
-		const searchMatches =
-			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.info.season;
-
-		const semesterMatches =
-			filters.semester.length === 0 ||
-			filters.semester.includes(subject.info.semester);
-
-		const levelMatches =
-			filters.level.length === 0 || filters.level.includes(subject.info.level);
-
-		const activatedMatches =
-			filters.activated == "" ||
-			(filters.activated == "activated" && subject.info.activated) ||
-			(filters.activated == "not_activated" && !subject.info.activated);
-
-		const mandatoryMatches =
-			filters.mandatoryFor.length === 0 ||
-			subject.info.mandatory_for.some((item) =>
-				filters.mandatoryFor.includes(item)
-			);
-
-		const electiveMatches =
-			filters.electiveFor.length === 0 ||
-			subject.info.elective_for.some((item) =>
-				filters.electiveFor.includes(item)
-			);
-
-		const professorsMatches =
-			professorSearchTerm == "" ||
-			subject.info.professors.some((item) =>
-				item.toLowerCase().includes(professorSearchTerm.toLowerCase())
-			);
-
-		const assistantsMatches =
-			assistantSearchTerm == "" ||
-			subject.info.assistants.some((item) =>
-				item.toLowerCase().includes(assistantSearchTerm.toLowerCase())
-			);
-
-		const prerequisitesMatch =
-			!filters.hasPrerequisites || subject.info.prerequisite == "";
-
-		return (
-			searchMatches &&
-			seasonMatches &&
-			semesterMatches &&
-			levelMatches &&
-			activatedMatches &&
-			mandatoryMatches &&
-			electiveMatches &&
-			professorsMatches &&
-			assistantsMatches &&
-			prerequisitesMatch
-		);
-	});
-
-	const resetFilters = () => {
-		setSearchTerm("");
-		setFilters({
-			season: "" as "W" | "S" | "",
-			semester: [] as number[],
-			level: [] as number[],
-			activated: "" as "activated" | "not_activated" | "",
-			mandatoryFor: [] as Programs[],
-			electiveFor: [] as Programs[],
-			professors: [] as string[],
-			assistants: [] as string[],
-			hasPrerequisites: false,
-		});
-	};
-
-	const FilterSidebar = () => {
-		return (
-			<div className="">
-				<div className="flex justify-between items-center mb-4">
-					<h2 className="text-lg font-semibold">Филтри</h2>
-					<button
-						onClick={resetFilters}
-						className="text-sm text-gray-600 hover:text-gray-900"
-					>
-						Избриши
-					</button>
-				</div>
-				<div className="mb-4">
-					{/* filter by season*/}
-					<div className="space-y-1 mb-4">
-						<h3 className="font-medium mb-2">Семестар</h3>
-						<div className="grid grid-cols-2">
-							{["Летен", "Зимски"].map((season) => {
-								const seasonValue = season === "Летен" ? "S" : "W";
-								return (
-									<div key={season} className="flex items-center space-x-2">
-										<input
-											type="checkbox"
-											name="season"
-											id={seasonValue}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													season:
-														prev.season === seasonValue ? "" : seasonValue,
-												}))
-											}
-											checked={filters.season === seasonValue}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label
-											htmlFor={seasonValue}
-											className="ml-2 text-sm text-gray-700"
-										>
-											{season}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-
-					{/* filter by semester*/}
-					<div className="space-y-1 mb-4">
-						{/* <h3 className="font-medium mb-2">Семестар</h3> */}
-						<div className="grid grid-cols-4 gap-2">
-							{Array.from(Array(8)).map((_, index) => {
-								const i = index + 1;
-								return (
-									<div key={i} className="flex items-center space-x-2">
-										<input
-											type="checkbox"
-											name="season"
-											id={`s${i}`}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													semester: prev.semester.includes(i)
-														? prev.semester.filter((item) => item !== i)
-														: [...prev.semester, i],
-												}))
-											}
-											checked={filters.semester.includes(i)}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label htmlFor={`s${i}`} className="text-sm text-gray-700">
-											{i}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-					{/* filter by level */}
-					<div className="space-y-1 mb-4">
-						<h3 className="font-medium mb-2">Ниво</h3>
-						<div className="grid grid-cols-3">
-							{Array.from(Array(3)).map((_, index) => {
-								const i = index + 1;
-								const level = `L${i}`;
-								return (
-									<div key={i} className="flex items-center space-x-2">
-										<input
-											type="checkbox"
-											name="level"
-											id={level}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													level: prev.level.includes(i)
-														? prev.level.filter((item) => item !== i)
-														: [...prev.level, i],
-												}))
-											}
-											checked={filters.level.includes(i)}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label
-											htmlFor={`s${level}`}
-											className="text-sm text-gray-700"
-										>
-											{level}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-					{/* filter by activation*/}
-					<div className="space-y-1 mb-4">
-						<h3 className="font-medium mb-2">Активирани</h3>
-						<div className="grid grid-cols-2">
-							{["Активирани", "Неактивирани"].map((value) => {
-								const activeValue =
-									value === "Активирани" ? "activated" : "not_activated";
-								return (
-									<div
-										key={activeValue}
-										className="flex items-center space-x-2"
-									>
-										<input
-											type="checkbox"
-											name="season"
-											id={activeValue}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													activated:
-														prev.activated === activeValue ? "" : activeValue,
-												}))
-											}
-											checked={filters.activated === activeValue}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label
-											htmlFor={activeValue}
-											className="ml-2 text-sm text-gray-700"
-										>
-											{value}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-					{/* filter by mandatoryFor */}
-					<div className="space-y-1 mb-4">
-						<h3 className="font-medium mb-2">Задолжителен за:</h3>
-						<div className="grid grid-cols-3 gap-2">
-							{PROGRAMS.map((program) => {
-								const programName = program.replace(/\d+$/, "");
-								return (
-									<div key={program} className="flex items-center space-x-2">
-										<input
-											type="checkbox"
-											name="level"
-											id={program}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													mandatoryFor: prev.mandatoryFor.includes(program)
-														? prev.mandatoryFor.filter(
-																(item) => item !== program
-														  )
-														: [...prev.mandatoryFor, program],
-												}))
-											}
-											checked={filters.mandatoryFor.includes(program)}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label
-											htmlFor={`s${program}`}
-											className="text-sm text-gray-700"
-										>
-											{programName}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-					{/* filter by electiveFor */}
-					<div className="space-y-1 mb-6">
-						<h3 className="font-medium mb-2">Изборен за:</h3>
-						<div className="grid grid-cols-3 gap-2">
-							{PROGRAMS.map((program) => {
-								const programName = program.replace(/\d+$/, "");
-								return (
-									<div key={program} className="flex items-center space-x-2">
-										<input
-											type="checkbox"
-											name="level"
-											id={program}
-											onChange={() =>
-												setFilters((prev) => ({
-													...prev,
-													electiveFor: prev.electiveFor.includes(program)
-														? prev.electiveFor.filter(
-																(item) => item !== program
-														  )
-														: [...prev.electiveFor, program],
-												}))
-											}
-											checked={filters.electiveFor.includes(program)}
-											className="h-4 w-4 rounded border-gray-300 text-blue-600"
-										/>
-										<label
-											htmlFor={`s${program}`}
-											className="text-sm text-gray-700"
-										>
-											{programName}
-										</label>
-									</div>
-								);
-							})}
-						</div>
-					</div>
-					{/* filter by prereq */}
-					<div className="space-y-1 mb-4">
-						<div className="flex items-center space-x-2">
-							<input
-								type="checkbox"
-								name="prereq"
-								id="prereq"
-								onChange={() =>
-									setFilters((prev) => ({
-										...prev,
-										hasPrerequisites: !prev.hasPrerequisites,
-									}))
-								}
-								checked={filters.hasPrerequisites}
-								className="h-4 w-4 rounded border-gray-300 text-blue-600"
-							/>
-							<label htmlFor={"prereq"} className="text-sm text-gray-700">
-								Предметот нема предуслови
-							</label>
-						</div>
-					</div>
-				</div>
-			</div>
-		);
-	};
-
-	const SkeletonCard = () => {
-		return (
-			<div className="w-full px-4 py-8 border rounded-md shadow animate-pulse bg-white">
-				<div className="h-4 w-3/4 bg-gray-300 rounded mb-2.5"></div>
-				<div className="h-4 w-1/2 bg-gray-200 rounded mb-7"></div>
-
-				<div className="h-4 w-full bg-gray-200 rounded mb-1"></div>
-				<div className="h-4 w-5/6 bg-gray-200 rounded mb-3"></div>
-
-				<div className="flex gap-2 mb-7">
-					<div className="h-5 w-20 bg-gray-300 rounded-full"></div>
-					<div className="h-5 w-24 bg-gray-300 rounded-full"></div>
-					<div className="h-5 w-16 bg-gray-300 rounded-full"></div>
-				</div>
-
-				<div className="flex justify-between items-center">
-					<div className="h-6 w-20 bg-gray-300 rounded-lg"></div>
-					<div className="h-6 w-20 bg-gray-300 rounded-full"></div>
-				</div>
-			</div>
-		);
-	};
-
-	useEffect(() => {
-		const fetchData = async () => {
-			const response = await fetch("http://localhost:8000/subjects");
-			const data = await response.json();
-			setSubjectData(data.subjects);
-			setIsLoaded(true);
-		};
-		fetchData();
-	}, []);
-
-	useEffect(() => {
-		if (subjectData.length == 0) return;
-		const getRandomProfessor = () => {
-			const randomSubject1 =
-				subjectData[Math.floor(Math.random() * subjectData.length)];
-			return randomSubject1?.info.professors[
-				Math.floor(Math.random() * randomSubject1.info.professors.length)
-			];
-		};
-		const getRandomAssistant = () => {
-			const randomSubject2 =
-				subjectData[Math.floor(Math.random() * subjectData.length)];
-			return randomSubject2?.info.assistants[
-				Math.floor(Math.random() * randomSubject2.info.assistants.length)
-			];
-		};
-		let randomProfessor = "";
-		let randomAssistant = "";
-
-		while (!randomProfessor) randomProfessor = getRandomProfessor();
-		while (!randomAssistant) randomAssistant = getRandomAssistant();
-
-		setRandomStaff([randomProfessor, randomAssistant]);
-	}, [subjectData]);
-
-	const loadMore = () => {
-		setVisibleCourses((prev) => prev + 10);
-	};
-
-	const openSubjectDetails = (subject: Subject) => {
-		setSelectedSubject(subjectData[subject.id - 1]);
-		setShowModal(true);
-	};
-
-	const closeModal = () => {
-		setShowModal(false);
-	};
-	return (
-		<div className="mx-auto p-4 bg-white min-h-screen">
-			<h1 className="text-3xl font-bold mb-6">Преглед на сите предмети</h1>
-			<div className="flex flex-col md:flex-row gap-6">
-				<div className="w-full md:w-64 bg-gray-50 p-4 rounded-lg">
-					<FilterSidebar />
-					<div className="mb-6 relative">
-						<h3 className="mb-2 font-medium">Пребарај по професор: </h3>
-						<input
-							type="text"
-							placeholder={randomStaff[0]}
-							value={professorSearchTerm}
-							onChange={(e) => {
-								return setProfessorSearchTerm(e.target.value);
-							}}
-							className="w-full py-3 px-2 border border-gray-300 rounded-lg
-								focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
-						/>
-					</div>
-					<div className="mb-6 relative">
-						<h3 className="mb-2 font-medium">Пребарај по асистент: </h3>
-						<input
-							type="text"
-							placeholder={randomStaff[1]}
-							value={assistantSearchTerm}
-							onChange={(e) => {
-								return setAssistantSearchTerm(e.target.value);
-							}}
-							className="w-full py-3 px-2 border border-gray-300 rounded-lg
-								focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
-						/>
-					</div>
-				</div>
-				{/* Main content */}
-				<div className="flex-1">
-					{/* Search bar */}
-					<div className="mb-6 relative">
-						<input
-							type="text"
-							placeholder="Пребарувај предмети по име, код, опис"
-							value={searchTerm}
-							onChange={(e) => setSearchTerm(e.target.value)}
-							className="w-full p-3 pl-4 pr-12 border border-gray-300 rounded-lg 
-							focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
-						/>
-						{/* <button
-							className="absolute right-2 top-1/2 transform -translate-y-1/2
-						 bg-gray-800 text-white px-4 py-1 rounded-lg"
-						>
-							Избриши
-						</button> */}
-					</div>
-
-					{/* Course grid */}
-
-					{!isLoaded ? (
-						<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
-							{[...Array(9)].map((_, index) => (
-								<SkeletonCard key={index} />
-							))}
-						</div>
-					) : (
-						<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
-							{filteredSubjects.slice(0, visibleCourses).map((subject) => (
-								<div
-									key={subject.id}
-									className="border border-gray-200 rounded-lg overflow-hidden shadow-sm 
-                                    hover:shadow-md transition-shadow duration-200"
-								>
-									<div className="p-4 min-h-full flex flex-col">
-										<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>
-
-										<p className="text-gray-700 text-sm mb-4 line-clamp-2">
-											<strong>tuka treba abstract:</strong> Lorem ipsum dolor
-											sit, amet consectetur adipisicing elit. Et praesentium
-											dolores est animi officiis aperiam.
-											{subject.abstract}
-										</p>
-
-										<div className="flex flex-wrap gap-2 mb-4">
-											{/* these tags are for listing the domains a subject covers, ex. backend, AI ...*/}
-											{[
-												"Web Development",
-												"Machine Learning",
-												"Data Science",
-											].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">
-											{/* these tags could be used as certain flags for some subjects, like most picked subject, best match etc. */}
-											<div className="flex gap-3">
-												<div className="bg-red-500 px-1 py-1 rounded-full text-sm font-medium">
-													TAG1
-												</div>
-												<div className="bg-green-500 px-1 py-1 rounded-full text-sm font-medium">
-													TAG2
-												</div>
-											</div>
-											<button
-												onClick={() => openSubjectDetails(subject)}
-												className="flex items-center text-gray-700 hover:text-gray-900"
-											>
-												<img
-													src="src/assets/eye.svg"
-													className="w-4 h-4 mr-1"
-												/>
-												Погледни детали
-											</button>
-											{/* this could lead to a subject view page, for now there is no such thing*/}
-											{/* if implemented, tags should be moved elsewhere*/}
-											{/* <button
-											onClick={() => openCourseDetails(course)}
-											className="flex items-center text-blue-600 hover:text-blue-800"
-										>
-											Погледни детали
-											<svg
-												className="w-4 h-4 ml-1"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-												xmlns="http://www.w3.org/2000/svg"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M9 5l7 7-7 7"
-												/>
-											</svg>
-										</button> */}
-										</div>
-									</div>
-								</div>
-							))}
-						</div>
-					)}
-
-					{/* Load more button */}
-					{isLoaded && filteredSubjects.length > visibleCourses && (
-						<div className="mt-5 text-center">
-							<button
-								onClick={loadMore}
-								className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg font-medium transition-colors duration-200"
-							>
-								Погледни повеќе
-							</button>
-						</div>
-					)}
-
-					{/* No results message */}
-					{isLoaded && filteredSubjects.length === 0 && (
-						<div className="text-center py-12">
-							<p className="text-gray-500 text-lg">
-								Не постојат такви предмети
-							</p>
-							<button
-								onClick={resetFilters}
-								className="mt-2 text-blue-600 hover:text-blue-800"
-							>
-								Ресетирај филтри
-							</button>
-						</div>
-					)}
-				</div>
-			</div>
-			{showModal && selectedSubject && (
-				<SubjectModal
-					selectedSubject={selectedSubject}
-					closeModal={closeModal}
-				/>
-			)}
-		</div>
-	);
-};
-
-export default SubjectCatalog;
Index: frontend/src/components/SubjectCatalog/FilterSidebar.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/FilterSidebar.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/FilterSidebar.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,265 @@
+import { PROGRAMS } from "../../constants/subjects";
+import { Filters } from "./types";
+import { resetFilters } from "./utils";
+interface FilterSidebarProps {
+	setSearchTerm: (term: string) => void;
+	setProfessorSearchTerm: (term: string) => void;
+	setAssistantSearchTerm: (term: string) => void;
+	setFilters: (filters: (prev: Filters) => Filters) => void;
+	filters: Filters;
+}
+
+const FilterSidebar = ({
+	setSearchTerm,
+	setProfessorSearchTerm,
+	setAssistantSearchTerm,
+	setFilters,
+	filters,
+}: FilterSidebarProps) => {
+	return (
+		<div className="">
+			<div className="flex justify-between items-center mb-4">
+				<h2 className="text-lg font-semibold">Филтри</h2>
+				<button
+					onClick={() =>
+						resetFilters(
+							setSearchTerm,
+							setProfessorSearchTerm,
+							setAssistantSearchTerm,
+							setFilters
+						)
+					}
+					className="text-sm text-gray-600 hover:text-gray-900"
+				>
+					Избриши
+				</button>
+			</div>
+			<div className="mb-4">
+				{/* filter by season*/}
+				<div className="space-y-1 mb-4">
+					<h3 className="font-medium mb-2">Семестар</h3>
+					<div className="grid grid-cols-2">
+						{["Летен", "Зимски"].map((season) => {
+							const seasonValue = season === "Летен" ? "S" : "W";
+							return (
+								<div key={season} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="season"
+										id={seasonValue}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												season: prev.season === seasonValue ? "" : seasonValue,
+											}))
+										}
+										checked={filters.season === seasonValue}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label
+										htmlFor={seasonValue}
+										className="ml-2 text-sm text-gray-700"
+									>
+										{season}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+
+				{/* filter by semester*/}
+				<div className="space-y-1 mb-4">
+					{/* <h3 className="font-medium mb-2">Семестар</h3> */}
+					<div className="grid grid-cols-4 gap-2">
+						{Array.from(Array(8)).map((_, index) => {
+							const i = index + 1;
+							return (
+								<div key={i} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="season"
+										id={`s${i}`}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												semester: prev.semester.includes(i)
+													? prev.semester.filter((item) => item !== i)
+													: [...prev.semester, i],
+											}))
+										}
+										checked={filters.semester.includes(i)}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label htmlFor={`s${i}`} className="text-sm text-gray-700">
+										{i}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+				{/* filter by level */}
+				<div className="space-y-1 mb-4">
+					<h3 className="font-medium mb-2">Ниво</h3>
+					<div className="grid grid-cols-3">
+						{Array.from(Array(3)).map((_, index) => {
+							const i = index + 1;
+							const level = `L${i}`;
+							return (
+								<div key={i} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="level"
+										id={level}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												level: prev.level.includes(i)
+													? prev.level.filter((item) => item !== i)
+													: [...prev.level, i],
+											}))
+										}
+										checked={filters.level.includes(i)}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label
+										htmlFor={`s${level}`}
+										className="text-sm text-gray-700"
+									>
+										{level}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+				{/* filter by activation*/}
+				<div className="space-y-1 mb-4">
+					<h3 className="font-medium mb-2">Активирани</h3>
+					<div className="grid grid-cols-2">
+						{["Активирани", "Неактивирани"].map((value) => {
+							const activeValue =
+								value === "Активирани" ? "activated" : "not_activated";
+							return (
+								<div key={activeValue} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="season"
+										id={activeValue}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												activated:
+													prev.activated === activeValue ? "" : activeValue,
+											}))
+										}
+										checked={filters.activated === activeValue}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label
+										htmlFor={activeValue}
+										className="ml-2 text-sm text-gray-700"
+									>
+										{value}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+				{/* filter by mandatoryFor */}
+				<div className="space-y-1 mb-4">
+					<h3 className="font-medium mb-2">Задолжителен за:</h3>
+					<div className="grid grid-cols-3 gap-2">
+						{PROGRAMS.map((program) => {
+							const programName = program.replace(/\d+$/, "");
+							return (
+								<div key={program} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="level"
+										id={program}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												mandatoryFor: prev.mandatoryFor.includes(program)
+													? prev.mandatoryFor.filter((item) => item !== program)
+													: [...prev.mandatoryFor, program],
+											}))
+										}
+										checked={filters.mandatoryFor.includes(program)}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label
+										htmlFor={`s${program}`}
+										className="text-sm text-gray-700"
+									>
+										{programName}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+				{/* filter by electiveFor */}
+				<div className="space-y-1 mb-6">
+					<h3 className="font-medium mb-2">Изборен за:</h3>
+					<div className="grid grid-cols-3 gap-2">
+						{PROGRAMS.map((program) => {
+							const programName = program.replace(/\d+$/, "");
+							return (
+								<div key={program} className="flex items-center space-x-2">
+									<input
+										type="checkbox"
+										name="level"
+										id={program}
+										onChange={() =>
+											setFilters((prev) => ({
+												...prev,
+												electiveFor: prev.electiveFor.includes(program)
+													? prev.electiveFor.filter((item) => item !== program)
+													: [...prev.electiveFor, program],
+											}))
+										}
+										checked={filters.electiveFor.includes(program)}
+										className="h-4 w-4 rounded border-gray-300 text-blue-600"
+									/>
+									<label
+										htmlFor={`s${program}`}
+										className="text-sm text-gray-700"
+									>
+										{programName}
+									</label>
+								</div>
+							);
+						})}
+					</div>
+				</div>
+				{/* filter by prereq */}
+				<div className="space-y-1 mb-4">
+					<div className="flex items-center space-x-2">
+						<input
+							type="checkbox"
+							name="prereq"
+							id="prereq"
+							onChange={() =>
+								setFilters((prev) => ({
+									...prev,
+									hasPrerequisites: !prev.hasPrerequisites,
+								}))
+							}
+							checked={filters.hasPrerequisites}
+							className="h-4 w-4 rounded border-gray-300 text-blue-600"
+						/>
+						<label htmlFor={"prereq"} className="text-sm text-gray-700">
+							Предметот нема предуслови
+						</label>
+					</div>
+				</div>
+			</div>
+		</div>
+	);
+};
+
+export default FilterSidebar;
Index: frontend/src/components/SubjectCatalog/SkeletonCard.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SkeletonCard.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/SkeletonCard.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,23 @@
+const SkeletonCard = () => {
+	return (
+		<div className="w-full px-4 py-8 border rounded-md shadow animate-pulse bg-white">
+			<div className="h-4 w-3/4 bg-gray-300 rounded mb-2.5"></div>
+			<div className="h-4 w-1/2 bg-gray-200 rounded mb-7"></div>
+
+			<div className="h-4 w-full bg-gray-200 rounded mb-1"></div>
+			<div className="h-4 w-5/6 bg-gray-200 rounded mb-3"></div>
+
+			<div className="flex gap-2 mb-7">
+				<div className="h-5 w-20 bg-gray-300 rounded-full"></div>
+				<div className="h-5 w-24 bg-gray-300 rounded-full"></div>
+				<div className="h-5 w-16 bg-gray-300 rounded-full"></div>
+			</div>
+
+			<div className="flex justify-between items-center">
+				<div className="h-6 w-20 bg-gray-300 rounded-lg"></div>
+				<div className="h-6 w-20 bg-gray-300 rounded-full"></div>
+			</div>
+		</div>
+	);
+};
+export default SkeletonCard;
Index: frontend/src/components/SubjectCatalog/StaffSearch.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/StaffSearch.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/StaffSearch.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,48 @@
+interface StaffSearchProps {
+	randomStaff: string[];
+	professorSearchTerm: string;
+	setProfessorSearchTerm: (val: string) => void;
+	assistantSearchTerm: string;
+	setAssistantSearchTerm: (val: string) => void;
+}
+
+function StaffSearch({
+	randomStaff,
+	professorSearchTerm,
+	setProfessorSearchTerm,
+	assistantSearchTerm,
+	setAssistantSearchTerm,
+}: StaffSearchProps) {
+	return (
+		<>
+			<div className="mb-6 relative">
+				<h3 className="mb-2 font-medium">Пребарај по професор: </h3>
+				<input
+					type="text"
+					placeholder={randomStaff[0]}
+					value={professorSearchTerm}
+					onChange={(e) => {
+						return setProfessorSearchTerm(e.target.value);
+					}}
+					className="w-full py-3 px-2 border border-gray-300 rounded-lg
+								focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
+				/>
+			</div>
+			<div className="mb-6 relative">
+				<h3 className="mb-2 font-medium">Пребарај по асистент: </h3>
+				<input
+					type="text"
+					placeholder={randomStaff[1]}
+					value={assistantSearchTerm}
+					onChange={(e) => {
+						return setAssistantSearchTerm(e.target.value);
+					}}
+					className="w-full py-3 px-2 border border-gray-300 rounded-lg
+								focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
+				/>
+			</div>
+		</>
+	);
+}
+
+export default StaffSearch;
Index: frontend/src/components/SubjectCatalog/SubjectCatalog.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/SubjectCatalog.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,166 @@
+import { useEffect, useState } from "react";
+import FilterSidebar from "./FilterSidebar";
+import SkeletonCard from "./SkeletonCard";
+import StaffSearch from "./StaffSearch";
+import SubjectList from "./SubjectList";
+import SubjectModal from "./SubjectModal";
+import { Filters, Subject } from "./types";
+import { filterSubjects, getRandomStaff, resetFilters } from "./utils";
+const SubjectCatalog = () => {
+	const [visibleCourses, setVisibleCourses] = useState<number>(10);
+	const [searchTerm, setSearchTerm] = useState<string>("");
+	const [professorSearchTerm, setProfessorSearchTerm] = useState<string>("");
+	const [assistantSearchTerm, setAssistantSearchTerm] = useState<string>("");
+	const [selectedSubject, setSelectedSubject] = useState<Subject | null>(null);
+	const [subjectData, setSubjectData] = useState<Subject[]>([]);
+	const [isLoaded, setIsLoaded] = useState(false);
+	const [randomStaff, setRandomStaff] = useState(["", ""]);
+	const [showModal, setShowModal] = useState(false);
+	const [filters, setFilters] = useState<Filters>({
+		season: "",
+		semester: [],
+		level: [],
+		activated: "",
+		mandatoryFor: [],
+		electiveFor: [],
+		professors: [],
+		assistants: [],
+		hasPrerequisites: false,
+	});
+
+	const filteredSubjects: Subject[] = filterSubjects({
+		subjectData,
+		searchTerm,
+		professorSearchTerm,
+		assistantSearchTerm,
+		filters,
+	});
+
+	useEffect(() => {
+		const fetchData = async () => {
+			const response = await fetch("http://localhost:8000/subjects");
+			const data = await response.json();
+			setSubjectData(data.subjects);
+			setIsLoaded(true);
+		};
+		fetchData();
+	}, []);
+
+	useEffect(() => {
+		getRandomStaff(subjectData, setRandomStaff);
+	}, [subjectData]);
+
+	const loadMore = () => {
+		setVisibleCourses((prev) => prev + 10);
+	};
+
+	const openSubjectDetails = (subject: Subject) => {
+		setSelectedSubject(subjectData[subject.id - 1]);
+		setShowModal(true);
+	};
+
+	const closeModal = () => {
+		setShowModal(false);
+	};
+	return (
+		<div className="mx-auto p-4 bg-white min-h-screen">
+			<h1 className="text-3xl font-bold mb-6">Преглед на сите предмети</h1>
+			<div className="flex flex-col md:flex-row gap-6">
+				<div className="w-full md:w-64 bg-gray-50 p-4 rounded-lg">
+					<FilterSidebar
+						setSearchTerm={setSearchTerm}
+						setProfessorSearchTerm={setProfessorSearchTerm}
+						setAssistantSearchTerm={setAssistantSearchTerm}
+						setFilters={setFilters}
+						filters={filters}
+					/>
+					<StaffSearch
+						randomStaff={randomStaff}
+						professorSearchTerm={professorSearchTerm}
+						assistantSearchTerm={assistantSearchTerm}
+						setProfessorSearchTerm={setProfessorSearchTerm}
+						setAssistantSearchTerm={setAssistantSearchTerm}
+					/>
+				</div>
+				{/* Main content */}
+				<div className="flex-1">
+					{/* Search bar */}
+					<div className="mb-6 relative">
+						<input
+							type="text"
+							placeholder="Пребарувај предмети по име, код, опис"
+							value={searchTerm}
+							onChange={(e) => setSearchTerm(e.target.value)}
+							className="w-full p-3 pl-4 pr-12 border border-gray-300 rounded-lg 
+							focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
+						/>
+						{/* <button
+							className="absolute right-2 top-1/2 transform -translate-y-1/2
+						 bg-gray-800 text-white px-4 py-1 rounded-lg"
+						>
+							Избриши
+						</button> */}
+					</div>
+
+					{/* Course grid */}
+
+					{!isLoaded ? (
+						<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
+							{[...Array(9)].map((_, index) => (
+								<SkeletonCard key={index} />
+							))}
+						</div>
+					) : (
+						<SubjectList
+							filteredSubjects={filteredSubjects}
+							visibleCourses={visibleCourses}
+							openSubjectDetails={openSubjectDetails}
+						/>
+					)}
+
+					{/* Load more button */}
+					{isLoaded && filteredSubjects.length > visibleCourses && (
+						<div className="mt-5 text-center">
+							<button
+								onClick={loadMore}
+								className="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg font-medium transition-colors duration-200"
+							>
+								Погледни повеќе
+							</button>
+						</div>
+					)}
+
+					{/* No results message */}
+					{isLoaded && filteredSubjects.length === 0 && (
+						<div className="text-center py-12">
+							<p className="text-gray-500 text-lg">
+								Не постојат такви предмети
+							</p>
+							<button
+								onClick={() =>
+									resetFilters(
+										setSearchTerm,
+										setProfessorSearchTerm,
+										setAssistantSearchTerm,
+										setFilters
+									)
+								}
+								className="mt-2 text-blue-600 hover:text-blue-800"
+							>
+								Ресетирај филтри
+							</button>
+						</div>
+					)}
+				</div>
+			</div>
+			{showModal && selectedSubject && (
+				<SubjectModal
+					selectedSubject={selectedSubject}
+					closeModal={closeModal}
+				/>
+			)}
+		</div>
+	);
+};
+
+export default SubjectCatalog;
Index: frontend/src/components/SubjectCatalog/SubjectList.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/SubjectList.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,98 @@
+import { Subject } from "./types";
+
+interface SubjectListProps {
+	filteredSubjects: Subject[];
+	visibleCourses: number;
+	openSubjectDetails: (subject: Subject) => void;
+}
+
+const SubjectList = ({
+	filteredSubjects,
+	visibleCourses,
+	openSubjectDetails,
+}: SubjectListProps) => {
+	return (
+		<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
+			{filteredSubjects.slice(0, visibleCourses).map((subject) => (
+				<div
+					key={subject.id}
+					className="border border-gray-200 rounded-lg overflow-hidden shadow-sm 
+                                    hover:shadow-md transition-shadow duration-200"
+				>
+					<div className="p-4 min-h-full flex flex-col">
+						<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>
+
+						<p className="text-gray-700 text-sm mb-4 line-clamp-2">
+							<strong>tuka treba abstract:</strong> Lorem ipsum dolor sit, amet
+							consectetur adipisicing elit. Et praesentium dolores est animi
+							officiis aperiam.
+							{subject.abstract}
+						</p>
+
+						<div className="flex flex-wrap gap-2 mb-4">
+							{/* these tags are for listing the domains a subject covers, ex. backend, AI ...*/}
+							{["Web Development", "Machine Learning", "Data Science"].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">
+							{/* these tags could be used as certain flags for some subjects, like most picked subject, best match etc. */}
+							<div className="flex gap-3">
+								<div className="bg-red-500 px-1 py-1 rounded-full text-sm font-medium">
+									TAG1
+								</div>
+								<div className="bg-green-500 px-1 py-1 rounded-full text-sm font-medium">
+									TAG2
+								</div>
+							</div>
+							<button
+								onClick={() => openSubjectDetails(subject)}
+								className="flex items-center text-gray-700 hover:text-gray-900"
+							>
+								<img src="src/assets/eye.svg" className="w-4 h-4 mr-1" />
+								Погледни детали
+							</button>
+							{/* this could lead to a subject view page, for now there is no such thing*/}
+							{/* if implemented, tags should be moved elsewhere*/}
+							{/* <button
+											onClick={() => openCourseDetails(course)}
+											className="flex items-center text-blue-600 hover:text-blue-800"
+										>
+											Погледни детали
+											<svg
+												className="w-4 h-4 ml-1"
+												fill="none"
+												stroke="currentColor"
+												viewBox="0 0 24 24"
+												xmlns="http://www.w3.org/2000/svg"
+											>
+												<path
+													strokeLinecap="round"
+													strokeLinejoin="round"
+													strokeWidth={2}
+													d="M9 5l7 7-7 7"
+												/>
+											</svg>
+										</button> */}
+						</div>
+					</div>
+				</div>
+			))}
+		</div>
+	);
+};
+
+export default SubjectList;
Index: frontend/src/components/SubjectCatalog/SubjectModal.tsx
===================================================================
--- frontend/src/components/SubjectCatalog/SubjectModal.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/SubjectModal.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,187 @@
+import { Subject } from "./types";
+
+interface SubjectModalProps {
+	selectedSubject: Subject;
+	closeModal: () => void;
+}
+
+function SubjectModal({ selectedSubject, closeModal }: SubjectModalProps) {
+	return (
+		<>
+			<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
+				<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
+					<div className="p-6">
+						<div className="flex justify-between items-start mb-4">
+							<div>
+								<h2 className="text-2xl font-bold">{selectedSubject.name}</h2>
+								<p className="text-gray-600">{selectedSubject.code}</p>
+							</div>
+							<button
+								onClick={closeModal}
+								className="text-gray-400 hover:text-gray-600"
+							>
+								<svg
+									className="w-6 h-6"
+									fill="none"
+									stroke="currentColor"
+									viewBox="0 0 24 24"
+									xmlns="http://www.w3.org/2000/svg"
+								>
+									<path
+										strokeLinecap="round"
+										strokeLinejoin="round"
+										strokeWidth={2}
+										d="M6 18L18 6M6 6l12 12"
+									/>
+								</svg>
+							</button>
+						</div>
+
+						<div className="mb-4">
+							<p className="text-gray-700">
+								<strong>tuka ide abstract</strong> Lorem ipsum dolor, sit amet
+								consectetur adipisicing elit. Quia, ad repellat consectetur
+								laboriosam aperiam cumque.
+								{selectedSubject.abstract}
+							</p>
+						</div>
+
+						<div className="mb-2">
+							<h3 className="text-lg font-medium">Професори:</h3>
+							<p>
+								{selectedSubject.info.professors.length == 0
+									? "Нема одредени професори"
+									: selectedSubject.info.professors.join(", ")}
+							</p>
+						</div>
+						<div className="mb-4">
+							<h3 className="text-lg font-medium">Асистенти:</h3>
+							<p>
+								{selectedSubject.info.assistants.length == 0
+									? "Нема одредени асистенти"
+									: selectedSubject.info.assistants.join(", ")}
+							</p>
+						</div>
+
+						<div className="bg-gray-50 rounded-lg p-4 mb-3">
+							<h3 className="text-lg font-medium mb-4">
+								Информации за предметот
+							</h3>
+
+							<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+								<div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">
+												Препорачан семестар
+											</p>
+											<p className="font-medium">
+												{selectedSubject.info.semester}
+											</p>
+										</div>
+									</div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">Зимски / Летен</p>
+											<p className="font-medium">
+												{selectedSubject.info.season == "S"
+													? "Летен"
+													: "Зимски"}
+											</p>
+										</div>
+									</div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">Ниво</p>
+											<p className="font-medium">
+												L{selectedSubject.info.level}
+											</p>
+										</div>
+									</div>
+								</div>
+								<div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">Задолжителен за:</p>
+											<p className="font-medium">
+												{selectedSubject.info.mandatory_for.length == 0
+													? "Не е задолжителен предмет"
+													: selectedSubject.info.mandatory_for
+															.map((s) => s.replace(/\d+$/, ""))
+															.join(", ")}
+											</p>
+										</div>
+									</div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">Изборен за:</p>
+											<p className="font-medium">
+												{selectedSubject.info.elective_for.length == 0
+													? "Не е изборен предмет"
+													: selectedSubject.info.elective_for
+															.map((s) => s.replace(/\d+$/, ""))
+															.join(", ")}
+											</p>
+										</div>
+									</div>
+									<div className="flex items-center mb-3">
+										<div>
+											<p className="text-sm text-gray-500">Предуслови:</p>
+											<p className="font-medium">
+												{selectedSubject.info.prerequisite.length == 0
+													? "Нема предуслов"
+													: selectedSubject.info.prerequisite}
+											</p>
+										</div>
+									</div>
+								</div>
+							</div>
+						</div>
+						<div>
+							{selectedSubject.info.participants[0] == 0 ? (
+								<div className="bg-red-500 py-3 pl-2 rounded-md">
+									Овој предмет не бил активиран минатиот семестар.
+								</div>
+							) : (
+								<p>{`Овој предмет минатиот семестар бил запишан од
+									${selectedSubject.info.participants[0]} студенти.`}</p>
+							)}
+						</div>
+						<div className="mt-6">
+							<h3 className="text-lg font-medium mb-2">Тагови</h3>
+							<div className="flex flex-wrap gap-2">
+								{/* TODO: change this when real tags are added in the database*/}
+								{["Web Development", "Machine Learning", "Data Science"].map(
+									(tag) => (
+										<span
+											key={tag}
+											className="bg-gray-100 text-gray-800 px-3 py-1 rounded-full"
+										>
+											{tag}
+										</span>
+									)
+								)}
+							</div>
+						</div>
+
+						<div className="mt-8 flex justify-end space-x-3">
+							<button
+								onClick={closeModal}
+								className="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50"
+							>
+								Затвори
+							</button>
+							{/* <button
+									onClick={closeModal}
+									className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
+								>
+									Погледни детали
+								</button> */}
+						</div>
+					</div>
+				</div>
+			</div>
+		</>
+	);
+}
+export default SubjectModal;
Index: frontend/src/components/SubjectCatalog/types.ts
===================================================================
--- frontend/src/components/SubjectCatalog/types.ts	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/types.ts	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,38 @@
+import { PROGRAMS } from "../../constants/subjects";
+
+export interface Subject {
+	id: number;
+	code: string;
+	name: string;
+	abstract: string;
+	info: SubjectInfo;
+}
+
+export interface SubjectInfo {
+	level: number;
+	short: string;
+	prerequisite: string;
+	activated: boolean;
+	participants: number[];
+	mandatory: boolean;
+	mandatory_for: Programs[];
+	semester: number;
+	season: string;
+	elective_for: Programs[];
+	professors: string[];
+	assistants: string[];
+}
+
+export type Filters = {
+	season: "W" | "S" | "";
+	semester: number[];
+	level: number[];
+	activated: "activated" | "not_activated" | "";
+	mandatoryFor: Programs[];
+	electiveFor: Programs[];
+	professors: string[];
+	assistants: string[];
+	hasPrerequisites: boolean;
+};
+
+export type Programs = (typeof PROGRAMS)[number];
Index: frontend/src/components/SubjectCatalog/utils.ts
===================================================================
--- frontend/src/components/SubjectCatalog/utils.ts	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
+++ frontend/src/components/SubjectCatalog/utils.ts	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -0,0 +1,138 @@
+import { Filters, Programs, Subject } from "./types";
+
+interface filteredSubjectsParams {
+	subjectData: Subject[];
+	searchTerm: string;
+	professorSearchTerm: string;
+	assistantSearchTerm: string;
+	filters: {
+		season: "W" | "S" | "";
+		semester: number[];
+		level: number[];
+		activated: "activated" | "not_activated" | "";
+		mandatoryFor: Programs[];
+		electiveFor: Programs[];
+		professors: string[];
+		assistants: string[];
+		hasPrerequisites: boolean;
+	};
+}
+
+export const filterSubjects = ({
+	subjectData,
+	searchTerm,
+	professorSearchTerm,
+	assistantSearchTerm,
+	filters,
+}: filteredSubjectsParams) =>
+	subjectData.filter((subject) => {
+		const searchMatches =
+			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.info.season;
+
+		const semesterMatches =
+			filters.semester.length === 0 ||
+			filters.semester.includes(subject.info.semester);
+
+		const levelMatches =
+			filters.level.length === 0 || filters.level.includes(subject.info.level);
+
+		const activatedMatches =
+			filters.activated == "" ||
+			(filters.activated == "activated" && subject.info.activated) ||
+			(filters.activated == "not_activated" && !subject.info.activated);
+
+		const mandatoryMatches =
+			filters.mandatoryFor.length === 0 ||
+			subject.info.mandatory_for.some((item) =>
+				filters.mandatoryFor.includes(item)
+			);
+
+		const electiveMatches =
+			filters.electiveFor.length === 0 ||
+			subject.info.elective_for.some((item) =>
+				filters.electiveFor.includes(item)
+			);
+
+		const professorsMatches =
+			professorSearchTerm == "" ||
+			subject.info.professors.some((item) =>
+				item.toLowerCase().includes(professorSearchTerm.toLowerCase())
+			);
+
+		const assistantsMatches =
+			assistantSearchTerm == "" ||
+			subject.info.assistants.some((item) =>
+				item.toLowerCase().includes(assistantSearchTerm.toLowerCase())
+			);
+
+		const prerequisitesMatch =
+			!filters.hasPrerequisites || subject.info.prerequisite == "";
+
+		return (
+			searchMatches &&
+			seasonMatches &&
+			semesterMatches &&
+			levelMatches &&
+			activatedMatches &&
+			mandatoryMatches &&
+			electiveMatches &&
+			professorsMatches &&
+			assistantsMatches &&
+			prerequisitesMatch
+		);
+	});
+
+export const resetFilters = (
+	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,
+	}));
+};
+
+export const getRandomStaff = (
+	subjectData: Subject[],
+	setRandomStaff: ([]: string[]) => void
+) => {
+	if (subjectData.length == 0) return;
+	const getRandomProfessor = () => {
+		const randomSubject1 =
+			subjectData[Math.floor(Math.random() * subjectData.length)];
+		return randomSubject1?.info.professors[
+			Math.floor(Math.random() * randomSubject1.info.professors.length)
+		];
+	};
+	const getRandomAssistant = () => {
+		const randomSubject2 =
+			subjectData[Math.floor(Math.random() * subjectData.length)];
+		return randomSubject2?.info.assistants[
+			Math.floor(Math.random() * randomSubject2.info.assistants.length)
+		];
+	};
+	let randomProfessor = "";
+	let randomAssistant = "";
+
+	while (!randomProfessor) randomProfessor = getRandomProfessor();
+	while (!randomAssistant) randomAssistant = getRandomAssistant();
+
+	setRandomStaff([randomProfessor, randomAssistant]);
+};
Index: ontend/src/components/SubjectModal.tsx
===================================================================
--- frontend/src/components/SubjectModal.tsx	(revision ff9e2e0b894acd6b30ee578a2ca46b95813ccdeb)
+++ 	(revision )
@@ -1,187 +1,0 @@
-import { Subject } from "../types";
-
-interface SubjectModalProps {
-	selectedSubject: Subject;
-	closeModal: () => void;
-}
-
-function SubjectModal({ selectedSubject, closeModal }: SubjectModalProps) {
-	return (
-		<>
-			<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
-				<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
-					<div className="p-6">
-						<div className="flex justify-between items-start mb-4">
-							<div>
-								<h2 className="text-2xl font-bold">{selectedSubject.name}</h2>
-								<p className="text-gray-600">{selectedSubject.code}</p>
-							</div>
-							<button
-								onClick={closeModal}
-								className="text-gray-400 hover:text-gray-600"
-							>
-								<svg
-									className="w-6 h-6"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-									xmlns="http://www.w3.org/2000/svg"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={2}
-										d="M6 18L18 6M6 6l12 12"
-									/>
-								</svg>
-							</button>
-						</div>
-
-						<div className="mb-4">
-							<p className="text-gray-700">
-								<strong>tuka ide abstract</strong> Lorem ipsum dolor, sit amet
-								consectetur adipisicing elit. Quia, ad repellat consectetur
-								laboriosam aperiam cumque.
-								{selectedSubject.abstract}
-							</p>
-						</div>
-
-						<div className="mb-2">
-							<h3 className="text-lg font-medium">Професори:</h3>
-							<p>
-								{selectedSubject.info.professors.length == 0
-									? "Нема одредени професори"
-									: selectedSubject.info.professors.join(", ")}
-							</p>
-						</div>
-						<div className="mb-4">
-							<h3 className="text-lg font-medium">Асистенти:</h3>
-							<p>
-								{selectedSubject.info.assistants.length == 0
-									? "Нема одредени асистенти"
-									: selectedSubject.info.assistants.join(", ")}
-							</p>
-						</div>
-
-						<div className="bg-gray-50 rounded-lg p-4 mb-3">
-							<h3 className="text-lg font-medium mb-4">
-								Информации за предметот
-							</h3>
-
-							<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
-								<div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">
-												Препорачан семестар
-											</p>
-											<p className="font-medium">
-												{selectedSubject.info.semester}
-											</p>
-										</div>
-									</div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">Зимски / Летен</p>
-											<p className="font-medium">
-												{selectedSubject.info.season == "S"
-													? "Летен"
-													: "Зимски"}
-											</p>
-										</div>
-									</div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">Ниво</p>
-											<p className="font-medium">
-												L{selectedSubject.info.level}
-											</p>
-										</div>
-									</div>
-								</div>
-								<div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">Задолжителен за:</p>
-											<p className="font-medium">
-												{selectedSubject.info.mandatory_for.length == 0
-													? "Не е задолжителен предмет"
-													: selectedSubject.info.mandatory_for
-															.map((s) => s.replace(/\d+$/, ""))
-															.join(", ")}
-											</p>
-										</div>
-									</div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">Изборен за:</p>
-											<p className="font-medium">
-												{selectedSubject.info.elective_for.length == 0
-													? "Не е изборен предмет"
-													: selectedSubject.info.elective_for
-															.map((s) => s.replace(/\d+$/, ""))
-															.join(", ")}
-											</p>
-										</div>
-									</div>
-									<div className="flex items-center mb-3">
-										<div>
-											<p className="text-sm text-gray-500">Предуслови:</p>
-											<p className="font-medium">
-												{selectedSubject.info.prerequisite.length == 0
-													? "Нема предуслов"
-													: selectedSubject.info.prerequisite}
-											</p>
-										</div>
-									</div>
-								</div>
-							</div>
-						</div>
-						<div>
-							{selectedSubject.info.participants[0] == 0 ? (
-								<div className="bg-red-500 py-3 pl-2 rounded-md">
-									Овој предмет не бил активиран минатиот семестар.
-								</div>
-							) : (
-								<p>{`Овој предмет минатиот семестар бил запишан од
-									${selectedSubject.info.participants[0]} студенти.`}</p>
-							)}
-						</div>
-						<div className="mt-6">
-							<h3 className="text-lg font-medium mb-2">Тагови</h3>
-							<div className="flex flex-wrap gap-2">
-								{/* TODO: change this when real tags are added in the database*/}
-								{["Web Development", "Machine Learning", "Data Science"].map(
-									(tag) => (
-										<span
-											key={tag}
-											className="bg-gray-100 text-gray-800 px-3 py-1 rounded-full"
-										>
-											{tag}
-										</span>
-									)
-								)}
-							</div>
-						</div>
-
-						<div className="mt-8 flex justify-end space-x-3">
-							<button
-								onClick={closeModal}
-								className="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50"
-							>
-								Затвори
-							</button>
-							{/* <button
-									onClick={closeModal}
-									className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
-								>
-									Погледни детали
-								</button> */}
-						</div>
-					</div>
-				</div>
-			</div>
-		</>
-	);
-}
-export default SubjectModal;
Index: frontend/src/pages/SubjectsView.tsx
===================================================================
--- frontend/src/pages/SubjectsView.tsx	(revision ff9e2e0b894acd6b30ee578a2ca46b95813ccdeb)
+++ frontend/src/pages/SubjectsView.tsx	(revision b0495c9fc7619057d3883c0985b9723a41f5dabd)
@@ -1,3 +1,3 @@
-import SubjectCatalog from "../components/SubjectCatalog";
+import SubjectCatalog from "../components/SubjectCatalog/SubjectCatalog";
 
 function SubjectsView() {
Index: ontend/src/types.ts
===================================================================
--- frontend/src/types.ts	(revision ff9e2e0b894acd6b30ee578a2ca46b95813ccdeb)
+++ 	(revision )
@@ -1,26 +1,0 @@
-import { PROGRAMS } from "./constants/subjects";
-
-export interface Subject {
-	id: number;
-	code: string;
-	name: string;
-	abstract: string;
-	info: SubjectInfo;
-}
-
-export interface SubjectInfo {
-	level: number;
-	short: string;
-	prerequisite: string;
-	activated: boolean;
-	participants: number[];
-	mandatory: boolean;
-	mandatory_for: Programs[];
-	semester: number;
-	season: string;
-	elective_for: Programs[];
-	professors: string[];
-	assistants: string[];
-}
-
-export type Programs = (typeof PROGRAMS)[number];
