Changeset b67f274 for src/app/students/profile/page.tsx
- Timestamp:
- 12/21/25 18:28:25 (9 months ago)
- Branches:
- master
- Children:
- 90f7842
- Parents:
- 82c9c53
- File:
-
- 1 edited
-
src/app/students/profile/page.tsx (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/app/students/profile/page.tsx
r82c9c53 rb67f274 17 17 faPassport 18 18 } from '@fortawesome/free-solid-svg-icons'; 19 import studentData from '@/data/student-profile.json';20 19 import { useEffect, useState } from 'react'; 20 import { getAccessToken } from '@/lib/auth'; 21 21 import { IconDefinition } from '@fortawesome/fontawesome-svg-core'; 22 23 type 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 41 type BirthInfo = { 42 placeOfBirth: string; 43 municipalityOfBirth: string; 44 country: string; 45 }; 46 47 type 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 58 type 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 68 type 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 82 type StudentProfile = { 83 personalInfo: PersonalInfo; 84 birthInfo: BirthInfo; 85 previousEducation: PreviousEducation; 86 enrollmentInfo: EnrollmentInfo; 87 contact: Contact; 88 }; 22 89 23 90 interface InfoRowProps { … … 60 127 61 128 export 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 62 198 const { personalInfo, birthInfo, previousEducation, enrollmentInfo, contact } = studentData; 63 199
Note:
See TracChangeset
for help on using the changeset viewer.
