Ignore:
Timestamp:
12/21/25 18:28:25 (9 months ago)
Author:
Stefan-Saveski <stefansaveski19@…>
Branches:
master
Children:
90f7842
Parents:
82c9c53
Message:

Refactor Exams component to fetch passed subjects from API and remove hardcoded data; delete unused JSON data files; implement authentication token management in auth.ts

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/app/students/profile/page.tsx

    r82c9c53 rb67f274  
    1717  faPassport
    1818} from '@fortawesome/free-solid-svg-icons';
    19 import studentData from '@/data/student-profile.json';
    20 
     19import { useEffect, useState } from 'react';
     20import { getAccessToken } from '@/lib/auth';
    2121import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
     22
     23type PersonalInfo = {
     24  firstName: string;
     25  middleName: string;
     26  lastName: string;
     27  maidenName: string;
     28  dateOfBirth: string;
     29  gender: string;
     30  nationality: string;
     31  citizenship: string;
     32  scholarship: string;
     33  currentPlan: string;
     34  registryNumber: string;
     35  studyGroup: string;
     36  notes?: string;
     37  index: string;
     38  embg: string;
     39};
     40
     41type BirthInfo = {
     42  placeOfBirth: string;
     43  municipalityOfBirth: string;
     44  country: string;
     45};
     46
     47type PreviousEducation = {
     48  type: string;
     49  profession: string;
     50  average: string | number;
     51  language: string;
     52  country: string;
     53  previousUniversity: string;
     54  previousFaculty: string;
     55  previousStudyMode: string;
     56};
     57
     58type EnrollmentInfo = {
     59  enrollmentYear: string | number;
     60  status: string;
     61  cycle: string;
     62  program: string;
     63  quota: string;
     64  secondaryEducationNumber: string;
     65  previousEducationCredits: string | number;
     66};
     67
     68type Contact = {
     69  placeOfResidence: string;
     70  municipalityOfResidence: string;
     71  country: string;
     72  address: string;
     73  temporaryAddress: string;
     74  phone: string;
     75  mobilePhone: string;
     76  passportNumber: string;
     77  passportExpiryDate: string;
     78  email: string;
     79  microsoftEmail: string;
     80};
     81
     82type StudentProfile = {
     83  personalInfo: PersonalInfo;
     84  birthInfo: BirthInfo;
     85  previousEducation: PreviousEducation;
     86  enrollmentInfo: EnrollmentInfo;
     87  contact: Contact;
     88};
    2289
    2390interface InfoRowProps {
     
    60127
    61128export default function ProfilePage() {
     129  const [studentData, setStudentData] = useState<StudentProfile | null>(null);
     130  const [isLoading, setIsLoading] = useState(true);
     131  const [errorMessage, setErrorMessage] = useState<string | null>(null);
     132
     133  useEffect(() => {
     134    let cancelled = false;
     135
     136    async function load() {
     137      setIsLoading(true);
     138      setErrorMessage(null);
     139
     140      const token = getAccessToken();
     141      if (!token) {
     142        setErrorMessage('Not authenticated. Please login again.');
     143        setIsLoading(false);
     144        return;
     145      }
     146
     147      try {
     148        const response = await fetch('http://localhost:5147/api/user/getUser', {
     149          method: 'GET',
     150          headers: {
     151            Authorization: `Bearer ${token}`,
     152          },
     153        });
     154
     155        if (!response.ok) {
     156          const text = await response.text().catch(() => '');
     157          throw new Error(text || `Failed to load profile (${response.status})`);
     158        }
     159
     160        const data = (await response.json()) as StudentProfile;
     161        if (!cancelled) setStudentData(data);
     162      } catch (err) {
     163        if (!cancelled) {
     164          setErrorMessage(err instanceof Error ? err.message : 'Failed to load profile.');
     165        }
     166      } finally {
     167        if (!cancelled) setIsLoading(false);
     168      }
     169    }
     170
     171    void load();
     172
     173    return () => {
     174      cancelled = true;
     175    };
     176  }, []);
     177
     178  if (isLoading) {
     179    return (
     180      <div className="min-h-screen pb-8">
     181        <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
     182          Loading...
     183        </div>
     184      </div>
     185    );
     186  }
     187
     188  if (errorMessage || !studentData) {
     189    return (
     190      <div className="min-h-screen pb-8">
     191        <div className="rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
     192          {errorMessage ?? 'Failed to load profile.'}
     193        </div>
     194      </div>
     195    );
     196  }
     197
    62198  const { personalInfo, birthInfo, previousEducation, enrollmentInfo, contact } = studentData;
    63199
Note: See TracChangeset for help on using the changeset viewer.