Professor category

This commit is contained in:
2026-05-05 11:55:20 +05:30
parent 7b88426f96
commit 4fc0be9071
2 changed files with 346 additions and 188 deletions
+118 -76
View File
@@ -9,7 +9,10 @@ interface TeamListingProps {
onMemberClick?: (member: TeamMember) => void;
}
const TeamListing: React.FC<TeamListingProps> = ({
const GUIDES_FRIENDS_PATRONS_CATEGORIES = ['GUIDES', 'FRIENDS', 'PATRONS'];
const NON_CLICKABLE_CATEGORIES = ['TRAINEE_FELLOW', 'SUPPORT_TEAM', 'GUIDES', 'FRIENDS', 'PATRONS'];
const TeamListing: React.FC<TeamListingProps> = ({
title = "Our Team",
onMemberClick
}) => {
@@ -35,25 +38,36 @@ const TeamListing: React.FC<TeamListingProps> = ({
loadFacultyData();
}, []);
// Filter members by category and status
const facultyMembers = teamMembers.filter(member =>
// Active faculty members only
const facultyMembers = teamMembers.filter(member =>
member.category === 'FACULTY' && member.status !== 'RETIRED'
);
const supportTeam = teamMembers.filter(member =>
// Active support team only
const supportTeam = teamMembers.filter(member =>
member.category === 'SUPPORT_TEAM' && member.status !== 'RETIRED'
);
const traineesAndFellows = teamMembers.filter(member =>
// Active trainees and fellows only
const traineesAndFellows = teamMembers.filter(member =>
member.category === 'TRAINEE_FELLOW' && member.status !== 'RETIRED'
);
const retiredStaff = teamMembers.filter(member =>
member.status === 'RETIRED'
// Guides, Friends, Patrons — all three categories in one section
const guidesFriendsPatrons = teamMembers.filter(member =>
GUIDES_FRIENDS_PATRONS_CATEGORIES.includes(member.category) && member.status !== 'RETIRED'
);
// Alumni = RETIRED (any category) + RESIGNED (any status)
const alumniStaff = teamMembers.filter(member =>
member.status === 'RETIRED' || member.category === 'RESIGNED'
);
const handleMemberClick = (member: TeamMember) => {
if (onMemberClick) {
onMemberClick(member);
} else {
window.location.href = `/faculty/${member.id}`;
window.location.href = `/faculty/${member.professorId}`;
}
};
@@ -73,8 +87,8 @@ const TeamListing: React.FC<TeamListingProps> = ({
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<p className="text-red-600 mb-4">{error}</p>
<button
onClick={() => window.location.reload()}
<button
onClick={() => window.location.reload()}
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
>
Retry
@@ -87,45 +101,44 @@ const TeamListing: React.FC<TeamListingProps> = ({
const TeamMemberCard: React.FC<{ member: TeamMember }> = ({ member }) => {
const [imageError, setImageError] = useState(false);
const [imageLoading, setImageLoading] = useState(true);
const isTrainee = member.category === 'TRAINEE_FELLOW';
const isSupportTeam = member.category === 'SUPPORT_TEAM';
const isRetired = member.status === 'RETIRED';
const isNonClickable = isTrainee || isSupportTeam;
// Check if image URL is valid and not a default placeholder
const hasValidImage = member.image &&
member.image.trim() !== '' &&
!member.image.includes('default-avatar') &&
!member.image.includes('placeholder.') &&
!member.image.includes('robot') &&
// Only filter if URL ENDS with /profile-image (backend default endpoint)
!(member.image.endsWith('/profile-image') ||
member.image.includes('/profile-image?') ||
member.image === 'https://via.placeholder.com/400');
// Don't show images for trainees or support team
const isNonClickable = NON_CLICKABLE_CATEGORIES.includes(member.category);
const isRetired = member.status === 'RETIRED';
const isResigned = member.category === 'RESIGNED';
// Check if image URL is valid and not a default placeholder
const hasValidImage =
member.image &&
member.image.trim() !== '' &&
!member.image.includes('default-avatar') &&
!member.image.includes('placeholder.') &&
!member.image.includes('robot') &&
!(
member.image.endsWith('/profile-image') ||
member.image.includes('/profile-image?') ||
member.image === 'https://via.placeholder.com/400'
);
// Don't show images for non-clickable categories
const shouldShowImage = !isNonClickable && hasValidImage;
const handleImageError = (e: React.SyntheticEvent<HTMLImageElement>) => {
console.error('Image failed to load:', member.image);
console.error('Member:', member.name, 'Professor ID:', member.professorId);
const handleImageError = () => {
setImageError(true);
setImageLoading(false);
};
const handleImageLoad = () => {
console.log('Image loaded successfully:', member.image);
setImageLoading(false);
};
return (
<div
<div
className={`bg-white rounded-lg border border-gray-300 overflow-hidden transition-all duration-300 ${
!isNonClickable ? 'group cursor-pointer hover:shadow-lg' : 'cursor-default'
}`}
onClick={() => !isNonClickable && handleMemberClick(member)}
>
{/* Only show image section for faculty */}
{/* Only show image section for clickable categories (Faculty + Alumni) */}
{!isNonClickable && (
<div className="relative aspect-square overflow-hidden bg-gray-50">
{shouldShowImage && !imageError ? (
@@ -135,9 +148,8 @@ const TeamListing: React.FC<TeamListingProps> = ({
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
)}
<img
src={member.image}
<img
src={member.image}
alt={member.name}
className={`w-full h-full object-cover transition-transform duration-300 group-hover:scale-105 ${
imageLoading ? 'opacity-0' : 'opacity-100'
@@ -148,29 +160,41 @@ const TeamListing: React.FC<TeamListingProps> = ({
/>
</>
) : (
<div
<div
className="w-full h-full flex items-center justify-center"
style={{ backgroundColor: '#e0e5eb' }}
>
<svg
className="w-32 h-32 text-gray-400"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
<svg className="w-32 h-32 text-gray-400" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
</div>
)}
</div>
)}
<div className="p-4 sm:p-6">
<h3 className="text-lg font-medium mb-2 group-hover:opacity-70 transition-opacity" style={{ color: '#012068' }}>
{/* Status badge for alumni */}
{(isRetired || isResigned) && (
<div className="mb-2">
<span
className="inline-block px-2 py-0.5 text-xs font-medium rounded-full text-white"
style={{ backgroundColor: isResigned ? '#6b7280' : '#dc2626' }}
>
{isResigned ? 'Resigned' : 'Retired'}
</span>
</div>
)}
<h3
className="text-lg font-medium mb-2 group-hover:opacity-70 transition-opacity"
style={{ color: '#012068' }}
>
{member.name}
</h3>
<p className="text-sm leading-relaxed" style={{ color: '#e64838' }}>
{member.position}
</p>
{!isNonClickable && (
<>
{member.department && (
@@ -196,8 +220,8 @@ const TeamListing: React.FC<TeamListingProps> = ({
<section className="py-4" style={{ backgroundColor: '#f4f4f4' }}>
<div className="max-w-7xl mx-auto px-4">
<nav className="flex items-center space-x-2 text-sm">
<Link
href="/"
<Link
href="/"
className="hover:opacity-70 transition-opacity duration-200"
style={{ color: '#012068' }}
>
@@ -208,7 +232,7 @@ const TeamListing: React.FC<TeamListingProps> = ({
Faculty
</span>
</nav>
<div className="mt-6">
<div className="flex items-center mb-4">
<h1 className="text-3xl font-bold" style={{ color: '#012068' }}>
@@ -216,7 +240,9 @@ const TeamListing: React.FC<TeamListingProps> = ({
</h1>
</div>
<p className="text-base max-w-3xl leading-relaxed" style={{ color: '#333' }}>
Meet our dedicated team of medical professionals, researchers, and support staff committed to advancing healthcare, education, and patient outcomes at Christian Medical College, Vellore
Meet our dedicated team of medical professionals, researchers, and support staff
committed to advancing healthcare, education, and patient outcomes at Christian
Medical College, Vellore
</p>
</div>
</div>
@@ -243,8 +269,8 @@ const TeamListing: React.FC<TeamListingProps> = ({
</section>
)}
{/* Retired Staff Section */}
{retiredStaff.length > 0 && (
{/* Faculty Alumni Section — RETIRED + RESIGNED */}
{alumniStaff.length > 0 && (
<section className="py-8" style={{ backgroundColor: '#f9f9f9' }}>
<div className="max-w-7xl mx-auto px-4">
<div className="mb-8">
@@ -252,11 +278,11 @@ const TeamListing: React.FC<TeamListingProps> = ({
Faculty Alumni
</h2>
<p className="text-sm mb-2" style={{ color: '#666' }}>
Honoring our retired faculty and staff members for their dedicated service
Honoring our retired and former faculty members for their dedicated service
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{retiredStaff.map((member) => (
{alumniStaff.map((member) => (
<TeamMemberCard key={member.id} member={member} />
))}
</div>
@@ -273,10 +299,12 @@ const TeamListing: React.FC<TeamListingProps> = ({
Support Team
</h2>
<p className="text-base leading-relaxed mb-2" style={{ color: '#012068' }}>
<strong>Clinical Support Staff</strong> - Essential team members providing specialized support services
<strong>Clinical Support Staff</strong> — Essential team members providing
specialised support services
</p>
<p className="text-sm mb-1" style={{ color: '#012068' }}>
<strong>Administrative & Technical Support</strong> - Dedicated professionals ensuring smooth operations
<strong>Administrative &amp; Technical Support</strong> — Dedicated professionals
ensuring smooth operations
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
@@ -288,16 +316,43 @@ const TeamListing: React.FC<TeamListingProps> = ({
</section>
)}
{/* Trainees & Fellows Section */}
{traineesAndFellows.length > 0 && (
{/* Guides / Friends / Patrons Section */}
{guidesFriendsPatrons.length > 0 && (
<section className="py-8" style={{ backgroundColor: '#f9f9f9' }}>
<div className="max-w-7xl mx-auto px-4">
<div className="mb-8">
<h2 className="text-2xl font-bold mb-4" style={{ color: '#012068' }}>
Trainees & Fellows
Guides / Friends / Patrons
</h2>
<p className="text-base leading-relaxed mb-2" style={{ color: '#012068' }}>
<strong>Guides</strong> — Mentors and senior professionals who have shaped our
department
</p>
<p className="text-sm mb-1" style={{ color: '#012068' }}>
<strong>Friends &amp; Patrons</strong> — Valued supporters and well-wishers of our
institution
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{guidesFriendsPatrons.map((member) => (
<TeamMemberCard key={member.id} member={member} />
))}
</div>
</div>
</section>
)}
{/* Trainees & Fellows Section */}
{traineesAndFellows.length > 0 && (
<section className="py-8" style={{ backgroundColor: '#fff' }}>
<div className="max-w-7xl mx-auto px-4">
<div className="mb-8">
<h2 className="text-2xl font-bold mb-4" style={{ color: '#012068' }}>
Trainees &amp; Fellows
</h2>
<p className="text-sm mb-2" style={{ color: '#666' }}>
Medical trainees, residents, and fellows advancing their skills and contributing to patient care
Medical trainees, residents, and fellows advancing their skills and contributing
to patient care
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
@@ -309,7 +364,7 @@ const TeamListing: React.FC<TeamListingProps> = ({
</section>
)}
{/* Show message if no faculty data */}
{/* No data message */}
{teamMembers.length === 0 && !loading && (
<section className="py-16 text-center">
<div className="max-w-2xl mx-auto px-4">
@@ -317,10 +372,11 @@ const TeamListing: React.FC<TeamListingProps> = ({
No Faculty Data Available
</h2>
<p className="text-gray-600 mb-6">
Faculty information is currently being updated. Please check back later or contact administration.
Faculty information is currently being updated. Please check back later or contact
administration.
</p>
<button
onClick={() => window.location.reload()}
<button
onClick={() => window.location.reload()}
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
Refresh Page
@@ -328,20 +384,6 @@ const TeamListing: React.FC<TeamListingProps> = ({
</div>
</section>
)}
{/* Show message if all categories are empty but we have data */}
{teamMembers.length > 0 && facultyMembers.length === 0 && supportTeam.length === 0 && traineesAndFellows.length === 0 && retiredStaff.length === 0 && (
<section className="py-16 text-center">
<div className="max-w-2xl mx-auto px-4">
<h2 className="text-2xl font-bold mb-4" style={{ color: '#012068' }}>
No Categorized Faculty Available
</h2>
<p className="text-gray-600 mb-6">
Faculty members need to be assigned to categories. Please contact administration.
</p>
</div>
</section>
)}
</div>
);
};
+228 -112
View File
@@ -1,9 +1,9 @@
'use client'
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import {
Phone,
Mail,
import {
Phone,
Mail,
Share,
ChevronRight,
Check,
@@ -16,6 +16,8 @@ interface TeamMemberDetailProps {
memberData?: TeamMember;
}
const GUIDES_FRIENDS_PATRONS_CATEGORIES = ['GUIDES', 'FRIENDS', 'PATRONS'];
const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberData }) => {
const [member, setMember] = useState<TeamMember | null>(memberData || null);
const [loading, setLoading] = useState(!memberData);
@@ -25,7 +27,7 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
useEffect(() => {
const loadMemberData = async () => {
if (memberData) return; // Already have data
if (memberData) return;
try {
setLoading(true);
@@ -62,8 +64,8 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<p className="text-red-600 mb-4">{error || 'Faculty member not found'}</p>
<Link
href="/teamMember"
<Link
href="/teamMember"
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
>
Back to Faculty
@@ -75,56 +77,87 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
const isTrainee = member.category === 'TRAINEE_FELLOW';
const isRetired = member.status === 'RETIRED';
const isResigned = member.category === 'RESIGNED';
const isGuidesFriendsPatrons = GUIDES_FRIENDS_PATRONS_CATEGORIES.includes(member.category);
// Check if image URL is valid and not a default placeholder
const hasValidImage = member.image &&
member.image.trim() !== '' &&
!member.image.includes('default-avatar') &&
!member.image.includes('placeholder.') &&
!member.image.includes('robot') &&
// Only filter if URL ENDS with /profile-image (backend default endpoint)
!(member.image.endsWith('/profile-image') ||
member.image.includes('/profile-image?') ||
member.image === 'https://via.placeholder.com/400');
const hasValidImage =
member.image &&
member.image.trim() !== '' &&
!member.image.includes('default-avatar') &&
!member.image.includes('placeholder.') &&
!member.image.includes('robot') &&
!(
member.image.endsWith('/profile-image') ||
member.image.includes('/profile-image?') ||
member.image === 'https://via.placeholder.com/400'
);
const shouldShowImage = !isTrainee && hasValidImage && !imageError;
const shouldShowImage = !isTrainee && !isGuidesFriendsPatrons && hasValidImage && !imageError;
// Create a comprehensive description from the member's details
const getFullDescription = () => {
return member.description || `${member.name} is a dedicated member of our ${isTrainee ? 'trainee program' : 'faculty'} with expertise in ${member.specialty?.toLowerCase() || 'medical practice'}. They bring valuable experience in ${isTrainee ? 'clinical training' : 'surgical education'}, patient care, and clinical research to Christian Medical College, Vellore.`;
return (
member.description ||
`${member.name} is a dedicated member of our ${isTrainee ? 'trainee program' : 'faculty'} with expertise in ${member.specialty?.toLowerCase() || 'medical practice'}. They bring valuable experience in ${isTrainee ? 'clinical training' : 'surgical education'}, patient care, and clinical research to Christian Medical College, Vellore.`
);
};
// Parse phone numbers if multiple are provided
const getFormattedPhone = () => {
if (!member.phone || member.phone === 'Not available') {
return 'Contact through main office';
}
return member.phone.includes(',')
? member.phone.split(',').map(p => p.trim()).join(' / ')
return member.phone.includes(',')
? member.phone
.split(',')
.map((p) => p.trim())
.join(' / ')
: member.phone;
};
const handleImageError = (e: React.SyntheticEvent<HTMLImageElement>) => {
console.error('Image failed to load:', member.image);
const handleImageError = () => {
setImageError(true);
};
// Determine status badge config
const getStatusBadge = () => {
if (isRetired) {
return { label: 'RETIRED', bg: '#dc2626' };
}
if (isResigned) {
return { label: 'RESIGNED', bg: '#6b7280' };
}
if (isTrainee) {
return { label: 'Trainee / Fellow', bg: '#374151' };
}
if (isGuidesFriendsPatrons) {
const labels: Record<string, string> = {
GUIDES: 'Guide',
FRIENDS: 'Friend',
PATRONS: 'Patron',
};
return { label: labels[member.category] || member.category, bg: '#012068' };
}
return null;
};
const statusBadge = getStatusBadge();
return (
<div className="min-h-screen bg-white">
{/* Breadcrumb Section */}
<section className="py-4" style={{ backgroundColor: '#f4f4f4' }}>
<div className="max-w-7xl mx-auto px-4">
<nav className="flex items-center space-x-2 text-sm">
<Link
href="/"
<Link
href="/"
className="hover:opacity-70 transition-opacity duration-200"
style={{ color: '#012068' }}
>
Home
</Link>
<ChevronRight className="w-4 h-4" style={{ color: '#012068' }} />
<Link
href="/teamMember"
<Link
href="/teamMember"
className="hover:opacity-70 transition-opacity duration-200"
style={{ color: '#012068' }}
>
@@ -135,26 +168,25 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
{member.name}
</span>
</nav>
{/* Page Header */}
<div className="mt-6">
<div className="flex items-center mb-4">
<div className="flex items-center flex-wrap gap-3 mb-4">
<h1 className="text-3xl font-bold" style={{ color: '#012068' }}>
{member.name}
</h1>
{isTrainee && (
<span className="ml-4 px-3 py-1 text-xs font-medium rounded-full bg-gray-200 text-gray-700">
Trainee/Fellow
</span>
)}
{isRetired && (
<span className="ml-4 px-3 py-1 text-xs font-medium rounded-full bg-red-600 text-white">
RETIRED
{statusBadge && (
<span
className="px-3 py-1 text-xs font-medium rounded-full text-white"
style={{ backgroundColor: statusBadge.bg }}
>
{statusBadge.label}
</span>
)}
</div>
<p className="text-base max-w-2xl leading-relaxed" style={{ color: '#333' }}>
{member.designation || member.position} {member.experience && `with ${member.experience} of experience`} at CMC Vellore
{member.designation || member.position}{' '}
{member.experience && `with ${member.experience} of experience`} at CMC Vellore
</p>
</div>
</div>
@@ -169,112 +201,143 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
{/* Profile Image or Avatar */}
<div className="aspect-square relative overflow-hidden bg-gray-50">
{shouldShowImage ? (
<img
src={member.image}
<img
src={member.image}
alt={member.name}
className="w-full h-full object-cover transform hover:scale-105 transition-transform duration-300"
onError={handleImageError}
/>
) : (
<div
<div
className="w-full h-full flex items-center justify-center"
style={{ backgroundColor: '#e0e5eb' }}
>
<svg
<svg
className="w-48 h-48 text-gray-400"
fill="currentColor"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
</svg>
</div>
)}
</div>
{/* Profile Info */}
<div className="p-4 sm:p-6">
<div className="mb-6">
<div
<div
className="inline-flex items-center py-1 text-sm font-medium mb-3"
style={{ color: '#012068' }}
>
{member.designation || member.position}
</div>
<h2 className="text-xl font-bold mb-2" style={{ color: '#012068' }}>{member.name}</h2>
<h2 className="text-xl font-bold mb-2" style={{ color: '#012068' }}>
{member.name}
</h2>
</div>
<p className="text-sm mb-6 leading-relaxed" style={{ color: '#333' }}>
{member.specialty || `${member.name} is a dedicated ${isTrainee ? 'trainee' : 'faculty member'} at CMC Vellore.`}
{member.specialty ||
`${member.name} is a dedicated ${isTrainee ? 'trainee' : 'faculty member'} at CMC Vellore.`}
</p>
<div className="space-y-4 mb-6">
<div className="flex items-start">
<Phone className="w-4 h-4 mr-3 mt-0.5 flex-shrink-0" style={{ color: '#e64838' }} />
<Phone
className="w-4 h-4 mr-3 mt-0.5 flex-shrink-0"
style={{ color: '#e64838' }}
/>
<div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>Phone</div>
<div className="text-sm" style={{ color: '#333' }}>{getFormattedPhone()}</div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>
Phone
</div>
<div className="text-sm" style={{ color: '#333' }}>
{getFormattedPhone()}
</div>
</div>
</div>
<div className="flex items-start">
<Mail className="w-4 h-4 mr-3 mt-0.5 flex-shrink-0" style={{ color: '#e64838' }} />
<Mail
className="w-4 h-4 mr-3 mt-0.5 flex-shrink-0"
style={{ color: '#e64838' }}
/>
<div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>Email</div>
<a href={`mailto:${member.email}`} className="text-sm hover:underline transition-colors" style={{ color: '#e64838' }}>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>
Email
</div>
<a
href={`mailto:${member.email}`}
className="text-sm hover:underline transition-colors"
style={{ color: '#e64838' }}
>
{member.email}
</a>
</div>
</div>
{member.experience && (
<div className="flex items-start">
<div
<div
className="w-4 h-4 rounded-full mr-3 mt-0.5 flex-shrink-0 flex items-center justify-center"
style={{ backgroundColor: '#e64838' }}
>
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
<div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>Experience</div>
<div className="text-sm" style={{ color: '#333' }}>{member.experience}</div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>
Experience
</div>
<div className="text-sm" style={{ color: '#333' }}>
{member.experience}
</div>
</div>
</div>
)}
{member.department && (
<div className="flex items-start">
<div
<div
className="w-4 h-4 rounded-full mr-3 mt-0.5 flex-shrink-0 flex items-center justify-center"
style={{ backgroundColor: '#012068' }}
>
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
<div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>Department</div>
<div className="text-sm" style={{ color: '#333' }}>{member.department}</div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>
Department
</div>
<div className="text-sm" style={{ color: '#333' }}>
{member.department}
</div>
</div>
</div>
)}
{member.officeLocation && (
<div className="flex items-start">
<div
<div
className="w-4 h-4 rounded-full mr-3 mt-0.5 flex-shrink-0 flex items-center justify-center"
style={{ backgroundColor: '#012068' }}
>
<div className="w-2 h-2 bg-white rounded-full"></div>
</div>
<div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>Office Location</div>
<div className="text-sm" style={{ color: '#333' }}>{member.officeLocation}</div>
<div className="text-sm font-medium mb-1" style={{ color: '#012068' }}>
Office Location
</div>
<div className="text-sm" style={{ color: '#333' }}>
{member.officeLocation}
</div>
</div>
</div>
)}
</div>
{/* Social Share */}
<div className="relative">
<button
<button
onClick={() => setShowSocialShare(!showSocialShare)}
className="flex items-center justify-center w-full px-4 py-3 rounded-lg transition-opacity font-medium text-sm hover:opacity-90"
style={{ backgroundColor: '#f4f4f4', color: '#012068' }}
@@ -290,57 +353,84 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
{/* Main Content */}
<div className="xl:col-span-3">
<div className="bg-white rounded-md border border-gray-300 overflow-hidden">
{/* Personal Info */}
<div className="p-6 sm:p-8">
<div className="mb-8">
<div className="flex items-center mb-6">
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>About</h3>
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>
About
</h3>
</div>
<div className="prose prose-lg max-w-none mb-8 leading-relaxed">
<p className="text-base text-gray-700">
{getFullDescription()}
</p>
<p className="text-base text-gray-700">{getFullDescription()}</p>
<p className="mt-6 text-base text-gray-700">
As a dedicated member of the Department of {member.department || 'Medicine'} at Christian Medical College, Vellore,
{member.name.split(' ')[1] || member.name} contributes to advancing medical education, patient care, and
clinical research. Their commitment to excellence in healthcare and medical education makes
them an invaluable asset to the medical community and the patients they serve.
As a dedicated member of the Department of {member.department || 'Medicine'}{' '}
at Christian Medical College, Vellore,{' '}
{member.name.split(' ')[1] || member.name} contributes to advancing medical
education, patient care, and clinical research. Their commitment to excellence
in healthcare and medical education makes them an invaluable asset to the
medical community and the patients they serve.
</p>
</div>
{/* Details Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-6">
<div className="rounded-lg p-4 border border-gray-300" style={{ backgroundColor: '#f4f4f4' }}>
<div className="font-medium mb-2 text-sm" style={{ color: '#012068' }}>Education & Certification</div>
<div className="text-sm leading-relaxed" style={{ color: '#333' }}>{member.certification || 'Medical certification details available upon request'}</div>
<div
className="rounded-lg p-4 border border-gray-300"
style={{ backgroundColor: '#f4f4f4' }}
>
<div className="font-medium mb-2 text-sm" style={{ color: '#012068' }}>
Education &amp; Certification
</div>
<div className="text-sm leading-relaxed" style={{ color: '#333' }}>
{member.certification ||
'Medical certification details available upon request'}
</div>
</div>
</div>
<div className="space-y-6">
{/* Only show Training section if NOT retired */}
{!isRetired && (
<div className="rounded-lg p-4 border border-gray-300" style={{ backgroundColor: '#f4f4f4' }}>
<div className="font-medium mb-2 text-sm" style={{ color: '#012068' }}>Training & Professional Development</div>
<div className="text-sm leading-relaxed" style={{ color: '#333' }}>{member.training || 'Professional training details available upon request'}</div>
{/* Hide Training section for retired and resigned */}
{!isRetired && !isResigned && (
<div
className="rounded-lg p-4 border border-gray-300"
style={{ backgroundColor: '#f4f4f4' }}
>
<div className="font-medium mb-2 text-sm" style={{ color: '#012068' }}>
Training &amp; Professional Development
</div>
<div className="text-sm leading-relaxed" style={{ color: '#333' }}>
{member.training ||
'Professional training details available upon request'}
</div>
</div>
)}
{member.workDays && member.workDays.length > 0 && (
<div className="rounded-lg p-4 border border-gray-300" style={{ backgroundColor: '#f4f4f4' }}>
<div className="font-medium mb-3 text-sm" style={{ color: '#012068' }}>Clinical Days</div>
<div
className="rounded-lg p-4 border border-gray-300"
style={{ backgroundColor: '#f4f4f4' }}
>
<div className="font-medium mb-3 text-sm" style={{ color: '#012068' }}>
Clinical Days
</div>
<div className="space-y-2">
{member.workDays.map((day, index) => (
<div key={index} className="flex items-center">
<div
<div
className="w-4 h-4 rounded flex items-center justify-center mr-3"
style={{ backgroundColor: '#e64838' }}
>
<Check className="w-3 h-3 text-white" />
</div>
<span className="text-sm font-medium" style={{ color: '#012068' }}>{day}</span>
<span
className="text-sm font-medium"
style={{ color: '#012068' }}
>
{day}
</span>
</div>
))}
</div>
@@ -356,18 +446,30 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
{member.skills && member.skills.length > 0 && (
<div>
<div className="flex items-center mb-6">
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>Research Interests & Expertise</h3>
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>
Research Interests &amp; Expertise
</h3>
</div>
<p className="text-sm mb-6 leading-relaxed" style={{ color: '#333' }}>
Areas of clinical expertise, research focus, and professional competencies that contribute to advancing medical practice and education at CMC Vellore.
Areas of clinical expertise, research focus, and professional competencies
that contribute to advancing medical practice and education at CMC Vellore.
</p>
<div className="space-y-4">
{member.skills.map((skill, index) => (
<div key={index} className="rounded-lg p-4 border border-gray-300" style={{ backgroundColor: '#f4f4f4' }}>
<div
key={index}
className="rounded-lg p-4 border border-gray-300"
style={{ backgroundColor: '#f4f4f4' }}
>
<div className="flex justify-between items-center">
<span className="font-medium text-sm" style={{ color: '#012068' }}>{skill.name}</span>
<span
className="font-medium text-sm"
style={{ color: '#012068' }}
>
{skill.name}
</span>
{skill.level}
</div>
</div>
@@ -380,19 +482,26 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
{member.awards && member.awards.length > 0 && (
<div>
<div className="flex items-center mb-6">
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>Awards and Recognition</h3>
<h3 className="text-xl font-semibold" style={{ color: '#012068' }}>
Awards and Recognition
</h3>
</div>
<p className="text-sm mb-6 leading-relaxed" style={{ color: '#333' }}>
Professional achievements, awards, and recognition received for excellence in medical practice, research, and education.
Professional achievements, awards, and recognition received for excellence
in medical practice, research, and education.
</p>
<div className="space-y-6">
{member.awards.map((award, index) => (
<div key={index} className="rounded-lg p-4 border border-gray-300" style={{ backgroundColor: '#f4f4f4' }}>
<div
key={index}
className="rounded-lg p-4 border border-gray-300"
style={{ backgroundColor: '#f4f4f4' }}
>
<div className="flex items-start space-x-3">
<img
src={award.image}
<img
src={award.image}
alt={award.title}
className="w-12 h-12 rounded object-cover border border-gray-300 flex-shrink-0"
onError={(e) => {
@@ -401,14 +510,21 @@ const TeamMemberDetail: React.FC<TeamMemberDetailProps> = ({ memberId, memberDat
}}
/>
<div className="flex-1">
<div
<div
className="inline-flex items-center px-2 py-1 rounded text-xs font-medium mb-2"
style={{ backgroundColor: '#e64838', color: 'white' }}
>
{award.year}
</div>
<h4 className="text-base font-medium mb-2" style={{ color: '#012068' }}>{award.title}</h4>
<p className="text-sm leading-relaxed" style={{ color: '#333' }}>{award.description}</p>
<h4
className="text-base font-medium mb-2"
style={{ color: '#012068' }}
>
{award.title}
</h4>
<p className="text-sm leading-relaxed" style={{ color: '#333' }}>
{award.description}
</p>
</div>
</div>
</div>