Ignore:
Timestamp:
01/30/26 01:40:27 (8 months ago)
Author:
Stefan-Saveski <stefansaveski19@…>
Branches:
master
Children:
ba52069
Parents:
298f9b3
Message:

Added dual language feature.

File:
1 edited

Legend:

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

    r298f9b3 r50f2fb4  
    2020import { getAccessToken } from '@/lib/auth';
    2121import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
     22import { useTranslation } from 'react-i18next';
    2223
    2324type PersonalInfo = {
     
    9495}
    9596
    96 const InfoRow = ({ label, value, icon }: InfoRowProps) => (
    97   <div className="flex justify-between items-center py-3 border-b border-gray-100 last:border-b-0">
    98     <div className="flex items-center gap-2 text-gray-600 font-medium">
    99       {icon && <FontAwesomeIcon icon={icon} className="w-4 h-4" />}
    100       <span>{label}:</span>
     97const InfoRow = ({ label, value, icon }: InfoRowProps) => {
     98  const { t } = useTranslation();
     99  return (
     100    <div className="flex justify-between items-center py-3 border-b border-gray-100 last:border-b-0">
     101      <div className="flex items-center gap-2 text-gray-600 font-medium">
     102        {icon && <FontAwesomeIcon icon={icon} className="w-4 h-4" />}
     103        <span>{t(label)}:</span>
     104      </div>
     105      <div className="text-gray-900 font-semibold text-right max-w-xs break-words">
     106        {value || t('n_a')}
     107      </div>
    101108    </div>
    102     <div className="text-gray-900 font-semibold text-right max-w-xs break-words">
    103       {value || "N/A"}
    104     </div>
    105   </div>
    106 );
     109  );
     110};
    107111
    108112interface SectionProps {
     
    112116}
    113117
    114 const Section = ({ title, icon, children }: SectionProps) => (
    115   <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
    116     <div className="bg-primary text-white px-6 py-4">
    117       <div className="flex items-center gap-3">
    118         <FontAwesomeIcon icon={icon} className="text-xl" />
    119         <h2 className="text-xl font-bold">{title}</h2>
     118const Section = ({ title, icon, children }: SectionProps) => {
     119  const { t } = useTranslation();
     120  return (
     121    <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
     122      <div className="bg-primary text-white px-6 py-4">
     123        <div className="flex items-center gap-3">
     124          <FontAwesomeIcon icon={icon} className="text-xl" />
     125          <h2 className="text-xl font-bold">{t(title)}</h2>
     126        </div>
     127      </div>
     128      <div className="p-6">
     129        {children}
    120130      </div>
    121131    </div>
    122     <div className="p-6">
    123       {children}
    124     </div>
    125   </div>
    126 );
     132  );
     133};
    127134
    128135export default function ProfilePage() {
     
    130137  const [isLoading, setIsLoading] = useState(true);
    131138  const [errorMessage, setErrorMessage] = useState<string | null>(null);
     139  const { t } = useTranslation();
    132140
    133141  useEffect(() => {
     
    180188      <div className="min-h-screen pb-8">
    181189        <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
    182           Loading...
     190          {t('loading')}
    183191        </div>
    184192      </div>
     
    190198      <div className="min-h-screen pb-8">
    191199        <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.'}
     200          {errorMessage ?? t('failed_to_load_profile')}
    193201        </div>
    194202      </div>
     
    214222            </h1>
    215223            <div className="text-lg opacity-90">
    216               Индекс: {personalInfo.index} | ЕМБГ: {personalInfo.embg}
     224              {t('index')}: {personalInfo.index} | {t('embg')}: {personalInfo.embg}
    217225            </div>
    218226            <div className="text-base opacity-80 mt-1">
     
    227235       
    228236        {/* Personal Information */}
    229         <Section title="Лични податоци" icon={faIdCard}>
    230           <InfoRow label="Име" value={personalInfo.firstName} />
    231           <InfoRow label="Средно име" value={personalInfo.middleName} />
    232           <InfoRow label="Презиме" value={personalInfo.lastName} />
    233           <InfoRow label="Моминско презиме" value={personalInfo.maidenName} />
     237        <Section title="personal_info" icon={faIdCard}>
     238          <InfoRow label="first_name" value={personalInfo.firstName} />
     239          <InfoRow label="middle_name" value={personalInfo.middleName} />
     240          <InfoRow label="last_name" value={personalInfo.lastName} />
     241          <InfoRow label="maiden_name" value={personalInfo.maidenName} />
    234242          <InfoRow
    235             label="Датум на раѓање"
     243            label="date_of_birth"
    236244            value={personalInfo.dateOfBirth}
    237245            icon={faCalendarAlt}
    238246          />
    239247          <InfoRow
    240             label="Пол"
     248            label="gender"
    241249            value={personalInfo.gender}
    242             icon={personalInfo.gender === 'машки' ? faMars : faVenus}
     250            icon={personalInfo.gender === t('male') ? faMars : faVenus}
    243251          />
    244252          <InfoRow
    245             label="Националност"
     253            label="nationality"
    246254            value={personalInfo.nationality}
    247255            icon={faFlag}
    248256          />
    249           <InfoRow label="Државјанство" value={personalInfo.citizenship} />
    250           <InfoRow label="Стипендија" value={personalInfo.scholarship} />
    251           <InfoRow label="Тековен план" value={personalInfo.currentPlan} />
    252           <InfoRow label="Бр. во матична книга" value={personalInfo.registryNumber} />
    253           <InfoRow label="Група на студирање" value={personalInfo.studyGroup} />
     257          <InfoRow label="citizenship" value={personalInfo.citizenship} />
     258          <InfoRow label="scholarship" value={personalInfo.scholarship} />
     259          <InfoRow label="current_plan" value={personalInfo.currentPlan} />
     260          <InfoRow label="registry_number" value={personalInfo.registryNumber} />
     261          <InfoRow label="study_group" value={personalInfo.studyGroup} />
    254262          {personalInfo.notes && (
    255263            <div className="mt-4 p-4 bg-blue-50 rounded-lg">
    256               <div className="text-sm font-medium text-blue-800 mb-1">Забелешка:</div>
     264              <div className="text-sm font-medium text-blue-800 mb-1">{t('note')}:</div>
    257265              <div className="text-sm text-blue-700">{personalInfo.notes}</div>
    258266            </div>
     
    261269
    262270        {/* Birth Information */}
    263         <Section title="Податоци за раѓање" icon={faMapMarkerAlt}>
    264           <InfoRow label="Место на раѓање" value={birthInfo.placeOfBirth} />
    265           <InfoRow label="Општина на раѓање" value={birthInfo.municipalityOfBirth} />
    266           <InfoRow label="Земја" value={birthInfo.country} />
     271        <Section title="birth_info" icon={faMapMarkerAlt}>
     272          <InfoRow label="place_of_birth" value={birthInfo.placeOfBirth} />
     273          <InfoRow label="municipality_of_birth" value={birthInfo.municipalityOfBirth} />
     274          <InfoRow label="country" value={birthInfo.country} />
    267275        </Section>
    268276
    269277        {/* Previous Education */}
    270         <Section title="Претходно образование" icon={faSchool}>
    271           <InfoRow label="Тип" value={previousEducation.type} />
    272           <InfoRow label="Професија" value={previousEducation.profession} />
    273           <InfoRow label="Просек" value={previousEducation.average} />
    274           <InfoRow label="Јазик" value={previousEducation.language} />
    275           <InfoRow label="Земја" value={previousEducation.country} />
    276           <InfoRow label="Претходен универзитет" value={previousEducation.previousUniversity} />
    277           <InfoRow label="Претходен факултет" value={previousEducation.previousFaculty} />
    278           <InfoRow label="Режим на претходни студии" value={previousEducation.previousStudyMode} />
     278        <Section title="previous_education" icon={faSchool}>
     279          <InfoRow label="type" value={previousEducation.type} />
     280          <InfoRow label="profession" value={previousEducation.profession} />
     281          <InfoRow label="average" value={previousEducation.average} />
     282          <InfoRow label="language" value={previousEducation.language} />
     283          <InfoRow label="country" value={previousEducation.country} />
     284          <InfoRow label="previous_university" value={previousEducation.previousUniversity} />
     285          <InfoRow label="previous_faculty" value={previousEducation.previousFaculty} />
     286          <InfoRow label="previous_study_mode" value={previousEducation.previousStudyMode} />
    279287        </Section>
    280288
    281289        {/* Enrollment Information */}
    282         <Section title="Податоци за упис" icon={faGraduationCap}>
    283           <InfoRow label="Година на упис" value={enrollmentInfo.enrollmentYear} />
    284           <InfoRow label="Статус" value={enrollmentInfo.status} />
    285           <InfoRow label="Циклус" value={enrollmentInfo.cycle} />
    286           <InfoRow label="Запишана програма" value={enrollmentInfo.program} />
    287           <InfoRow label="Квота на прв упис" value={enrollmentInfo.quota} />
    288           <InfoRow label="Бр. дипл. ср. образование" value={enrollmentInfo.secondaryEducationNumber} />
    289           <InfoRow label="Кред. пр. образование" value={enrollmentInfo.previousEducationCredits} />
     290        <Section title="enrollment_info" icon={faGraduationCap}>
     291          <InfoRow label="enrollment_year" value={enrollmentInfo.enrollmentYear} />
     292          <InfoRow label="status" value={enrollmentInfo.status} />
     293          <InfoRow label="cycle" value={enrollmentInfo.cycle} />
     294          <InfoRow label="program" value={enrollmentInfo.program} />
     295          <InfoRow label="quota" value={enrollmentInfo.quota} />
     296          <InfoRow label="secondary_education_number" value={enrollmentInfo.secondaryEducationNumber} />
     297          <InfoRow label="previous_education_credits" value={enrollmentInfo.previousEducationCredits} />
    290298        </Section>
    291299
    292300        {/* Contact Information */}
    293301        <div className="lg:col-span-2">
    294           <Section title="Контакт" icon={faAddressCard}>
     302          <Section title="contact" icon={faAddressCard}>
    295303            <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
    296304              <div>
    297305                <InfoRow
    298                   label="Место на живеење"
     306                  label="place_of_residence"
    299307                  value={contact.placeOfResidence}
    300308                  icon={faMapMarkerAlt}
    301309                />
    302                 <InfoRow label="Општина на живеење" value={contact.municipalityOfResidence} />
    303                 <InfoRow label="Држава" value={contact.country} />
    304                 <InfoRow label="Адреса" value={contact.address} />
    305                 <InfoRow label="Адреса на престој" value={contact.temporaryAddress} />
     310                <InfoRow label="municipality_of_residence" value={contact.municipalityOfResidence} />
     311                <InfoRow label="country" value={contact.country} />
     312                <InfoRow label="address" value={contact.address} />
     313                <InfoRow label="temporary_address" value={contact.temporaryAddress} />
    306314              </div>
    307315              <div>
    308                 <InfoRow label="Телефон" value={contact.phone} icon={faPhone} />
    309                 <InfoRow label="Моб. телефон" value={contact.mobilePhone} icon={faPhone} />
    310                 <InfoRow label="Број на пасош" value={contact.passportNumber} icon={faPassport} />
    311                 <InfoRow label="Датум на истекување на пасошот" value={contact.passportExpiryDate} />
     316                <InfoRow label="phone" value={contact.phone} icon={faPhone} />
     317                <InfoRow label="mobile_phone" value={contact.mobilePhone} icon={faPhone} />
     318                <InfoRow label="passport_number" value={contact.passportNumber} icon={faPassport} />
     319                <InfoRow label="passport_expiry_date" value={contact.passportExpiryDate} />
    312320                <InfoRow
    313                   label="Е-пошта"
     321                  label="email"
    314322                  value={contact.email}
    315323                  icon={faEnvelope}
    316324                />
    317325                <InfoRow
    318                   label="Microsoft email"
     326                  label="microsoft_email"
    319327                  value={contact.microsoftEmail}
    320328                  icon={faEnvelope}
Note: See TracChangeset for help on using the changeset viewer.