@ -0,0 +1,212 @@ | |||||
<div> | |||||
<p-table #dt2 dataKey="id" [value]="patients" [paginator]="true" [rows]="10" [totalRecords]="totalRecords" | |||||
[lazy]="true" (onLazyLoad)="loadPatient($event)" [rowsPerPageOptions]="[10, 20, 50]" | |||||
[responsiveLayout]="'scroll'" [globalFilterFields]="['id', 'name', 'status']" | |||||
[filters]="{ global: { value: '', matchMode: 'contains' } }" class="table table-striped"> | |||||
<ng-template pTemplate="caption"> | |||||
<div class="flex"> | |||||
<h2 class="mr-auto">Patient List</h2> | |||||
<div> | |||||
<button *ngIf="createpermission" pButton class="p-button-rounded p-button-success ml-2" | |||||
(click)="openNewPatientDialog()"> | |||||
<i class="pi pi-plus-circle"></i> | |||||
</button> | |||||
<button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportPatient()"> | |||||
<i class="pi pi-download"></i> | |||||
</button> | |||||
<p-iconField iconPosition="right" class="ml-2"> | |||||
<p-inputIcon> | |||||
<i class="pi pi-search"></i> | |||||
</p-inputIcon> | |||||
<input pInputText type="text" (input)="dt2.filterGlobal($event.target.value, 'contains')" | |||||
[(ngModel)]="globalFilter" placeholder="Search keyword" /> | |||||
</p-iconField> | |||||
</div> | |||||
</div> | |||||
</ng-template> | |||||
<ng-template pTemplate="header"> | |||||
<tr> | |||||
<th class="hidden" pSortableColumn="id">Patient ID <p-sortIcon field="id" /></th> | |||||
<th pSortableColumn="name">Full Name <p-sortIcon field="name" /></th> | |||||
<th pSortableColumn="gender">Gender <p-sortIcon field="gender" /></th> | |||||
<th pSortableColumn="admissionDate">Date of Admission <p-sortIcon field="admissionDate" /></th> | |||||
<th pSortableColumn="bloodGroup">Blood Group <p-sortIcon field="bloodGroup" /></th> | |||||
<th>Mobile</th> | |||||
<th>Email</th> | |||||
<th pSortableColumn="status">Status <p-sortIcon field="status" /></th> | |||||
<th>Actions</th> | |||||
</tr> | |||||
</ng-template> | |||||
<ng-template pTemplate="body" let-patient> | |||||
<tr> | |||||
<td class="hidden">{{ patient.id }}</td> | |||||
<td>{{ patient.name }}</td> | |||||
<td> | |||||
<span class="badge" [ngClass]="patient.gender === 1 ? 'male' : 'female'"> | |||||
{{ gender[patient.gender] }} | |||||
</span> | |||||
</td> | |||||
<td>{{ patient.admissionDate | date }}</td> | |||||
<td>{{ patient.bloodGroup }}</td> | |||||
<td>{{ patient.mobile }}</td> | |||||
<td>{{ patient.email }}</td> | |||||
<td>{{ status[patient.status] }}</td> | |||||
<td class="d-flex"> | |||||
<button *ngIf="createpermission" pButton class="btn btn-success btn-sm" | |||||
(click)="addnewrecord(patient.id)"> | |||||
<i class="pi pi-plus-circle"></i> | |||||
</button> | |||||
<button *ngIf="editpermission" class="btn btn-warning btn-sm ml-1" (click)="editPatient(patient)"><i | |||||
class="pi pi-pencil"></i></button> | |||||
<button *ngIf="deletepermission" class="btn btn-danger btn-sm ml-1" | |||||
(click)="deletePatient(patient.id)"><i class="pi pi-trash"></i></button> | |||||
</td> | |||||
</tr> | |||||
</ng-template> | |||||
<ng-template pTemplate="emptymessage"> | |||||
<tr> | |||||
<td colspan="10">No Patients found.</td> | |||||
</tr> | |||||
</ng-template> | |||||
</p-table> | |||||
<span>Total Records: {{totalRecords}}</span> | |||||
</div> | |||||
<div> | |||||
<p-dialog *ngIf="patientDialog" header="{{patientDialogTitle}}" [(visible)]="patientDialog" [modal]="true" | |||||
[closable]="true" [style]="{width: '85%', height: '100%'}"> | |||||
<form #patientrecord="ngForm" (ngSubmit)="savePatient(patientrecord)"> | |||||
<div class="p-fluid"> | |||||
<div class="p-grid"> | |||||
<!-- Full Name --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="name">Full Name</label> | |||||
<input id="name" name="name" type="text" pInputText [(ngModel)]="selectedPatient.name" | |||||
placeholder="Enter full patient name" required #name="ngModel" /> | |||||
<small *ngIf="name.invalid && name.touched" class="p-error">Full Name is required</small> | |||||
</div> | |||||
</div> | |||||
<!-- Mobile --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="mobile">Mobile</label> | |||||
<input id="mobile" name="mobile" type="text" pInputText [(ngModel)]="selectedPatient.mobile" | |||||
placeholder="Enter mobile number" maxlength="10" required pattern="[0-9]{10}" | |||||
#mobile="ngModel" /> | |||||
<small *ngIf="mobile.invalid && mobile.touched" class="p-error"> | |||||
Mobile is required and must be 10 digits | |||||
</small> | |||||
</div> | |||||
</div> | |||||
<!-- Address --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="address">Address</label> | |||||
<input id="address" name="address" type="text" pInputText | |||||
[(ngModel)]="selectedPatient.address" placeholder="Enter address" required | |||||
#address="ngModel" /> | |||||
<small *ngIf="address.invalid && address.touched" class="p-error">Address is | |||||
required</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<!-- Gender --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="gender">Gender</label> | |||||
<div> | |||||
<label class="mx-1"> | |||||
<input id="male" type="radio" name="gender" [(ngModel)]="selectedgender" [value]="1" | |||||
required /> | |||||
Male | |||||
</label> | |||||
<label> | |||||
<input id="female" type="radio" name="gender" [(ngModel)]="selectedgender" | |||||
[value]="2" /> | |||||
Female | |||||
</label> | |||||
</div> | |||||
<small *ngIf="!selectedgender" class="p-error">Gender is required</small> | |||||
</div> | |||||
</div> | |||||
<!-- Admission Date --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="admissionDate">Admission Date</label> | |||||
<p-calendar id="admissionDate" name="admissionDate" [(ngModel)]="selectadmissionDate" | |||||
showIcon styleClass="small-calendar" required #admissionDate="ngModel"></p-calendar> | |||||
<small *ngIf="admissionDate.invalid && admissionDate.touched" class="p-error"> | |||||
Admission Date is required | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<!-- Blood Group --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="bloodGroup">Blood Group</label> | |||||
<input id="bloodGroup" name="bloodGroup" type="text" pInputText | |||||
[(ngModel)]="selectedPatient.bloodGroup" placeholder="Enter blood group" required | |||||
#bloodGroup="ngModel" /> | |||||
<small *ngIf="bloodGroup.invalid && bloodGroup.touched" class="p-error">Blood Group is | |||||
required</small> | |||||
</div> | |||||
</div> | |||||
<!-- Email --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="email">Email</label> | |||||
<input id="email" name="email" type="email" pInputText [(ngModel)]="selectedPatient.email" | |||||
placeholder="Enter email address" required email #email="ngModel" /> | |||||
<small *ngIf="email.invalid && email.touched" class="p-error">Enter a valid email | |||||
address</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<!-- Age --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="age">Age</label> | |||||
<input id="age" name="age" type="number" pInputText [(ngModel)]="selectedPatient.age" | |||||
placeholder="Enter age" required min="1" max="120" #age="ngModel" /> | |||||
<small *ngIf="age.invalid && age.touched" class="p-error"> | |||||
Age is required and must be between 1 and 90 | |||||
</small> | |||||
</div> | |||||
</div> | |||||
<!-- Status --> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="status">Status</label> | |||||
<p-dropdown name="status" id="status" [options]="statuslist" [(ngModel)]="selectedstatus" | |||||
optionLabel="label" optionValue="value" placeholder="Select status" | |||||
required></p-dropdown> | |||||
<small *ngIf="selectedstatus === 0" class="p-error">Status is required</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div> | |||||
<button type="submit" pButton class="btn btn-primary" | |||||
[disabled]="(patientrecord.invalid || selectedstatus === 0 || !selectedgender)">Save</button> | |||||
<button pButton class="btn btn-secondary ml-1" (click)="closeDialog()">Close</button> | |||||
</div> | |||||
</form> | |||||
</p-dialog> | |||||
</div> |
@ -0,0 +1,46 @@ | |||||
/* Adjusting the calendar popup */ | |||||
.small-calendar .p-datepicker { | |||||
width: 200px !important; /* Adjust the width as per your needs */ | |||||
font-size: 12px !important; /* Adjust the font size */ | |||||
} | |||||
.small-calendar .p-datepicker-header { | |||||
padding: 2px !important; /* Adjust the header padding */ | |||||
} | |||||
.small-calendar .p-datepicker-calendar th { | |||||
font-size: 10px !important; /* Smaller font size for the header */ | |||||
} | |||||
.small-calendar .p-datepicker-calendar td { | |||||
font-size: 10px !important; /* Smaller font size for the days */ | |||||
} | |||||
.table-header { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
} | |||||
.badge { | |||||
display: inline-block; | |||||
padding: 0.2rem 0.6rem; | |||||
border-radius: 0.5rem; | |||||
color: white; | |||||
font-weight: bold; | |||||
font-size: 0.8rem; | |||||
} | |||||
.male { | |||||
background-color: green; | |||||
} | |||||
.female { | |||||
background-color: purple; | |||||
} | |||||
.pdf-icon { | |||||
color: red; | |||||
font-size: 1.2rem; | |||||
} | |||||
@ -0,0 +1,226 @@ | |||||
import { PermissionService } from '@abp/ng.core'; | |||||
import { HttpClient } from '@angular/common/http'; | |||||
import { Component, OnInit } from '@angular/core'; | |||||
import { NgForm } from '@angular/forms'; | |||||
import { Router } from '@angular/router'; | |||||
import { PagingSortPatientResultDto } from '@proxy/dto'; | |||||
import { Gender, Status } from '@proxy/global-enum'; | |||||
import { PatientService } from '@proxy/patients'; | |||||
import { PatientDto, CreateUpdatePatientDto } from '@proxy/patients/dto'; | |||||
import { MessageService } from 'primeng/api'; | |||||
@Component({ | |||||
selector: 'app-all-patients', | |||||
templateUrl: './all-patients.component.html', | |||||
styleUrl: './all-patients.component.scss', | |||||
providers: [PatientService, MessageService, PermissionService], | |||||
}) | |||||
export class AllPatientsComponent implements OnInit { | |||||
globalFilter: string = ''; | |||||
patients: PatientDto[]; | |||||
totalRecords: number = 0; | |||||
loading: boolean = false; | |||||
patientDialog: boolean = false; | |||||
selectedPatient: CreateUpdatePatientDto; | |||||
isEditMode: boolean = false; | |||||
patientDialogTitle: string = ''; | |||||
params: PagingSortPatientResultDto; | |||||
status: any; | |||||
gender: any; | |||||
statuslist: any; | |||||
selectedstatus: any = 0; | |||||
selectedgender: any = 0; | |||||
selectadmissionDate: Date = new Date(); | |||||
selectdischargeDate: Date = new Date(); | |||||
uploadfile: { | |||||
file: File[]; | |||||
name: string; | |||||
}[] = []; | |||||
createpermission: boolean; | |||||
editpermission: boolean; | |||||
deletepermission: boolean; | |||||
constructor( | |||||
private patientService: PatientService, | |||||
private http: HttpClient, | |||||
private messageService: MessageService, | |||||
private permissionChecker: PermissionService, | |||||
private router: Router | |||||
) {} | |||||
ngOnInit() { | |||||
this.createpermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Create' | |||||
); | |||||
this.editpermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Edit' | |||||
); | |||||
this.deletepermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Delete' | |||||
); | |||||
this.status = Status; | |||||
this.gender = Gender; | |||||
this.patientService.getStatusDropdown().subscribe(result => { | |||||
this.statuslist = result; | |||||
}); | |||||
this.resetselectpatient(); | |||||
this.loadPatient({ | |||||
first: 0, | |||||
rows: 10, | |||||
sortField: 'id', | |||||
sortOrder: 1, | |||||
globalFilter: null, | |||||
}); | |||||
} | |||||
resetselectpatient() { | |||||
this.selectedPatient = { | |||||
name: '', | |||||
gender: Gender.Male, | |||||
mobile: '', | |||||
email: '', | |||||
age: 0, | |||||
treatment: '', | |||||
doctorAssigned: '', | |||||
address: '', | |||||
bloodGroup: '', | |||||
admissionDate: '', | |||||
dischargeDate: '', | |||||
status: Status.InTreatment, | |||||
}; | |||||
} | |||||
loadPatient(event: any) { | |||||
this.loading = true; | |||||
let order = event.sortOrder == 1 ? ' asc' : ' desc'; | |||||
event.sortField = event.sortField == undefined ? 'id' : event.sortField; | |||||
this.params = { | |||||
skipCount: event.first, | |||||
maxResultCount: event.rows, | |||||
sorting: event.sortField + order, | |||||
search: event.globalFilter == null ? '' : event.globalFilter, | |||||
}; | |||||
this.patientService.getPatientList(this.params).subscribe(data => { | |||||
this.patients = data.items; | |||||
this.totalRecords = data.totalCount; | |||||
this.loading = false; | |||||
}); | |||||
} | |||||
exportPatient() { | |||||
this.patientService.getExportPatientData().subscribe(result => { | |||||
const binary = atob(result.fileContent); | |||||
const len = binary.length; | |||||
const bytes = new Uint8Array(len); | |||||
for (let i = 0; i < len; i++) { | |||||
bytes[i] = binary.charCodeAt(i); | |||||
} | |||||
const blob = new Blob([bytes], { type: 'application/xlsx' }); | |||||
const url = window.URL.createObjectURL(blob); | |||||
const link = document.createElement('a'); | |||||
link.href = url; | |||||
link.download = result.fileName; | |||||
document.body.appendChild(link); | |||||
link.click(); | |||||
document.body.removeChild(link); | |||||
window.URL.revokeObjectURL(url); | |||||
}); | |||||
} | |||||
openNewPatientDialog() { | |||||
this.patientDialogTitle = 'New Patient'; | |||||
this.resetselectpatient(); | |||||
this.selectedgender = 0; | |||||
this.selectedstatus = 0; | |||||
this.patientDialog = true; | |||||
this.isEditMode = false; | |||||
} | |||||
addnewrecord(id: any) { | |||||
this.router.navigate(['/patients/patient-record', id]); | |||||
} | |||||
editPatient(Patient: any) { | |||||
this.patientDialogTitle = 'Edit Patient'; | |||||
this.selectedPatient = { ...Patient }; | |||||
this.selectedgender = this.selectedPatient.gender; | |||||
this.selectedstatus = this.selectedPatient.status; | |||||
this.selectadmissionDate = new Date(this.selectedPatient.admissionDate); | |||||
this.selectdischargeDate = new Date(this.selectedPatient.dischargeDate); | |||||
this.patientDialog = true; | |||||
this.isEditMode = true; | |||||
} | |||||
deletePatient(id: any) { | |||||
this.patientService.deletePatient(id).subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient deleted successfully', | |||||
}); | |||||
this.loadPatient(this.params); | |||||
}); | |||||
} | |||||
savePatient(form: NgForm) { | |||||
debugger; | |||||
console.log(form.controls); | |||||
if (form.invalid) { | |||||
Object.values(form.controls).forEach(control => control.markAsTouched()); | |||||
return; | |||||
} | |||||
this.selectedPatient.gender = this.selectedgender; | |||||
this.selectedPatient.status = this.selectedstatus; | |||||
this.selectedPatient.admissionDate = this.selectadmissionDate.toDateString(); | |||||
this.selectedPatient.dischargeDate = this.selectdischargeDate.toDateString(); | |||||
console.log(this.selectedPatient); | |||||
if (this.isEditMode) { | |||||
this.patientService | |||||
.updatePatient(this.selectedPatient.id, this.selectedPatient) | |||||
.subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient updated successfully', | |||||
}); | |||||
this.patientDialog = false; | |||||
this.loadPatient({ | |||||
first: 0, | |||||
rows: 10, | |||||
sortField: 'id', | |||||
sortOrder: 1, | |||||
globalFilter: null, | |||||
}); | |||||
}); | |||||
} else { | |||||
this.patientService.createPatient(this.selectedPatient).subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient created successfully', | |||||
}); | |||||
this.patientDialog = false; | |||||
this.loadPatient({ | |||||
first: 0, | |||||
rows: 10, | |||||
sortField: 'id', | |||||
sortOrder: 1, | |||||
globalFilter: null, | |||||
}); | |||||
}); | |||||
} | |||||
} | |||||
closeDialog() { | |||||
this.patientDialog = false; | |||||
} | |||||
} |
@ -0,0 +1,266 @@ | |||||
<div class="patient-container"> | |||||
<div class="patient-card"> | |||||
<!-- Patient Image --> | |||||
<div class="patient-image"> | |||||
<img [src]="patientImageUrl || 'assets/default-profile.png'" alt="Patient Image"> | |||||
</div> | |||||
<!-- Patient Information --> | |||||
<div class="patient-info"> | |||||
<h2 class="patient-name">{{ patientdto?.name }}</h2> | |||||
<div class="patient-details"> | |||||
<div class="info-item"> | |||||
<strong>Age:</strong> {{ patientdto?.age }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Gender:</strong> {{ gender[patientdto?.gender] }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Mobile:</strong> {{ patientdto?.mobile }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Email:</strong> {{ patientdto?.email }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Blood Group:</strong> {{ patientdto?.bloodGroup }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Doctor:</strong> {{ patientdto?.doctorAssigned || 'N/A' }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Admission:</strong> {{ patientdto?.admissionDate | date }} | |||||
</div> | |||||
<div class="info-item"> | |||||
<strong>Status:</strong> | |||||
<span class="status" [ngClass]="{'active': patientdto?.status === 'Active', 'inactive': patientdto?.status === 'Inactive'}"> | |||||
{{ status[patientdto?.status] }} | |||||
</span> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div> | |||||
<p-table #dt2 dataKey="id" [value]="patientrecords" [paginator]="true" [rows]="10" [totalRecords]="totalRecords" | |||||
[lazy]="true" (onLazyLoad)="loadPatient($event,userid)" [rowsPerPageOptions]="[10, 20, 50]" | |||||
[responsiveLayout]="'scroll'" [globalFilterFields]="['id', 'name', 'diagnosis']" | |||||
[filters]="{ global: { value: '', matchMode: 'contains' } }" class="table table-striped"> | |||||
<ng-template pTemplate="caption"> | |||||
<div class="flex"> | |||||
<h2 class="mr-auto">{{'::PatientHeader' | abpLocalization}}</h2> | |||||
<div> | |||||
<button *ngIf="createpermission" pButton class="p-button-rounded p-button-success ml-2" | |||||
(click)="openNewPatientDialog()"> | |||||
<i class="pi pi-plus-circle"></i> | |||||
</button> | |||||
<button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportPatient()"> | |||||
<i class="pi pi-download"></i> | |||||
</button> | |||||
<p-iconField iconPosition="right" class="ml-2"> | |||||
<p-inputIcon> | |||||
<i class="pi pi-search"></i> | |||||
</p-inputIcon> | |||||
<input pInputText type="text" (input)="dt2.filterGlobal($event.target.value, 'contains')" | |||||
[(ngModel)]="globalFilter" placeholder="Search keyword" /> | |||||
</p-iconField> | |||||
</div> | |||||
</div> | |||||
</ng-template> | |||||
<ng-template pTemplate="header"> | |||||
<tr> | |||||
<th class="hidden" pSortableColumn="id">Patient ID <p-sortIcon field="id" /></th> | |||||
<th pSortableColumn="fullName">Full Name <p-sortIcon field="fullName" /></th> | |||||
<th pSortableColumn="gender">Gender <p-sortIcon field="fullName" /></th> | |||||
<th pSortableColumn="dateOfAdmission">Date of Admission <p-sortIcon field="dateOfAdmission" /></th> | |||||
<th pSortableColumn="diagnosis">Diagnosis <p-sortIcon field="diagnosis" /></th> | |||||
<th>Lab Reports</th> | |||||
<th>Medications</th> | |||||
<th pSortableColumn="nextFollowUp">Next Follow-Up <p-sortIcon field="nextFollowUp" /></th> | |||||
<th pSortableColumn="status">Status <p-sortIcon field="status" /></th> | |||||
<th>Actions</th> | |||||
</tr> | |||||
</ng-template> | |||||
<ng-template pTemplate="body" let-patientrecord> | |||||
<tr> | |||||
<td class="hidden">{{ patientrecord.id }}</td> | |||||
<td>{{ patientrecord.patients.name }}</td> | |||||
<td> | |||||
<span class="badge" [ngClass]="patientrecord.patients.gender === 1 ? 'male' : 'female'"> | |||||
{{ gender[patientrecord.patients.gender] }} | |||||
</span> | |||||
</td> | |||||
<td>{{ patientrecord.dateOfAdmission | date }}</td> | |||||
<td>{{ patientrecord.diagnosis }}</td> | |||||
<td><i class="pi pi-file-pdf pdf-icon"></i></td> | |||||
<td><i class="pi pi-file-pdf pdf-icon"></i></td> | |||||
<td>{{ patientrecord.nextFollowUp | date }}</td> | |||||
<td>{{ status[patientrecord.patients.status] }}</td> | |||||
<td class="d-flex"> | |||||
<button *ngIf="editpermission" class="btn btn-warning btn-sm" (click)="editPatient(patientrecord)"><i | |||||
class="pi pi-pencil"></i></button> | |||||
<button *ngIf="deletepermission" class="btn btn-danger btn-sm ml-1" (click)="deletePatient(patientrecord.id)"><i | |||||
class="pi pi-trash"></i></button> | |||||
</td> | |||||
</tr> | |||||
</ng-template> | |||||
<ng-template pTemplate="emptymessage"> | |||||
<tr> | |||||
<td colspan="11">No Patients found.</td> | |||||
</tr> | |||||
</ng-template> | |||||
</p-table> | |||||
<span>Total Records: {{totalRecords}}</span> | |||||
</div> | |||||
<div> | |||||
<p-dialog *ngIf="patientDialog" header="{{patientDialogTitle}}" [(visible)]="patientDialog" [modal]="true" | |||||
[closable]="true" [style]="{width: '85%', height: '100%'}"> | |||||
<form #patientrecord="ngForm" (ngSubmit)="savePatient(patientrecord)" novalidate> | |||||
<div class="p-fluid"> | |||||
<div class="p-grid"> | |||||
<!-- <div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="fullname">Full Name</label> | |||||
<input id="fullname" name="fullname" type="text" autocomplete="off" pInputText | |||||
[(ngModel)]="selectedPatient.fullName" placeholder="Enter full patient name" required | |||||
#fullname="ngModel" /> | |||||
<small *ngIf="fullname.invalid && fullname.touched" class="p-error"> | |||||
Full Name is required. | |||||
</small> | |||||
</div> | |||||
</div> --> | |||||
<!-- <div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="mobile">Mobile</label> | |||||
<input id="mobile" name="mobile" type="text" autocomplete="off" pInputText | |||||
[(ngModel)]="selectedPatient.mobile" maxlength="10" pattern="^[0-9]{10}$" | |||||
placeholder="Enter mobile number" required #mobile="ngModel" /> | |||||
<small *ngIf="mobile.invalid && mobile.touched" class="p-error"> | |||||
Mobile number is required and must be 10 digits. | |||||
</small> | |||||
</div> | |||||
</div> --> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<div class="p-col-6"> | |||||
<!-- <div class="field"> | |||||
<label for="gender">Gender</label> | |||||
<div> | |||||
<label class="mx-1"> | |||||
<input style="background-color: #fff;" id="male" type="radio" name="gender" | |||||
[(ngModel)]="selectedgender" [value]="1" required #gender="ngModel" /> | |||||
Male | |||||
</label> | |||||
<label> | |||||
<input style="background-color: #fff;" id="female" type="radio" name="gender" | |||||
[(ngModel)]="selectedgender" [value]="2" required /> | |||||
Female | |||||
</label> | |||||
<small *ngIf="!selectedgender" class="p-error"> | |||||
Please select a gender. | |||||
</small> | |||||
</div> | |||||
</div> --> | |||||
</div> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="admissionDate">Admission Date</label> | |||||
<p-calendar id="admissionDate" name="admissionDate" [(ngModel)]="selectdateOfAdmission" showIcon required | |||||
#admissionDate="ngModel"></p-calendar> | |||||
<small *ngIf="admissionDate.invalid && admissionDate.touched" class="p-error"> | |||||
Admission Date is required. | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="labReport">Lab Report</label> | |||||
<input type="file" id="labReport" name="labReport" accept=".pdf,.doc,.docx" | |||||
(change)="handleLabReportUpload($event)" /> | |||||
</div> | |||||
</div> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="medications">Medications</label> | |||||
<input type="file" id="medications" name="medications" accept=".pdf,.doc,.docx" | |||||
(change)="handleMedicationsUpload($event)" /> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="medicationHistory">Medication History</label> | |||||
<input type="file" id="medicationHistory" name="medicationHistory" accept=".pdf,.doc,.docx" | |||||
(change)="handleMedicationHistoryUpload($event)" /> | |||||
</div> | |||||
</div> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="nextFollowUp">Next FollowUp Date</label> | |||||
<p-calendar id="nextFollowUp" name="nextFollowUp" [(ngModel)]="selectnextFollowUp" showIcon required | |||||
#nextFollowUp="ngModel"></p-calendar> | |||||
<small *ngIf="nextFollowUp.invalid && nextFollowUp.touched" class="p-error"> | |||||
Next Follow-Up Date is required. | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<div class="p-col-12"> | |||||
<div class="field"> | |||||
<div> | |||||
<label for="diagnosis">Diagnosis</label> | |||||
</div> | |||||
<textarea style="width: 100%; background-color: #fff; color: black;" id="diagnosis" name="diagnosis" | |||||
pInputTextarea rows="5" cols="30" [(ngModel)]="selectedPatient.diagnosis" required | |||||
#diagnosis="ngModel"></textarea> | |||||
<small *ngIf="diagnosis.invalid && diagnosis.touched" class="p-error"> | |||||
Diagnosis is required. | |||||
</small> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="p-grid"> | |||||
<div class="p-col-6"> | |||||
<div class="field"> | |||||
<label for="insuranceProvider">Insurance Provider</label> | |||||
<input id="insuranceProvider" name="insuranceProvider" type="text" autocomplete="off" pInputText | |||||
[(ngModel)]="selectedPatient.insuranceProvider" required placeholder="Enter insurance provider" #insurance="ngModel" /> | |||||
<small *ngIf="insurance.invalid && insurance.touched" class="p-error"> | |||||
Insurance is required. | |||||
</small> | |||||
</div> | |||||
</div> | |||||
<div class="p-col-6"> | |||||
<!-- <div class="field"> | |||||
<label for="status">Status</label> | |||||
<p-dropdown name="status" id="status" [options]="statuslist" [(ngModel)]="selectedstatus" | |||||
optionLabel="label" optionValue="value" placeholder="Select status" required | |||||
#status="ngModel"></p-dropdown> | |||||
<small *ngIf="selectedstatus === 0" class="p-error"> | |||||
Status is required. | |||||
</small> | |||||
</div> --> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div> | |||||
<button type="submit" pButton class="btn btn-primary" | |||||
[disabled]="patientrecord.invalid">Save</button> | |||||
<button pButton class="btn btn-secondary ml-1" (click)="closeDialog()">Close</button> | |||||
</div> | |||||
</form> | |||||
</p-dialog> | |||||
</div> |
@ -0,0 +1,96 @@ | |||||
.table-header { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
align-items: center; | |||||
} | |||||
.badge { | |||||
display: inline-block; | |||||
padding: 0.2rem 0.6rem; | |||||
border-radius: 0.5rem; | |||||
color: white; | |||||
font-weight: bold; | |||||
font-size: 0.8rem; | |||||
} | |||||
.male { | |||||
background-color: green; | |||||
} | |||||
.female { | |||||
background-color: purple; | |||||
} | |||||
.pdf-icon { | |||||
color: red; | |||||
font-size: 1.2rem; | |||||
} | |||||
.patient-container { | |||||
display: flex; | |||||
justify-content: center; | |||||
margin-bottom: 20px; | |||||
} | |||||
.patient-card { | |||||
display: flex; | |||||
align-items: center; | |||||
width: 100%; | |||||
max-width: 800px; | |||||
background: #ffffff; | |||||
border-radius: 12px; | |||||
padding: 20px; | |||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1); | |||||
border-left: 5px solid #007bff; | |||||
} | |||||
.patient-image img { | |||||
width: 100px; | |||||
height: 100px; | |||||
border-radius: 50%; | |||||
object-fit: cover; | |||||
border: 3px solid #007bff; | |||||
} | |||||
.patient-info { | |||||
flex: 1; | |||||
margin-left: 20px; | |||||
} | |||||
.patient-name { | |||||
font-size: 22px; | |||||
font-weight: bold; | |||||
color: #333; | |||||
margin-bottom: 8px; | |||||
} | |||||
.patient-details { | |||||
display: grid; | |||||
grid-template-columns: repeat(2, minmax(150px, 1fr)); | |||||
gap: 8px; | |||||
} | |||||
.info-item { | |||||
font-size: 14px; | |||||
background: #f8f9fa; | |||||
padding: 6px 12px; | |||||
border-radius: 6px; | |||||
} | |||||
.status { | |||||
font-weight: bold; | |||||
padding: 4px 8px; | |||||
border-radius: 4px; | |||||
} | |||||
.status.active { | |||||
background: #28a745; | |||||
color: white; | |||||
} | |||||
.status.inactive { | |||||
background: #dc3545; | |||||
color: white; | |||||
} | |||||
@ -0,0 +1,254 @@ | |||||
import { Component, OnInit } from '@angular/core'; | |||||
import { NgForm } from '@angular/forms'; | |||||
import { PagingSortPatientResultDto } from '@proxy/dto'; | |||||
import { Gender, Status } from '@proxy/global-enum'; | |||||
import { PatientService } from '@proxy/patients'; | |||||
import { CreateUpdatePatientRecordDto, PatientDto, PatientRecordDto } from '@proxy/patients/dto'; | |||||
import { MessageService } from 'primeng/api'; | |||||
import { PermissionService } from '@abp/ng.core'; | |||||
import { ActivatedRoute } from '@angular/router'; | |||||
@Component({ | |||||
selector: 'app-patient-record', | |||||
templateUrl: './patient-record.component.html', | |||||
styleUrl: './patient-record.component.scss', | |||||
providers: [PatientService, MessageService, PermissionService], | |||||
}) | |||||
export class PatientRecordComponent implements OnInit { | |||||
globalFilter: string = ''; | |||||
patientrecords: PatientRecordDto[]; | |||||
totalRecords: number = 0; | |||||
loading: boolean = false; | |||||
patientDialog: boolean = false; | |||||
selectedPatient: CreateUpdatePatientRecordDto; | |||||
patientdto: PatientDto; | |||||
isEditMode: boolean = false; | |||||
patientDialogTitle: string = ''; | |||||
params: PagingSortPatientResultDto; | |||||
status: any; | |||||
gender: any; | |||||
statuslist: any; | |||||
selectdateOfAdmission: Date = new Date(); | |||||
selectnextFollowUp: Date = new Date(); | |||||
uploadfile: { | |||||
file: File[]; | |||||
name: string; | |||||
}[] = []; | |||||
createpermission: boolean; | |||||
editpermission: boolean; | |||||
deletepermission: boolean; | |||||
userid: any; | |||||
patientImageUrl: string; | |||||
constructor( | |||||
private patientService: PatientService, | |||||
private messageService: MessageService, | |||||
private permissionChecker: PermissionService, | |||||
private route: ActivatedRoute | |||||
) {} | |||||
ngOnInit() { | |||||
this.userid = this.route.snapshot.paramMap.get('id'); | |||||
console.log(this.userid); | |||||
this.createpermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Create' | |||||
); | |||||
this.editpermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Edit' | |||||
); | |||||
this.deletepermission = this.permissionChecker.getGrantedPolicy( | |||||
'HospitalManagementSystem.Patient.Delete' | |||||
); | |||||
this.status = Status; | |||||
this.gender = Gender; | |||||
this.patientService.getStatusDropdown().subscribe(result => { | |||||
this.statuslist = result; | |||||
}); | |||||
this.resetselectpatient(); | |||||
} | |||||
resetselectpatient() { | |||||
this.selectedPatient = { | |||||
patientId: this.userid, | |||||
dateOfAdmission: '', | |||||
labReportUrl: '', | |||||
medicationUrl: '', | |||||
medicationHistoryUrl: '', | |||||
nextFollowUp: '', | |||||
diagnosis: '', | |||||
treatmentPlan: '', | |||||
doctorNotes: '', | |||||
insuranceProvider: '', | |||||
status: Status.InTreatment, | |||||
}; | |||||
} | |||||
loadPatient(event: any, id: any) { | |||||
this.selectedPatient.patientId = this.userid; | |||||
this.loading = true; | |||||
let order = event.sortOrder == 1 ? ' asc' : ' desc'; | |||||
event.sortField = event.sortField == undefined ? 'id' : event.sortField; | |||||
this.params = { | |||||
skipCount: event.first, | |||||
maxResultCount: event.rows, | |||||
sorting: event.sortField + order, | |||||
search: event.globalFilter == null ? '' : event.globalFilter, | |||||
}; | |||||
this.patientService.getPatientById(this.userid).subscribe(result => { | |||||
this.patientdto = result; | |||||
}); | |||||
this.patientService.getPatientRecordList(this.params, id).subscribe(data => { | |||||
this.patientrecords = data.items; | |||||
this.totalRecords = data.totalCount; | |||||
this.loading = false; | |||||
}); | |||||
} | |||||
exportPatient() { | |||||
this.patientService.getExportPatientRecord().subscribe(result => { | |||||
const binary = atob(result.fileContent); | |||||
const len = binary.length; | |||||
const bytes = new Uint8Array(len); | |||||
for (let i = 0; i < len; i++) { | |||||
bytes[i] = binary.charCodeAt(i); | |||||
} | |||||
const blob = new Blob([bytes], { type: 'application/xlsx' }); | |||||
const url = window.URL.createObjectURL(blob); | |||||
const link = document.createElement('a'); | |||||
link.href = url; | |||||
link.download = result.fileName; | |||||
document.body.appendChild(link); | |||||
link.click(); | |||||
document.body.removeChild(link); | |||||
window.URL.revokeObjectURL(url); | |||||
}); | |||||
} | |||||
openNewPatientDialog() { | |||||
this.patientDialogTitle = 'New Patient Record'; | |||||
this.resetselectpatient(); | |||||
this.patientDialog = true; | |||||
this.isEditMode = false; | |||||
} | |||||
editPatient(Patient: any) { | |||||
this.patientDialogTitle = 'Edit Patient'; | |||||
this.selectedPatient = { ...Patient }; | |||||
this.selectedPatient.patientId = this.userid; | |||||
this.selectdateOfAdmission = new Date(this.selectedPatient.dateOfAdmission); | |||||
this.selectnextFollowUp = new Date(this.selectedPatient.nextFollowUp); | |||||
this.patientDialog = true; | |||||
this.isEditMode = true; | |||||
console.log(this.selectedPatient); | |||||
} | |||||
deletePatient(id: any) { | |||||
this.patientService.deletePatientRecord(id).subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient deleted successfully', | |||||
}); | |||||
this.loadPatient(this.params, this.userid); | |||||
}); | |||||
} | |||||
// handleLabReportUpload(event: any): void { | |||||
// const input = event.target as HTMLInputElement; | |||||
// console.log(input); | |||||
// const files: File[] = event.files; // Files uploaded | |||||
// this.addToUploadList(files, 'Lab-Report'); | |||||
// } | |||||
handleLabReportUpload(event: Event): void { | |||||
const input = event.target as HTMLInputElement; | |||||
if (input && input.files) { | |||||
const files: File[] = Array.from(input.files); // Convert FileList to an array of File | |||||
this.addToUploadList(files, 'Lab-Report'); | |||||
} else { | |||||
console.error('No files selected'); | |||||
} | |||||
} | |||||
handleMedicationsUpload(event: any): void { | |||||
const files: File[] = event.files; // Files uploaded | |||||
this.addToUploadList(files, 'Medications'); | |||||
} | |||||
handleMedicationHistoryUpload(event: any): void { | |||||
const files: File[] = event.files; // Files uploaded | |||||
this.addToUploadList(files, 'Medication-History'); | |||||
} | |||||
private addToUploadList(files: File[], name: string): void { | |||||
const existingIndex = this.uploadfile.findIndex(item => item.name === name); | |||||
if (existingIndex > -1) { | |||||
this.uploadfile[existingIndex].file = files; | |||||
} else { | |||||
this.uploadfile.push({ file: files, name }); | |||||
} | |||||
console.log(this.uploadfile); | |||||
} | |||||
savePatient(form: NgForm) { | |||||
// console.log(form); | |||||
this.selectedPatient.patientId = this.userid; | |||||
this.selectedPatient.status = this.patientdto.status; | |||||
this.selectedPatient.dateOfAdmission = this.selectdateOfAdmission.toDateString(); | |||||
this.selectedPatient.nextFollowUp = this.selectnextFollowUp.toDateString(); | |||||
if (this.isEditMode) { | |||||
this.patientService | |||||
.updatePatientRecord(this.selectedPatient.id, this.selectedPatient) | |||||
.subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient updated successfully', | |||||
}); | |||||
this.patientDialog = false; | |||||
this.loadPatient( | |||||
{ | |||||
first: 0, | |||||
rows: 10, | |||||
sortField: 'id', | |||||
sortOrder: 1, | |||||
globalFilter: null, | |||||
}, | |||||
this.userid | |||||
); | |||||
}); | |||||
} else { | |||||
this.patientService.createPatientRecord(this.selectedPatient).subscribe(() => { | |||||
this.messageService.add({ | |||||
severity: 'success', | |||||
summary: 'Success', | |||||
detail: 'Patient created successfully', | |||||
}); | |||||
this.patientDialog = false; | |||||
this.loadPatient( | |||||
{ | |||||
first: 0, | |||||
rows: 10, | |||||
sortField: 'id', | |||||
sortOrder: 1, | |||||
globalFilter: null, | |||||
}, | |||||
this.userid | |||||
); | |||||
}); | |||||
} | |||||
} | |||||
closeDialog() { | |||||
this.patientDialog = false; | |||||
} | |||||
} |
@ -0,0 +1,26 @@ | |||||
import { NgModule } from '@angular/core'; | |||||
import { RouterModule, Routes } from '@angular/router'; | |||||
import { AllPatientsComponent } from './all-patients/all-patients.component'; | |||||
import { PatientRecordComponent } from './patient-record/patient-record.component'; | |||||
import { authGuard, permissionGuard } from '@abp/ng.core'; | |||||
const routes: Routes = [ | |||||
{ | |||||
path: '', | |||||
children: [ | |||||
{ | |||||
path: 'patient-record/:id', | |||||
component: PatientRecordComponent, | |||||
// canActivate: [authGuard, permissionGuard], | |||||
}, | |||||
{ path: 'all-patients', component: AllPatientsComponent }, | |||||
// { path: 'create-new/:id', component: FaqCreateComponent }, | |||||
], | |||||
}, | |||||
]; | |||||
@NgModule({ | |||||
imports: [RouterModule.forChild(routes)], | |||||
exports: [RouterModule], | |||||
}) | |||||
export class PatientsRoutingModule {} |
@ -0,0 +1,37 @@ | |||||
import { NgModule } from '@angular/core'; | |||||
import { CommonModule } from '@angular/common'; | |||||
import { PatientsRoutingModule } from './patients-routing.module'; | |||||
import { AllPatientsComponent } from './all-patients/all-patients.component'; | |||||
import { PatientRecordComponent } from './patient-record/patient-record.component'; | |||||
import { TableModule } from 'primeng/table'; | |||||
import { IconFieldModule } from 'primeng/iconfield'; | |||||
import { InputIconModule } from 'primeng/inputicon'; | |||||
import { FormsModule } from '@angular/forms'; | |||||
import { InputTextModule } from 'primeng/inputtext'; | |||||
import { PaginatorModule } from 'primeng/paginator'; | |||||
import { DialogModule } from 'primeng/dialog'; | |||||
import { DropdownModule } from 'primeng/dropdown'; | |||||
import { FileUploadModule } from 'primeng/fileupload'; | |||||
import { CalendarModule } from 'primeng/calendar'; | |||||
import { SharedModule } from '../shared/shared.module'; | |||||
@NgModule({ | |||||
declarations: [AllPatientsComponent, PatientRecordComponent], | |||||
imports: [ | |||||
CommonModule, | |||||
PatientsRoutingModule, | |||||
TableModule, | |||||
InputIconModule, | |||||
IconFieldModule, | |||||
FormsModule, | |||||
InputTextModule, | |||||
PaginatorModule, | |||||
DialogModule, | |||||
DropdownModule, | |||||
FileUploadModule, | |||||
CalendarModule, | |||||
SharedModule | |||||
], | |||||
}) | |||||
export class PatientsModule {} |
@ -0,0 +1 @@ | |||||
export * from './models'; |
@ -0,0 +1,15 @@ | |||||
import type { PagedAndSortedResultRequestDto } from '@abp/ng.core'; | |||||
export interface DropDownItems { | |||||
label?: string; | |||||
value: number; | |||||
} | |||||
export interface FileDownloadDto { | |||||
fileName?: string; | |||||
fileContent?: string; | |||||
} | |||||
export interface PagingSortPatientResultDto extends PagedAndSortedResultRequestDto { | |||||
search?: string; | |||||
} |
@ -0,0 +1,8 @@ | |||||
import { mapEnumToOptions } from '@abp/ng.core'; | |||||
export enum Gender { | |||||
Male = 1, | |||||
Female = 2, | |||||
} | |||||
export const genderOptions = mapEnumToOptions(Gender); |
@ -0,0 +1,2 @@ | |||||
export * from './gender.enum'; | |||||
export * from './status.enum'; |
@ -0,0 +1,9 @@ | |||||
import { mapEnumToOptions } from '@abp/ng.core'; | |||||
export enum Status { | |||||
Recovered = 1, | |||||
Observation = 2, | |||||
InTreatment = 3, | |||||
} | |||||
export const statusOptions = mapEnumToOptions(Status); |
@ -0,0 +1,4 @@ | |||||
import * as Dto from './dto'; | |||||
import * as GlobalEnum from './global-enum'; | |||||
import * as Patients from './patients'; | |||||
export { Dto, GlobalEnum, Patients }; |
@ -0,0 +1 @@ | |||||
export * from './models'; |
@ -0,0 +1,65 @@ | |||||
import type { Gender } from '../../global-enum/gender.enum'; | |||||
import type { Status } from '../../global-enum/status.enum'; | |||||
export interface CreateUpdatePatientDto { | |||||
id?: string; | |||||
name?: string; | |||||
gender: Gender; | |||||
mobile?: string; | |||||
email?: string; | |||||
age: number; | |||||
treatment?: string; | |||||
doctorAssigned?: string; | |||||
address?: string; | |||||
bloodGroup?: string; | |||||
admissionDate?: string; | |||||
dischargeDate?: string; | |||||
status: Status; | |||||
} | |||||
export interface CreateUpdatePatientRecordDto { | |||||
id?: string; | |||||
patientId?: string; | |||||
dateOfAdmission?: string; | |||||
labReportUrl?: string; | |||||
medicationUrl?: string; | |||||
medicationHistoryUrl?: string; | |||||
nextFollowUp?: string; | |||||
diagnosis?: string; | |||||
treatmentPlan?: string; | |||||
doctorNotes?: string; | |||||
insuranceProvider?: string; | |||||
status: Status; | |||||
} | |||||
export interface PatientDto { | |||||
id?: string; | |||||
name?: string; | |||||
gender: Gender; | |||||
mobile?: string; | |||||
email?: string; | |||||
age: number; | |||||
treatment?: string; | |||||
doctorAssigned?: string; | |||||
address?: string; | |||||
bloodGroup?: string; | |||||
admissionDate?: string; | |||||
dischargeDate?: string; | |||||
status: Status; | |||||
} | |||||
export interface PatientRecordDto { | |||||
id?: string; | |||||
patientId?: string; | |||||
patients: PatientDto; | |||||
dateOfAdmission?: string; | |||||
diagnosis?: string; | |||||
treatmentPlan?: string; | |||||
doctorNotes?: string; | |||||
labReportUrl?: string; | |||||
medicationUrl?: string; | |||||
medicationHistoryUrl?: string; | |||||
nextFollowUp?: string; | |||||
insuranceProvider?: string; | |||||
status: Status; | |||||
} |
@ -0,0 +1,3 @@ | |||||
import * as Dto from './dto'; | |||||
export * from './patient.service'; | |||||
export { Dto }; |
@ -0,0 +1,124 @@ | |||||
import type { CreateUpdatePatientDto, CreateUpdatePatientRecordDto, PatientDto, PatientRecordDto } from './dto/models'; | |||||
import { RestService, Rest } from '@abp/ng.core'; | |||||
import type { PagedResultDto } from '@abp/ng.core'; | |||||
import { Injectable } from '@angular/core'; | |||||
import type { DropDownItems, FileDownloadDto, PagingSortPatientResultDto } from '../dto/models'; | |||||
@Injectable({ | |||||
providedIn: 'root', | |||||
}) | |||||
export class PatientService { | |||||
apiName = 'Default'; | |||||
createPatient = (input: CreateUpdatePatientDto, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientDto>({ | |||||
method: 'POST', | |||||
url: '/api/app/patient/patient', | |||||
body: input, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
createPatientRecord = (input: CreateUpdatePatientRecordDto, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientRecordDto>({ | |||||
method: 'POST', | |||||
url: '/api/app/patient/patient-record', | |||||
body: input, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
deletePatient = (id: string, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, void>({ | |||||
method: 'DELETE', | |||||
url: `/api/app/patient/${id}/patient`, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
deletePatientRecord = (id: string, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, void>({ | |||||
method: 'DELETE', | |||||
url: `/api/app/patient/${id}/patient-record`, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getExportPatientData = (config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, FileDownloadDto>({ | |||||
method: 'GET', | |||||
url: '/api/app/patient/export-patient-data', | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getExportPatientRecord = (config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, FileDownloadDto>({ | |||||
method: 'GET', | |||||
url: '/api/app/patient/export-patient-record', | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getPatientById = (id: string, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientDto>({ | |||||
method: 'GET', | |||||
url: `/api/app/patient/${id}/patient-by-id`, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getPatientList = (input: PagingSortPatientResultDto, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PagedResultDto<PatientDto>>({ | |||||
method: 'GET', | |||||
url: '/api/app/patient/patient-list', | |||||
params: { search: input.search, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getPatientRecordById = (id: string, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientRecordDto>({ | |||||
method: 'GET', | |||||
url: `/api/app/patient/${id}/patient-record-by-id`, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getPatientRecordList = (input: PagingSortPatientResultDto, Id: string, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PagedResultDto<PatientRecordDto>>({ | |||||
method: 'GET', | |||||
url: `/api/app/patient/patient-record-list/${Id}`, | |||||
params: { search: input.search, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
getStatusDropdown = (config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, DropDownItems[]>({ | |||||
method: 'GET', | |||||
url: '/api/app/patient/status-dropdown', | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
updatePatient = (id: string, input: CreateUpdatePatientDto, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientDto>({ | |||||
method: 'PUT', | |||||
url: `/api/app/patient/${id}/patient`, | |||||
body: input, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
updatePatientRecord = (id: string, input: CreateUpdatePatientRecordDto, config?: Partial<Rest.Config>) => | |||||
this.restService.request<any, PatientRecordDto>({ | |||||
method: 'PUT', | |||||
url: `/api/app/patient/${id}/patient-record`, | |||||
body: input, | |||||
}, | |||||
{ apiName: this.apiName,...config }); | |||||
constructor(private restService: RestService) {} | |||||
} |
@ -0,0 +1,27 @@ | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.ComponentModel.DataAnnotations; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Patients.Dto | |||||
{ | |||||
public class CreateUpdatePatientDto | |||||
{ | |||||
public Guid Id { get; set; } | |||||
public string Name { get; set; } | |||||
public Gender Gender { get; set; } | |||||
public string Mobile { get; set; } | |||||
public string Email { get; set; } | |||||
public int Age { get; set; } | |||||
public string Treatment { get; set; } | |||||
public string DoctorAssigned { get; set; } | |||||
public string Address { get; set; } | |||||
public string BloodGroup { get; set; } | |||||
public DateTime AdmissionDate { get; set; } | |||||
public DateTime? DischargeDate { get; set; } | |||||
public Status Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,46 @@ | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using Microsoft.AspNetCore.Http; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.ComponentModel.DataAnnotations.Schema; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Patients.Dto | |||||
{ | |||||
public class CreateUpdatePatientRecordDto | |||||
{ | |||||
public Guid Id { get; set; } | |||||
//public string FullName { get; set; } | |||||
//public string Mobile { get; set; } | |||||
//public Gender Gender { get; set; } | |||||
public Guid PatientId { get; set; } | |||||
public DateTime DateOfAdmission { get; set; } | |||||
public string? LabReportUrl { get; set; } | |||||
public string? MedicationUrl { get; set; } | |||||
public string? MedicationHistoryUrl { get; set; } | |||||
public DateTime? NextFollowUp { get; set; } | |||||
public string Diagnosis { get; set; } | |||||
public string TreatmentPlan { get; set; } | |||||
public string DoctorNotes { get; set; } | |||||
public string InsuranceProvider { get; set; } | |||||
public Status Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,26 @@ | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Patients.Dto | |||||
{ | |||||
public class PatientDto | |||||
{ | |||||
public Guid Id { get; set; } | |||||
public string Name { get; set; } | |||||
public Gender Gender { get; set; } | |||||
public string Mobile { get; set; } | |||||
public string Email { get; set; } | |||||
public int Age { get; set; } | |||||
public string Treatment { get; set; } | |||||
public string DoctorAssigned { get; set; } | |||||
public string Address { get; set; } | |||||
public string BloodGroup { get; set; } | |||||
public DateTime AdmissionDate { get; set; } | |||||
public DateTime? DischargeDate { get; set; } | |||||
public Status Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,48 @@ | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using static HospitalManagementSystem.Permissions.HospitalManagementSystemPermissions; | |||||
using HospitalManagementSystem.Patients; | |||||
using System.ComponentModel.DataAnnotations.Schema; | |||||
namespace HospitalManagementSystem.Patients.Dto | |||||
{ | |||||
public class PatientRecordDto | |||||
{ | |||||
public Guid Id { get; set; } | |||||
//public string FullName { get; set; } | |||||
//public string Mobile { get; set; } | |||||
//public Gender Gender { get; set; } | |||||
public Guid PatientId { get; set; } | |||||
public PatientDto Patients { get; set; } | |||||
public DateTime DateOfAdmission { get; set; } | |||||
public string Diagnosis { get; set; } | |||||
public string TreatmentPlan { get; set; } | |||||
public string DoctorNotes { get; set; } | |||||
public string LabReportUrl { get; set; } | |||||
public string MedicationUrl { get; set; } | |||||
public string MedicationHistoryUrl { get; set; } | |||||
public DateTime? NextFollowUp { get; set; } | |||||
public string InsuranceProvider { get; set; } | |||||
public Status Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,31 @@ | |||||
using AutoMapper; | |||||
using HospitalManagementSystem.Patients; | |||||
using HospitalManagementSystem.Patients.Dto; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem | |||||
{ | |||||
public class PatientAutoMapperProfile : Profile | |||||
{ | |||||
public PatientAutoMapperProfile() | |||||
{ | |||||
// Entity to DTO mappings | |||||
CreateMap<PatientRecord, PatientRecordDto>(); | |||||
CreateMap<PatientRecord, CreateUpdatePatientRecordDto>(); | |||||
// DTO to Entity mappings | |||||
CreateMap<CreateUpdatePatientRecordDto, PatientRecord>(); | |||||
// Entity to DTO mappings | |||||
CreateMap<Patient, PatientDto>(); | |||||
CreateMap<Patient, CreateUpdatePatientDto>(); | |||||
// DTO to Entity mappings | |||||
CreateMap<CreateUpdatePatientDto, Patient>(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,347 @@ | |||||
using ClosedXML.Excel; | |||||
using HospitalManagementSystem.Dto; | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using HospitalManagementSystem.Patients.Dto; | |||||
using HospitalManagementSystem.Permissions; | |||||
using Microsoft.AspNetCore.Authorization; | |||||
using Microsoft.EntityFrameworkCore; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Linq.Dynamic.Core; | |||||
using System.Threading.Tasks; | |||||
using Volo.Abp.Application.Dtos; | |||||
using Volo.Abp.Application.Services; | |||||
using Volo.Abp.Domain.Repositories; | |||||
namespace HospitalManagementSystem.Patients | |||||
{ | |||||
public class PatientAppService : ApplicationService | |||||
{ | |||||
private IRepository<PatientRecord, Guid> _patientrecordRepository; | |||||
private IRepository<Patient, Guid> _patientRepository; | |||||
public PatientAppService(IRepository<PatientRecord, Guid> patientrecordRepository, IRepository<Patient, Guid> patientRepository) | |||||
{ | |||||
_patientrecordRepository = patientrecordRepository; | |||||
_patientRepository = patientRepository; | |||||
} | |||||
#region PatientRecord | |||||
#region Get Patient List with Paging and Searching | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)] | |||||
public async Task<PagedResultDto<PatientRecordDto>> GetPatientRecordListAsync(PagingSortPatientResultDto input, Guid Id) | |||||
{ | |||||
//List<PatientRecord>? query; | |||||
//query = _patientrecordRepository.GetQueryableAsync().Result | |||||
// .Include(x => x.Patients) | |||||
// .WhereIf(!String.IsNullOrEmpty(input.Search), x => x.Patients.Name.ToLower().Contains(input.Search.ToLower())) | |||||
// .Where(x => x.Patients.Id == Id) | |||||
// .OrderBy(input.Sorting ?? (nameof(PatientRecord.Id) + " asc")) | |||||
// .Skip(input.SkipCount) | |||||
// .Take(input.MaxResultCount) | |||||
// .ToList(); | |||||
//var totalCount = await _patientrecordRepository.CountAsync(); | |||||
//return new PagedResultDto<PatientRecordDto>( | |||||
// totalCount, | |||||
// ObjectMapper.Map<List<PatientRecord>, List<PatientRecordDto>>(query) | |||||
//); | |||||
var queryable = await _patientrecordRepository.GetQueryableAsync(); | |||||
var filteredQuery = queryable | |||||
.Include(x => x.Patients) | |||||
.WhereIf(!string.IsNullOrEmpty(input.Search), x => x.Patients.Name.ToLower().Contains(input.Search.ToLower())) | |||||
.Where(x => x.Patients.Id == Id); | |||||
// Get total count after filtering | |||||
var totalCount = await filteredQuery.CountAsync(); | |||||
// Apply sorting dynamically (ensure input.Sorting is valid) | |||||
filteredQuery = !string.IsNullOrEmpty(input.Sorting) | |||||
? filteredQuery.OrderBy(input.Sorting) | |||||
: filteredQuery.OrderBy(x => x.Id); | |||||
// Apply paging | |||||
var pagedQuery = await filteredQuery | |||||
.Skip(input.SkipCount) | |||||
.Take(input.MaxResultCount) | |||||
.ToListAsync(); | |||||
return new PagedResultDto<PatientRecordDto>( | |||||
totalCount, | |||||
ObjectMapper.Map<List<PatientRecord>, List<PatientRecordDto>>(pagedQuery) | |||||
); | |||||
} | |||||
#endregion | |||||
#region Get Single Patient by Id | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)] | |||||
public async Task<PatientRecordDto> GetPatientRecordByIdAsync(Guid id) | |||||
{ | |||||
var patient = await _patientrecordRepository.GetAsync(id); | |||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patient); | |||||
} | |||||
#endregion | |||||
#region Export Patient Data to Excel | |||||
public async Task<FileDownloadDto> GetExportPatientRecordAsync() | |||||
{ | |||||
var patients = await _patientrecordRepository.GetListAsync(); | |||||
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports"); | |||||
if (!Directory.Exists(folderPath)) | |||||
{ | |||||
Directory.CreateDirectory(folderPath); // Ensure the folder exists | |||||
} | |||||
var filename = "Patients_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx"; | |||||
var filePath = Path.Combine(folderPath, filename); | |||||
// Create a workbook and worksheet | |||||
using (var workbook = new XLWorkbook()) | |||||
{ | |||||
var worksheet = workbook.Worksheets.Add("Patients"); | |||||
// Add headers | |||||
worksheet.Cell(1, 1).Value = "Full Name"; | |||||
worksheet.Cell(1, 2).Value = "Gender"; | |||||
worksheet.Cell(1, 3).Value = "Date of Admission"; | |||||
worksheet.Cell(1, 4).Value = "Diagnosis"; | |||||
worksheet.Cell(1, 5).Value = "Next Follow-Up"; | |||||
worksheet.Cell(1, 6).Value = "Status"; | |||||
for (int i = 0; i < patients.Count; i++) | |||||
{ | |||||
worksheet.Cell(i + 2, 1).Value = patients[i].Patients.Name; | |||||
worksheet.Cell(i + 2, 2).Value = patients[i].Patients.Gender.ToString(); | |||||
worksheet.Cell(i + 2, 3).Value = patients[i].DateOfAdmission.ToShortDateString(); | |||||
worksheet.Cell(i + 2, 4).Value = patients[i].Diagnosis; | |||||
worksheet.Cell(i + 2, 5).Value = patients[i].NextFollowUp?.ToShortDateString(); | |||||
worksheet.Cell(i + 2, 6).Value = patients[i].Status.ToString(); | |||||
} | |||||
worksheet.Columns().AdjustToContents(); | |||||
workbook.SaveAs(filePath); | |||||
} | |||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath); | |||||
File.Delete(filePath); | |||||
return new FileDownloadDto | |||||
{ | |||||
FileName = filename, | |||||
FileContent = Convert.ToBase64String(fileBytes) // Use Base64 encoding for file content | |||||
}; | |||||
} | |||||
#endregion | |||||
#region Create Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Create)] | |||||
public async Task<PatientRecordDto> CreatePatientRecordAsync(CreateUpdatePatientRecordDto input) | |||||
{ | |||||
var patientEntity = await _patientRepository.GetAsync(input.PatientId); // Get Patient from DB | |||||
var patientRecord = ObjectMapper.Map<CreateUpdatePatientRecordDto, PatientRecord>(input); | |||||
patientRecord.Patients = patientEntity; // Assign the fetched entity | |||||
patientRecord = await _patientrecordRepository.InsertAsync(patientRecord); | |||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patientRecord); | |||||
} | |||||
#endregion | |||||
#region Update Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Edit)] | |||||
public async Task<PatientRecordDto> UpdatePatientRecordAsync(Guid id, CreateUpdatePatientRecordDto input) | |||||
{ | |||||
var patientRecord = await _patientrecordRepository.GetAsync(id); | |||||
if (patientRecord.Patients.Id != input.PatientId) // If PatientId is updated, fetch new Patient | |||||
{ | |||||
var newPatient = await _patientRepository.GetAsync(input.PatientId); | |||||
patientRecord.Patients = newPatient; | |||||
} | |||||
ObjectMapper.Map(input, patientRecord); | |||||
patientRecord = await _patientrecordRepository.UpdateAsync(patientRecord); | |||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patientRecord); | |||||
} | |||||
#endregion | |||||
#region Delete Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Delete)] | |||||
public async Task DeletePatientRecordAsync(Guid id) | |||||
{ | |||||
await _patientrecordRepository.DeleteAsync(id); | |||||
} | |||||
#endregion | |||||
#endregion | |||||
#region Patient | |||||
#region Get Patient List with Paging and Searching | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)] | |||||
public async Task<PagedResultDto<PatientDto>> GetPatientListAsync(PagingSortPatientResultDto input) | |||||
{ | |||||
List<Patient> query; | |||||
if (!string.IsNullOrEmpty(input.Search)) | |||||
{ | |||||
query = _patientRepository.GetQueryableAsync().Result | |||||
.Where(x => x.Name.ToLower().Contains(input.Search.ToLower())) | |||||
.OrderBy(input.Sorting ?? (nameof(Patient.Id) + " asc")) | |||||
.Skip(input.SkipCount) | |||||
.Take(input.MaxResultCount) | |||||
.ToList(); | |||||
} | |||||
else | |||||
{ | |||||
query = await _patientRepository.GetPagedListAsync( | |||||
input.SkipCount, | |||||
input.MaxResultCount, | |||||
input.Sorting ?? nameof(Patient.Name) | |||||
); | |||||
} | |||||
var totalCount = await _patientRepository.CountAsync(); | |||||
return new PagedResultDto<PatientDto>( | |||||
totalCount, | |||||
ObjectMapper.Map<List<Patient>, List<PatientDto>>(query) | |||||
); | |||||
} | |||||
#endregion | |||||
#region Get Single Patient by Id | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)] | |||||
public async Task<PatientDto> GetPatientByIdAsync(Guid id) | |||||
{ | |||||
var patient = await _patientRepository.GetAsync(id); | |||||
return ObjectMapper.Map<Patient, PatientDto>(patient); | |||||
} | |||||
#endregion | |||||
#region Export Patient Data to Excel | |||||
public async Task<FileDownloadDto> GetExportPatientDataAsync() | |||||
{ | |||||
var patients = await _patientRepository.GetListAsync(); | |||||
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports"); | |||||
if (!Directory.Exists(folderPath)) | |||||
{ | |||||
Directory.CreateDirectory(folderPath); | |||||
} | |||||
var filename = "Patients_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx"; | |||||
var filePath = Path.Combine(folderPath, filename); | |||||
using (var workbook = new XLWorkbook()) | |||||
{ | |||||
var worksheet = workbook.Worksheets.Add("Patients"); | |||||
// Add headers | |||||
worksheet.Cell(1, 1).Value = "Name"; | |||||
worksheet.Cell(1, 2).Value = "Gender"; | |||||
worksheet.Cell(1, 3).Value = "Age"; | |||||
worksheet.Cell(1, 4).Value = "Treatment"; | |||||
worksheet.Cell(1, 5).Value = "Doctor Assigned"; | |||||
worksheet.Cell(1, 6).Value = "Admission Date"; | |||||
worksheet.Cell(1, 7).Value = "Discharge Date"; | |||||
worksheet.Cell(1, 8).Value = "Status"; | |||||
// Add data rows | |||||
for (int i = 0; i < patients.Count; i++) | |||||
{ | |||||
worksheet.Cell(i + 2, 1).Value = patients[i].Name; | |||||
worksheet.Cell(i + 2, 2).Value = patients[i].Gender.ToString(); | |||||
worksheet.Cell(i + 2, 3).Value = patients[i].Age; | |||||
worksheet.Cell(i + 2, 4).Value = patients[i].Treatment; | |||||
worksheet.Cell(i + 2, 5).Value = patients[i].DoctorAssigned; | |||||
worksheet.Cell(i + 2, 6).Value = patients[i].AdmissionDate.ToShortDateString(); | |||||
worksheet.Cell(i + 2, 7).Value = patients[i].DischargeDate?.ToShortDateString(); | |||||
worksheet.Cell(i + 2, 8).Value = patients[i].Status.ToString(); | |||||
} | |||||
worksheet.Columns().AdjustToContents(); | |||||
workbook.SaveAs(filePath); | |||||
} | |||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath); | |||||
File.Delete(filePath); | |||||
return new FileDownloadDto | |||||
{ | |||||
FileName = filename, | |||||
FileContent = Convert.ToBase64String(fileBytes) | |||||
}; | |||||
} | |||||
#endregion | |||||
#region Create Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Create)] | |||||
public async Task<PatientDto> CreatePatientAsync(CreateUpdatePatientDto input) | |||||
{ | |||||
var patient = ObjectMapper.Map<CreateUpdatePatientDto, Patient>(input); | |||||
patient = await _patientRepository.InsertAsync(patient); | |||||
return ObjectMapper.Map<Patient, PatientDto>(patient); | |||||
} | |||||
#endregion | |||||
#region Update Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Edit)] | |||||
public async Task<PatientDto> UpdatePatientAsync(Guid id, CreateUpdatePatientDto input) | |||||
{ | |||||
var patient = await _patientRepository.GetAsync(id); | |||||
ObjectMapper.Map(input, patient); | |||||
patient = await _patientRepository.UpdateAsync(patient); | |||||
return ObjectMapper.Map<Patient, PatientDto>(patient); | |||||
} | |||||
#endregion | |||||
#region Delete Patient | |||||
[Authorize(HospitalManagementSystemPermissions.Patient.Delete)] | |||||
public async Task DeletePatientAsync(Guid id) | |||||
{ | |||||
await _patientRepository.DeleteAsync(id); | |||||
} | |||||
#endregion | |||||
#endregion | |||||
#region Get Status Dropdown | |||||
public async Task<List<DropDownItems>> GetStatusDropdownAsync() | |||||
{ | |||||
List<DropDownItems> statuslist = new List<DropDownItems>(); | |||||
statuslist = Enum.GetValues(typeof(Status)) | |||||
.Cast<Status>() | |||||
.Select(e => new DropDownItems | |||||
{ | |||||
Label = e.ToString(), | |||||
Value = (int)e | |||||
}) | |||||
.ToList(); | |||||
statuslist.Add(new DropDownItems | |||||
{ | |||||
Label = "Select a Status", | |||||
Value = 0 | |||||
}); | |||||
statuslist = statuslist.OrderBy(x => x.Value).ToList(); | |||||
return await Task.FromResult(statuslist); | |||||
} | |||||
#endregion | |||||
} | |||||
} |
@ -0,0 +1,14 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Dto | |||||
{ | |||||
public class DropDownItems | |||||
{ | |||||
public string Label { get; set; } | |||||
public int Value { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,15 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Dto | |||||
{ | |||||
public class FileDownloadDto | |||||
{ | |||||
public string FileName { get; set; } | |||||
public string FileContent { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,14 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Volo.Abp.Application.Dtos; | |||||
namespace HospitalManagementSystem.Dto | |||||
{ | |||||
public class PagingSortPatientResultDto : PagedAndSortedResultRequestDto | |||||
{ | |||||
public string? Search { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.Dto | |||||
{ | |||||
using System.Linq.Dynamic.Core; | |||||
public static class QueryableExtensions | |||||
{ | |||||
public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string orderBy) | |||||
{ | |||||
return source.AsQueryable().OrderBy(orderBy); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,22 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace HospitalManagementSystem.GlobalEnum | |||||
{ | |||||
public enum Gender | |||||
{ | |||||
Male = 1, | |||||
Female = 2 | |||||
} | |||||
public enum Status | |||||
{ | |||||
Recovered = 1, | |||||
Observation = 2, | |||||
InTreatment = 3 | |||||
} | |||||
} |
@ -0,0 +1,36 @@ | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.ComponentModel.DataAnnotations; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
using Volo.Abp.Domain.Entities.Auditing; | |||||
namespace HospitalManagementSystem.Patients | |||||
{ | |||||
public class Patient : AuditedAggregateRoot<Guid> | |||||
{ | |||||
[Required] | |||||
public string Name { get; set; } | |||||
[Required] | |||||
public Gender Gender { get; set; } | |||||
[Required] | |||||
public string Mobile { get; set; } | |||||
[Required] | |||||
public string Email { get; set; } | |||||
[Required] | |||||
public int Age { get; set; } | |||||
public string Treatment { get; set; } | |||||
public string DoctorAssigned { get; set; } | |||||
[Required] | |||||
public string Address { get; set; } | |||||
[Required] | |||||
public string BloodGroup { get; set; } | |||||
public DateTime AdmissionDate { get; set; } | |||||
public DateTime? DischargeDate { get; set; } | |||||
[Required] | |||||
public Status Status { get; set; } | |||||
} | |||||
} | |||||
@ -0,0 +1,48 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Text; | |||||
using Volo.Abp.Domain.Entities.Auditing; | |||||
using System.Threading.Tasks; | |||||
using System.ComponentModel.DataAnnotations; | |||||
using HospitalManagementSystem.GlobalEnum; | |||||
using System.ComponentModel.DataAnnotations.Schema; | |||||
namespace HospitalManagementSystem.Patients | |||||
{ | |||||
public class PatientRecord : AuditedAggregateRoot<Guid> | |||||
{ | |||||
//[Required] | |||||
//public string FullName { get; set; } | |||||
//[Required] | |||||
//public string Mobile { get; set; } | |||||
//[Required] | |||||
//public Gender Gender { get; set; } | |||||
public virtual Patient Patients { get; set; } | |||||
[Required] | |||||
public DateTime DateOfAdmission { get; set; } | |||||
public string Diagnosis { get; set; } | |||||
public string TreatmentPlan { get; set; } | |||||
public string DoctorNotes { get; set; } | |||||
public string? LabReportUrl { get; set; } | |||||
public string? MedicationUrl { get; set; } | |||||
public string? MedicationHistoryUrl { get; set; } | |||||
public DateTime? NextFollowUp { get; set; } | |||||
public string InsuranceProvider { get; set; } | |||||
[Required] | |||||
public Status Status { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,93 @@ | |||||
using System; | |||||
using Microsoft.EntityFrameworkCore.Migrations; | |||||
#nullable disable | |||||
namespace HospitalManagementSystem.Migrations | |||||
{ | |||||
/// <inheritdoc /> | |||||
public partial class added_patientinpatientrecord : Migration | |||||
{ | |||||
/// <inheritdoc /> | |||||
protected override void Up(MigrationBuilder migrationBuilder) | |||||
{ | |||||
migrationBuilder.CreateTable( | |||||
name: "Patient", | |||||
columns: table => new | |||||
{ | |||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||||
Name = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
Gender = table.Column<int>(type: "int", nullable: false), | |||||
Mobile = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
Email = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
Age = table.Column<int>(type: "int", nullable: false), | |||||
Treatment = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
DoctorAssigned = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
Address = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
BloodGroup = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
AdmissionDate = table.Column<DateTime>(type: "datetime2", nullable: false), | |||||
DischargeDate = table.Column<DateTime>(type: "datetime2", nullable: true), | |||||
Status = table.Column<int>(type: "int", 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) | |||||
}, | |||||
constraints: table => | |||||
{ | |||||
table.PrimaryKey("PK_Patient", x => x.Id); | |||||
}); | |||||
migrationBuilder.CreateTable( | |||||
name: "PatientRecords", | |||||
columns: table => new | |||||
{ | |||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||||
PatientsId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||||
DateOfAdmission = table.Column<DateTime>(type: "datetime2", nullable: false), | |||||
Diagnosis = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
TreatmentPlan = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
DoctorNotes = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
LabReportUrl = table.Column<string>(type: "nvarchar(max)", nullable: true), | |||||
MedicationUrl = table.Column<string>(type: "nvarchar(max)", nullable: true), | |||||
MedicationHistoryUrl = table.Column<string>(type: "nvarchar(max)", nullable: true), | |||||
NextFollowUp = table.Column<DateTime>(type: "datetime2", nullable: true), | |||||
InsuranceProvider = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||||
Status = table.Column<int>(type: "int", 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) | |||||
}, | |||||
constraints: table => | |||||
{ | |||||
table.PrimaryKey("PK_PatientRecords", x => x.Id); | |||||
table.ForeignKey( | |||||
name: "FK_PatientRecords_Patient_PatientsId", | |||||
column: x => x.PatientsId, | |||||
principalTable: "Patient", | |||||
principalColumn: "Id", | |||||
onDelete: ReferentialAction.Cascade); | |||||
}); | |||||
migrationBuilder.CreateIndex( | |||||
name: "IX_PatientRecords_PatientsId", | |||||
table: "PatientRecords", | |||||
column: "PatientsId"); | |||||
} | |||||
/// <inheritdoc /> | |||||
protected override void Down(MigrationBuilder migrationBuilder) | |||||
{ | |||||
migrationBuilder.DropTable( | |||||
name: "PatientRecords"); | |||||
migrationBuilder.DropTable( | |||||
name: "Patient"); | |||||
} | |||||
} | |||||
} |