Index: frontend/src/components/LanguageSwitcher.tsx
===================================================================
--- frontend/src/components/LanguageSwitcher.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/LanguageSwitcher.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,29 @@
+"use client";
+import { useTranslation } from 'react-i18next';
+
+export default function LanguageSwitcher() {
+  const { i18n } = useTranslation();
+
+  const changeLanguage = (lng: string) => {
+    i18n.changeLanguage(lng);
+  };
+
+  return (
+    <div className="flex gap-2 items-center">
+      <button
+        onClick={() => changeLanguage('mk')}
+        className={`px-3 py-1 rounded border-2 text-sm font-semibold transition-all duration-150 ${i18n.language === 'mk' ? 'border-primary text-primary bg-accent' : 'border-border text-muted-foreground bg-card hover:border-primary hover:text-primary'}`}
+        aria-label="Macedonian"
+      >
+        MK
+      </button>
+      <button
+        onClick={() => changeLanguage('en')}
+        className={`px-3 py-1 rounded border-2 text-sm font-semibold transition-all duration-150 ${i18n.language === 'en' ? 'border-primary text-primary bg-accent' : 'border-border text-muted-foreground bg-card hover:border-primary hover:text-primary'}`}
+        aria-label="English"
+      >
+        EN
+      </button>
+    </div>
+  );
+}
Index: frontend/src/components/admin-navbar.tsx
===================================================================
--- frontend/src/components/admin-navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/admin-navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,67 @@
+"use client";
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faBook, faCalendarPlus, faChalkboardUser, faBars, faTimes, faUserGear } from "@fortawesome/free-solid-svg-icons";
+import Link from "next/link";
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+
+const AdminNavbar = () => {
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const toggleMenu = () => setIsMenuOpen((v) => !v);
+
+  const { t } = useTranslation();
+  const menuItems = [
+    { icon: faBook, label: t("admin_subjects"), href: "/admin/subjects" },
+    { icon: faCalendarPlus, label: t("admin_semesters"), href: "/admin/semesters" },
+    { icon: faChalkboardUser, label: t("admin_schedule"), href: "/admin/schedule" },
+  ];
+
+  return (
+    <>
+      {/* Desktop Navbar */}
+      <nav className="hidden md:flex flex-row gap-2 justify-evenly bg-primary text-primary-foreground p-7 rounded-xl my-5 text-xl">
+        {menuItems.map((item) => (
+          <Link key={item.href} href={item.href}>
+            <div className="group flex flex-row items-center gap-2 px-3 py-2 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground hover:scale-105 hover:shadow-lg">
+              <FontAwesomeIcon icon={item.icon} className="transition-transform duration-300 group-hover:rotate-12" />
+              <span>{item.label}</span>
+            </div>
+          </Link>
+        ))}
+      </nav>
+
+      {/* Mobile Navbar */}
+      <nav className="md:hidden bg-primary text-primary-foreground rounded-xl my-5">
+        <div className="flex justify-between items-center p-4">
+          <div className="flex items-center gap-2 text-xl font-bold">
+            <FontAwesomeIcon icon={faUserGear} className="text-xl" />
+            {t("admin_portal")}
+          </div>
+          <button
+            onClick={toggleMenu}
+            className="p-2 rounded-lg hover:bg-card hover:text-card-foreground transition-colors duration-300"
+            aria-label="Toggle menu"
+          >
+            <FontAwesomeIcon icon={isMenuOpen ? faTimes : faBars} className="text-xl transition-transform duration-300" />
+          </button>
+        </div>
+
+        <div className={`overflow-hidden transition-all duration-300 ease-in-out ${isMenuOpen ? "max-h-64 opacity-100" : "max-h-0 opacity-0"}`}>
+          <div className="px-4 pb-4 space-y-2">
+            {menuItems.map((item) => (
+              <Link key={item.href} href={item.href}>
+                <div className="group flex flex-row items-center gap-3 px-3 py-3 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground">
+                  <FontAwesomeIcon icon={item.icon} className="transition-transform duration-300 group-hover:rotate-12" />
+                  <span className="text-lg">{item.label}</span>
+                </div>
+              </Link>
+            ))}
+          </div>
+        </div>
+      </nav>
+    </>
+  );
+};
+
+export default AdminNavbar;
Index: frontend/src/components/contact-bubble.tsx
===================================================================
--- frontend/src/components/contact-bubble.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/contact-bubble.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,176 @@
+"use client"
+
+import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faEnvelope, faTimes, faPaperPlane, faSpinner } from '@fortawesome/free-solid-svg-icons';
+
+export default function ContactBubble() {
+  const { t } = useTranslation();
+  const [isOpen, setIsOpen] = useState(false);
+  const [isSending, setIsSending] = useState(false);
+  const [sent, setSent] = useState(false);
+  const [form, setForm] = useState({ name: '', email: '', subject: '', message: '' });
+
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
+    setForm((prev) => ({ ...prev, [e.target.name]: e.target.value }));
+  };
+
+  const handleSubmit = async (e: React.FormEvent) => {
+    e.preventDefault();
+    setIsSending(true);
+    // Simulate sending
+    await new Promise((r) => setTimeout(r, 1200));
+    setIsSending(false);
+    setSent(true);
+    setTimeout(() => {
+      setSent(false);
+      setIsOpen(false);
+      setForm({ name: '', email: '', subject: '', message: '' });
+    }, 2500);
+  };
+
+  return (
+    <>
+      {/* Floating bubble */}
+      <button
+        onClick={() => setIsOpen(true)}
+        className={`fixed bottom-6 right-6 z-50 flex items-center gap-2 bg-primary hover:bg-blue-700 text-white px-5 py-3 rounded-full shadow-lg transition-all duration-300 hover:scale-105 hover:shadow-xl ${isOpen ? 'scale-0 opacity-0' : 'scale-100 opacity-100'}`}
+        aria-label={t('contact_us', 'Контактирај нè')}
+      >
+        <FontAwesomeIcon icon={faEnvelope} className="w-5 h-5" />
+        <span className="font-medium text-sm">{t('contact_us', 'Контактирај нè')}</span>
+      </button>
+
+      {/* Backdrop */}
+      {isOpen && (
+        <div
+          className="fixed inset-0 z-50 bg-black/40 backdrop-blur-sm transition-opacity duration-300"
+          onClick={() => setIsOpen(false)}
+        />
+      )}
+
+      {/* Modal */}
+      <div
+        className={`fixed z-50 bottom-6 right-6 w-[380px] max-w-[calc(100vw-2rem)] bg-card border border-border rounded-2xl shadow-2xl transition-all duration-300 origin-bottom-right ${isOpen ? 'scale-100 opacity-100' : 'scale-0 opacity-0 pointer-events-none'}`}
+      >
+        {/* Modal header */}
+        <div className="bg-primary text-white rounded-t-2xl px-6 py-4 flex items-center justify-between">
+          <div className="flex items-center gap-3">
+            <FontAwesomeIcon icon={faEnvelope} className="w-5 h-5" />
+            <h2 className="text-lg font-bold">{t('contact_us', 'Контактирај нè')}</h2>
+          </div>
+          <button
+            onClick={() => setIsOpen(false)}
+            className="text-white/80 hover:text-white transition-colors p-1"
+            aria-label={t('close', 'Затвори')}
+          >
+            <FontAwesomeIcon icon={faTimes} className="w-5 h-5" />
+          </button>
+        </div>
+
+        {/* Modal body */}
+        <div className="p-6">
+          {sent ? (
+            <div className="text-center py-8">
+              <div className="w-16 h-16 bg-green-100 text-green-600 rounded-full flex items-center justify-center mx-auto mb-4">
+                <FontAwesomeIcon icon={faPaperPlane} className="w-7 h-7" />
+              </div>
+              <h3 className="text-lg font-bold text-card-foreground mb-1">
+                {t('contact_sent_title', 'Пораката е испратена!')}
+              </h3>
+              <p className="text-sm text-muted-foreground">
+                {t('contact_sent_desc', 'Ќе ви одговориме наскоро.')}
+              </p>
+            </div>
+          ) : (
+            <form onSubmit={handleSubmit} className="space-y-4">
+              {/* Name */}
+              <div>
+                <label className="block text-sm font-medium text-muted-foreground mb-1">
+                  {t('contact_name', 'Име и презиме')}
+                </label>
+                <input
+                  type="text"
+                  name="name"
+                  required
+                  value={form.name}
+                  onChange={handleChange}
+                  placeholder={t('contact_name_placeholder', 'Вашето име')}
+                  className="w-full border border-border rounded-lg px-3 py-2 text-sm bg-card text-card-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary"
+                />
+              </div>
+
+              {/* Email */}
+              <div>
+                <label className="block text-sm font-medium text-muted-foreground mb-1">
+                  {t('contact_email', 'Е-пошта')}
+                </label>
+                <input
+                  type="email"
+                  name="email"
+                  required
+                  value={form.email}
+                  onChange={handleChange}
+                  placeholder={t('contact_email_placeholder', 'example@email.com')}
+                  className="w-full border border-border rounded-lg px-3 py-2 text-sm bg-card text-card-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary"
+                />
+              </div>
+
+              {/* Subject */}
+              <div>
+                <label className="block text-sm font-medium text-muted-foreground mb-1">
+                  {t('contact_subject', 'Наслов')}
+                </label>
+                <input
+                  type="text"
+                  name="subject"
+                  required
+                  value={form.subject}
+                  onChange={handleChange}
+                  placeholder={t('contact_subject_placeholder', 'Тема на пораката')}
+                  className="w-full border border-border rounded-lg px-3 py-2 text-sm bg-card text-card-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary"
+                />
+              </div>
+
+              {/* Message */}
+              <div>
+                <label className="block text-sm font-medium text-muted-foreground mb-1">
+                  {t('contact_message', 'Порака')}
+                </label>
+                <textarea
+                  name="message"
+                  required
+                  rows={3}
+                  value={form.message}
+                  onChange={handleChange}
+                  placeholder={t('contact_message_placeholder', 'Напишете ја вашата порака...')}
+                  className="w-full border border-border rounded-lg px-3 py-2 text-sm bg-card text-card-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary resize-none"
+                />
+              </div>
+
+              {/* Submit */}
+              <button
+                type="submit"
+                disabled={isSending}
+                className="w-full bg-primary hover:bg-blue-700 text-white font-medium py-2.5 rounded-lg transition-colors duration-200 flex items-center justify-center gap-2 disabled:opacity-60 disabled:cursor-not-allowed"
+              >
+                {isSending ? (
+                  <>
+                    <FontAwesomeIcon icon={faSpinner} className="w-4 h-4 animate-spin" />
+                    {t('contact_sending', 'Испраќа...')}
+                  </>
+                ) : (
+                  <>
+                    <FontAwesomeIcon icon={faPaperPlane} className="w-4 h-4" />
+                    {t('contact_send', 'Испрати')}
+                  </>
+                )}
+              </button>
+            </form>
+          )}
+        </div>
+      </div>
+    </>
+  );
+}
Index: frontend/src/components/enroll-semester-dialog.tsx
===================================================================
--- frontend/src/components/enroll-semester-dialog.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/enroll-semester-dialog.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,287 @@
+"use client";
+
+import { useEffect, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { apiUrl } from "@/lib/api";
+import { getAccessToken } from "@/lib/auth";
+
+type SubjectOption = {
+  id: number;
+  name?: string;
+  code?: string;
+  credits: number;
+  mandatorySemester: number;
+  alreadyPassed: boolean;
+};
+
+type MajorOption = {
+  id: number;
+  name?: string;
+  subjects: SubjectOption[];
+};
+
+type SemesterOption = {
+  id: number;
+  name?: string;
+  year: number;
+  type?: string;
+};
+
+type EnrollmentOptions = {
+  requiredSubjects: number;
+  semesters: SemesterOption[];
+  majors: MajorOption[];
+  defaultMajorId: number | null;
+};
+
+export default function EnrollSemesterDialog({
+  open,
+  onClose,
+  onEnrolled,
+}: {
+  open: boolean;
+  onClose: () => void;
+  onEnrolled: () => void;
+}) {
+  const { t } = useTranslation();
+
+  const [options, setOptions] = useState<EnrollmentOptions | null>(null);
+  const [loading, setLoading] = useState(false);
+  const [submitting, setSubmitting] = useState(false);
+  const [error, setError] = useState<string | null>(null);
+
+  const [semesterId, setSemesterId] = useState<number | null>(null);
+  const [majorId, setMajorId] = useState<number | null>(null);
+  const [picked, setPicked] = useState<number[]>([]);
+
+  useEffect(() => {
+    if (!open) return;
+
+    let cancelled = false;
+
+    async function load() {
+      setLoading(true);
+      setError(null);
+      try {
+        const token = getAccessToken();
+        if (!token) throw new Error(t("enroll_not_signed_in"));
+
+        const res = await fetch(apiUrl("/api/enrollment/options"), {
+          cache: "no-store",
+          headers: { Authorization: `Bearer ${token}` },
+        });
+        if (!res.ok) throw new Error(`${t("enroll_options_failed")} (${res.status})`);
+
+        const data = (await res.json()) as EnrollmentOptions;
+        if (cancelled) return;
+
+        setOptions(data);
+        setSemesterId(data.semesters[0]?.id ?? null);
+        setMajorId(data.defaultMajorId ?? data.majors[0]?.id ?? null);
+        setPicked([]);
+      } catch (e) {
+        if (!cancelled) setError(e instanceof Error ? e.message : String(e));
+      } finally {
+        if (!cancelled) setLoading(false);
+      }
+    }
+
+    void load();
+    return () => {
+      cancelled = true;
+    };
+  }, [open, t]);
+
+  const required = options?.requiredSubjects ?? 5;
+
+  const subjects = useMemo(
+    () => options?.majors.find((m) => m.id === majorId)?.subjects ?? [],
+    [options, majorId],
+  );
+
+  function toggle(subjectId: number) {
+    setPicked((prev) => {
+      if (prev.includes(subjectId)) return prev.filter((id) => id !== subjectId);
+      if (prev.length >= required) return prev; // the cap is the point of the form
+      return [...prev, subjectId];
+    });
+  }
+
+  async function submit() {
+    setSubmitting(true);
+    setError(null);
+    try {
+      const token = getAccessToken();
+      if (!token) throw new Error(t("enroll_not_signed_in"));
+
+      const res = await fetch(apiUrl("/api/enrollment"), {
+        method: "POST",
+        headers: {
+          "Content-Type": "application/json",
+          Authorization: `Bearer ${token}`,
+        },
+        body: JSON.stringify({
+          SemesterId: semesterId,
+          MajorId: majorId,
+          SubjectIds: picked,
+        }),
+      });
+
+      const body = (await res.json()) as { ok: boolean; message?: string };
+      if (!res.ok || !body.ok) {
+        throw new Error(body.message || `${t("enroll_failed")} (${res.status})`);
+      }
+
+      onEnrolled();
+      onClose();
+    } catch (e) {
+      setError(e instanceof Error ? e.message : String(e));
+    } finally {
+      setSubmitting(false);
+    }
+  }
+
+  if (!open) return null;
+
+  const noSemestersLeft = !loading && options !== null && options.semesters.length === 0;
+  const canSubmit =
+    !submitting && semesterId !== null && majorId !== null && picked.length === required;
+
+  return (
+    <div
+      className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/50 p-4 sm:items-center"
+      role="dialog"
+      aria-modal="true"
+      onClick={onClose}
+    >
+      <div
+        className="w-full max-w-3xl rounded-xl border border-border bg-card shadow-lg"
+        onClick={(e) => e.stopPropagation()}
+      >
+        <div className="flex items-center justify-between rounded-t-xl bg-primary px-6 py-4 text-white">
+          <h2 className="text-xl font-bold">{t("enroll_semester")}</h2>
+          <button
+            className="rounded-lg px-3 py-1 text-sm hover:bg-white/20"
+            onClick={onClose}
+            aria-label={t("close")}
+          >
+            ✕
+          </button>
+        </div>
+
+        <div className="p-6">
+          {loading ? (
+            <p className="text-muted-foreground">{t("loading")}</p>
+          ) : noSemestersLeft ? (
+            <p className="text-muted-foreground">{t("enroll_no_semesters")}</p>
+          ) : (
+            <>
+              <div className="grid gap-4 sm:grid-cols-2">
+                <div className="flex flex-col">
+                  <label className="text-sm text-muted-foreground">{t("semester")}</label>
+                  <select
+                    className="rounded-lg border border-border bg-background px-3 py-2"
+                    value={semesterId ?? ""}
+                    onChange={(e) => setSemesterId(Number.parseInt(e.target.value, 10))}
+                  >
+                    {options?.semesters.map((s) => (
+                      <option key={s.id} value={s.id}>
+                        {s.name}
+                      </option>
+                    ))}
+                  </select>
+                </div>
+
+                <div className="flex flex-col">
+                  <label className="text-sm text-muted-foreground">{t("direction")}</label>
+                  <select
+                    className="rounded-lg border border-border bg-background px-3 py-2"
+                    value={majorId ?? ""}
+                    onChange={(e) => {
+                      setMajorId(Number.parseInt(e.target.value, 10));
+                      setPicked([]); // subjects differ per programme
+                    }}
+                  >
+                    {options?.majors.map((m) => (
+                      <option key={m.id} value={m.id}>
+                        {m.name}
+                      </option>
+                    ))}
+                  </select>
+                </div>
+              </div>
+
+              <div className="mt-6 flex items-center justify-between">
+                <h3 className="font-semibold text-card-foreground">{t("subjects")}</h3>
+                <span
+                  className={`text-sm font-medium ${
+                    picked.length === required ? "text-green-700" : "text-muted-foreground"
+                  }`}
+                >
+                  {picked.length} / {required}
+                </span>
+              </div>
+
+              <div className="mt-2 max-h-80 overflow-y-auto rounded-lg border border-border">
+                {subjects.map((s) => {
+                  const checked = picked.includes(s.id);
+                  const atLimit = !checked && picked.length >= required;
+                  return (
+                    <label
+                      key={s.id}
+                      className={`flex items-center gap-3 border-b border-border px-4 py-3 last:border-b-0 ${
+                        atLimit ? "opacity-50" : "cursor-pointer hover:bg-accent"
+                      }`}
+                    >
+                      <input
+                        type="checkbox"
+                        checked={checked}
+                        disabled={atLimit}
+                        onChange={() => toggle(s.id)}
+                      />
+                      <span className="flex-1">
+                        <span className="text-card-foreground">{s.name}</span>
+                        <span className="ml-2 font-mono text-xs text-muted-foreground">{s.code}</span>
+                        {s.alreadyPassed && (
+                          <span className="ml-2 rounded-full bg-green-100 px-2 py-0.5 text-xs text-green-800">
+                            {t("enroll_already_passed")}
+                          </span>
+                        )}
+                      </span>
+                      <span className="text-xs text-muted-foreground">
+                        {t("enroll_semester_short")} {s.mandatorySemester} · {s.credits} {t("enroll_credits")}
+                      </span>
+                    </label>
+                  );
+                })}
+              </div>
+            </>
+          )}
+
+          {error && (
+            <div className="mt-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800">
+              {error}
+            </div>
+          )}
+
+          <div className="mt-6 flex justify-end gap-3">
+            <button
+              className="rounded-lg border border-border px-4 py-2 text-sm font-medium"
+              onClick={onClose}
+              disabled={submitting}
+            >
+              {t("cancel")}
+            </button>
+            <button
+              className="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white disabled:opacity-50"
+              onClick={() => void submit()}
+              disabled={!canSubmit}
+            >
+              {submitting ? t("loading") : t("enroll_confirm")}
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
Index: frontend/src/components/exams.tsx
===================================================================
--- frontend/src/components/exams.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/exams.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,312 @@
+"use client"
+import { useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faSort, faSortUp, faSortDown } from '@fortawesome/free-solid-svg-icons';
+import { getAccessToken } from '@/lib/auth';
+import { apiUrl } from '@/lib/api';
+
+type PassedSubject = {
+  id: number;
+  subjectId: number;
+  code: string;
+  subject: string;
+  credits: number;
+  grade: number;
+  gradeText: string;
+  date: string; // DD.MM.YYYY
+  semester: string;
+  professor: string;
+};
+
+type PassedSubjectsResponse = {
+  passedSubjects: PassedSubject[];
+};
+
+type ExamRow = {
+  id: number;
+  code: string;
+  subject: string;
+  date: string;
+  semester: string;
+  credits: number;
+  grade: number;
+};
+
+const Exams = () => {
+  const { t } = useTranslation();
+  const [sortField, setSortField] = useState<'grade' | 'date' | null>(null);
+  const [sortOrder, setSortOrder] = useState<'asc' | 'desc' | null>(null);
+  const [exams, setExams] = useState<ExamRow[]>([]);
+  const [isLoading, setIsLoading] = useState(true);
+  const [errorMessage, setErrorMessage] = useState<string | null>(null);
+
+  useEffect(() => {
+    let cancelled = false;
+
+    async function load() {
+      setIsLoading(true);
+      setErrorMessage(null);
+
+      const token = getAccessToken();
+      if (!token) {
+        setErrorMessage('Not authenticated. Please login again.');
+        setIsLoading(false);
+        return;
+      }
+
+      try {
+        const response = await fetch(apiUrl('/api/user/getPassedSubjects'), {
+          method: 'GET',
+          headers: {
+            Authorization: `Bearer ${token}`,
+          },
+        });
+
+        if (!response.ok) {
+          const text = await response.text().catch(() => '');
+          throw new Error(text || `Failed to load passed subjects (${response.status})`);
+        }
+
+        const data = (await response.json()) as PassedSubjectsResponse;
+        const rows: ExamRow[] = (data?.passedSubjects ?? []).map((s) => ({
+          id: s.id,
+          code: s.code,
+          subject: s.subject,
+          date: s.date,
+          semester: s.semester,
+          credits: s.credits,
+          grade: s.grade,
+        }));
+
+        if (!cancelled) setExams(rows);
+      } catch (err) {
+        if (!cancelled) {
+          setErrorMessage(err instanceof Error ? err.message : 'Failed to load passed subjects.');
+        }
+      } finally {
+        if (!cancelled) setIsLoading(false);
+      }
+    }
+
+    void load();
+
+    return () => {
+      cancelled = true;
+    };
+  }, []);
+
+  const stats = useMemo(() => {
+    const passed = exams.length;
+    const creditsCurrent = exams.reduce((sum, s) => sum + (typeof s.credits === 'number' ? s.credits : 0), 0);
+    const numericGrades = exams.map((e) => (typeof e.grade === 'number' ? e.grade : null)).filter((g): g is number => g !== null);
+    const average =
+      numericGrades.length > 0
+        ? numericGrades.reduce((sum, g) => sum + g, 0) / numericGrades.length
+        : 0;
+
+    const totalCredits = 240;
+    const totalExams = 40;
+    return {
+      average: Number.isFinite(average) ? Number(average.toFixed(2)) : 0,
+      credits: { current: creditsCurrent, total: totalCredits },
+      passed,
+      remaining: Math.max(0, totalExams - passed),
+    };
+  }, [exams]);
+
+  const getGradeColor = (grade: number) => {
+    if (grade >= 9) return "bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20";
+    if (grade >= 8) return "bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 border-yellow-500/20";
+    if (grade >= 6) return "bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/20";
+    return "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20";
+  };
+
+  const handleSortByGrade = () => {
+    if (sortField === 'grade') {
+      if (sortOrder === 'desc') {
+        setSortOrder('asc');
+      } else if (sortOrder === 'asc') {
+        setSortField(null);
+        setSortOrder(null);
+      } else {
+        setSortOrder('desc');
+      }
+    } else {
+      setSortField('grade');
+      setSortOrder('desc');
+    }
+  };
+
+  const handleSortByDate = () => {
+    if (sortField === 'date') {
+      if (sortOrder === 'desc') {
+        setSortOrder('asc');
+      } else if (sortOrder === 'asc') {
+        setSortField(null);
+        setSortOrder(null);
+      } else {
+        setSortOrder('desc');
+      }
+    } else {
+      setSortField('date');
+      setSortOrder('desc');
+    }
+  };
+
+  const getSortedExams = () => {
+    if (!sortField || !sortOrder) return exams;
+    
+    return [...exams].sort((a, b) => {
+      if (sortField === 'grade') {
+        return sortOrder === 'asc' ? a.grade - b.grade : b.grade - a.grade;
+      }
+      
+      if (sortField === 'date') {
+        // Convert date strings to Date objects for proper sorting
+        const dateA = new Date(a.date.split('.').reverse().join('-')); // Convert DD.MM.YYYY to YYYY-MM-DD
+        const dateB = new Date(b.date.split('.').reverse().join('-'));
+        
+        return sortOrder === 'asc' ? dateA.getTime() - dateB.getTime() : dateB.getTime() - dateA.getTime();
+      }
+      
+      return 0;
+    });
+  };
+
+  const getSortIcon = (field: 'grade' | 'date') => {
+    if (sortField === field) {
+      if (sortOrder === 'asc') return faSortUp;
+      if (sortOrder === 'desc') return faSortDown;
+    }
+    return faSort;
+  };
+
+  const creditsPercentage = stats.credits.total > 0 ? (stats.credits.current / stats.credits.total) * 100 : 0;
+
+  if (isLoading) {
+    return (
+      <div className="bg-card rounded-lg shadow-sm p-6">
+        {t('loading', 'Loading...')}
+      </div>
+    );
+  }
+
+  if (errorMessage) {
+    return (
+      <div className="bg-card rounded-lg shadow-sm p-6">
+        <div className="rounded-lg border border-red-500/20 bg-red-500/10 px-4 py-3 text-sm text-red-600 dark:text-red-400">
+          {t('failed_to_load_exams', errorMessage)}
+        </div>
+      </div>
+    );
+  }
+
+  return (
+    <div className="bg-card rounded-lg shadow-sm p-6 space-y-6">
+      {/* Statistics Section */}
+      <div className="space-y-4">
+        <div className="grid grid-cols-2 md:grid-cols-4 gap-6">
+          {/* Average Grade */}
+          <div className="text-center">
+            <div className="text-3xl font-bold text-card-foreground">{stats.average}</div>
+            <div className="text-sm text-muted-foreground mt-1">{t('average', 'Просек')}</div>
+          </div>
+
+          {/* Credits */}
+          <div className="text-center">
+            <div className="text-3xl font-bold text-card-foreground">
+              {stats.credits.current}
+              <span className="text-lg text-muted-foreground">/{stats.credits.total}</span>
+            </div>
+            <div className="text-sm text-muted-foreground mt-1">{t('credits', 'Кредити')}</div>
+          </div>
+
+          {/* Passed Exams */}
+          <div className="text-center">
+            <div className="text-3xl font-bold text-card-foreground">{stats.passed}</div>
+            <div className="text-sm text-muted-foreground mt-1">{t('passed', 'Положени')}</div>
+          </div>
+
+          {/* Remaining Exams */}
+          <div className="text-center">
+            <div className="text-3xl font-bold text-card-foreground">{stats.remaining}</div>
+            <div className="text-sm text-muted-foreground mt-1">{t('remaining', 'Останато')}</div>
+          </div>
+        </div>
+
+        {/* Progress Bar spanning entire statistics section */}
+        <div className="w-full bg-secondary rounded-full h-2">
+          <div
+            className="bg-primary h-2 rounded-full transition-all duration-300"
+            style={{ width: `${creditsPercentage}%` }}
+          ></div>
+        </div>
+      </div>
+
+      {/* Exams Table */}
+      <div>
+        <h3 className="text-xl font-semibold text-card-foreground mb-4">{t('exams', 'Испити')}</h3>
+
+        <div className="overflow-x-auto">
+          <table className="min-w-full">
+            <thead>
+              <tr className="border-b border-border">
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">#</th>
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">{t('subject', 'Предмет')}</th>
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">{t('semester', 'Семестар')}</th>
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">{t('credits', 'Кредити')}</th>
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">
+                  <button
+                    onClick={handleSortByDate}
+                    className="flex items-center gap-2 px-2 py-1 rounded-md hover:bg-accent hover:text-accent-foreground transition-all duration-200 transform hover:scale-105"
+                  >
+                    {t('date', 'Датум')}
+                    <FontAwesomeIcon
+                      icon={getSortIcon('date')}
+                      className={`text-xs transition-colors duration-200 ${
+                        sortField === 'date' ? 'text-primary' : 'text-muted-foreground group-hover:text-foreground'
+                      }`}
+                    />
+                  </button>
+                </th>
+                <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">
+                  <button
+                    onClick={handleSortByGrade}
+                    className="flex items-center gap-2 px-2 py-1 rounded-md hover:bg-accent hover:text-accent-foreground transition-all duration-200 transform hover:scale-105"
+                  >
+                    {t('grade', 'Оценка')}
+                    <FontAwesomeIcon
+                      icon={getSortIcon('grade')}
+                      className={`text-xs transition-colors duration-200 ${
+                        sortField === 'grade' ? 'text-primary' : 'text-muted-foreground group-hover:text-foreground'
+                      }`}
+                    />
+                  </button>
+                </th>
+              </tr>
+            </thead>
+            <tbody className="divide-y divide-border">
+              {getSortedExams().map((exam) => (
+                <tr key={exam.id} className="hover:bg-accent/50 transition-colors duration-150">
+                  <td className="py-4 px-4 text-sm text-card-foreground">{exam.id}</td>
+                  <td className="py-4 px-4 text-sm text-card-foreground font-medium">{t(exam.subject, exam.subject)}</td>
+                  <td className="py-4 px-4 text-sm text-muted-foreground">{t(exam.semester, exam.semester)}</td>
+                  <td className="py-4 px-4 text-sm text-muted-foreground">{exam.credits}</td>
+                  <td className="py-4 px-4 text-sm text-muted-foreground">{exam.date}</td>
+                  <td className="py-4 px-4">
+                    <span className={`inline-flex items-center px-2.5 py-1 rounded-md text-sm font-medium border ${getGradeColor(exam.grade)}`}>
+                      {exam.grade}
+                    </span>
+                  </td>
+                </tr>
+              ))}
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Exams;
Index: frontend/src/components/header.tsx
===================================================================
--- frontend/src/components/header.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/header.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,114 @@
+"use client"
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faUser } from '@fortawesome/free-solid-svg-icons';
+import Image from 'next/image';
+
+import { useEffect, useState } from 'react';
+import { getAccessToken, clearAuthTokens } from '@/lib/auth';
+import { useTranslation } from 'react-i18next';
+import LanguageSwitcher from './LanguageSwitcher';
+import { apiUrl } from '@/lib/api';
+
+const Header = () => {
+
+  const [userName, setUserName] = useState<string>('');
+  const { t } = useTranslation();
+
+  useEffect(() => {
+    async function fetchUser() {
+      const token = getAccessToken();
+      if (!token) return;
+      try {
+        const response = await fetch(apiUrl('/api/user/getUser'), {
+          method: 'GET',
+          headers: { Authorization: `Bearer ${token}` },
+        });
+        if (!response.ok) return;
+        const data = await response.json();
+        // Try both student and professor shape
+        if (data?.personalInfo) {
+          const p = data.personalInfo;
+          setUserName([p.firstName, p.middleName, p.lastName].filter(Boolean).join(' '));
+        }
+      } catch {}
+    }
+    fetchUser();
+    return () => {};
+  }, []);
+
+  const handleLogout = () => {
+    clearAuthTokens();
+    if (typeof window !== 'undefined') {
+      window.location.href = '/';
+    }
+  };
+
+  return (
+    <header className="bg-card shadow-sm border-b border-border">
+      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div className="flex flex-col sm:flex-row sm:justify-between sm:items-center py-4 gap-4 sm:gap-0">
+          {/* Left side - Logos and University Info */}
+          <div className="flex items-center gap-2 justify-center sm:justify-start">
+            {/* UKIM Logo */}
+            <div className="flex-shrink-0">
+              <Image
+                src="/ukim-logo.png"
+                alt="UKIM Logo"
+                width={40}
+                height={40}
+                className="h-10 w-auto"
+              />
+            </div>
+            {/* FINKI Logo */}
+            <div className="flex-shrink-0">
+              <Image
+                src="/finki-logo.png"
+                alt="FINKI Logo"
+                width={40}
+                height={40}
+                className="h-10 w-auto"
+              />
+            </div>
+            {/* University Text */}
+            <div className="hidden sm:block">
+              <div className="text-card-foreground font-medium text-sm">
+                {t('university')}
+              </div>
+              <div className="text-muted-foreground text-sm">
+                {t('faculty')}
+              </div>
+            </div>
+          </div>
+          {/* Right side - User Profile */}
+          <div className="flex flex-col sm:flex-row items-center gap-2 sm:gap-4 w-full sm:w-auto justify-center sm:justify-end">
+            {/* Language Switcher - now left of user info */}
+            <div className="sm:mr-2 w-full sm:w-auto flex justify-center sm:justify-end">
+              <LanguageSwitcher />
+            </div>
+            <div className="flex items-center gap-2 sm:gap-3 w-full sm:w-auto justify-center sm:justify-end">
+              {/* User Avatar */}
+              <div className="hidden sm:flex items-center justify-center w-10 h-10 bg-primary text-primary-foreground rounded-full">
+                <FontAwesomeIcon icon={faUser} className="text-sm" />
+              </div>
+              {/* User Name */}
+              <div className="hidden sm:block text-card-foreground font-medium">
+                {userName || '...'}
+              </div>
+              {/* Logout Button - more stylish and full width on mobile */}
+              <button
+                className="w-full sm:w-auto ml-0 sm:ml-2 px-4 py-2 border-2 border-primary text-primary bg-card rounded-lg font-semibold flex items-center justify-center gap-2 hover:bg-accent transition-all duration-200 shadow-sm"
+                onClick={handleLogout}
+              >
+                <svg xmlns='http://www.w3.org/2000/svg' className='h-4 w-4' fill='none' viewBox='0 0 24 24' stroke='currentColor'><path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a2 2 0 01-2 2H7a2 2 0 01-2-2V7a2 2 0 012-2h4a2 2 0 012 2v1' /></svg>
+                {t('logout')}
+              </button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </header>
+  );
+};
+
+export default Header;
Index: frontend/src/components/navbar.tsx
===================================================================
--- frontend/src/components/navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,86 @@
+"use client"
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faUser } from '@fortawesome/free-solid-svg-icons';
+import { faBookmark } from '@fortawesome/free-solid-svg-icons';
+import { faBook } from '@fortawesome/free-solid-svg-icons';
+import { faPenToSquare } from '@fortawesome/free-solid-svg-icons';
+import { faListCheck } from '@fortawesome/free-solid-svg-icons';
+import { faFilePdf } from '@fortawesome/free-solid-svg-icons';
+import { faBars, faTimes, faGraduationCap } from '@fortawesome/free-solid-svg-icons';
+import { useState } from 'react';
+import Link from 'next/link';
+import { useTranslation } from 'react-i18next';
+
+const Navbar = () => {
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+  const toggleMenu = () => {
+    setIsMenuOpen(!isMenuOpen);
+  };
+
+  const { t } = useTranslation();
+  const menuItems = [
+    { icon: faUser, label: t('profile'), href: '/students/profile' },
+    { icon: faBookmark, label: t('semesters'), href: '/students/semesters' },
+    { icon: faBook, label: t('subjects'), href: '/students/subjects' },
+    { icon: faPenToSquare, label: t('applications'), href: '/students/applications' },
+    { icon: faListCheck, label: t('exams'), href: '/students/exams' },
+    { icon: faFilePdf, label: t('documents'), href: '/students/documents' }
+  ];
+
+  return (
+    <>
+      {/* Desktop Navbar */}
+      <nav className="hidden md:flex flex-row gap-2 justify-evenly bg-primary text-primary-foreground p-7 rounded-xl my-5 text-xl">
+        {menuItems.map((item, index) => (
+          <Link key={index} href={item.href}>
+            <div className="group flex flex-row items-center gap-2 px-3 py-2 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground hover:scale-105 hover:shadow-lg">
+              <FontAwesomeIcon icon={item.icon} className="transition-transform duration-300 group-hover:rotate-12" />
+              <span>{item.label}</span>
+            </div>
+          </Link>
+        ))}
+      </nav>
+
+      {/* Mobile Navbar */}
+      <nav className="md:hidden bg-primary text-primary-foreground rounded-xl my-5">
+        <div className="flex justify-between items-center p-4">
+          {/* IKnow Logo/Text */}
+          <div className="flex items-center gap-2 text-xl font-bold">
+            <FontAwesomeIcon icon={faGraduationCap} className="text-xl" />
+            IKnow
+          </div>
+          
+          {/* Hamburger Menu Button */}
+          <button
+            onClick={toggleMenu}
+            className="p-2 rounded-lg hover:bg-card hover:text-card-foreground transition-colors duration-300"
+          >
+            <FontAwesomeIcon 
+              icon={isMenuOpen ? faTimes : faBars} 
+              className="text-xl transition-transform duration-300"
+            />
+          </button>
+        </div>
+
+        {/* Mobile Menu Items */}
+        <div className={`overflow-hidden transition-all duration-300 ease-in-out ${
+          isMenuOpen ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'
+        }`}>
+          <div className="px-4 pb-4 space-y-2">
+            {menuItems.map((item, index) => (
+              <Link key={index} href={item.href}>
+                <div className="group flex flex-row items-center gap-3 px-3 py-3 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground">
+                  <FontAwesomeIcon icon={item.icon} className="transition-transform duration-300 group-hover:rotate-12" />
+                  <span className="text-lg">{item.label}</span>
+                </div>
+              </Link>
+            ))}
+          </div>
+        </div>
+      </nav>
+    </>
+  );
+};
+
+export default Navbar;
Index: frontend/src/components/professor-navbar.tsx
===================================================================
--- frontend/src/components/professor-navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/professor-navbar.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,80 @@
+"use client";
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faUser, faUsers, faBars, faTimes, faChalkboardUser } from "@fortawesome/free-solid-svg-icons";
+import Link from "next/link";
+import { useState } from "react";
+import { useTranslation } from 'react-i18next';
+
+const ProfessorNavbar = () => {
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+
+  const toggleMenu = () => {
+    setIsMenuOpen((v) => !v);
+  };
+
+  const { t } = useTranslation();
+  const menuItems = [
+    { icon: faUser, label: t('profile'), href: "/professor/profile" },
+    { icon: faUsers, label: t('students') || 'Студенти', href: "/professor/students" },
+  ];
+
+  return (
+    <>
+      {/* Desktop Navbar */}
+      <nav className="hidden md:flex flex-row gap-2 justify-evenly bg-primary text-primary-foreground p-7 rounded-xl my-5 text-xl">
+        {menuItems.map((item) => (
+          <Link key={item.href} href={item.href}>
+            <div className="group flex flex-row items-center gap-2 px-3 py-2 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground hover:scale-105 hover:shadow-lg">
+              <FontAwesomeIcon icon={item.icon} className="transition-transform duration-300 group-hover:rotate-12" />
+              <span>{item.label}</span>
+            </div>
+          </Link>
+        ))}
+      </nav>
+
+      {/* Mobile Navbar */}
+      <nav className="md:hidden bg-primary text-primary-foreground rounded-xl my-5">
+        <div className="flex justify-between items-center p-4">
+          <div className="flex items-center gap-2 text-xl font-bold">
+            <FontAwesomeIcon icon={faChalkboardUser} className="text-xl" />
+            Professor
+          </div>
+
+          <button
+            onClick={toggleMenu}
+            className="p-2 rounded-lg hover:bg-card hover:text-card-foreground transition-colors duration-300"
+            aria-label="Toggle menu"
+          >
+            <FontAwesomeIcon
+              icon={isMenuOpen ? faTimes : faBars}
+              className="text-xl transition-transform duration-300"
+            />
+          </button>
+        </div>
+
+        <div
+          className={`overflow-hidden transition-all duration-300 ease-in-out ${
+            isMenuOpen ? "max-h-64 opacity-100" : "max-h-0 opacity-0"
+          }`}
+        >
+          <div className="px-4 pb-4 space-y-2">
+            {menuItems.map((item) => (
+              <Link key={item.href} href={item.href}>
+                <div className="group flex flex-row items-center gap-3 px-3 py-3 rounded-lg cursor-pointer transition-all duration-300 hover:bg-card hover:text-card-foreground">
+                  <FontAwesomeIcon
+                    icon={item.icon}
+                    className="transition-transform duration-300 group-hover:rotate-12"
+                  />
+                  <span className="text-lg">{item.label}</span>
+                </div>
+              </Link>
+            ))}
+          </div>
+        </div>
+      </nav>
+    </>
+  );
+};
+
+export default ProfessorNavbar;
Index: frontend/src/components/theme-provider.tsx
===================================================================
--- frontend/src/components/theme-provider.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/theme-provider.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,8 @@
+"use client";
+
+import { ThemeProvider as NextThemesProvider } from "next-themes";
+import { type ThemeProviderProps } from "next-themes";
+
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+  return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
+}
Index: frontend/src/components/theme-toggle.tsx
===================================================================
--- frontend/src/components/theme-toggle.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
+++ frontend/src/components/theme-toggle.tsx	(revision b8093a091d45f33bab33deb8ff2fffc4734972c0)
@@ -0,0 +1,37 @@
+"use client";
+
+import { Moon, Sun } from "lucide-react";
+import { useTheme } from "next-themes";
+import { useEffect, useState } from "react";
+
+export function ThemeToggle() {
+  const [mounted, setMounted] = useState(false);
+  const { theme, setTheme } = useTheme();
+
+  // Avoid hydration mismatch
+  useEffect(() => {
+    setMounted(true);
+  }, []);
+
+  if (!mounted) {
+    return (
+      <button className="p-2 rounded-md hover:bg-accent">
+        <Sun className="h-5 w-5" />
+      </button>
+    );
+  }
+
+  return (
+    <button
+      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
+      className="p-2 rounded-md hover:bg-accent transition-colors"
+      aria-label="Toggle theme"
+    >
+      {theme === "dark" ? (
+        <Sun className="h-5 w-5" />
+      ) : (
+        <Moon className="h-5 w-5" />
+      )}
+    </button>
+  );
+}
