Modified Doctor Module ,add shift management

This commit is contained in:
Sk Shaifat Murshed 2025-02-18 19:21:07 +05:30
parent 74c18e7b07
commit 0e14f4e199
38 changed files with 6715 additions and 270 deletions

View File

@ -270,7 +270,7 @@
</small>
</div>
<!-- Rating -->
<div class="field col-md-10">
<div class="field col-md-5">
<label for="rating">Rating</label><br />
<p-rating
[(ngModel)]="doctor.rating"
@ -280,83 +280,79 @@
></p-rating>
</div>
<div class="field col-md-1"></div>
<!-- <div class="field col-md-5">
<label for="availability">Availability</label>
<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>
<!-- Button to open the popup -->
<div class="button-container">
<button
pButton
type="button"
label="Select Availability"
icon="pi pi-calendar"
(click)="openDialog()"
class="p-mr-2"
></button>
</div>
<!-- Popup Dialog -->
<p-dialog
header="Select Days and Times"
[(visible)]="displayDialog"
modal="true"
closable="true"
[style]="{ width: '80%', height: '100%' }"
[baseZIndex]="10000"
styleClass="availability-dialog"
>
<div class="p-fluid grid">
<div class="field col-md-5">
<label for="availability">Select Available Days</label>
<p-multiSelect
[options]="workScheduleOptions"
[(ngModel)]="selectedDays"
optionLabel="label"
placeholder="Select Days"
(onChange)="onDaysChange($event)"
></p-multiSelect>
</div>
<div class="field col-md-1"></div>
<div class="field col-md-5">
<!-- Display time selection for each selected day -->
<div *ngIf="selectedDays && selectedDays.length" class="selected-days-container">
<h3 class="selected-days-header">Set Time for Selected Days</h3>
<div *ngFor="let day of selectedDays" class="day-time-row">
<span class="day-label">{{ day.label }}</span>
<p-dropdown
[options]="timeSlotOptions"
[ngModel]="selectedTimes[day.value]"
(onChange)="onTimeChange(day.value, $event)"
placeholder="Select Time"
style="width: 80%"
></p-dropdown>
</div>
</div>
</div>
</div>
<p-footer>
<div class="footer-buttons p-d-flex p-jc-end">
<button
pButton
type="button"
label="Save"
icon="pi pi-check"
(click)="saveSelection()"
class="p-button-success p-mr-2"
></button
>&nbsp;
<button
pButton
type="button"
label="Cancel"
icon="pi pi-times"
(click)="closeDialog()"
class="p-button-secondary"
></button>
</div>
</p-footer>
</p-dialog>
<!-- Description -->
<div class="field col-11">

View File

@ -32,4 +32,54 @@
.w-full {
width: 100%;
}
.dropdown-item-container {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem 0; /* adjust as needed */
}
.day-label {
flex: 0 0 auto;
}
.time-options {
flex: 1;
display: flex;
gap: 0.5rem;
justify-content: flex-end;
}
.time-label {
display: flex;
align-items: center;
}
/* Style for the container below the multi-select */
.selected-days-container {
margin-top: 1rem;
padding: 1rem;
border: 1px solid #e0e0e0;
border-radius: 4px;
background: #fafafa;
}
/* Header styling */
.selected-days-header {
margin-bottom: 0.75rem;
font-size: 1.1rem;
color: #333;
}
/* Each day row */
.day-time-row {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.5rem;
}
/* Fixed width for day label */
.day-label {
width: 100px;
font-weight: 600;
}

View File

@ -14,12 +14,14 @@ import { InputTextareaModule } from 'primeng/inputtextarea';
import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table';
import { RatingModule } from 'primeng/rating';
import { TimeSlot, WorkSchedule, workScheduleOptions } from '@proxy/global-enum';
import { MultiSelectModule } from 'primeng/multiselect';
import { TimeSlot, timeSlotOptions, WorkSchedule, workScheduleOptions } from '@proxy/global-enum';
// Define Type for Availability
interface AvailabilitySchedule {
schedule: WorkSchedule | null;
startTime: Date | null;
endTime: Date | null;
interface ScheduleOption {
label: string;
value: string;
items?: ScheduleOption[];
}
@Component({
selector: 'app-doctor-dialog',
@ -39,6 +41,7 @@ interface AvailabilitySchedule {
ChipModule,
CommonModule,
RatingModule,
MultiSelectModule,
],
templateUrl: './doctor-dialog.component.html',
styleUrl: './doctor-dialog.component.scss',
@ -53,15 +56,24 @@ export class DoctorDialogComponent implements OnInit {
doctorDialog: boolean;
JoiningDate: Date;
dateofbirth: Date;
availabilitySchedules: AvailabilitySchedule[] = []; // Separate storage for availability
isSchedulePopupVisible = false;
selectedDays: { label: string; value: string }[] = [];
selectedTimeSlots: { [key: number]: number | null } = {};
displayDialog: boolean = false;
selectedDay: any = null;
selectedTime: any = null;
selectedTimes: { [key: number]: number } = {};
workScheduleOptions: { label: string; value: number }[] = [];
timeSlotOptions: { label: string; value: number }[] = [];
constructor(private DoctorService: DoctorService, private toaster: ToasterService) {}
ngOnInit(): void {
if (this.isEditMode) {
this.fetchDoctorData();
}
else{
} else {
this.doctor = {
firstName: '',
lastName: '',
@ -80,11 +92,12 @@ export class DoctorDialogComponent implements OnInit {
experience: 0,
consultationFee: 0,
availability: null,
timeSlot:null,
rating: 0,
clinicLocation: '',
};
}
this.initializeWorkScheduleOptions();
this.initializeTimeSlotOptions();
}
doctor: CreateDoctorDto = {
@ -106,28 +119,48 @@ export class DoctorDialogComponent implements OnInit {
experience: 0,
consultationFee: 0,
availability: null,
timeSlot:null,
rating: 0,
clinicLocation: '',
};
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
}));
openDialog() {
this.displayDialog = true;
}
onDaysChange(event: any) {
this.selectedDays=event.value;
}
onTimeChange(dayValue: number, timeValue: number) {
this.selectedTimes[dayValue] = timeValue;
}
closeDialog() {
this.displayDialog = false;
}
initializeWorkScheduleOptions() {
this.workScheduleOptions = Object.keys(WorkSchedule)
.filter(key => isNaN(Number(key)))
.map(key => {
const value = WorkSchedule[key as keyof typeof WorkSchedule];
return { label: key, value };
});
}
initializeTimeSlotOptions() {
this.timeSlotOptions = Object.keys(TimeSlot)
.filter(key => isNaN(Number(key)))
.map(key => {
const value = TimeSlot[key as keyof typeof TimeSlot];
return { label: key, value };
});
}
saveSelection() {
const availability = this.selectedDays.map(day => ({
day: day.value,
time: this.selectedTimes[day.value] || null,
}));
this.displayDialog = false;
}
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;
@ -168,18 +201,4 @@ 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

@ -1,8 +1,12 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DoctorsComponent } from './doctors.component';
import { ShiftManagementComponent } from './shift-management/shift-management.component';
const routes: Routes = [{ path: '', component: DoctorsComponent }];
const routes: Routes = [
{ path: '', component: DoctorsComponent },
{ path: 'shift-management/:id', component: ShiftManagementComponent },
];
@NgModule({
imports: [RouterModule.forChild(routes)],

View File

@ -69,6 +69,9 @@
<button class="btn btn-danger btn-sm ml-1" (click)="deleteDoctor(doctor.id)">
<i class="pi pi-trash"></i>
</button>
<button class="btn btn-warning btn-sm ml-1" (click)="GotoShiftManagement(doctor.id)">
<i class="pi pi-arrow-right"></i>
</button>
</td>
</tr>
</ng-template>

View File

@ -1,6 +1,7 @@
import { ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { DoctorService } from '@proxy/doctors';
import { PagingSortResultDto } from '@proxy/dto';
import { workScheduleOptions } from '@proxy/global-enum';
@ -15,7 +16,7 @@ export class DoctorsComponent implements OnInit {
doctors = [];
loading: boolean = false;
params: PagingSortResultDto;
isModalVisible: boolean=false;
isModalVisible: boolean = false;
isEditMode: boolean = false;
DoctorIdToEdit: string;
@ -32,7 +33,8 @@ export class DoctorsComponent implements OnInit {
private DoctorService: DoctorService,
private http: HttpClient,
private confirmation: ConfirmationService,
private toaster: ToasterService
private toaster: ToasterService,
private router: Router
) {}
workSchedule = Object.keys(workScheduleOptions)
.filter(key => !isNaN(Number(key)))
@ -60,13 +62,13 @@ export class DoctorsComponent implements OnInit {
}
openNewDoctorDialog() {
this.isModalVisible=true;
this.isModalVisible = true;
this.isEditMode = false;
}
editDoctor(Doctor: any) {
this.isEditMode = true;
this.DoctorIdToEdit = Doctor.id;
this.isModalVisible=true;
this.DoctorIdToEdit = Doctor.id;
this.isModalVisible = true;
}
closeDialog() {
@ -105,4 +107,9 @@ export class DoctorsComponent implements OnInit {
window.URL.revokeObjectURL(url);
});
}
GotoShiftManagement(id:string) {
this.router.navigate(['/doctors/shift-management', id]);
}
}

View File

@ -14,9 +14,10 @@ import { InputTextareaModule } from 'primeng/inputtextarea';
import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table';
import { DoctorDialogComponent } from './doctor-dialog.component';
import { ShiftManagementComponent } from './shift-management/shift-management.component';
@NgModule({
declarations: [DoctorsComponent],
declarations: [DoctorsComponent,ShiftManagementComponent],
imports: [
CommonModule,
DoctorsRoutingModule,
@ -32,7 +33,9 @@ import { DoctorDialogComponent } from './doctor-dialog.component';
RadioButtonModule,
InputTextareaModule,
ChipModule,
DoctorDialogComponent
DoctorDialogComponent,
],
})

View File

@ -0,0 +1,52 @@
<div class="card p-4 shift-management">
<h4>Shift Management</h4>
<div class="field">
<p-dropdown
[options]="doctors"
[(ngModel)]="selectedDoctor"
placeholder="Select Doctor"
optionLabel="label"
optionValue="value"
class="w-full"
(onChange)="onDoctorSelect($event.value)"
></p-dropdown>
</div>
<div *ngIf="selectedDoctor" class="shift-grid-container">
<div class="shift-column-layout">
<!-- Column Layout for Days & Time Slots -->
<div *ngFor="let day of selectedDays" class="shift-column">
<div class="day-header">
<strong>{{ day }}</strong>
</div>
<p-dropdown
[options]="timeSlotOptions"
[(ngModel)]="selectedTimeSlots[day]"
optionLabel="label"
optionValue="value"
placeholder="Select Time Slot"
class="w-full"
></p-dropdown>
</div>
</div>
<!-- Buttons -->
<div class="button-container">
<button
pButton
type="button"
label="Save Shift"
class="p-button-success mt-3"
(click)="saveShiftData()"
></button>
<button
pButton
type="button"
label="Back"
class="p-button-primary mt-3"
(click)="backToDoctor()"
></button>
</div>
</div>
</div>

View File

@ -0,0 +1,66 @@
.shift-column-layout {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
margin-top: 20px;
}
.shift-column {
display: flex;
flex-direction: column;
align-items: center;
background: #f8f9fa;
border-radius: 8px;
padding: 15px;
min-width: 150px;
max-width: 180px;
flex: 1;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease-in-out;
}
.shift-column:hover {
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.day-header {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
color: #007bff;
text-transform: uppercase;
}
.dropdown-item {
width: 100%;
}
/* Center the button (optional) */
.button-container {
margin: 1rem 0;
}
/* Styling for the dialog */
.availability-dialog .p-dialog-header {
background-color: #1976d2;
color: #fff;
font-weight: 600;
}
.availability-dialog .p-dialog-content {
padding: 1.5rem;
}
.footer-buttons {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
}
/* Optional: Adjust field spacing */
.field {
margin-bottom: 1rem;
}

View File

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

View File

@ -0,0 +1,173 @@
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { DoctorService } from '@proxy/doctors';
import { CreateUpdateShiftManagementDto } from '@proxy/doctors/dto';
import { TimeSlot, WorkSchedule } from '@proxy/global-enum';
import { ShiftManagementService } from '@proxy/shift-management';
@Component({
selector: 'app-shift-management',
templateUrl: './shift-management.component.html',
styleUrl: './shift-management.component.scss',
})
export class ShiftManagementComponent implements OnInit {
doctors = [];
selectedDoctor: string | null = null;
selectedDoctorName = '';
selectedDoctorEmail = '';
selectedDoctorPhone = '';
selectedDoctorSpecialty = '';
selectedDays = [];
selectedTimeSlots: { [key: string]: TimeSlot } = {};
DoctorID: string;
constructor(
private DoctorService: DoctorService,
private shiftService: ShiftManagementService,
private toaster: ToasterService,
private router: Router,
private route: ActivatedRoute
) {}
ngOnInit(): void {
this.getdoctorlist();
setTimeout(() => {
this.DoctorID = this.route.snapshot.paramMap.get('id');
this.onDoctorSelect(this.DoctorID);
}, 10);
}
getdoctorlist() {
this.DoctorService.get().subscribe(result => {
const doctors = result;
this.doctors = doctors.map(doctor => ({
label: `Dr. ${doctor.firstName} ${doctor.lastName}`,
value: doctor.id,
availability: doctor.availability,
email: doctor.email,
phoneNo: doctor.mobile,
specialist: doctor.specialization,
}));
});
}
shiftData: CreateUpdateShiftManagementDto = {
doctorId: this.selectedDoctor,
shifts: {} as Record<WorkSchedule, TimeSlot>,
isActive: true,
};
workScheduleOptions = Object.keys(WorkSchedule)
.filter(key => isNaN(Number(key)))
.map(key => ({
label: key.replace(/([A-Z])/g, ' $1').trim(),
value: WorkSchedule[key as keyof typeof WorkSchedule],
}));
getTimeRangeLabel(value: TimeSlot): string {
const timeRanges = {
[TimeSlot.TenToSeven]: { start: 10, end: 19 },
[TimeSlot.NineToFive]: { start: 9, end: 17 },
[TimeSlot.EightToFour]: { start: 8, end: 16 },
[TimeSlot.SevenToFour]: { start: 7, end: 16 },
[TimeSlot.SixToThree]: { start: 6, end: 15 },
[TimeSlot.TwelveToNine]: { start: 12, end: 21 },
[TimeSlot.TenToSix]: { start: 10, end: 18 },
[TimeSlot.ElevenToEight]: { start: 11, end: 20 },
};
const { start, end } = timeRanges[value];
const formatTime = (hour: number): string => {
const period = hour >= 12 ? 'PM' : 'AM';
const formattedHour = hour % 12 || 12;
return `${formattedHour}:00 ${period}`;
};
return `${formatTime(start)} - ${formatTime(end)}`;
}
timeSlotOptions = Object.keys(TimeSlot)
.filter(key => isNaN(Number(key)))
.map(key => ({
label: this.getTimeRangeLabel(TimeSlot[key as keyof typeof TimeSlot]),
value: TimeSlot[key as keyof typeof TimeSlot],
}));
onDoctorSelect(doctorId: string) {
const selectedDoctor = this.doctors.find(doctor => doctor.value === doctorId);
if (selectedDoctor) {
this.selectedDoctorName = selectedDoctor.label;
this.selectedDoctorEmail = selectedDoctor.email;
this.selectedDoctorPhone = selectedDoctor.phoneNo;
this.selectedDoctorSpecialty = selectedDoctor.specialist;
this.shiftService.getShiftsByDoctorId(doctorId).subscribe(data => {
if (data && data.shifts && Object.keys(data.shifts).length > 0) {
this.selectedTimeSlots = {};
this.selectedDays = Object.keys(data.shifts).map(key => {
return this.daysOfWeek[WorkSchedule[key as keyof typeof WorkSchedule] - 1];
});
for (const [day, timeSlot] of Object.entries(data.shifts)) {
const dayEnumKey = WorkSchedule[day as keyof typeof WorkSchedule];
if (dayEnumKey !== undefined) {
this.selectedTimeSlots[this.daysOfWeek[dayEnumKey - 1]] = timeSlot;
}
}
} else {
this.selectedDays = this.getDaysFromSchedule(selectedDoctor.availability);
this.selectedDays.forEach(day => {
this.selectedTimeSlots[day] = TimeSlot.NineToFive;
});
}
});
}
}
daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
getDaysFromSchedule(scheduleValue: WorkSchedule): string[] {
let days: string[] = [];
if (scheduleValue >= 1 && scheduleValue <= 7) {
days.push(this.daysOfWeek[scheduleValue - 1]);
} else {
const startDayIndex = (scheduleValue - 8) % 7;
const endDayIndex = (startDayIndex + 4) % 7;
for (let i = 0; i < 5; i++) {
days.push(this.daysOfWeek[(startDayIndex + i) % 7]);
}
}
return days;
}
saveShiftData() {
if (!this.selectedDoctor) {
return;
}
this.selectedDays;
const shiftData: CreateUpdateShiftManagementDto = {
doctorId: this.selectedDoctor,
shifts: Object.keys(this.selectedTimeSlots).reduce((acc, day) => {
const timeSlot = this.selectedTimeSlots[day]; // Get selected time slot
const dayEnumKey = WorkSchedule[day as keyof typeof WorkSchedule]; // Convert string to WorkSchedule enum
if (timeSlot !== undefined && dayEnumKey !== undefined) {
acc[dayEnumKey] = timeSlot; // Store correctly in shifts
}
return acc;
}, {} as Record<WorkSchedule, TimeSlot>),
isActive: true,
};
this.shiftService.createOrUpdateShift(shiftData).subscribe({
next: response => {
this.toaster.success('Updated Successfully', 'Success');
},
error: err => {
this.toaster.error(err, 'Error');
},
});
}
backToDoctor() {
this.router.navigate(['/doctors']);
}
}

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 { FullAuditedEntityDto } from '@abp/ng.core';
import type { TimeSlot } from '../../global-enum/time-slot.enum';
export interface DoctorDto extends FullAuditedEntity<string> {
@ -19,8 +20,20 @@ export interface DoctorDto extends FullAuditedEntity<string> {
joiningDate?: string;
experience?: number;
consultationFee?: number;
availability?: WorkSchedule;
timeSlot: TimeSlot;
availability: WorkSchedule[];
rating?: number;
clinicLocation?: string;
shifts: ShiftManagementDto[];
}
export interface ShiftManagementDto extends FullAuditedEntityDto<string> {
doctorId?: string;
shifts: Record<WorkSchedule, TimeSlot>;
isActive: boolean;
}
export interface CreateUpdateShiftManagementDto {
doctorId?: string;
shifts: Record<WorkSchedule, TimeSlot>;
isActive: boolean;
}

View File

@ -1,5 +1,4 @@
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,8 +29,7 @@ export interface CreateDoctorDto {
joiningDate?: string;
experience?: number;
consultationFee?: number;
availability?: WorkSchedule;
timeSlot: TimeSlot;
availability: WorkSchedule[];
rating?: number;
clinicLocation?: string;
}

View File

@ -2383,6 +2383,143 @@
"implementFrom": "HospitalManagementSystem.Shared.SharedAppService"
}
}
},
"HospitalManagementSystem.Shift_Management.ShiftManagementAppService": {
"controllerName": "ShiftManagement",
"controllerGroupName": "ShiftManagement",
"isRemoteService": true,
"isIntegrationService": false,
"apiVersion": null,
"type": "HospitalManagementSystem.Shift_Management.ShiftManagementAppService",
"interfaces": [],
"actions": {
"GetAllShiftsAsync": {
"uniqueName": "GetAllShiftsAsync",
"name": "GetAllShiftsAsync",
"httpMethod": "GET",
"url": "api/app/shift-management/shifts",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
"returnValue": {
"type": "System.Collections.Generic.List<HospitalManagementSystem.Doctors.Dto.ShiftManagementDto>",
"typeSimple": "[HospitalManagementSystem.Doctors.Dto.ShiftManagementDto]"
},
"allowAnonymous": null,
"implementFrom": "HospitalManagementSystem.Shift_Management.ShiftManagementAppService"
},
"GetShiftsByDoctorIdAsyncByDoctorId": {
"uniqueName": "GetShiftsByDoctorIdAsyncByDoctorId",
"name": "GetShiftsByDoctorIdAsync",
"httpMethod": "GET",
"url": "api/app/shift-management/shifts-by-doctor-id/{doctorId}",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "doctorId",
"typeAsString": "System.Guid, System.Private.CoreLib",
"type": "System.Guid",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "doctorId",
"name": "doctorId",
"jsonName": null,
"type": "System.Guid",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": [],
"bindingSourceId": "Path",
"descriptorName": ""
}
],
"returnValue": {
"type": "HospitalManagementSystem.Doctors.Dto.ShiftManagementDto",
"typeSimple": "HospitalManagementSystem.Doctors.Dto.ShiftManagementDto"
},
"allowAnonymous": null,
"implementFrom": "HospitalManagementSystem.Shift_Management.ShiftManagementAppService"
},
"CreateOrUpdateShiftAsyncByInput": {
"uniqueName": "CreateOrUpdateShiftAsyncByInput",
"name": "CreateOrUpdateShiftAsync",
"httpMethod": "POST",
"url": "api/app/shift-management/or-update-shift",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto, HospitalManagementSystem.Application.Contracts",
"type": "HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto",
"typeSimple": "HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "input",
"name": "input",
"jsonName": null,
"type": "HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto",
"typeSimple": "HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "Body",
"descriptorName": ""
}
],
"returnValue": {
"type": "HospitalManagementSystem.Doctors.Dto.ShiftManagementDto",
"typeSimple": "HospitalManagementSystem.Doctors.Dto.ShiftManagementDto"
},
"allowAnonymous": null,
"implementFrom": "HospitalManagementSystem.Shift_Management.ShiftManagementAppService"
},
"DeleteShiftAsyncById": {
"uniqueName": "DeleteShiftAsyncById",
"name": "DeleteShiftAsync",
"httpMethod": "DELETE",
"url": "api/app/shift-management/{id}/shift",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "id",
"typeAsString": "System.Guid, System.Private.CoreLib",
"type": "System.Guid",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "id",
"name": "id",
"jsonName": null,
"type": "System.Guid",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": [],
"bindingSourceId": "Path",
"descriptorName": ""
}
],
"returnValue": {
"type": "System.Void",
"typeSimple": "System.Void"
},
"allowAnonymous": null,
"implementFrom": "HospitalManagementSystem.Shift_Management.ShiftManagementAppService"
}
}
}
}
},
@ -5513,6 +5650,51 @@
}
]
},
"HospitalManagementSystem.Doctors.Dto.CreateUpdateShiftManagementDto": {
"baseType": null,
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "DoctorId",
"jsonName": null,
"type": "System.Guid",
"typeSimple": "string",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Shifts",
"jsonName": null,
"type": "{HospitalManagementSystem.GlobalEnum.WorkSchedule:HospitalManagementSystem.GlobalEnum.TimeSlot}",
"typeSimple": "{HospitalManagementSystem.GlobalEnum.WorkSchedule:HospitalManagementSystem.GlobalEnum.TimeSlot}",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "IsActive",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"HospitalManagementSystem.Doctors.Dto.DoctorDto": {
"baseType": "Volo.Abp.Domain.Entities.Auditing.FullAuditedEntity<System.Guid>",
"isEnum": false,
@ -5715,20 +5897,8 @@
{
"name": "Availability",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.WorkSchedule?",
"typeSimple": "HospitalManagementSystem.GlobalEnum.WorkSchedule?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "TimeSlot",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"typeSimple": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"type": "[HospitalManagementSystem.GlobalEnum.WorkSchedule]",
"typeSimple": "[HospitalManagementSystem.GlobalEnum.WorkSchedule]",
"isRequired": false,
"minLength": null,
"maxLength": null,
@ -5759,6 +5929,63 @@
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Shifts",
"jsonName": null,
"type": "[HospitalManagementSystem.Doctors.Dto.ShiftManagementDto]",
"typeSimple": "[HospitalManagementSystem.Doctors.Dto.ShiftManagementDto]",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"HospitalManagementSystem.Doctors.Dto.ShiftManagementDto": {
"baseType": "Volo.Abp.Application.Dtos.FullAuditedEntityDto<System.Guid>",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "DoctorId",
"jsonName": null,
"type": "System.Guid",
"typeSimple": "string",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Shifts",
"jsonName": null,
"type": "{HospitalManagementSystem.GlobalEnum.WorkSchedule:HospitalManagementSystem.GlobalEnum.TimeSlot}",
"typeSimple": "{HospitalManagementSystem.GlobalEnum.WorkSchedule:HospitalManagementSystem.GlobalEnum.TimeSlot}",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "IsActive",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
@ -6249,20 +6476,8 @@
{
"name": "Availability",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.WorkSchedule?",
"typeSimple": "HospitalManagementSystem.GlobalEnum.WorkSchedule?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "TimeSlot",
"jsonName": null,
"type": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"typeSimple": "HospitalManagementSystem.GlobalEnum.TimeSlot",
"type": "[HospitalManagementSystem.GlobalEnum.WorkSchedule]",
"typeSimple": "[HospitalManagementSystem.GlobalEnum.WorkSchedule]",
"isRequired": false,
"minLength": null,
"maxLength": null,
@ -6489,21 +6704,7 @@
"Thursday",
"Friday",
"Saturday",
"Sunday",
"MondayToFriday",
"TuesdayToSaturday",
"WednesdayToSunday",
"ThursdayToMonday",
"FridayToTuesday",
"SaturdayToWednesday",
"SundayToThursday",
"MondayToThursday",
"TuesdayToFriday",
"WednesdayToSaturday",
"ThursdayToSunday",
"FridayToMonday",
"SaturdayToTuesday",
"SundayToWednesday"
"Sunday"
],
"enumValues": [
1,
@ -6512,21 +6713,7 @@
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21
7
],
"genericArguments": null,
"properties": null
@ -7284,41 +7471,6 @@
}
]
},
"System.Nullable<T0>": {
"baseType": "System.ValueType",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": [
"T"
],
"properties": [
{
"name": "HasValue",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "Value",
"jsonName": null,
"type": "T",
"typeSimple": "T",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"Volo.Abp.Account.ChangePasswordInput": {
"baseType": null,
"isEnum": false,
@ -7828,6 +7980,107 @@
}
]
},
"Volo.Abp.Application.Dtos.AuditedEntityDto<T0>": {
"baseType": "Volo.Abp.Application.Dtos.CreationAuditedEntityDto<TPrimaryKey>",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": [
"TPrimaryKey"
],
"properties": [
{
"name": "LastModificationTime",
"jsonName": null,
"type": "System.DateTime?",
"typeSimple": "string?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "LastModifierId",
"jsonName": null,
"type": "System.Guid?",
"typeSimple": "string?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"Volo.Abp.Application.Dtos.CreationAuditedEntityDto<T0>": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto<TPrimaryKey>",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": [
"TPrimaryKey"
],
"properties": [
{
"name": "CreationTime",
"jsonName": null,
"type": "System.DateTime",
"typeSimple": "string",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "CreatorId",
"jsonName": null,
"type": "System.Guid?",
"typeSimple": "string?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"Volo.Abp.Application.Dtos.EntityDto": {
"baseType": null,
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": []
},
"Volo.Abp.Application.Dtos.EntityDto<T0>": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": [
"TKey"
],
"properties": [
{
"name": "Id",
"jsonName": null,
"type": "TKey",
"typeSimple": "TKey",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"Volo.Abp.Application.Dtos.ExtensibleAuditedEntityDto<T0>": {
"baseType": "Volo.Abp.Application.Dtos.ExtensibleCreationAuditedEntityDto<TPrimaryKey>",
"isEnum": false,
@ -8063,6 +8316,53 @@
}
]
},
"Volo.Abp.Application.Dtos.FullAuditedEntityDto<T0>": {
"baseType": "Volo.Abp.Application.Dtos.AuditedEntityDto<TPrimaryKey>",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": [
"TPrimaryKey"
],
"properties": [
{
"name": "IsDeleted",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "DeleterId",
"jsonName": null,
"type": "System.Guid?",
"typeSimple": "string?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
},
{
"name": "DeletionTime",
"jsonName": null,
"type": "System.DateTime?",
"typeSimple": "string?",
"isRequired": false,
"minLength": null,
"maxLength": null,
"minimum": null,
"maximum": null,
"regex": null
}
]
},
"Volo.Abp.Application.Dtos.LimitedResultRequestDto": {
"baseType": null,
"isEnum": false,

View File

@ -8,20 +8,6 @@ export enum WorkSchedule {
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

@ -9,5 +9,6 @@ import * as Dtos from './dtos';
import * as GlobalEnum from './global-enum';
import * as Patients from './patients';
import * as Shared from './shared';
import * as ShiftManagement from './shift-management';
import * as Volo from './volo';
export { Abp, Appoinments, Appointments, Departments, Doctors, Documents, Dto, Dtos, GlobalEnum, Patients, Shared, Volo };
export { Abp, Appoinments, Appointments, Departments, Doctors, Documents, Dto, Dtos, GlobalEnum, Patients, Shared, ShiftManagement, Volo };

View File

@ -0,0 +1 @@
export * from './shift-management.service';

View File

@ -0,0 +1,45 @@
import { RestService, Rest } from '@abp/ng.core';
import { Injectable } from '@angular/core';
import type { CreateUpdateShiftManagementDto, ShiftManagementDto } from '../doctors/dto/models';
@Injectable({
providedIn: 'root',
})
export class ShiftManagementService {
apiName = 'Default';
createOrUpdateShift = (input: CreateUpdateShiftManagementDto, config?: Partial<Rest.Config>) =>
this.restService.request<any, ShiftManagementDto>({
method: 'POST',
url: '/api/app/shift-management/or-update-shift',
body: input,
},
{ apiName: this.apiName,...config });
deleteShift = (id: string, config?: Partial<Rest.Config>) =>
this.restService.request<any, void>({
method: 'DELETE',
url: `/api/app/shift-management/${id}/shift`,
},
{ apiName: this.apiName,...config });
getAllShifts = (config?: Partial<Rest.Config>) =>
this.restService.request<any, ShiftManagementDto[]>({
method: 'GET',
url: '/api/app/shift-management/shifts',
},
{ apiName: this.apiName,...config });
getShiftsByDoctorId = (doctorId: string, config?: Partial<Rest.Config>) =>
this.restService.request<any, ShiftManagementDto>({
method: 'GET',
url: `/api/app/shift-management/shifts-by-doctor-id/${doctorId}`,
},
{ apiName: this.apiName,...config });
constructor(private restService: RestService) {}
}

View File

@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { RoomsComponent } from './rooms.component';
const routes: Routes = [
{ path: '', component: RoomsComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class RoomManagementRoutingModule { }

View File

@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RoomManagementRoutingModule } from './room-management-routing.module';
import { RoomsComponent } from './rooms.component';
import { FormsModule } from '@angular/forms';
import { CalendarModule } from 'primeng/calendar';
import { ButtonModule } from 'primeng/button';
@NgModule({
declarations: [RoomsComponent],
imports: [
CommonModule,
RoomManagementRoutingModule,
FormsModule ,
CalendarModule,
ButtonModule,
]
})
export class RoomManagementModule { }

View File

@ -2,13 +2,12 @@ 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
selectedDate: Date = new Date();
roomData = [
{ roomName: 'Room 101' },
@ -23,7 +22,7 @@ export class RoomsComponent {
{ roomName: 'Room 303' },
{ roomName: 'Room 401' },
{ roomName: 'Room 402' },
// Add more rooms as necessary
];
roomStatus = {
@ -39,19 +38,15 @@ export class RoomsComponent {
'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
return this.roomStatus[room] || 'available';
}
getRoomStatusLabel(room: string) {

View File

@ -91,6 +91,14 @@ function configureRoutes(routesService: RoutesService) {
order: 402,
requiredPolicy:'HospitalManagementSystem.Doctor'
},
// {
// path: '/doctors/shift-management',
// name: 'Shift Management',
// parentName: 'Doctors',
// iconClass: 'fas fa-clock',
// order: 403,
// requiredPolicy:'HospitalManagementSystem.Doctor'
// },
{
path: '',
name: 'Rooms',

View File

@ -0,0 +1,17 @@
using HospitalManagementSystem.GlobalEnum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HospitalManagementSystem.Doctors.Dto
{
public class CreateUpdateShiftManagementDto
{
public Guid DoctorId { get; set; }
public Dictionary<WorkSchedule, TimeSlot> Shifts { get; set; } = new Dictionary<WorkSchedule, TimeSlot>();
public bool IsActive { get; set; } = true;
}
}

View File

@ -26,9 +26,11 @@ namespace HospitalManagementSystem.Doctors.Dto
public DateTime? JoiningDate { get; set; }
public int? Experience { get; set; }
public decimal? ConsultationFee { get; set; }
public WorkSchedule? Availability { get; set; }
public TimeSlot TimeSlot { get; set; }
public List<WorkSchedule> Availability { get; set; } = new List<WorkSchedule>();
public decimal? Rating { get; set; }
public string? ClinicLocation { get; set; }
public List<ShiftManagementDto>? Shifts { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using HospitalManagementSystem.GlobalEnum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
namespace HospitalManagementSystem.Doctors.Dto
{
public class ShiftManagementDto : FullAuditedEntityDto<Guid>
{
public Guid DoctorId { get; set; }
public Dictionary<WorkSchedule, TimeSlot> Shifts { get; set; } = new Dictionary<WorkSchedule, TimeSlot>();
public bool IsActive { get; set; } = true;
}
}

View File

@ -23,6 +23,7 @@ namespace HospitalManagementSystem.Doctors
public class DoctorAppService : ApplicationService
{
private readonly IRepository<Doctor, Guid> _doctorRepository;
private readonly IWebHostEnvironment _env;
public DoctorAppService(IRepository<Doctor, Guid> doctorRepository, IWebHostEnvironment env)
@ -190,5 +191,8 @@ namespace HospitalManagementSystem.Doctors
await _doctorRepository.DeleteAsync(id);
}
#endregion
}
}

View File

@ -28,8 +28,7 @@ namespace HospitalManagementSystem.Dtos
public DateTime? JoiningDate { get; set; }
public int? Experience { get; set; }
public decimal? ConsultationFee { get; set; }
public WorkSchedule? Availability { get; set; }
public TimeSlot TimeSlot { get; set; }
public List<WorkSchedule> Availability { get; set; } = new List<WorkSchedule>();
public decimal? Rating { get; set; }
public string? ClinicLocation { get; set; }

View File

@ -53,6 +53,13 @@ namespace HospitalManagementSystem
CreateMap<Doctor, CreateDoctorDto>();
CreateMap<CreateDoctorDto, Doctor>();
#endregion
#region shiftManagement
CreateMap<ShiftManagement, ShiftManagementDto>();
CreateMap<ShiftManagementDto, ShiftManagement>();
CreateMap<ShiftManagement, CreateUpdateShiftManagementDto>();
CreateMap<CreateUpdateShiftManagementDto, ShiftManagement>();
#endregion
}
}
}

View File

@ -0,0 +1,100 @@
using Volo.Abp.Domain.Repositories;
using HospitalManagementSystem.Doctors;
using HospitalManagementSystem.Doctors.Dto;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Linq.Dynamic.Core;
using Microsoft.EntityFrameworkCore;
namespace HospitalManagementSystem.Shift_Management
{
public class ShiftManagementAppService : ApplicationService
{
private readonly IRepository<ShiftManagement, Guid> _shiftManagementRepository;
private readonly IRepository<Doctor, Guid> _doctorRepository;
public ShiftManagementAppService(IRepository<ShiftManagement, Guid> shiftManagementRepository,
IRepository<Doctor, Guid> doctorRepository)
{
_shiftManagementRepository = shiftManagementRepository;
_doctorRepository = doctorRepository;
}
// Fetch all shifts
public async Task<List<ShiftManagementDto>> GetAllShiftsAsync()
{
var shifts = await _shiftManagementRepository.GetListAsync();
return ObjectMapper.Map<List<ShiftManagement>, List<ShiftManagementDto>>(shifts);
}
// Fetch shifts by doctor ID
public async Task<ShiftManagementDto> GetShiftsByDoctorIdAsync(Guid doctorId)
{
var shifts = await _shiftManagementRepository.GetListAsync(x => x.DoctorId == doctorId);
var shiftDictionary = shifts.ToDictionary(s => s.ShiftDays, s => s.ShiftTime);
return new ShiftManagementDto
{
DoctorId = doctorId,
Shifts = shiftDictionary,
IsActive = shifts.Any() && shifts.First().IsActive
};
}
// Create or update a shift
public async Task<ShiftManagementDto> CreateOrUpdateShiftAsync(CreateUpdateShiftManagementDto input)
{
{
// Get existing shifts for the doctor
var existingShifts = await _shiftManagementRepository.GetListAsync(x => x.DoctorId == input.DoctorId);
// Iterate through each shift in the dictionary
foreach (var shiftEntry in input.Shifts)
{
var shiftDay = shiftEntry.Key;
var shiftTime = shiftEntry.Value;
// Check if a shift already exists for the same doctor and day
var existingShift = existingShifts.FirstOrDefault(x => x.ShiftDays == shiftDay);
if (existingShift != null)
{
// Update existing shift
existingShift.ShiftTime = shiftTime;
existingShift.IsActive = input.IsActive;
await _shiftManagementRepository.UpdateAsync(existingShift);
}
else
{
// Create new shift entry
var newShift = new ShiftManagement(
GuidGenerator.Create(),
input.DoctorId,
shiftTime,
shiftDay,
input.IsActive
);
await _shiftManagementRepository.InsertAsync(newShift);
}
}
// Returning a simple DTO response (You can customize it as needed)
return new ShiftManagementDto
{
DoctorId = input.DoctorId,
Shifts = input.Shifts,
IsActive = input.IsActive
};
}
}
// Delete a shift
public async Task DeleteShiftAsync(Guid id)
{
await _shiftManagementRepository.DeleteAsync(id);
}
}
}

View File

@ -46,21 +46,6 @@ namespace HospitalManagementSystem.GlobalEnum
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
{

View File

@ -33,6 +33,8 @@ namespace HospitalManagementSystem.Doctors
public decimal? Rating { get; set; }
public string? ClinicLocation { get; set; }
public virtual ICollection<Appointment> Appointments { get; set; } = new List<Appointment>();
public virtual ICollection<ShiftManagement> Shifts { get; set; } = new List<ShiftManagement>();
public Doctor()
{
//Appointments = new List<Appointment>();

View File

@ -0,0 +1,30 @@
using HospitalManagementSystem.GlobalEnum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities.Auditing;
namespace HospitalManagementSystem.Doctors
{
public class ShiftManagement : FullAuditedAggregateRoot<Guid>
{
public Guid DoctorId { get; set; }
public virtual Doctor Doctor { get; set; } = null!;
public TimeSlot ShiftTime { get; set; } // Using Enum for Shift Time
public WorkSchedule ShiftDays { get; set; } // Using Enum for Shift Days
public bool IsActive { get; set; } = true;
protected ShiftManagement() { }
public ShiftManagement(Guid id, Guid doctorId, TimeSlot shiftTime, WorkSchedule shiftDays, bool isActive)
: base(id)
{
DoctorId = doctorId;
ShiftTime = shiftTime;
ShiftDays = shiftDays;
IsActive = isActive;
}
}
}

View File

@ -32,6 +32,7 @@ public class HospitalManagementSystemDbContext :
public DbSet<Patient> Patients { get; set; }
public DbSet<EntityDocument> EntityDocuments { get; set; }
public DbSet<PatientDocument> PatientDocuments { get; set; }
public DbSet<ShiftManagement> ShiftManagements { get; set; }
#region Entities from the modules
@ -110,6 +111,11 @@ public class HospitalManagementSystemDbContext :
b.ToTable("PatientDocuments");
b.ConfigureByConvention(); //auto configure for the base class props
});
builder.Entity<ShiftManagement>(b =>
{
b.ToTable("ShiftManagements");
b.ConfigureByConvention(); //auto configure for the base class props
});
//builder.Entity<YourEntity>(b =>
//{

View File

@ -0,0 +1,58 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace HospitalManagementSystem.Migrations
{
/// <inheritdoc />
public partial class ShiftManagement : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ShiftManagements",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
DoctorId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ShiftStartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
ShiftEndTime = table.Column<DateTime>(type: "datetime2", nullable: false),
ShiftDays = table.Column<string>(type: "nvarchar(max)", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ShiftManagements", x => x.Id);
table.ForeignKey(
name: "FK_ShiftManagements_Doctors_DoctorId",
column: x => x.DoctorId,
principalTable: "Doctors",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ShiftManagements_DoctorId",
table: "ShiftManagements",
column: "DoctorId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ShiftManagements");
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace HospitalManagementSystem.Migrations
{
/// <inheritdoc />
public partial class Shifttable_modified : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ShiftEndTime",
table: "ShiftManagements");
migrationBuilder.DropColumn(
name: "ShiftStartTime",
table: "ShiftManagements");
migrationBuilder.AlterColumn<int>(
name: "ShiftDays",
table: "ShiftManagements",
type: "int",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AddColumn<int>(
name: "ShiftTime",
table: "ShiftManagements",
type: "int",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ShiftTime",
table: "ShiftManagements");
migrationBuilder.AlterColumn<string>(
name: "ShiftDays",
table: "ShiftManagements",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddColumn<DateTime>(
name: "ShiftEndTime",
table: "ShiftManagements",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<DateTime>(
name: "ShiftStartTime",
table: "ShiftManagements",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
}
}

View File

@ -180,8 +180,9 @@ namespace HospitalManagementSystem.Migrations
b.Property<string>("Address")
.HasColumnType("nvarchar(max)");
b.Property<int?>("Availability")
.HasColumnType("int");
b.PrimitiveCollection<string>("Availability")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ClinicLocation")
.HasColumnType("nvarchar(max)");
@ -271,6 +272,72 @@ namespace HospitalManagementSystem.Migrations
b.ToTable("Doctors");
});
modelBuilder.Entity("HospitalManagementSystem.Doctors.ShiftManagement", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<Guid>("DoctorId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<int>("ShiftDays")
.HasColumnType("int");
b.Property<int>("ShiftTime")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("DoctorId");
b.ToTable("ShiftManagements", (string)null);
});
modelBuilder.Entity("HospitalManagementSystem.Documents.EntityDocument", b =>
{
b.Property<Guid>("Id")
@ -2307,6 +2374,17 @@ namespace HospitalManagementSystem.Migrations
b.Navigation("Department");
});
modelBuilder.Entity("HospitalManagementSystem.Doctors.ShiftManagement", b =>
{
b.HasOne("HospitalManagementSystem.Doctors.Doctor", "Doctor")
.WithMany("Shifts")
.HasForeignKey("DoctorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Doctor");
});
modelBuilder.Entity("HospitalManagementSystem.Documents.PatientDocument", b =>
{
b.HasOne("HospitalManagementSystem.Documents.EntityDocument", "EntityDocuments")
@ -2515,6 +2593,8 @@ namespace HospitalManagementSystem.Migrations
modelBuilder.Entity("HospitalManagementSystem.Doctors.Doctor", b =>
{
b.Navigation("Appointments");
b.Navigation("Shifts");
});
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>