Modified Doctors Module & Add Room Management component.

This commit is contained in:
Sk Shaifat Murshed 2025-02-14 20:22:43 +05:30
parent 2b5b7be681
commit 74c18e7b07
20 changed files with 710 additions and 95 deletions

View File

@ -52,6 +52,10 @@ const routes: Routes = [
path: 'doctors',
loadChildren: () => import('./doctors/doctors.module').then(m => m.DoctorsModule),
},
{
path: 'rooms',
loadChildren: () => import('./room-management/room-management.module').then(m => m.RoomManagementModule),
},
];
@NgModule({

View File

@ -22,75 +22,371 @@
</div>
<form #doctorForm="ngForm" (ngSubmit)="saveDoctor(doctorForm)">
<div class="p-fluid grid justify-content-center">
<!-- First Name -->
<div class="field col-md-5">
<label for="firstName">First Name <span class="text-danger">*</span></label>
<input pInputText id="firstName" name="firstName" [(ngModel)]="doctor.firstName" required #firstNameCtrl="ngModel"
[ngClass]="{'is-invalid': firstNameCtrl.invalid && firstNameCtrl.touched}" />
<small class="text-danger" *ngIf="firstNameCtrl.invalid && firstNameCtrl.touched">First Name is required.</small>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-user"></i>
<input
pInputText
id="firstName"
name="firstName"
[(ngModel)]="doctor.firstName"
#firstNameCtrl="ngModel"
required
minlength="2"
maxlength="30"
[ngClass]="{
'is-valid': firstNameCtrl.valid && firstNameCtrl.touched,
'is-invalid': firstNameCtrl.invalid && firstNameCtrl.touched
}"
/>
<i
*ngIf="firstNameCtrl.valid && firstNameCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="firstNameCtrl.invalid && firstNameCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="firstNameCtrl.invalid && firstNameCtrl.touched">
<span *ngIf="firstNameCtrl.errors?.required">First Name is required.</span>
<span *ngIf="firstNameCtrl.errors?.minlength">Minimum 2 characters required.</span>
<span *ngIf="firstNameCtrl.errors?.maxlength">Maximum 30 characters allowed.</span>
</small>
</div>
<div class="field col-md-1"></div>
<!-- Last Name -->
<div class="field col-md-5">
<label for="lastName">Last Name <span class="text-danger">*</span></label>
<input pInputText id="lastName" name="lastName" [(ngModel)]="doctor.lastName" required #lastNameCtrl="ngModel"
[ngClass]="{'is-invalid': lastNameCtrl.invalid && lastNameCtrl.touched}" />
<small class="text-danger" *ngIf="lastNameCtrl.invalid && lastNameCtrl.touched">Last Name is required.</small>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-user"></i>
<input
pInputText
id="lastName"
name="lastName"
[(ngModel)]="doctor.lastName"
#lastNameCtrl="ngModel"
required
minlength="2"
maxlength="30"
[ngClass]="{
'is-valid': lastNameCtrl.valid && lastNameCtrl.touched,
'is-invalid': lastNameCtrl.invalid && lastNameCtrl.touched
}"
/>
<i
*ngIf="lastNameCtrl.valid && lastNameCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="lastNameCtrl.invalid && lastNameCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="lastNameCtrl.invalid && lastNameCtrl.touched">
<span *ngIf="lastNameCtrl.errors?.required">Last Name is required.</span>
</small>
</div>
<!-- Mobile -->
<div class="field col-md-5">
<label for="mobile">Mobile <span class="text-danger">*</span></label>
<input pInputText id="mobile" name="mobile" [(ngModel)]="doctor.mobile" required #mobileCtrl="ngModel"
[ngClass]="{'is-invalid': mobileCtrl.invalid && mobileCtrl.touched}" />
<small class="text-danger" *ngIf="mobileCtrl.invalid && mobileCtrl.touched">Mobile is required.</small>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-phone"></i>
<input
pInputText
id="mobile"
name="mobile"
[(ngModel)]="doctor.mobile"
#mobileCtrl="ngModel"
required
pattern="^[0-9]{10}$"
[ngClass]="{
'is-valid': mobileCtrl.valid && mobileCtrl.touched,
'is-invalid': mobileCtrl.invalid && mobileCtrl.touched
}"
/>
<i
*ngIf="mobileCtrl.valid && mobileCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="mobileCtrl.invalid && mobileCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="mobileCtrl.invalid && mobileCtrl.touched">
<span *ngIf="mobileCtrl.errors?.required">Mobile is required.</span>
<span *ngIf="mobileCtrl.errors?.pattern">Enter a valid 10-digit number.</span>
</small>
</div>
<div class="field col-md-1"></div>
<!-- Email -->
<div class="field col-md-5">
<label for="email">Email <span class="text-danger">*</span></label>
<input pInputText id="email" name="email" [(ngModel)]="doctor.email" required type="email" #emailCtrl="ngModel"
[ngClass]="{'is-invalid': emailCtrl.invalid && emailCtrl.touched}" />
<small class="text-danger" *ngIf="emailCtrl.invalid && emailCtrl.touched">Valid Email is required.</small>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-envelope"></i>
<input
pInputText
id="email"
name="email"
[(ngModel)]="doctor.email"
#emailCtrl="ngModel"
required
type="email"
pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
[ngClass]="{
'is-valid': emailCtrl.valid && emailCtrl.touched,
'is-invalid': emailCtrl.invalid && emailCtrl.touched
}"
/>
<i *ngIf="emailCtrl.valid && emailCtrl.touched" class="pi pi-check text-success"></i>
<i *ngIf="emailCtrl.invalid && emailCtrl.touched" class="pi pi-times text-danger"></i>
</span>
<small class="text-danger" *ngIf="emailCtrl.invalid && emailCtrl.touched">
<span *ngIf="emailCtrl.errors?.required">Email is required.</span>
<span *ngIf="emailCtrl.errors?.pattern">Enter a valid email address.</span>
</small>
</div>
<!-- Specialization -->
<div class="field col-md-5">
<label for="specialization">Specialization</label>
<input pInputText id="specialization" name="specialization" [(ngModel)]="doctor.specialization" />
<input
pInputText
id="specialization"
name="specialization"
[(ngModel)]="doctor.specialization"
/>
</div>
<div class="field col-md-1"></div>
<!-- Experience -->
<div class="field col-md-5">
<label for="experience">Experience (Years)</label>
<input type="number" pInputText id="experience" name="experience" [(ngModel)]="doctor.experience" min="0" />
<input
type="number"
pInputText
id="experience"
name="experience"
[(ngModel)]="doctor.experience"
min="0"
/>
</div>
<!-- Consultation Fee -->
<div class="field col-md-5">
<label for="consultationFee">Consultation Fee</label>
<input type="number" pInputText id="consultationFee" name="consultationFee" [(ngModel)]="doctor.consultationFee" min="0" />
<input
type="number"
pInputText
id="consultationFee"
name="consultationFee"
[(ngModel)]="doctor.consultationFee"
min="0"
/>
</div>
<div class="field col-md-1"></div>
<!-- Clinic Location -->
<div class="field col-md-5">
<label for="clinicLocation">Clinic Location</label>
<input pInputText id="clinicLocation" name="clinicLocation" [(ngModel)]="doctor.clinicLocation" />
<input
pInputText
id="clinicLocation"
name="clinicLocation"
[(ngModel)]="doctor.clinicLocation"
/>
</div>
<div class="field col-md-3">
<label for="rating">Rating</label><br>
<p-rating [(ngModel)]="doctor.rating" [stars]="5" [cancel]="false" name="rating"></p-rating>
<div class="field col-md-5">
<label for="dateofbirth">Date Of Birth <span class="text-danger">*</span></label>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-calendar"></i>
<p-calendar
id="dateofbirth"
name="dateofbirth"
[(ngModel)]="dateofbirth"
#dateofbirthCtrl="ngModel"
required
[showIcon]="true"
dateFormat="dd/mm/yy"
[ngClass]="{
'is-valid': dateofbirthCtrl.valid && dateofbirthCtrl.touched,
'is-invalid': dateofbirthCtrl.invalid && dateofbirthCtrl.touched
}"
>
</p-calendar>
<i
*ngIf="dateofbirthCtrl.valid && dateofbirthCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="dateofbirthCtrl.invalid && dateofbirthCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="dateofbirthCtrl.invalid && dateofbirthCtrl.touched">
<span *ngIf="dateofbirthCtrl.errors?.required">DOB is required.</span>
</small>
</div>
<div class="field col-md-4">
<label for="degree">Degree</label>
<input pInputText id="degree" name="degree" [(ngModel)]="doctor.degree" />
<div class="field col-md-1"></div>
<div class="field col-md-5">
<label for="joiningDate">Joining Date <span class="text-danger">*</span></label>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-calendar"></i>
<p-calendar
id="joiningDate"
name="joiningDate"
[(ngModel)]="JoiningDate"
#joiningDateCtrl="ngModel"
required
[showIcon]="true"
dateFormat="dd/mm/yy"
[ngClass]="{
'is-valid': joiningDateCtrl.valid && joiningDateCtrl.touched,
'is-invalid': joiningDateCtrl.invalid && joiningDateCtrl.touched
}"
>
</p-calendar>
<i
*ngIf="joiningDateCtrl.valid && joiningDateCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="joiningDateCtrl.invalid && joiningDateCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="joiningDateCtrl.invalid && joiningDateCtrl.touched">
<span *ngIf="joiningDateCtrl.errors?.required">Joining Date is required.</span>
</small>
</div>
<!-- Rating -->
<div class="field col-md-10">
<label for="rating">Rating</label><br />
<p-rating
[(ngModel)]="doctor.rating"
[stars]="5"
[cancel]="false"
name="rating"
></p-rating>
</div>
<div class="field col-md-1"></div>
<div class="field col-md-3">
<!-- <div class="field col-md-5">
<label for="availability">Availability</label>
<p-dropdown [options]="workScheduleOptions" [(ngModel)]="doctor.availability" name="availability" placeholder="Select Availability"></p-dropdown>
<p-dropdown
[options]="workScheduleOptions"
[(ngModel)]="doctor.availability"
name="availability"
placeholder="Select Availability"
optionLabel="label"
optionValue="value"
></p-dropdown>
</div> -->
<div class="card p-4">
<h4>Doctor Availability Schedule</h4>
<!-- Add Availability Button -->
<div class="field">
<button pButton type="button" (click)="addAvailability()" icon="pi pi-plus" label="Add Schedule"></button>
</div>
<!-- Loop Through Availability Schedules -->
<div *ngFor="let avail of availabilitySchedules; let i = index" class="availability-container">
<!-- Work Schedule Selection -->
<div class="field col-md-3">
<label for="availability-{{ i }}">Select Day</label>
<p-dropdown
[options]="workScheduleOptions"
[(ngModel)]="avail.schedule"
name="availability-{{ i }}"
placeholder="Select Availability"
optionLabel="label"
optionValue="value"
class="w-full"
></p-dropdown>
</div>
<!-- Start Time -->
<div class="field col-md-3">
<label for="start-time-{{ i }}">Start Time</label>
<p-calendar
id="start-time-{{ i }}"
[(ngModel)]="avail.startTime"
name="startTime-{{ i }}"
showTime
timeOnly
hourFormat="24"
placeholder="Select Start Time"
class="w-full"
></p-calendar>
</div>
<!-- End Time -->
<div class="field col-md-3">
<label for="end-time-{{ i }}">End Time</label>
<p-calendar
id="end-time-{{ i }}"
[(ngModel)]="avail.endTime"
name="endTime-{{ i }}"
showTime
timeOnly
hourFormat="24"
placeholder="Select End Time"
class="w-full"
></p-calendar>
</div>
<!-- Remove Button -->
<div class="field col-md-2 flex align-items-end">
<button pButton type="button" (click)="removeAvailability(i)" icon="pi pi-trash" class="p-button-danger"></button>
</div>
</div>
</div>
<!-- Description -->
<div class="field col-11">
<label for="description">Description</label>
<textarea id="description" name="description" [(ngModel)]="doctor.description" rows="5" cols="30" pInputTextarea></textarea>
<textarea
id="description"
name="description"
[(ngModel)]="doctor.description"
rows="5"
cols="30"
pInputTextarea
></textarea>
</div>
<!-- Buttons -->
<div class="field col-11 flex justify-content-end">
<button pButton type="submit" label="Save" class="p-button-success" [disabled]="doctorForm.invalid"></button>
<button pButton type="button" label="Cancel" class="p-button-secondary ml-2" (click)="onClose()"></button>
<button
pButton
type="submit"
label="Save"
class="p-button-success"
[disabled]="doctorForm.invalid"
></button>
<button
pButton
type="button"
label="Cancel"
class="p-button-secondary ml-2"
(click)="onClose()"
></button>
</div>
</div>
</form>

View File

@ -20,4 +20,16 @@
.modal {
z-index: 1040; /* Set lower z-index to ensure modal is behind the calendar */
}
.availability-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
padding: 10px;
border-bottom: 1px solid #ddd;
margin-bottom: 10px;
}
.w-full {
width: 100%;
}

View File

@ -14,8 +14,13 @@ import { InputTextareaModule } from 'primeng/inputtextarea';
import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table';
import { RatingModule } from 'primeng/rating';
import { workScheduleOptions } from '@proxy/global-enum';
import { TimeSlot, WorkSchedule, workScheduleOptions } from '@proxy/global-enum';
// Define Type for Availability
interface AvailabilitySchedule {
schedule: WorkSchedule | null;
startTime: Date | null;
endTime: Date | null;
}
@Component({
selector: 'app-doctor-dialog',
standalone: true,
@ -33,7 +38,7 @@ import { workScheduleOptions } from '@proxy/global-enum';
InputTextareaModule,
ChipModule,
CommonModule,
RatingModule
RatingModule,
],
templateUrl: './doctor-dialog.component.html',
styleUrl: './doctor-dialog.component.scss',
@ -48,14 +53,38 @@ export class DoctorDialogComponent implements OnInit {
doctorDialog: boolean;
JoiningDate: Date;
dateofbirth: Date;
availabilitySchedules: AvailabilitySchedule[] = []; // Separate storage for availability
constructor(private DoctorService: DoctorService, private toaster: ToasterService) {}
ngOnInit(): void {
if (this.isEditMode) {
this.fetchDoctorData();
}
else{
this.doctor = {
firstName: '',
lastName: '',
gender: '',
mobile: '',
password: '',
designation: '',
departmentId: '',
address: '',
email: '',
dob: '',
education: '',
specialization: '',
degree: '',
joiningDate: '',
experience: 0,
consultationFee: 0,
availability: null,
timeSlot:null,
rating: 0,
clinicLocation: '',
};
}
}
doctor: CreateDoctorDto = {
@ -77,15 +106,28 @@ export class DoctorDialogComponent implements OnInit {
experience: 0,
consultationFee: 0,
availability: null,
timeSlot:null,
rating: 0,
clinicLocation: '',
};
workScheduleOptions = Object.keys(workScheduleOptions)
.filter(key => isNaN(Number(key)))
.map(key => ({
label: key.replace(/([A-Z])/g, ' $1').trim(),
value: workScheduleOptions[key as keyof typeof workScheduleOptions]
}));
workScheduleOptions = Object.keys(WorkSchedule)
.filter((key) => isNaN(Number(key))) // Only get string keys (not numeric values)
.map((key) => ({
label: key.replace(/([A-Z])/g, ' $1').trim(), // Format enum keys as readable labels
value: WorkSchedule[key as keyof typeof WorkSchedule], // Get enum value
}));
timeSlotOptions: { label: string, value: TimeSlot }[] = [
{ label: '10:00 AM - 7:00 PM', value: TimeSlot.TenToSeven },
{ label: '09:00 AM - 5:00 PM', value: TimeSlot.NineToFive },
{ label: '08:00 AM - 4:00 PM', value: TimeSlot.EightToFour },
{ label: '07:00 AM - 4:00 PM', value: TimeSlot.SevenToFour },
{ label: '06:00 AM - 3:00 PM', value: TimeSlot.SixToThree },
{ label: '12:00 PM - 9:00 PM', value: TimeSlot.TwelveToNine },
{ label: '10:00 AM - 6:00 PM', value: TimeSlot.TenToSix },
{ label: '11:00 AM - 8:00 PM', value: TimeSlot.ElevenToEight },
];
fetchDoctorData() {
this.DoctorService.getDoctorById(this.Id).subscribe(result => {
this.doctor = result;
@ -99,7 +141,7 @@ export class DoctorDialogComponent implements OnInit {
return;
}
this.doctor.dob = this.dateofbirth.toDateString();
this.doctor.joiningDate = this.JoiningDate.toDateString();
if (this.isEditMode) {
this.DoctorService.updatDoctor(this.doctor).subscribe(
() => {
@ -126,4 +168,18 @@ export class DoctorDialogComponent implements OnInit {
this.Id = '';
this.close.emit();
}
addAvailability() {
this.availabilitySchedules.push({ schedule: null, startTime: null, endTime: null });
this.syncDoctorAvailability(); // Sync with doctor object
}
removeAvailability(index: number) {
this.availabilitySchedules.splice(index, 1);
this.syncDoctorAvailability(); // Sync after removal
}
syncDoctorAvailability() {
// this.doctor.availability = [...this.availabilitySchedules]; // Keep doctor object updated
}
}

View File

@ -45,8 +45,7 @@
</ng-template>
<ng-template pTemplate="header">
<tr>
<th pSortableColumn="firstName">First Name <p-sortIcon field="firstName" /></th>
<th pSortableColumn="lastName">Last Name <p-sortIcon field="lastName" /></th>
<th pSortableColumn="firstName">Name <p-sortIcon field="firstName" /></th>
<th pSortableColumn="mobile">Mobile <p-sortIcon field="mobile" /></th>
<th pSortableColumn="email">Email <p-sortIcon field="email" /></th>
<th pSortableColumn="specialization">Specialization <p-sortIcon field="specialization" /></th>
@ -57,8 +56,7 @@
</ng-template>
<ng-template pTemplate="body" let-doctor>
<tr>
<td>{{ doctor.firstName }}</td>
<td>{{ doctor.lastName }}</td>
<td>Dr. {{ doctor.firstName }} {{ doctor.lastName }}</td>
<td>{{ doctor.mobile }}</td>
<td>{{ doctor.email }}</td>
<td>{{ doctor.specialization }}</td>

View File

@ -1,5 +1,6 @@
import type { FullAuditedEntity } from '../../volo/abp/domain/entities/auditing/models';
import type { WorkSchedule } from '../../global-enum/work-schedule.enum';
import type { TimeSlot } from '../../global-enum/time-slot.enum';
export interface DoctorDto extends FullAuditedEntity<string> {
id?: string;
@ -19,6 +20,7 @@ export interface DoctorDto extends FullAuditedEntity<string> {
experience?: number;
consultationFee?: number;
availability?: WorkSchedule;
timeSlot: TimeSlot;
rating?: number;
clinicLocation?: string;
}

View File

@ -1,4 +1,5 @@
import type { WorkSchedule } from '../global-enum/work-schedule.enum';
import type { TimeSlot } from '../global-enum/time-slot.enum';
import type { FullAuditedEntity } from '../volo/abp/domain/entities/auditing/models';
export interface CreateDepartmentDto {
@ -30,6 +31,7 @@ export interface CreateDoctorDto {
experience?: number;
consultationFee?: number;
availability?: WorkSchedule;
timeSlot: TimeSlot;
rating?: number;
clinicLocation?: string;
}

View File

@ -5724,6 +5724,18 @@
"maximum": null,
"regex": null
},
{
"name": "TimeSlot",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"typeSimple": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Rating",
"jsonName": null,
@ -6246,6 +6258,18 @@
"maximum": null,
"regex": null
},
{
"name": "TimeSlot",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"typeSimple": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Rating",
"jsonName": null,
@ -6415,6 +6439,32 @@
"genericArguments": null,
"properties": null
},
"HospitalManagementSystem.GlobalEnum.TimeSlot": {
"baseType": "System.Enum",
"isEnum": true,
"enumNames": [
"TenToSeven",
"NineToFive",
"EightToFour",
"SevenToFour",
"SixToThree",
"TwelveToNine",
"TenToSix",
"ElevenToEight"
],
"enumValues": [
1,
2,
3,
4,
5,
6,
7,
8
],
"genericArguments": null,
"properties": null
},
"HospitalManagementSystem.GlobalEnum.visitType": {
"baseType": "System.Enum",
"isEnum": true,
@ -6433,6 +6483,13 @@
"baseType": "System.Enum",
"isEnum": true,
"enumNames": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
"MondayToFriday",
"TuesdayToSaturday",
"WednesdayToSunday",
@ -6446,14 +6503,7 @@
"ThursdayToSunday",
"FridayToMonday",
"SaturdayToTuesday",
"SundayToWednesday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
"SundayToWednesday"
],
"enumValues": [
1,

View File

@ -2,5 +2,6 @@ export * from './appointment-status.enum';
export * from './gender.enum';
export * from './payment-status.enum';
export * from './status.enum';
export * from './time-slot.enum';
export * from './visit-type.enum';
export * from './work-schedule.enum';

View File

@ -0,0 +1,14 @@
import { mapEnumToOptions } from '@abp/ng.core';
export enum TimeSlot {
TenToSeven = 1,
NineToFive = 2,
EightToFour = 3,
SevenToFour = 4,
SixToThree = 5,
TwelveToNine = 6,
TenToSix = 7,
ElevenToEight = 8,
}
export const timeSlotOptions = mapEnumToOptions(TimeSlot);

View File

@ -1,27 +1,27 @@
import { mapEnumToOptions } from '@abp/ng.core';
export enum WorkSchedule {
MondayToFriday = 1,
TuesdayToSaturday = 2,
WednesdayToSunday = 3,
ThursdayToMonday = 4,
FridayToTuesday = 5,
SaturdayToWednesday = 6,
SundayToThursday = 7,
MondayToThursday = 8,
TuesdayToFriday = 9,
WednesdayToSaturday = 10,
ThursdayToSunday = 11,
FridayToMonday = 12,
SaturdayToTuesday = 13,
SundayToWednesday = 14,
Monday = 15,
Tuesday = 16,
Wednesday = 17,
Thursday = 18,
Friday = 19,
Saturday = 20,
Sunday = 21,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
MondayToFriday = 8,
TuesdayToSaturday = 9,
WednesdayToSunday = 10,
ThursdayToMonday = 11,
FridayToTuesday = 12,
SaturdayToWednesday = 13,
SundayToThursday = 14,
MondayToThursday = 15,
TuesdayToFriday = 16,
WednesdayToSaturday = 17,
ThursdayToSunday = 18,
FridayToMonday = 19,
SaturdayToTuesday = 20,
SundayToWednesday = 21,
}
export const workScheduleOptions = mapEnumToOptions(WorkSchedule);

View File

@ -0,0 +1,22 @@
<div class="room-management-container">
<h2 class="heading">Room Management</h2>
<!-- Date Selection using PrimeNG -->
<div class="date-header">
<label for="date">Select Date:</label>
<p-calendar id="date" [(ngModel)]="selectedDate" dateFormat="dd-mm-yy" (onSelect)="onDateChange()" showIcon></p-calendar>
</div>
<!-- Room Grid -->
<div class="room-container p-grid">
<div *ngFor="let room of roomData" class="p-col-12 p-md-3">
<p-button
[label]="room.roomName"
[severity]="getRoomStatus(room.roomName) === 'occupied' ? 'danger' : 'success'"
class="room-button"
(click)="selectRoom(room.roomName)">
</p-button>
</div>
</div>
</div>

View File

@ -0,0 +1,45 @@
/* General Styling */
.room-management-container {
padding: 20px;
font-family: 'Arial', sans-serif;
background-color: #f4f7fa;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.heading {
text-align: center;
font-size: 24px;
font-weight: bold;
margin-bottom: 20px;
}
/* Date Picker */
.date-header {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-bottom: 20px;
font-size: 16px;
}
.date-header label {
font-weight: 600;
}
/* Room Grid */
.room-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 15px;
}
/* Room Buttons */
.room-button {
width: 100%;
font-size: 14px;
font-weight: bold;
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RoomsComponent } from './rooms.component';
describe('RoomsComponent', () => {
let component: RoomsComponent;
let fixture: ComponentFixture<RoomsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RoomsComponent]
})
.compileComponents();
fixture = TestBed.createComponent(RoomsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,60 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-rooms',
templateUrl: './rooms.component.html',
styleUrl: './rooms.component.scss'
})
export class RoomsComponent {
selectedDate: Date = new Date(); // Default to today
roomData = [
{ roomName: 'Room 101' },
{ roomName: 'Room 102' },
{ roomName: 'Room 103' },
{ roomName: 'Room 104' },
{ roomName: 'Room 201' },
{ roomName: 'Room 202' },
{ roomName: 'Room 203' },
{ roomName: 'Room 301' },
{ roomName: 'Room 302' },
{ roomName: 'Room 303' },
{ roomName: 'Room 401' },
{ roomName: 'Room 402' },
// Add more rooms as necessary
];
roomStatus = {
'Room 101': 'occupied',
'Room 102': 'available',
'Room 103': 'available',
'Room 104': 'occupied',
'Room 201': 'available',
'Room 202': 'occupied',
'Room 203': 'available',
'Room 301': 'available',
'Room 302': 'occupied',
'Room 303': 'available',
'Room 401': 'occupied',
'Room 402': 'available',
// Add more rooms and statuses as necessary
};
onDateChange() {
console.log('Selected date:', this.selectedDate);
// Logic to handle room status based on selected date, if needed
}
selectRoom(room: string) {
// Logic for selecting a room
console.log(`${room} selected.`);
}
getRoomStatus(room: string) {
return this.roomStatus[room] || 'available'; // Default to 'available' if not specified
}
getRoomStatusLabel(room: string) {
return this.getRoomStatus(room) === 'available' ? 'Available' : 'Occupied';
}
}

View File

@ -91,6 +91,21 @@ function configureRoutes(routesService: RoutesService) {
order: 402,
requiredPolicy:'HospitalManagementSystem.Doctor'
},
{
path: '',
name: 'Rooms',
order: 501,
iconClass: 'fas fa-user-md',
layout: eLayoutType.application,
},
{
path: '/rooms',
name: 'All Rooms',
parentName: 'Rooms',
iconClass: 'fas fa-clock',
order: 502,
requiredPolicy:'HospitalManagementSystem.Doctor'
},
]);
};
}

View File

@ -27,6 +27,7 @@ namespace HospitalManagementSystem.Doctors.Dto
public int? Experience { get; set; }
public decimal? ConsultationFee { get; set; }
public WorkSchedule? Availability { get; set; }
public TimeSlot TimeSlot { get; set; }
public decimal? Rating { get; set; }
public string? ClinicLocation { get; set; }
}

View File

@ -130,7 +130,7 @@ namespace HospitalManagementSystem.Doctors
worksheet.Cell(i + 2, 2).Value = DoctorRecord[i].Email;
worksheet.Cell(i + 2, 3).Value = DoctorRecord[i].Specialization;
worksheet.Cell(i + 2, 4).Value = DoctorRecord[i].JoiningDate?.ToShortDateString();
worksheet.Cell(i + 2, 5).Value = DoctorRecord[i].Department.DepartmentName;
worksheet.Cell(i + 2, 5).Value = DoctorRecord[i].Department==null?"": DoctorRecord[i].Department.DepartmentName;
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].Mobile;
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].Degree;
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].Experience;
@ -138,9 +138,7 @@ namespace HospitalManagementSystem.Doctors
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].Availability.ToString();
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].Rating;
worksheet.Cell(i + 2, 6).Value = DoctorRecord[i].ClinicLocation;
}
worksheet.Columns().AdjustToContents();
workbook.SaveAs(filePath);
}

View File

@ -29,6 +29,8 @@ namespace HospitalManagementSystem.Dtos
public int? Experience { get; set; }
public decimal? ConsultationFee { get; set; }
public WorkSchedule? Availability { get; set; }
public TimeSlot TimeSlot { get; set; }
public decimal? Rating { get; set; }
public string? ClinicLocation { get; set; }
}

View File

@ -39,28 +39,42 @@ namespace HospitalManagementSystem.GlobalEnum
public enum WorkSchedule
{
MondayToFriday = 1,
TuesdayToSaturday = 2,
WednesdayToSunday = 3,
ThursdayToMonday = 4,
FridayToTuesday = 5,
SaturdayToWednesday = 6,
SundayToThursday = 7,
MondayToThursday = 8,
TuesdayToFriday = 9,
WednesdayToSaturday = 10,
ThursdayToSunday = 11,
FridayToMonday = 12,
SaturdayToTuesday = 13,
SundayToWednesday = 14,
Monday = 15,
Tuesday = 16,
Wednesday = 17,
Thursday = 18,
Friday = 19,
Saturday = 20,
Sunday = 21
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
MondayToFriday = 8,
TuesdayToSaturday = 9,
WednesdayToSunday = 10,
ThursdayToMonday = 11,
FridayToTuesday = 12,
SaturdayToWednesday = 13,
SundayToThursday = 14,
MondayToThursday = 15,
TuesdayToFriday = 16,
WednesdayToSaturday = 17,
ThursdayToSunday = 18,
FridayToMonday = 19,
SaturdayToTuesday = 20,
SundayToWednesday = 21
}
public enum TimeSlot
{
TenToSeven = 1, // 10:00 AM to 7:00 PM
NineToFive = 2, // 09:00 AM to 5:00 PM
EightToFour = 3, // 08:00 AM to 4:00 PM
SevenToFour = 4, // 07:00 AM to 4:00 PM
SixToThree = 5, // 06:00 AM to 3:00 PM
TwelveToNine = 6, // 12:00 PM to 9:00 PM
TenToSix = 7, // 10:00 AM to 6:00 PM
ElevenToEight = 8, // 11:00 AM to 8:00 PM
}
}