Commit 91d82271 authored by Almouhannad's avatar Almouhannad

(F) Add doctors notifications

parent cc194ca7
...@@ -18,6 +18,7 @@ import { DoctorsComponent } from './components/receptionist/doctors/doctors.comp ...@@ -18,6 +18,7 @@ import { DoctorsComponent } from './components/receptionist/doctors/doctors.comp
import { CreateWitingListItemAccordionComponent } from './components/receptionist/create-witing-list-item-accordion/create-witing-list-item-accordion.component'; import { CreateWitingListItemAccordionComponent } from './components/receptionist/create-witing-list-item-accordion/create-witing-list-item-accordion.component';
import { CreateEmployeeFormComponent } from './components/receptionist/create-employee-form/create-employee-form.component'; import { CreateEmployeeFormComponent } from './components/receptionist/create-employee-form/create-employee-form.component';
import { EmployeeComponent } from './components/receptionist/employee/employee.component'; import { EmployeeComponent } from './components/receptionist/employee/employee.component';
import { DoctorDashboardComponent } from './components/doctor/doctor-dashboard/doctor-dashboard.component';
const routes: Routes = [ const routes: Routes = [
{ {
...@@ -72,6 +73,17 @@ const routes: Routes = [ ...@@ -72,6 +73,17 @@ const routes: Routes = [
] ]
}, },
{
path: 'doctor',
component: DoctorDashboardComponent,
canActivate: [RoleGuard],
canActivateChild: [RoleGuard],
data: { role: Roles.Doctor },
children: [
]
},
{ {
path: 'receptionist', path: 'receptionist',
component: ReceptionistDashboardComponent, component: ReceptionistDashboardComponent,
......
...@@ -44,6 +44,8 @@ import { EmployeeComponent } from './components/receptionist/employee/employee.c ...@@ -44,6 +44,8 @@ import { EmployeeComponent } from './components/receptionist/employee/employee.c
import { WaitingListService } from './services/waitingList/waiting-list.service'; import { WaitingListService } from './services/waitingList/waiting-list.service';
import { EmployeesDataService } from './services/employees/employees-data.service'; import { EmployeesDataService } from './services/employees/employees-data.service';
import { ScrollToTopDirective } from './directives/scroll-to-top.directive'; import { ScrollToTopDirective } from './directives/scroll-to-top.directive';
import { DoctorDashboardComponent } from './components/doctor/doctor-dashboard/doctor-dashboard.component';
import { DoctorNotificationsService } from './services/doctorsNotifications/doctor-notifications.service';
@NgModule({ @NgModule({
...@@ -69,7 +71,8 @@ import { ScrollToTopDirective } from './directives/scroll-to-top.directive'; ...@@ -69,7 +71,8 @@ import { ScrollToTopDirective } from './directives/scroll-to-top.directive';
DoctorUsersService, DoctorUsersService,
ReceptionistUsersService, ReceptionistUsersService,
WaitingListService, WaitingListService,
EmployeesDataService EmployeesDataService,
DoctorNotificationsService,
], ],
// components and directives that belong to this module // components and directives that belong to this module
...@@ -106,6 +109,7 @@ import { ScrollToTopDirective } from './directives/scroll-to-top.directive'; ...@@ -106,6 +109,7 @@ import { ScrollToTopDirective } from './directives/scroll-to-top.directive';
EmployeeSerialNumberPopUpComponent, EmployeeSerialNumberPopUpComponent,
EmployeeComponent, EmployeeComponent,
ScrollToTopDirective, ScrollToTopDirective,
DoctorDashboardComponent,
], ],
// identifies the root component that Angular should // identifies the root component that Angular should
......
<div class="custom-child">
<router-outlet></router-outlet>
</div>
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { DoctorNotificationsService } from '../../../services/doctorsNotifications/doctor-notifications.service';
import { AuthenticationService } from '../../../services/authentication/authentication.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-doctor-dashboard',
templateUrl: './doctor-dashboard.component.html',
styleUrl: './doctor-dashboard.component.css'
})
export class DoctorDashboardComponent {
}
...@@ -92,24 +92,25 @@ ...@@ -92,24 +92,25 @@
</select> </select>
</div> </div>
<div class="d-grid gap-3 custom-undo-button mb-3">
<a> <a>
<button class="btn btn-outline-secondary" style="width: 100%;" <div class="custom-edit-button mb-3">
(click)="modal.dismiss()"> <button class="btn btn-outline-secondary" style="width:100%;"
إلغاء (click)="onSendToDoctor(); modal.dismiss();"
[disabled]="selectedDoctorId===-1">
تأكيد
</button> </button>
</a>
</div> </div>
</a>
<div class="d-grid gap-3 custom-undo-button">
<a> <a>
<div class="custom-edit-button"> <button class="btn btn-outline-secondary" style="width: 100%;"
<button class="btn btn-outline-secondary" style="width:100%;" (click)="modal.dismiss()">
(click)="onSendToDoctor(); modal.dismiss();"> إلغاء
تأكيد
</button> </button>
</div>
</a> </a>
</div> </div>
</div>
</div> </div>
</ng-template> </ng-template>
\ No newline at end of file
...@@ -27,6 +27,11 @@ export class HeaderComponent { ...@@ -27,6 +27,11 @@ export class HeaderComponent {
@Input("userData") userData: UserData | null = null; @Input("userData") userData: UserData | null = null;
//#endregion //#endregion
// #region Outputs
@Output("loggedIn") loggedIn: EventEmitter<any> = new EventEmitter();
// #endregion
//#region Variables //#region Variables
//#region Roles //#region Roles
...@@ -60,6 +65,7 @@ export class HeaderComponent { ...@@ -60,6 +65,7 @@ export class HeaderComponent {
this.router.navigate(['']); this.router.navigate(['']);
this.selectedButton = 'Home'; this.selectedButton = 'Home';
this.scroller.scrollToPosition([0,0]); this.scroller.scrollToPosition([0,0]);
this.loggedIn.emit();
} }
//#endregion //#endregion
......
...@@ -139,4 +139,62 @@ app-footer { ...@@ -139,4 +139,62 @@ app-footer {
border-color: var(--heading-color); border-color: var(--heading-color);
color: white; color: white;
} }
::ng-deep .custom-ok-button .btn{
font-weight: 900;
width: 100%;
background-color: var(--accent-color);
border-color: var(--accent-color);
color: white;
}
::ng-deep .custom-ok-button .btn:focus{
font-weight: 900;
width: 100%;
background-color: var(--accent-color);
border-color: var(--accent-color);
color: white;
}
::ng-deep .custom-ok-button .btn:hover{
width: 100%;
background-color: white;
border-color: var(--accent-color);
color: var(--accent-color);
}
::ng-deep .custom-no-button .btn{
font-weight: 900;
width: 100%;
background-color: var(--heading-color);
border-color: var(--heading-color);
color: white;
}
::ng-deep .custom-no-button .btn:focus{
font-weight: 900;
width: 100%;
background-color: var(--heading-color);
border-color: var(--heading-color);
color: white;
}
::ng-deep .custom-no-button .btn:hover{
width: 100%;
background-color: white;
border-color: var(--heading-color);
color: var(--heading-color);
}
::ng-deep .custom-notification-message h2{
font-weight: 600;
color: var(--heading-color);
}
::ng-deep .custom-notification-message h3{
font-weight: 400;
color: var(--heading-color);
}
/* #endregion */ /* #endregion */
<div class="custom-parent"> <div class="custom-parent">
<app-header class="sticky-top custom-header" [userData]="userData"></app-header> <app-header class="sticky-top custom-header" [userData]="userData" (loggedIn)="onUpdateUserData()"></app-header>
<router-outlet></router-outlet> <router-outlet></router-outlet>
<app-footer></app-footer> <app-footer></app-footer>
</div> </div>
<ng-template #doctorNotificationModal let-modal>
<div class="custom-child" dir="rtl">
<!-- To avoid first field auto focus -->
<div class="form-group">
<input type="text" autofocus="autofocus" style="display:none" />
</div>
<section class="section">
<div class="custom-title mb-3">
<h2><i class="bi bi-exclamation-triangle-fill" style="color: var(--heading-color);"></i> إشعار هام</h2>
</div>
<div class="custom-notification-message text-center mb-3">
<h2>المريض {{doctorNotification.patientFullName}}</h2>
<h3>في طريقه إليك</h3>
</div>
<div class="container">
<div class="custom-ok-button">
<button class="btn btn-outline-primary" (click)="modal.dismiss()">استقبال</button>
</div>
</div>
</section>
</div>
</ng-template>
\ No newline at end of file
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { UserData } from '../../../../classes/authentication/user-data'; import { UserData } from '../../../../classes/authentication/user-data';
import { AuthenticationService } from '../../../../services/authentication/authentication.service'; import { AuthenticationService } from '../../../../services/authentication/authentication.service';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { DoctorNotificationsService } from '../../../../services/doctorsNotifications/doctor-notifications.service';
@Component({ @Component({
selector: 'app-layout', selector: 'app-layout',
...@@ -10,11 +12,18 @@ import { AuthenticationService } from '../../../../services/authentication/authe ...@@ -10,11 +12,18 @@ import { AuthenticationService } from '../../../../services/authentication/authe
export class LayoutComponent implements OnInit { export class LayoutComponent implements OnInit {
//#region CTOR DI //#region CTOR DI
constructor(private authenticationService: AuthenticationService){} constructor(private authenticationService: AuthenticationService,
private modalService: NgbModal,
private doctorNotificationsService: DoctorNotificationsService
){}
//#endregion //#endregion
//#region On init //#region On init
ngOnInit(): void { ngOnInit(): void {
this.setUserData();
this.listenToDoctorNotifications();
}
setUserData(): void {
this.userData = this.authenticationService.getUserData(); this.userData = this.authenticationService.getUserData();
} }
//#endregion //#endregion
...@@ -23,4 +32,39 @@ export class LayoutComponent implements OnInit { ...@@ -23,4 +32,39 @@ export class LayoutComponent implements OnInit {
userData: UserData | null = null; userData: UserData | null = null;
//#endregion //#endregion
onUpdateUserData(): void {
this.setUserData();
}
openModal(modal: any): void {
this.modalService.open(modal, {
centered: true,
size: 'lg',
backdrop: 'static',
keyboard: false
});
}
// #region Doctor notification
@ViewChild("doctorNotificationModal") doctorNotificationModal: any;
doctorNotification : {
patientId: Number,
patientFullName: string,
doctorId: Number,
doctorUserId: Number
}
listenToDoctorNotifications(): void {
this.doctorNotificationsService.startConnection();
this.doctorNotificationsService.hubConnection.on('ReceiveNotification', (message) => {
if(this.userData !== null) {
if (message.doctorUserId == this.userData.id) {
this.doctorNotification = message;
this.openModal(this.doctorNotificationModal);
}
}
});
}
// #endregion
} }
import { Injectable } from '@angular/core';
import { HubConnectionBuilder } from '@microsoft/signalr';
import * as config from '../../../../config'
@Injectable({
providedIn: 'root'
})
export class DoctorNotificationsService {
constructor() { }
private readonly NOTIFICATIONS_ENDPOINT: string = `${config.apiUrl}/Notifications/Doctors`;
hubConnection: signalR.HubConnection;
startConnection(): void {
this.hubConnection = new HubConnectionBuilder()
.withUrl(this.NOTIFICATIONS_ENDPOINT)
.build();
this.hubConnection
.start()
.then(() => {
console.log('Connected to signalR!')
})
.catch(err => console.error('Error while starting connection: ' + err))
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment