Team and service update

This commit is contained in:
2025-11-12 10:13:03 +05:30
parent 8eeed12d0b
commit d1173ed400
4 changed files with 239 additions and 203 deletions

View File

@ -21,6 +21,24 @@
width: calc(100% - 260px);
max-width: 1600px;
}
.form-textarea:disabled,
.form-input:disabled {
background: #f3f4f6;
color: #9ca3af;
cursor: not-allowed;
opacity: 0.7;
}
.form-text {
font-size: 12px;
margin-top: 4px;
display: block;
}
.text-muted {
color: #6b7280;
font-style: italic;
}
/* Header Section */
.professor-header {

View File

@ -13,14 +13,8 @@
<div class="header-actions">
<div class="search-box">
<i class="fa fa-search"></i>
<input
name="searchTerm"
#searchTerm="ngModel"
class="search-input"
type="search"
placeholder="Search professors..."
ngModel
(ngModelChange)="searchProfessors(searchTerm.value)">
<input name="searchTerm" #searchTerm="ngModel" class="search-input" type="search"
placeholder="Search professors..." ngModel (ngModelChange)="searchProfessors(searchTerm.value)">
</div>
<button *ngIf="isManager" class="btn-primary" data-bs-toggle="modal" data-bs-target="#addProfessorModal">
<i class="fa fa-plus"></i>
@ -71,22 +65,19 @@
<span class="department-text">{{ professor?.department || 'N/A' }}</span>
</td>
<td (click)="onSelectProfessor(professor)">
<span class="category-badge"
[class.badge-faculty]="professor?.category === 'FACULTY'"
[class.badge-support]="professor?.category === 'SUPPORT_TEAM'"
[class.badge-trainee]="professor?.category === 'TRAINEE_FELLOW'">
<span class="category-badge" [class.badge-faculty]="professor?.category === 'FACULTY'"
[class.badge-support]="professor?.category === 'SUPPORT_TEAM'"
[class.badge-trainee]="professor?.category === 'TRAINEE_FELLOW'">
{{ getCategoryDisplayName(professor?.category) }}
</span>
</td>
<td (click)="onSelectProfessor(professor)">
<span class="status-badge"
[class.status-active]="professor?.status === WorkingStatus.ACTIVE"
[class.status-leave]="professor?.status === WorkingStatus.ON_LEAVE"
[class.status-retired]="professor?.status === WorkingStatus.RETIRED">
<i class="fa"
[class.fa-check-circle]="professor?.status === WorkingStatus.ACTIVE"
[class.fa-pause-circle]="professor?.status === WorkingStatus.ON_LEAVE"
[class.fa-times-circle]="professor?.status === WorkingStatus.RETIRED"></i>
<span class="status-badge" [class.status-active]="professor?.status === WorkingStatus.ACTIVE"
[class.status-leave]="professor?.status === WorkingStatus.ON_LEAVE"
[class.status-retired]="professor?.status === WorkingStatus.RETIRED">
<i class="fa" [class.fa-check-circle]="professor?.status === WorkingStatus.ACTIVE"
[class.fa-pause-circle]="professor?.status === WorkingStatus.ON_LEAVE"
[class.fa-times-circle]="professor?.status === WorkingStatus.RETIRED"></i>
{{ professor?.status }}
</span>
</td>
@ -95,7 +86,8 @@
<button class="btn-action btn-edit" (click)="onEditProfessor(professor)" title="Edit">
<i class="fas fa-edit"></i>
</button>
<button *ngIf="isAdmin" class="btn-action btn-delete" (click)="onDeleteProfessor(professor)" title="Delete">
<button *ngIf="isAdmin" class="btn-action btn-delete" (click)="onDeleteProfessor(professor)"
title="Delete">
<i class="fas fa-trash"></i>
</button>
</div>
@ -116,8 +108,10 @@
</div>
<!-- Hidden Modal Triggers -->
<button [hidden]="true" type="button" id="openProfessorInfo" data-bs-toggle="modal" data-bs-target="#viewProfessorModal"></button>
<button [hidden]="true" type="button" id="openProfessorEdit" data-bs-toggle="modal" data-bs-target="#editProfessorModal"></button>
<button [hidden]="true" type="button" id="openProfessorInfo" data-bs-toggle="modal"
data-bs-target="#viewProfessorModal"></button>
<button [hidden]="true" type="button" id="openProfessorEdit" data-bs-toggle="modal"
data-bs-target="#editProfessorModal"></button>
<button [hidden]="true" type="button" id="new-professor-close" data-bs-dismiss="modal"></button>
<button [hidden]="true" type="button" id="closeEditProfessorButton" data-bs-dismiss="modal"></button>
@ -141,16 +135,14 @@
<h4>{{ selectedProfessor.firstName }} {{ selectedProfessor.lastName }}</h4>
<p class="email">{{ selectedProfessor.email }}</p>
<div class="badges-row">
<span class="category-badge"
[class.badge-faculty]="selectedProfessor.category === 'FACULTY'"
[class.badge-support]="selectedProfessor.category === 'SUPPORT_TEAM'"
[class.badge-trainee]="selectedProfessor.category === 'TRAINEE_FELLOW'">
<span class="category-badge" [class.badge-faculty]="selectedProfessor.category === 'FACULTY'"
[class.badge-support]="selectedProfessor.category === 'SUPPORT_TEAM'"
[class.badge-trainee]="selectedProfessor.category === 'TRAINEE_FELLOW'">
{{ getCategoryDisplayName(selectedProfessor.category) }}
</span>
<span class="status-badge"
[class.status-active]="selectedProfessor.status === 'ACTIVE'"
[class.status-leave]="selectedProfessor.status === 'ON_LEAVE'"
[class.status-retired]="selectedProfessor.status === 'RETIRED'">
<span class="status-badge" [class.status-active]="selectedProfessor.status === 'ACTIVE'"
[class.status-leave]="selectedProfessor.status === 'ON_LEAVE'"
[class.status-retired]="selectedProfessor.status === 'RETIRED'">
{{ selectedProfessor.status }}
</span>
</div>
@ -204,12 +196,14 @@
<p>{{ selectedProfessor.description }}</p>
</div>
<div class="detail-row" *ngIf="selectedProfessor.certification || selectedProfessor.training">
<div class="detail-row"
*ngIf="selectedProfessor.certification || (selectedProfessor.training && selectedProfessor.status !== WorkingStatus.RETIRED)">
<div class="detail-section" *ngIf="selectedProfessor.certification">
<h5>Certification</h5>
<p>{{ selectedProfessor.certification }}</p>
</div>
<div class="detail-section" *ngIf="selectedProfessor.training">
<div class="detail-section"
*ngIf="selectedProfessor.training && selectedProfessor.status !== WorkingStatus.RETIRED">
<h5>Training</h5>
<p>{{ selectedProfessor.training }}</p>
</div>
@ -256,26 +250,28 @@
</div>
<div class="modal-body">
<form #newProfessorForm="ngForm" (ngSubmit)="onAddNewProfessor(newProfessorForm)">
<!-- Basic Information Section -->
<div class="form-section">
<h4 class="section-title">Basic Information</h4>
<div class="form-row">
<div class="form-group">
<label for="firstName">
<i class="fa fa-user"></i>
First Name *
</label>
<input type="text" id="firstName" name="firstName" class="form-input" ngModel required placeholder="Enter first name">
<input type="text" id="firstName" name="firstName" class="form-input" ngModel required
placeholder="Enter first name">
</div>
<div class="form-group">
<label for="lastName">
<i class="fa fa-user"></i>
Last Name *
</label>
<input type="text" id="lastName" name="lastName" class="form-input" ngModel required placeholder="Enter last name">
<input type="text" id="lastName" name="lastName" class="form-input" ngModel required
placeholder="Enter last name">
</div>
</div>
@ -285,9 +281,10 @@
<i class="fa fa-envelope"></i>
Email *
</label>
<input type="email" id="email" name="email" class="form-input" ngModel required placeholder="professor@example.com">
<input type="email" id="email" name="email" class="form-input" ngModel required
placeholder="professor@example.com">
</div>
<div class="form-group">
<label for="phone">
<i class="fa fa-phone"></i>
@ -310,7 +307,7 @@
<option value="TRAINEE_FELLOW">Trainee/Fellow</option>
</select>
</div>
<div class="form-group">
<label for="status">
<i class="fa fa-info-circle"></i>
@ -328,7 +325,8 @@
<i class="fa fa-briefcase"></i>
Experience
</label>
<input type="text" id="experience" name="experience" class="form-input" ngModel placeholder="e.g., 10+ years">
<input type="text" id="experience" name="experience" class="form-input" ngModel
placeholder="e.g., 10+ years">
</div>
</div>
</div>
@ -336,22 +334,24 @@
<!-- Professional Details Section -->
<div class="form-section">
<h4 class="section-title">Professional Details</h4>
<div class="form-row">
<div class="form-group">
<label for="department">
<i class="fa fa-building"></i>
Department
</label>
<input type="text" id="department" name="department" class="form-input" ngModel placeholder="Enter department">
<input type="text" id="department" name="department" class="form-input" ngModel
placeholder="Enter department">
</div>
<div class="form-group">
<label for="position">
<i class="fa fa-id-badge"></i>
Position
</label>
<input type="text" id="position" name="position" class="form-input" ngModel placeholder="Enter position">
<input type="text" id="position" name="position" class="form-input" ngModel
placeholder="Enter position">
</div>
</div>
@ -361,15 +361,17 @@
<i class="fa fa-award"></i>
Designation
</label>
<input type="text" id="designation" name="designation" class="form-input" ngModel placeholder="Professional title">
<input type="text" id="designation" name="designation" class="form-input" ngModel
placeholder="Professional title">
</div>
<div class="form-group">
<label for="officeLocation">
<i class="fa fa-map-marker-alt"></i>
Office Location
</label>
<input type="text" id="officeLocation" name="officeLocation" class="form-input" ngModel placeholder="Office location">
<input type="text" id="officeLocation" name="officeLocation" class="form-input" ngModel
placeholder="Office location">
</div>
</div>
@ -378,7 +380,8 @@
<i class="fa fa-star"></i>
Specialty
</label>
<input type="text" id="specialty" name="specialty" class="form-input" ngModel placeholder="Medical specialty or area of expertise">
<input type="text" id="specialty" name="specialty" class="form-input" ngModel
placeholder="Medical specialty or area of expertise">
</div>
<div class="form-group">
@ -386,29 +389,37 @@
<i class="fa fa-align-left"></i>
Description
</label>
<textarea id="description" name="description" class="form-textarea" rows="3" ngModel placeholder="Brief professional description"></textarea>
<textarea id="description" name="description" class="form-textarea" rows="3" ngModel
placeholder="Brief professional description"></textarea>
</div>
</div>
<!-- Qualifications Section -->
<!-- Qualifications Section -->
<div class="form-section">
<h4 class="section-title">Qualifications</h4>
<div class="form-row">
<div class="form-group">
<label for="certification">
<i class="fa fa-certificate"></i>
Certification
</label>
<textarea id="certification" name="certification" class="form-textarea" rows="2" ngModel placeholder="Educational qualifications and certifications"></textarea>
<textarea id="certification" name="certification" class="form-textarea" rows="2" ngModel
placeholder="Educational qualifications and certifications"></textarea>
</div>
<div class="form-group">
<label for="training">
<i class="fa fa-graduation-cap"></i>
Training
Training & Professional Development
</label>
<textarea id="training" name="training" class="form-textarea" rows="2" ngModel placeholder="Professional training and development"></textarea>
<textarea id="training" name="training" class="form-textarea" rows="2" ngModel
placeholder="Professional training and development"
[disabled]="newProfessorForm.value.status === WorkingStatus.RETIRED"></textarea>
<small class="form-text text-muted" *ngIf="newProfessorForm.value.status === WorkingStatus.RETIRED">
Training field is disabled for retired faculty
</small>
</div>
</div>
</div>
@ -416,19 +427,15 @@
<!-- Work Days Section -->
<div class="form-section">
<h4 class="section-title">Work Schedule</h4>
<label class="work-days-label">
<i class="fa fa-calendar"></i>
Work Days
</label>
<div class="work-days-grid">
<div class="checkbox-wrapper" *ngFor="let day of availableDays">
<input type="checkbox"
[id]="'day-' + day"
[value]="day"
[(ngModel)]="selectedWorkDays[day]"
name="workDays"
class="checkbox-input">
<input type="checkbox" [id]="'day-' + day" [value]="day" [(ngModel)]="selectedWorkDays[day]"
name="workDays" class="checkbox-input">
<label [for]="'day-' + day" class="checkbox-label">
<span class="checkbox-custom"></span>
<span class="checkbox-text">{{ day }}</span>
@ -440,18 +447,21 @@
<!-- Awards Section -->
<div class="form-section">
<h4 class="section-title">Awards & Recognition</h4>
<div class="awards-manager">
<div class="award-item" *ngFor="let award of newProfessorAwards; let i = index">
<div class="award-fields">
<div class="form-group">
<input type="text" class="form-input" [(ngModel)]="award.title" [name]="'awardTitle' + i" placeholder="Award Title">
<input type="text" class="form-input" [(ngModel)]="award.title" [name]="'awardTitle' + i"
placeholder="Award Title">
</div>
<div class="form-group">
<input type="text" class="form-input" [(ngModel)]="award.year" [name]="'awardYear' + i" placeholder="Year">
<input type="text" class="form-input" [(ngModel)]="award.year" [name]="'awardYear' + i"
placeholder="Year">
</div>
<div class="form-group form-group-wide">
<textarea class="form-textarea" rows="2" [(ngModel)]="award.description" [name]="'awardDesc' + i" placeholder="Description"></textarea>
<textarea class="form-textarea" rows="2" [(ngModel)]="award.description"
[name]="'awardDesc' + i" placeholder="Description"></textarea>
</div>
<button type="button" class="btn-remove-award" (click)="removeAward(i)" title="Remove">
<i class="fas fa-trash"></i>
@ -465,32 +475,33 @@
</div>
</div>
<!-- Profile Picture Section -->
<!-- Profile Picture Section -->
<div class="form-section">
<h4 class="section-title">Profile Picture</h4>
<div class="form-group">
<label>
<i class="fa fa-image"></i>
Upload Profile Picture
</label>
<div class="file-upload-wrapper">
<input type="file"
id="newProfessorProfileImage"
accept="image/*"
name="profileImage"
(change)="onProfileImageChange($any($event).target.files)"
class="file-input"
[disabled]="newProfessorForm.value.category === 'TRAINEE_FELLOW'">
<label for="newProfessorProfileImage"
class="file-label"
[class.disabled]="newProfessorForm.value.category === 'TRAINEE_FELLOW'">
<input type="file" id="newProfessorProfileImage" accept="image/*" name="profileImage"
(change)="onProfileImageChange($any($event).target.files)" class="file-input"
[disabled]="newProfessorForm.value.category === 'TRAINEE_FELLOW' || newProfessorForm.value.category === 'SUPPORT_TEAM'">
<label for="newProfessorProfileImage" class="file-label"
[class.disabled]="newProfessorForm.value.category === 'TRAINEE_FELLOW' || newProfessorForm.value.category === 'SUPPORT_TEAM'">
<i class="fa fa-cloud-upload-alt"></i>
<span>{{ newProfessorForm.value.category === 'TRAINEE_FELLOW' ? 'Upload disabled for Trainee/Fellow' : (profileImageFileName || 'Choose profile picture') }}</span>
<span>{{ (newProfessorForm.value.category === 'TRAINEE_FELLOW' || newProfessorForm.value.category
=== 'SUPPORT_TEAM') ? 'Upload disabled for ' +
getCategoryDisplayName(newProfessorForm.value.category) : (profileImageFileName || 'Choose
profile picture') }}</span>
</label>
</div>
<small class="form-text text-muted" *ngIf="newProfessorForm.value.category === 'TRAINEE_FELLOW'">
Profile image upload is not available for Trainee/Fellow category
<small class="form-text text-muted"
*ngIf="newProfessorForm.value.category === 'TRAINEE_FELLOW' || newProfessorForm.value.category === 'SUPPORT_TEAM'">
Profile image upload is not available for {{ getCategoryDisplayName(newProfessorForm.value.category)
}} category
</small>
</div>
</div>
@ -521,26 +532,28 @@
</div>
<div class="modal-body">
<form #editProfessorForm="ngForm" (ngSubmit)="onUpdateProfessor(editProfessorForm)">
<!-- Basic Information Section -->
<div class="form-section">
<h4 class="section-title">Basic Information</h4>
<div class="form-row">
<div class="form-group">
<label for="editFirstName">
<i class="fa fa-user"></i>
First Name *
</label>
<input type="text" id="editFirstName" name="firstName" class="form-input" [(ngModel)]="selectedProfessor.firstName" required>
<input type="text" id="editFirstName" name="firstName" class="form-input"
[(ngModel)]="selectedProfessor.firstName" required>
</div>
<div class="form-group">
<label for="editLastName">
<i class="fa fa-user"></i>
Last Name *
</label>
<input type="text" id="editLastName" name="lastName" class="form-input" [(ngModel)]="selectedProfessor.lastName" required>
<input type="text" id="editLastName" name="lastName" class="form-input"
[(ngModel)]="selectedProfessor.lastName" required>
</div>
</div>
@ -550,15 +563,17 @@
<i class="fa fa-envelope"></i>
Email *
</label>
<input type="email" id="editEmail" name="email" class="form-input" [(ngModel)]="selectedProfessor.email" required>
<input type="email" id="editEmail" name="email" class="form-input"
[(ngModel)]="selectedProfessor.email" required>
</div>
<div class="form-group">
<label for="editPhone">
<i class="fa fa-phone"></i>
Phone
</label>
<input type="text" id="editPhone" name="phone" class="form-input" [(ngModel)]="selectedProfessor.phone">
<input type="text" id="editPhone" name="phone" class="form-input"
[(ngModel)]="selectedProfessor.phone">
</div>
</div>
@ -568,19 +583,21 @@
<i class="fa fa-tag"></i>
Category *
</label>
<select id="editCategory" name="category" class="form-select" [(ngModel)]="selectedProfessor.category" required>
<select id="editCategory" name="category" class="form-select"
[(ngModel)]="selectedProfessor.category" required>
<option value="FACULTY">Faculty</option>
<option value="SUPPORT_TEAM">Support Team</option>
<option value="TRAINEE_FELLOW">Trainee/Fellow</option>
</select>
</div>
<div class="form-group">
<label for="editStatus">
<i class="fa fa-info-circle"></i>
Status *
</label>
<select id="editStatus" name="status" class="form-select" [(ngModel)]="selectedProfessor.status" required>
<select id="editStatus" name="status" class="form-select" [(ngModel)]="selectedProfessor.status"
required>
<option [value]="WorkingStatus.ACTIVE">Active</option>
<option [value]="WorkingStatus.ON_LEAVE">On Leave</option>
<option [value]="WorkingStatus.RETIRED">Retired</option>
@ -592,7 +609,8 @@
<i class="fa fa-briefcase"></i>
Experience
</label>
<input type="text" id="editExperience" name="experience" class="form-input" [(ngModel)]="selectedProfessor.experience">
<input type="text" id="editExperience" name="experience" class="form-input"
[(ngModel)]="selectedProfessor.experience">
</div>
</div>
</div>
@ -600,22 +618,24 @@
<!-- Professional Details Section -->
<div class="form-section">
<h4 class="section-title">Professional Details</h4>
<div class="form-row">
<div class="form-group">
<label for="editDepartment">
<i class="fa fa-building"></i>
Department
</label>
<input type="text" id="editDepartment" name="department" class="form-input" [(ngModel)]="selectedProfessor.department">
<input type="text" id="editDepartment" name="department" class="form-input"
[(ngModel)]="selectedProfessor.department">
</div>
<div class="form-group">
<label for="editPosition">
<i class="fa fa-id-badge"></i>
Position
</label>
<input type="text" id="editPosition" name="position" class="form-input" [(ngModel)]="selectedProfessor.position">
<input type="text" id="editPosition" name="position" class="form-input"
[(ngModel)]="selectedProfessor.position">
</div>
</div>
@ -625,15 +645,17 @@
<i class="fa fa-award"></i>
Designation
</label>
<input type="text" id="editDesignation" name="designation" class="form-input" [(ngModel)]="selectedProfessor.designation">
<input type="text" id="editDesignation" name="designation" class="form-input"
[(ngModel)]="selectedProfessor.designation">
</div>
<div class="form-group">
<label for="editOfficeLocation">
<i class="fa fa-map-marker-alt"></i>
Office Location
</label>
<input type="text" id="editOfficeLocation" name="officeLocation" class="form-input" [(ngModel)]="selectedProfessor.officeLocation">
<input type="text" id="editOfficeLocation" name="officeLocation" class="form-input"
[(ngModel)]="selectedProfessor.officeLocation">
</div>
</div>
@ -642,7 +664,8 @@
<i class="fa fa-star"></i>
Specialty
</label>
<input type="text" id="editSpecialty" name="specialty" class="form-input" [(ngModel)]="selectedProfessor.specialty">
<input type="text" id="editSpecialty" name="specialty" class="form-input"
[(ngModel)]="selectedProfessor.specialty">
</div>
<div class="form-group">
@ -650,29 +673,36 @@
<i class="fa fa-align-left"></i>
Description
</label>
<textarea id="editDescription" name="description" class="form-textarea" rows="3" [(ngModel)]="selectedProfessor.description"></textarea>
<textarea id="editDescription" name="description" class="form-textarea" rows="3"
[(ngModel)]="selectedProfessor.description"></textarea>
</div>
</div>
<!-- Qualifications Section -->
<div class="form-section">
<h4 class="section-title">Qualifications</h4>
<div class="form-row">
<div class="form-group">
<label for="editCertification">
<i class="fa fa-certificate"></i>
Certification
</label>
<textarea id="editCertification" name="certification" class="form-textarea" rows="2" [(ngModel)]="selectedProfessor.certification"></textarea>
<textarea id="editCertification" name="certification" class="form-textarea" rows="2"
[(ngModel)]="selectedProfessor.certification"></textarea>
</div>
<div class="form-group">
<label for="editTraining">
<i class="fa fa-graduation-cap"></i>
Training
Training & Professional Development
</label>
<textarea id="editTraining" name="training" class="form-textarea" rows="2" [(ngModel)]="selectedProfessor.training"></textarea>
<textarea id="editTraining" name="training" class="form-textarea" rows="2"
[(ngModel)]="selectedProfessor.training"
[disabled]="selectedProfessor.status === WorkingStatus.RETIRED"></textarea>
<small class="form-text text-muted" *ngIf="selectedProfessor.status === WorkingStatus.RETIRED">
Training field is disabled for retired faculty
</small>
</div>
</div>
</div>
@ -680,19 +710,15 @@
<!-- Work Days Section -->
<div class="form-section">
<h4 class="section-title">Work Schedule</h4>
<label class="work-days-label">
<i class="fa fa-calendar"></i>
Work Days
</label>
<div class="work-days-grid">
<div class="checkbox-wrapper" *ngFor="let day of availableDays">
<input type="checkbox"
[id]="'edit-day-' + day"
[value]="day"
[(ngModel)]="selectedWorkDays[day]"
name="editWorkDays"
class="checkbox-input">
<input type="checkbox" [id]="'edit-day-' + day" [value]="day" [(ngModel)]="selectedWorkDays[day]"
name="editWorkDays" class="checkbox-input">
<label [for]="'edit-day-' + day" class="checkbox-label">
<span class="checkbox-custom"></span>
<span class="checkbox-text">{{ day }}</span>
@ -704,18 +730,21 @@
<!-- Awards Section -->
<div class="form-section">
<h4 class="section-title">Awards & Recognition</h4>
<div class="awards-manager">
<div class="award-item" *ngFor="let award of selectedProfessorAwards; let i = index">
<div class="award-fields">
<div class="form-group">
<input type="text" class="form-input" [(ngModel)]="award.title" [name]="'editAwardTitle' + i" placeholder="Award Title">
<input type="text" class="form-input" [(ngModel)]="award.title" [name]="'editAwardTitle' + i"
placeholder="Award Title">
</div>
<div class="form-group">
<input type="text" class="form-input" [(ngModel)]="award.year" [name]="'editAwardYear' + i" placeholder="Year">
<input type="text" class="form-input" [(ngModel)]="award.year" [name]="'editAwardYear' + i"
placeholder="Year">
</div>
<div class="form-group form-group-wide">
<textarea class="form-textarea" rows="2" [(ngModel)]="award.description" [name]="'editAwardDesc' + i" placeholder="Description"></textarea>
<textarea class="form-textarea" rows="2" [(ngModel)]="award.description"
[name]="'editAwardDesc' + i" placeholder="Description"></textarea>
</div>
<button type="button" class="btn-remove-award" (click)="removeEditAward(i)" title="Remove">
<i class="fas fa-trash"></i>
@ -729,32 +758,32 @@
</div>
</div>
<!-- Profile Picture Section -->
<!-- Profile Picture Section -->
<div class="form-section">
<h4 class="section-title">Profile Picture</h4>
<div class="form-group">
<label>
<i class="fa fa-image"></i>
Upload Profile Picture
</label>
<div class="file-upload-wrapper">
<input type="file"
id="editProfessorProfileImage"
accept="image/*"
name="profileImage"
(change)="onProfileImageChange($any($event).target.files)"
class="file-input"
[disabled]="!isManager || selectedProfessor.category === 'TRAINEE_FELLOW'">
<label for="editProfessorProfileImage"
class="file-label"
[class.disabled]="!isManager || selectedProfessor.category === 'TRAINEE_FELLOW'">
<input type="file" id="editProfessorProfileImage" accept="image/*" name="profileImage"
(change)="onProfileImageChange($any($event).target.files)" class="file-input"
[disabled]="!isManager || selectedProfessor.category === 'TRAINEE_FELLOW' || selectedProfessor.category === 'SUPPORT_TEAM'">
<label for="editProfessorProfileImage" class="file-label"
[class.disabled]="!isManager || selectedProfessor.category === 'TRAINEE_FELLOW' || selectedProfessor.category === 'SUPPORT_TEAM'">
<i class="fa fa-cloud-upload-alt"></i>
<span>{{ selectedProfessor.category === 'TRAINEE_FELLOW' ? 'Upload disabled for Trainee/Fellow' : (profileImageFileName || 'Choose profile picture') }}</span>
<span>{{ (selectedProfessor.category === 'TRAINEE_FELLOW' || selectedProfessor.category ===
'SUPPORT_TEAM') ? 'Upload disabled for ' + getCategoryDisplayName(selectedProfessor.category) :
(profileImageFileName || 'Choose profile picture') }}</span>
</label>
</div>
<small class="form-text text-muted" *ngIf="selectedProfessor.category === 'TRAINEE_FELLOW'">
Profile image upload is not available for Trainee/Fellow category
<small class="form-text text-muted"
*ngIf="selectedProfessor.category === 'TRAINEE_FELLOW' || selectedProfessor.category === 'SUPPORT_TEAM'">
Profile image upload is not available for {{ getCategoryDisplayName(selectedProfessor.category) }}
category
</small>
</div>
</div>
@ -763,7 +792,8 @@
</div>
<div class="modal-footer">
<button class="btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button class="btn-primary" (click)="editProfessorForm.ngSubmit.emit()" [disabled]="editProfessorForm.invalid">
<button class="btn-primary" (click)="editProfessorForm.ngSubmit.emit()"
[disabled]="editProfessorForm.invalid">
<i class="fa fa-save"></i>
Save Changes
</button>
@ -774,11 +804,8 @@
<!-- Profile Image Change Form (Hidden) -->
<form enctype="multipart/form-data" style="display:none;">
<input type="file"
(change)="onProfileImageChange($any($event).target.files); onUpdateProfileImage()"
name="profile-image-input"
id="profile-image-input"
accept="image/*"/>
<input type="file" (change)="onProfileImageChange($any($event).target.files); onUpdateProfileImage()"
name="profile-image-input" id="profile-image-input" accept="image/*" />
</form>
</div>

View File

@ -42,7 +42,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
public loggedInProfessor: Professor;
public refreshing: boolean;
private subs = new SubSink();
selectedProfessor: Professor = {
professorId: '',
firstName: '',
@ -79,16 +79,16 @@ export class ProfessorComponent implements OnInit, OnDestroy {
public selectedProfessorAwards: Award[] = [];
private closeModal(modalId: string): void {
const modalElement = document.getElementById(modalId);
if (!modalElement) return;
const modalElement = document.getElementById(modalId);
if (!modalElement) return;
const modalInstance = Modal.getInstance(modalElement) || new Modal(modalElement);
modalInstance.hide();
const modalInstance = Modal.getInstance(modalElement) || new Modal(modalElement);
modalInstance.hide();
// Force-remove leftover background overlays if any remain
document.body.classList.remove('modal-open');
document.querySelectorAll('.modal-backdrop').forEach(b => b.remove());
}
// Force-remove leftover background overlays if any remain
document.body.classList.remove('modal-open');
document.querySelectorAll('.modal-backdrop').forEach(b => b.remove());
}
constructor(
@ -96,7 +96,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
private notificationService: NotificationService,
private router: Router,
private authenticationService: AuthenticationService,
) {}
) { }
ngOnInit(): void {
this.getProfessors(true);
@ -233,12 +233,12 @@ export class ProfessorComponent implements OnInit, OnDestroy {
public onSelectProfessor(selectedProfessor: Professor): void {
// Create a deep copy to avoid reference issues
this.selectedProfessor = JSON.parse(JSON.stringify(selectedProfessor));
// Create a separate copy for awards to display
this.selectedProfessorAwards = selectedProfessor.awards
this.selectedProfessorAwards = selectedProfessor.awards
? JSON.parse(JSON.stringify(selectedProfessor.awards))
: [];
// Set up work days for viewing
this.selectedWorkDays = {};
if (selectedProfessor.workDays && Array.isArray(selectedProfessor.workDays)) {
@ -248,7 +248,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
}
});
}
this.clickButton('openProfessorInfo');
}
@ -260,8 +260,8 @@ export class ProfessorComponent implements OnInit, OnDestroy {
}
public onCategoryChange(category: string): void {
// Clear profile image if Trainee/Fellow is selected
if (category === 'TRAINEE_FELLOW') {
// Clear profile image if Trainee/Fellow or Support Team is selected
if (category === 'TRAINEE_FELLOW' || category === 'SUPPORT_TEAM') {
this.profileImage = null;
this.profileImageFileName = null;
// Reset file input
@ -335,7 +335,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
public onEditProfessor(professor: Professor): void {
// Create a deep copy to avoid reference issues
this.selectedProfessor = JSON.parse(JSON.stringify(professor));
// Set up work days for editing with validation
this.selectedWorkDays = {};
if (professor.workDays && Array.isArray(professor.workDays)) {
@ -347,10 +347,10 @@ export class ProfessorComponent implements OnInit, OnDestroy {
}
// Set up awards for editing - create a deep copy
this.selectedProfessorAwards = professor.awards
this.selectedProfessorAwards = professor.awards
? JSON.parse(JSON.stringify(professor.awards))
: [];
this.clickButton('openProfessorEdit');
}
@ -400,7 +400,13 @@ export class ProfessorComponent implements OnInit, OnDestroy {
formData.append('designation', professor.designation || professor.position || '');
formData.append('description', professor.description || '');
formData.append('certification', professor.certification || '');
formData.append('training', professor.training || '');
// Only include training if NOT retired
if (professor.status !== WorkingStatus.RETIRED) {
formData.append('training', professor.training || '');
} else {
formData.append('training', ''); // Clear training for retired faculty
}
// Work days - collect from selectedWorkDays object
const workDays = Object.keys(this.selectedWorkDays).filter(day => this.selectedWorkDays[day]);
@ -414,10 +420,10 @@ export class ProfessorComponent implements OnInit, OnDestroy {
const awardsToSubmit = professor.professorId ? this.selectedProfessorAwards : this.newProfessorAwards;
if (awardsToSubmit && awardsToSubmit.length > 0) {
// Filter out empty awards and only include those with at least title and year
const validAwards = awardsToSubmit.filter(award =>
const validAwards = awardsToSubmit.filter(award =>
award.title && award.title.trim() && award.year && award.year.trim()
);
validAwards.forEach((award, index) => {
formData.append(`awards[${index}].title`, award.title.trim());
formData.append(`awards[${index}].year`, award.year.trim());
@ -426,8 +432,8 @@ export class ProfessorComponent implements OnInit, OnDestroy {
});
}
// Profile image - only add if not Trainee/Fellow category
if (profileImage && professor.category !== 'TRAINEE_FELLOW') {
// Profile image - only add if not Trainee/Fellow or Support Team category
if (profileImage && professor.category !== 'TRAINEE_FELLOW' && professor.category !== 'SUPPORT_TEAM') {
formData.append('profileImage', profileImage);
}
@ -486,7 +492,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
case HttpEventType.UploadProgress:
this.fileUploadStatus.percentage = Math.round(100 * event.loaded / event.total!);
this.fileUploadStatus.status = 'progress';
break;
break;
case HttpEventType.Response:
if (event.status === 200) {
if (this.loggedInProfessor) {

View File

@ -10,9 +10,8 @@
<div class="header-actions">
<div class="search-box">
<i class="fa fa-search"></i>
<input name="searchTerm" #searchTerm="ngModel" class="search-input"
type="search" ngModel placeholder="Search service tiles..."
(ngModelChange)="searchServiceTiles(searchTerm.value)">
<input name="searchTerm" #searchTerm="ngModel" class="search-input" type="search" ngModel
placeholder="Search service tiles..." (ngModelChange)="searchServiceTiles(searchTerm.value)">
</div>
<button *ngIf="isManager" class="btn-primary" (click)="openAddModal()">
@ -26,19 +25,15 @@
</div>
<div class="service-tiles-list" *ngIf="serviceTiles?.length > 0">
<div *ngFor="let serviceTile of serviceTiles" class="service-tile-card"
[class.inactive]="!serviceTile?.isActive">
<div *ngFor="let serviceTile of serviceTiles" class="service-tile-card" [class.inactive]="!serviceTile?.isActive">
<div class="service-tile-content-area"
(click)="onSelectServiceTile(serviceTile)">
<div class="service-tile-content-area" (click)="onSelectServiceTile(serviceTile)">
<div class="service-tile-info">
<div class="service-tile-header-row">
<h3>{{ serviceTile?.title }}</h3>
<span class="status-badge"
[class.status-active]="serviceTile?.isActive"
<span class="status-badge" [class.status-active]="serviceTile?.isActive"
[class.status-inactive]="!serviceTile?.isActive">
<i class="fa"
[class.fa-check-circle]="serviceTile?.isActive"
<i class="fa" [class.fa-check-circle]="serviceTile?.isActive"
[class.fa-times-circle]="!serviceTile?.isActive"></i>
{{ serviceTile?.isActive ? 'Active' : 'Inactive' }}
</span>
@ -50,15 +45,12 @@
</div>
<div class="service-tile-actions">
<button class="btn-action btn-toggle"
(click)="onToggleActive(serviceTile); $event.stopPropagation()">
<i class="fas"
[class.fa-toggle-on]="serviceTile?.isActive"
<button class="btn-action btn-toggle" (click)="onToggleActive(serviceTile); $event.stopPropagation()">
<i class="fas" [class.fa-toggle-on]="serviceTile?.isActive"
[class.fa-toggle-off]="!serviceTile?.isActive"></i>
</button>
<button class="btn-action btn-edit"
(click)="onEditServiceTile(serviceTile); $event.stopPropagation()">
<button class="btn-action btn-edit" (click)="onEditServiceTile(serviceTile); $event.stopPropagation()">
<i class="fas fa-edit"></i>
</button>
@ -77,8 +69,7 @@
<p>Loading service tiles...</p>
</div>
<div *ngIf="!refreshing && (!serviceTiles || serviceTiles.length === 0)"
class="empty-state">
<div *ngIf="!refreshing && (!serviceTiles || serviceTiles.length === 0)" class="empty-state">
<div class="empty-icon">
<i class="fa fa-th-large"></i>
</div>
@ -104,8 +95,7 @@
<div class="detail-item"><span class="detail-label">Title:</span>
<span class="detail-value">{{ selectedServiceTile.title }}</span>
</div>
<div class="detail-item"><span
class="detail-label">Description:</span>
<div class="detail-item"><span class="detail-label">Description:</span>
<span class="detail-value">{{ selectedServiceTile.description }}</span>
</div>
<div class="detail-item"><span class="detail-label">Display
@ -124,8 +114,7 @@
<!-- Add Modal -->
<div class="modal fade" #addServiceTileModal tabindex="-1">
<div class="modal-dialog modal-lg">
<form class="modal-content" #newServiceTileForm="ngForm"
(ngSubmit)="onAddNewServiceTile(newServiceTileForm)">
<form class="modal-content" #newServiceTileForm="ngForm" (ngSubmit)="onAddNewServiceTile(newServiceTileForm)">
<div class="modal-header">
<h3>Add New Service Tile</h3>
<button type="button" class="modal-close" data-bs-dismiss="modal">
@ -138,21 +127,19 @@
<input class="form-input" name="title" ngModel required>
</div>
<div class="form-group">
<label>Description *</label>
<textarea class="form-textarea" name="description" ngModel required></textarea>
<label>Description * (Separate points with commas)</label>
<textarea class="form-textarea" name="description" ngModel required
placeholder="e.g., Point one, Point two, Point three"></textarea>
</div>
<div class="form-group">
<label>Display Order</label>
<input type="number" class="form-input" name="displayOrder"
ngModel value="0">
<input type="number" class="form-input" name="displayOrder" ngModel value="0">
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" type="button"
data-bs-dismiss="modal">Cancel</button>
<button class="btn-primary" type="submit"
[disabled]="newServiceTileForm.invalid">
<button class="btn-secondary" type="button" data-bs-dismiss="modal">Cancel</button>
<button class="btn-primary" type="submit" [disabled]="newServiceTileForm.invalid">
<i class="fa fa-save"></i> Create
</button>
</div>
@ -163,8 +150,7 @@
<!-- Edit Modal -->
<div class="modal fade" #editServiceTileModal tabindex="-1">
<div class="modal-dialog modal-lg">
<form class="modal-content" #editServiceTileForm="ngForm"
*ngIf="selectedServiceTile"
<form class="modal-content" #editServiceTileForm="ngForm" *ngIf="selectedServiceTile"
(ngSubmit)="onUpdateServiceTile(editServiceTileForm)">
<div class="modal-header">
<h3>Edit Service Tile</h3>
@ -178,8 +164,9 @@
<input class="form-input" name="title" [(ngModel)]="selectedServiceTile.title" required>
</div>
<div class="form-group">
<label>Description *</label>
<textarea class="form-textarea" name="description" [(ngModel)]="selectedServiceTile.description" required></textarea>
<label>Description * (Separate points with commas)</label>
<textarea class="form-textarea" name="description" [(ngModel)]="selectedServiceTile.description"
required placeholder="e.g., Point one, Point two, Point three"></textarea>
</div>
<div class="form-group">
<label>Display Order</label>
@ -189,10 +176,8 @@
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" type="button"
data-bs-dismiss="modal">Cancel</button>
<button class="btn-primary" type="submit"
[disabled]="editServiceTileForm.invalid">
<button class="btn-secondary" type="button" data-bs-dismiss="modal">Cancel</button>
<button class="btn-primary" type="submit" [disabled]="editServiceTileForm.invalid">
<i class="fa fa-save"></i> Save Changes
</button>
</div>
@ -201,4 +186,4 @@
</div>
</div>
</div>
</div>