File "MyProfile.tsx"

Full Path: /home/trinadezambia/public_html/student_panel/src/components/ui/pages/dashboard/MyProfile.tsx
File size: 9.74 KB
MIME-type: text/x-java
Charset: utf-8

'use client';

import React from 'react';
import { useSelector } from 'react-redux';
import { RootState } from '@/components/store';
import { useGetStudentProfile } from '@/lib/api/student/queryHooks';
import { StudentProfileData } from '@/lib/api/student/functions';
import Image from 'next/image';
import { useTranslate } from '@/components/hooks/useTranslate';

// Type for extra field items
type ExtraFieldItem = NonNullable<StudentProfileData['extra_details']>[number];

export default function MyProfile() {
  const translate = useTranslate();
  // Get school code from Redux store
  const schoolCode = useSelector(
    (state: RootState) => state.studentAuth.schoolCode
  );

  // Fetch profile data using the API hook
  const { data, isLoading, isError, error } = useGetStudentProfile(schoolCode);

  // Show loading state while fetching data
  if (isLoading) {
    return (
      <div className="bg-white rounded-[12px] border border-gray-200 p-8 flex items-center justify-center">
        <div className="text-gray-500 text-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
          <p>{translate('loadingProfileData')}</p>
        </div>
      </div>
    );
  }

  // Show error state if API call failed
  if (isError) {
    return (
      <div className="bg-white rounded-[12px] border border-gray-200 p-8">
        <div className="text-red-500 text-center">
          <p className="text-lg font-semibold mb-2">
            {translate('failedToLoadProfileData')}
          </p>
          <p className="text-sm text-gray-600">
            {error instanceof Error
              ? error.message
              : translate('unknownErrorOccurred')}
          </p>
        </div>
      </div>
    );
  }

  // If no data is available
  if (!data?.data) {
    return (
      <div className="bg-white rounded-[12px] border border-gray-200 p-8">
        <div className="text-gray-500 text-center">
          <p>{translate('noProfileDataAvailable')}</p>
        </div>
      </div>
    );
  }

  // Extract profile data from API response
  const profile = data.data;
  const fullName = `${profile.first_name} ${profile.last_name}`;
  const className = profile.class_section?.full_name || 'N/A';
  const mediumName = profile.class_section?.medium?.name || 'N/A';
  const schoolName = `${profile.school.name} (${profile.school.code})`;

  // Split extra fields into left and right columns
  const extraFields = profile.extra_details || [];
  const midPoint = Math.ceil(extraFields.length / 2);
  const leftExtraFields = extraFields.slice(0, midPoint);
  const rightExtraFields = extraFields.slice(midPoint);

  return (
    <div className="bg-white rounded-[12px] border border-gray-200">
      {/* Profile Header Section */}
      <div className="bg-[#F2F5F7] p-3 sm:p-4 m-2 sm:m-4 rounded-[12px]">
        <div className="flex flex-col sm:flex-row items-center space-y-4 sm:space-y-0 sm:space-x-6">
          {/* Profile Image */}
          <div className="flex-shrink-0 border border-gray-200 rounded-[4px] p-2">
            {profile.image ? (
              <Image
                src={profile.image}
                alt={fullName}
                width={128}
                height={128}
                className="w-24 h-24 sm:w-32 sm:h-32 rounded-[4px] object-cover"
              />
            ) : (
              <div className="w-24 h-24 sm:w-32 sm:h-32 bg-gray-300 rounded-[4px] flex items-center justify-center">
                <div className="text-gray-500 text-xs sm:text-sm text-center">
                  {translate('profileImage')
                    .split(' ')
                    .map((word, i, arr) => (
                      <React.Fragment key={i}>
                        {word}
                        {i < arr.length - 1 && <br />}
                      </React.Fragment>
                    ))}
                </div>
              </div>
            )}
          </div>

          {/* Profile Name */}
          <div className="flex-1 text-center sm:text-left flex items-center">
            <h1 className="text-xl sm:text-2xl font-bold text-gray-900">
              {fullName}
            </h1>
          </div>
        </div>
      </div>

      {/* Profile Details Section */}
      <div className="p-4 sm:p-6">
        {/* Two-column layout for profile details */}
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-6">
          {/* Left Column */}
          <div className="space-y-3 sm:space-y-4">
            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('grNumber')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.admission_no || 'N/A'}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('class')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {className}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('rollNumber')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.roll_number || 'N/A'}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('currentAddress')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.current_address || 'N/A'}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('gender')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.gender || 'N/A'}
              </span>
            </div>

            {/* Display left column extra fields */}
            {leftExtraFields.map((field: ExtraFieldItem) => (
              <div key={field.id} className="flex flex-col space-y-1">
                <label className="text-sm sm:text-base font-normal text-gray-500">
                  {field.form_field.name}
                </label>
                {field.file_url ? (
                  <a
                    href={field.file_url}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-sm sm:text-base text-black hover:underline font-normal break-all"
                  >
                    {field.file_url}
                  </a>
                ) : (
                  <span
                    className="text-sm sm:text-base text-gray-900 font-normal"
                    dangerouslySetInnerHTML={{
                      __html: field.data || 'N/A',
                    }}
                  />
                )}
              </div>
            ))}
          </div>

          {/* Right Column */}
          <div className="space-y-3 sm:space-y-4">
            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('school')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {schoolName}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('medium')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {mediumName}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('dateOfBirth')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.dob}
              </span>
            </div>

            <div className="flex flex-col space-y-1">
              <label className="text-sm sm:text-base font-normal text-gray-500">
                {translate('permanentAddress')}
              </label>
              <span className="text-sm sm:text-base text-gray-900 font-normal">
                {profile.permanent_address || 'N/A'}
              </span>
            </div>

            {/* Display right column extra fields */}
            {rightExtraFields.map((field: ExtraFieldItem) => (
              <div key={field.id} className="flex flex-col space-y-1">
                <label className="text-sm sm:text-base font-normal text-gray-500">
                  {field.form_field.name}
                </label>
                {field.file_url ? (
                  <a
                    href={field.file_url}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-sm sm:text-base text-black hover:underline font-normal break-all"
                  >
                    {field.file_url}
                  </a>
                ) : (
                  <span
                    className="text-sm sm:text-base text-gray-900 font-normal"
                    dangerouslySetInnerHTML={{
                      __html: field.data || 'N/A',
                    }}
                  />
                )}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}