Added Localization

This commit is contained in:
Sk Shaifat Murshed 2025-02-19 15:27:08 +05:30
parent 62a1030bd4
commit 666d66a339
26 changed files with 798 additions and 395 deletions

View File

@ -1,6 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { FullCalendarModule } from '@fullcalendar/angular';
import { CalendarOptions } from '@fullcalendar/core'; // useful for typechecking import { CalendarOptions } from '@fullcalendar/core'; // useful for typechecking
import dayGridPlugin from '@fullcalendar/daygrid'; import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction'; import interactionPlugin from '@fullcalendar/interaction';

View File

@ -2,8 +2,7 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router'; import { RouterOutlet } from '@angular/router';
import { FullCalendarModule } from '@fullcalendar/angular'; import { FullCalendarModule } from '@fullcalendar/angular';
import { CalendarOptions } from '@fullcalendar/core'; // useful for typechecking
import dayGridPlugin from '@fullcalendar/daygrid';
import { AppointmentCalendarRoutingModule } from './appointment-calendar-routing.module'; import { AppointmentCalendarRoutingModule } from './appointment-calendar-routing.module';
import { AppointmentCalendarComponent } from './appointment-calendar.component'; import { AppointmentCalendarComponent } from './appointment-calendar.component';
import { AppointmentDialogComponent } from '../appointment-dialog/appointment-dialog.component'; import { AppointmentDialogComponent } from '../appointment-dialog/appointment-dialog.component';

View File

@ -10,7 +10,8 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header py-4"> <div class="modal-header py-4">
<h4 class="text-success mb-0 fs-3 fw-normal"> <h4 class="text-success mb-0 fs-3 fw-normal">
{{ isEditMode ? 'Edit ' : 'Create ' }}{{name}} {{ isEditMode ? ('::edit' | abpLocalization) : ('::create' | abpLocalization) }}
{{ '::appointmentStatus' | abpLocalization }}
</h4> </h4>
<button <button
tabindex="0" tabindex="0"
@ -23,7 +24,9 @@
<form #appointmentForm="ngForm" (ngSubmit)="saveAppointment(appointmentForm)"> <form #appointmentForm="ngForm" (ngSubmit)="saveAppointment(appointmentForm)">
<div class="p-fluid grid justify-content-center"> <div class="p-fluid grid justify-content-center">
<div class="field col-md-5"> <div class="field col-md-5">
<label for="fname">First Name <span class="text-danger">*</span></label> <label for="fname"
>{{ '::firstName' | abpLocalization }}<span class="text-danger">*</span></label
>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-user"></i> <i class="pi pi-user"></i>
<input <input
@ -44,17 +47,30 @@
<i *ngIf="fnameCtrl.valid && fnameCtrl.touched" class="pi pi-check text-success"></i> <i *ngIf="fnameCtrl.valid && fnameCtrl.touched" class="pi pi-check text-success"></i>
<i *ngIf="fnameCtrl.invalid && fnameCtrl.touched" class="pi pi-times text-danger"></i> <i *ngIf="fnameCtrl.invalid && fnameCtrl.touched" class="pi pi-times text-danger"></i>
</span> </span>
<small class="text-danger" *ngIf="fnameCtrl.invalid && fnameCtrl.touched"> <small class="text-danger" *ngIf="fnameCtrl.invalid && fnameCtrl.touched">
<span *ngIf="fnameCtrl.errors?.required">First Name is required.</span> <span *ngIf="fnameCtrl.errors?.required">{{
<span *ngIf="fnameCtrl.errors?.minlength">Minimum 2 characters required.</span> '::firstNameRequired' | abpLocalization
<span *ngIf="fnameCtrl.errors?.maxlength">Maximum 30 characters allowed.</span> }}</span>
<span *ngIf="fnameCtrl.errors?.minlength">
{{
'::minLength'
| abpLocalization : { length: fnameCtrl.errors?.minlength.requiredLength }
}}
</span>
<span *ngIf="fnameCtrl.errors?.maxlength">{{
'::maxLength'
| abpLocalization : { length: fnameCtrl.errors?.maxlength.requiredLength }
}}</span>
</small> </small>
</div> </div>
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="lname">Last Name <span class="text-danger">*</span></label> <label for="lname"
>{{ '::lastName' | abpLocalization }}<span class="text-danger">*</span></label
>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-user"></i> <i class="pi pi-user"></i>
<input <input
@ -75,14 +91,26 @@
<i *ngIf="lnameCtrl.invalid && lnameCtrl.touched" class="pi pi-times text-danger"></i> <i *ngIf="lnameCtrl.invalid && lnameCtrl.touched" class="pi pi-times text-danger"></i>
</span> </span>
<small class="text-danger" *ngIf="lnameCtrl.invalid && lnameCtrl.touched"> <small class="text-danger" *ngIf="lnameCtrl.invalid && lnameCtrl.touched">
<span *ngIf="lnameCtrl.errors?.required">Last Name is required.</span> <span *ngIf="lnameCtrl.errors?.required">{{
<span *ngIf="lnameCtrl.errors?.minlength">Minimum 2 characters required.</span> '::lastNameRequired' | abpLocalization
<span *ngIf="lnameCtrl.errors?.maxlength">Maximum 30 characters allowed.</span> }}</span>
<span *ngIf="lnameCtrl.errors?.minlength">
{{
'::minLength'
| abpLocalization : { length: lnameCtrl.errors?.minlength.requiredLength }
}}
</span>
<span *ngIf="lnameCtrl.errors?.maxlength">
{{
'::maxLength'
| abpLocalization : { length: lnameCtrl.errors?.maxlength.requiredLength }
}}
</span>
</small> </small>
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label>Gender <span class="text-danger">*</span></label> <label>{{ '::gender' | abpLocalization }} <span class="text-danger">*</span></label>
<div class="flex align-items-center p-input-icon-right"> <div class="flex align-items-center p-input-icon-right">
<p-radioButton <p-radioButton
name="gender" name="gender"
@ -92,7 +120,7 @@
#genderCtrl="ngModel" #genderCtrl="ngModel"
required required
></p-radioButton> ></p-radioButton>
<label for="male" class="ml-2 mr-3">Male</label> <label for="male" class="ml-2 mr-3">{{ '::male' | abpLocalization }}</label>
<p-radioButton <p-radioButton
name="gender" name="gender"
@ -101,7 +129,7 @@
inputId="female" inputId="female"
required required
></p-radioButton> ></p-radioButton>
<label for="female" class="ml-2">Female</label> <label for="female" class="ml-2">{{ '::female' | abpLocalization }}</label>
<i <i
*ngIf="genderCtrl.valid && genderCtrl.touched" *ngIf="genderCtrl.valid && genderCtrl.touched"
@ -113,14 +141,16 @@
></i> ></i>
</div> </div>
<small class="text-danger d-block" *ngIf="genderCtrl.invalid && genderCtrl.touched"> <small class="text-danger d-block" *ngIf="genderCtrl.invalid && genderCtrl.touched">
Please select a gender. {{ '::genderRequired' | abpLocalization }}
</small> </small>
</div> </div>
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="mobile">Mobile No <span class="text-danger">*</span></label> <label for="mobile"
>{{ '::mobileNo' | abpLocalization }} <span class="text-danger">*</span></label
>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-phone"></i> <i class="pi pi-phone"></i>
<input <input
@ -146,13 +176,17 @@
></i> ></i>
</span> </span>
<small class="text-danger d-block" *ngIf="mobileCtrl.invalid && mobileCtrl.touched"> <small class="text-danger d-block" *ngIf="mobileCtrl.invalid && mobileCtrl.touched">
<span *ngIf="mobileCtrl.errors?.required">Mobile number is required.</span> <span *ngIf="mobileCtrl.errors?.required">{{
<span *ngIf="mobileCtrl.errors?.pattern">Enter a valid 10-digit mobile number.</span> '::mobileNoRequired' | abpLocalization
}}</span>
<span *ngIf="mobileCtrl.errors?.pattern">{{
'::mobileNoInvalid' | abpLocalization
}}</span>
</small> </small>
</div> </div>
<div class="field col-md-11"> <div class="field col-md-11">
<label for="address">Address <span class="text-danger">*</span></label> {{ '::address' | abpLocalization }} <span class="text-danger">*</span>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-map-marker"></i> <i class="pi pi-map-marker"></i>
<input <input
@ -179,14 +213,28 @@
></i> ></i>
</span> </span>
<small class="text-danger d-block" *ngIf="addressCtrl.invalid && addressCtrl.touched"> <small class="text-danger d-block" *ngIf="addressCtrl.invalid && addressCtrl.touched">
<span *ngIf="addressCtrl.errors?.required">Address is required.</span> <span *ngIf="addressCtrl.errors?.required">{{
<span *ngIf="addressCtrl.errors?.minlength">Minimum 5 characters required.</span> '::addressRequired' | abpLocalization
<span *ngIf="addressCtrl.errors?.maxlength">Maximum 100 characters allowed.</span> }}</span>
<span *ngIf="addressCtrl.errors?.minlength">
{{
'::minLength'
| abpLocalization : { length: addressCtrl.errors?.minlength.requiredLength }
}}
</span>
<span *ngIf="addressCtrl.errors?.maxlength">
{{
'::maxLength'
| abpLocalization : { length: addressCtrl.errors?.maxlength.requiredLength }
}}
</span>
</small> </small>
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="email">Email ID <span class="text-danger">*</span></label> <label for="email"
>{{ '::emailId' | abpLocalization }} <span class="text-danger">*</span></label
>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-envelope"></i> <i class="pi pi-envelope"></i>
<input <input
@ -206,15 +254,19 @@
<i *ngIf="emailCtrl.invalid && emailCtrl.touched" class="pi pi-times text-danger"></i> <i *ngIf="emailCtrl.invalid && emailCtrl.touched" class="pi pi-times text-danger"></i>
</span> </span>
<small class="text-danger d-block" *ngIf="emailCtrl.invalid && emailCtrl.touched"> <small class="text-danger d-block" *ngIf="emailCtrl.invalid && emailCtrl.touched">
<span *ngIf="emailCtrl.errors?.required">Email address is required.</span> <span *ngIf="emailCtrl.errors?.required">{{
<span *ngIf="emailCtrl.errors?.email">Enter a valid email address.</span> '::emailRequired' | abpLocalization
}}</span>
<span *ngIf="emailCtrl.errors?.email">{{ '::emailInvalid' | abpLocalization }}</span>
</small> </small>
</div> </div>
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="dob">Date of Birth <span class="text-danger">*</span></label> <label for="dob"
>{{ '::dateOfBirth' | abpLocalization }} <span class="text-danger">*</span></label
>
<p-calendar <p-calendar
id="dob" id="dob"
required required
@ -226,12 +278,16 @@
<small <small
class="p-error" class="p-error"
*ngIf="appointmentForm.controls.dob?.invalid && appointmentForm.controls.dob?.touched" *ngIf="appointmentForm.controls.dob?.invalid && appointmentForm.controls.dob?.touched"
>DOB Required</small
> >
{{ '::dobRequired' | abpLocalization }}
</small>
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="doctor">Consulting Doctor <span class="text-danger">*</span></label> <label for="doctor"
>{{ '::consultingDoctor' | abpLocalization }}
<span class="text-danger">*</span></label
>
<p-dropdown <p-dropdown
id="doctor" id="doctor"
name="doctor" name="doctor"
@ -246,7 +302,10 @@
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="date">Date of Appointment <span class="text-danger">*</span></label> <label for="date"
>{{ '::dateOfAppointment' | abpLocalization }}
<span class="text-danger">*</span></label
>
<p-calendar <p-calendar
id="date" id="date"
name="date" name="date"
@ -257,7 +316,10 @@
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="time">Time Of Appointment <span class="text-danger">*</span></label> <label for="time"
>{{ '::timeOfAppointment' | abpLocalization }}
<span class="text-danger">*</span></label
>
<span class="p-input-icon-left"> <span class="p-input-icon-left">
<i class="pi pi-clock"></i> <i class="pi pi-clock"></i>
<input <input
@ -273,7 +335,7 @@
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="injury">Injury/Condition</label> <label for="injury">{{ '::injuryCondition' | abpLocalization }}</label>
<span class="p-input-icon-left"> <span class="p-input-icon-left">
<i class="pi pi-exclamation-triangle"></i> <i class="pi pi-exclamation-triangle"></i>
<input <input
@ -286,7 +348,9 @@
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="insurance">Insurance Provider</label> <label for="insurance">
{{ '::insuranceProvider' | abpLocalization }}
</label>
<span class="p-input-icon-left"> <span class="p-input-icon-left">
<i class="pi pi-credit-card"></i> <i class="pi pi-credit-card"></i>
<input <input
@ -300,7 +364,9 @@
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="status">Appointment Status</label> <label for="status">
{{ '::appointmentStatus' | abpLocalization }}
</label>
<p-dropdown <p-dropdown
id="status" id="status"
name="status" name="status"
@ -313,7 +379,9 @@
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="visitType">Visit Type</label> <label for="visitType">
{{ '::visitType' | abpLocalization }}
</label>
<p-dropdown <p-dropdown
id="visitType" id="visitType"
name="visitType" name="visitType"
@ -327,7 +395,9 @@
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="paymentStatus">Payment Status</label> <label for="paymentStatus">
{{ '::paymentStatus' | abpLocalization }}
</label>
<p-dropdown <p-dropdown
id="paymentStatus" id="paymentStatus"
name="paymentStatus" name="paymentStatus"
@ -340,7 +410,9 @@
</div> </div>
<div class="field col-11"> <div class="field col-11">
<label for="notes">Notes</label> <label for="notes">
{{ '::notes' | abpLocalization }}
</label>
<textarea <textarea
id="notes" id="notes"
name="notes" name="notes"
@ -355,14 +427,14 @@
<button <button
pButton pButton
type="submit" type="submit"
label="Save" [label]="'::save' | abpLocalization"
class="p-button-success" class="p-button-success"
[disabled]="appointmentForm.invalid" [disabled]="appointmentForm.invalid"
></button> ></button>
<button <button
pButton pButton
type="button" type="button"
label="Cancel" [label]="'::cancel' | abpLocalization"
class="p-button-secondary ml-2" class="p-button-secondary ml-2"
(click)="onClose()" (click)="onClose()"
></button> ></button>

View File

@ -11,13 +11,11 @@
border-color: red !important; border-color: red !important;
} }
/* Adjust the z-index of the calendar dropdown */
.p-calendar .p-datepicker { .p-calendar .p-datepicker {
z-index: 1050 !important; /* Make sure it's above other elements */ z-index: 1050 !important;
} }
/* You can also adjust modal z-index if necessary */
.modal { .modal {
z-index: 1040; /* Set lower z-index to ensure modal is behind the calendar */ z-index: 1040;
} }

View File

@ -1,15 +1,5 @@
import { ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; import {ToasterService } from '@abp/ng.theme.shared';
import { HttpClient } from '@angular/common/http'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import {
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild,
} from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms'; import { FormsModule, NgForm } from '@angular/forms';
import { CreateOrUpdateAppointmentDto } from '@proxy/appoinments/dto'; import { CreateOrUpdateAppointmentDto } from '@proxy/appoinments/dto';
import { Gender, appointmentStatus, visitType, paymentStatus } from '@proxy/global-enum'; import { Gender, appointmentStatus, visitType, paymentStatus } from '@proxy/global-enum';
@ -26,6 +16,7 @@ import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { ViewAppointmentRoutingModule } from '../view-appointment/view-appointment-routing.module'; import { ViewAppointmentRoutingModule } from '../view-appointment/view-appointment-routing.module';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { SharedModule } from 'src/app/shared/shared.module';
@Component({ @Component({
selector: 'app-appointment-dialog', selector: 'app-appointment-dialog',
@ -45,17 +36,18 @@ import { CommonModule } from '@angular/common';
InputTextareaModule, InputTextareaModule,
ChipModule, ChipModule,
CommonModule, CommonModule,
SharedModule,
], ],
templateUrl: './appointment-dialog.component.html', templateUrl: './appointment-dialog.component.html',
styleUrl: './appointment-dialog.component.scss', styleUrl: './appointment-dialog.component.scss',
}) })
export class AppointmentDialogComponent implements OnInit { export class AppointmentDialogComponent implements OnInit {
@Input() visible: boolean = false; // Control modal visibility @Input() visible: boolean = false;
@Input() name: string; @Input() name: string;
@Input() isEditMode: boolean = false; // Determine if it's for edit or create @Input() isEditMode: boolean = false;
@Output() save = new EventEmitter<any>(); // Event emitter for saving appointment @Output() save = new EventEmitter<any>();
@Output() close = new EventEmitter<void>(); // Event emitter for closing the modal @Output() close = new EventEmitter<void>();
@Input() appointmentId: string; // To accept the appointment ID from the parent @Input() appointmentId: string;
@Input() selectedDate: string; @Input() selectedDate: string;
appointmentsForDate: any[] = []; appointmentsForDate: any[] = [];
@ -96,13 +88,11 @@ export class AppointmentDialogComponent implements OnInit {
paymentStatus: null, paymentStatus: null,
insuranceProvider: '', insuranceProvider: '',
}; };
} } else {
else{
this.fetchAppointmentData(); this.fetchAppointmentData();
} }
} }
fetchAppointmentData() { fetchAppointmentData() {
this.AppointmentService.getAppointmentById(this.appointmentId).subscribe(result => { this.AppointmentService.getAppointmentById(this.appointmentId).subscribe(result => {
this.appointment = result; this.appointment = result;

View File

@ -3,12 +3,14 @@ import { CommonModule } from '@angular/common';
import { AppointmentRoutingModule } from './appointment-routing.module'; import { AppointmentRoutingModule } from './appointment-routing.module';
import { AppointmentDialogComponent } from './appointment-dialog/appointment-dialog.component'; import { AppointmentDialogComponent } from './appointment-dialog/appointment-dialog.component';
import { SharedModule } from '../shared/shared.module';
@NgModule({ @NgModule({
declarations: [], declarations: [],
imports: [ imports: [
CommonModule, CommonModule,
SharedModule,
AppointmentRoutingModule, AppointmentRoutingModule,
AppointmentDialogComponent AppointmentDialogComponent
] ]

View File

@ -16,10 +16,8 @@
> >
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="flex align-items-center justify-content-between mb-3 gap-3"> <div class="flex align-items-center justify-content-between mb-3 gap-3">
<!-- Left: Title --> <h4 class="m-0">{{ '::appointmentList' | abpLocalization }}</h4>
<h4 class="m-0">Appointment List</h4>
<!-- Center: Search Bar with Icon Inside -->
<div class="flex-grow-1 flex justify-content-center"> <div class="flex-grow-1 flex justify-content-center">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"><i class="pi pi-search"></i></span> <span class="input-group-text"><i class="pi pi-search"></i></span>
@ -29,7 +27,7 @@
class="form-control" class="form-control"
(input)="dt2.filterGlobal($event.target.value, 'contains')" (input)="dt2.filterGlobal($event.target.value, 'contains')"
[(ngModel)]="globalFilter" [(ngModel)]="globalFilter"
placeholder="Search keyword" placeholder="{{ '::searchKeyword' | abpLocalization }}"
/> />
</div> </div>
</div> </div>
@ -38,6 +36,8 @@
pButton pButton
class="p-button-rounded p-button-secondary ml-2" class="p-button-rounded p-button-secondary ml-2"
(click)="loadappointments($event)" (click)="loadappointments($event)"
[title]="'::refresh' | abpLocalization"
> >
<i class="pi pi-refresh"></i> <i class="pi pi-refresh"></i>
</button> </button>
@ -46,7 +46,7 @@
pButton pButton
class="p-button-rounded p-button-success ml-2" class="p-button-rounded p-button-success ml-2"
(click)="openNewAppointmentDialog()" (click)="openNewAppointmentDialog()"
pTooltip="Add Appointment" pTooltip="{{ '::addAppointment' | abpLocalization }}"
tooltipPosition="left" tooltipPosition="left"
> >
<i class="pi pi-plus-circle"></i> <i class="pi pi-plus-circle"></i>
@ -55,6 +55,8 @@
pButton pButton
class="p-button-rounded p-button-warning ml-2" class="p-button-rounded p-button-warning ml-2"
(click)="exportAppointments()" (click)="exportAppointments()"
[title]="'::export' | abpLocalization"
> >
<i class="pi pi-download"></i> <i class="pi pi-download"></i>
</button> </button>
@ -64,25 +66,37 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="firstName">Name <p-sortIcon field="firstName" /></th> <th pSortableColumn="firstName">
<th pSortableColumn="doctor">Doctor <p-sortIcon field="doctor" /></th> {{ '::name' | abpLocalization }} <p-sortIcon field="firstName" />
<th pSortableColumn="gender">gender <p-sortIcon field="gender" /></th>
<th pSortableColumn="dateOfAppointment">Date <p-sortIcon field="dateOfAppointment" /></th>
<th pSortableColumn="timeOfAppointment">Time<p-sortIcon field="timeOfAppointment" /></th>
<th>Mobile No</th>
<th>Email</th>
<th pSortableColumn="appointmentStatus">
Appointment Status<p-sortIcon field="appointmentStatus" />
</th> </th>
<th pSortableColumn="visitType">Visit Type<p-sortIcon field="visitType" /></th> <th pSortableColumn="doctor">
<th>Actions</th> {{ '::doctor' | abpLocalization }} <p-sortIcon field="doctor" />
</th>
<th pSortableColumn="gender">
{{ '::gender' | abpLocalization }} <p-sortIcon field="gender" />
</th>
<th pSortableColumn="dateOfAppointment">
{{ '::date' | abpLocalization }} <p-sortIcon field="dateOfAppointment" />
</th>
<th pSortableColumn="timeOfAppointment">
{{ '::time' | abpLocalization }} <p-sortIcon field="timeOfAppointment" />
</th>
<th>{{ '::mobileNo' | abpLocalization }}</th>
<th>{{ '::email' | abpLocalization }}</th>
<th pSortableColumn="appointmentStatus">
{{ '::appointmentStatus' | abpLocalization }} <p-sortIcon field="appointmentStatus" />
</th>
<th pSortableColumn="visitType">
{{ '::visitType' | abpLocalization }} <p-sortIcon field="visitType" />
</th>
<th>{{ '::actions' | abpLocalization }}</th>
</tr> </tr>
</ng-template> </ng-template>
<ng-template pTemplate="body" let-appointment> <ng-template pTemplate="body" let-appointment>
<tr> <tr>
<td>{{ appointment.firstName }} {{ appointment.lastName }}</td> <td>{{ appointment.firstName }} {{ appointment.lastName }}</td>
<td>Dr. {{ appointment.doctor.firstName }} {{ appointment.doctor.lastName }}</td> <td>{{ '::doctorPrefix' | abpLocalization }} {{ appointment.doctor.firstName }} {{ appointment.doctor.lastName }}</td>
<td> <td>
<span class="badge" [ngClass]="appointment.gender === 1 ? 'bg-primary' : 'bg-pink'"> <span class="badge" [ngClass]="appointment.gender === 1 ? 'bg-primary' : 'bg-pink'">
{{ getGenderLabel(appointment.gender) }} {{ getGenderLabel(appointment.gender) }}
@ -125,4 +139,6 @@
</div> </div>
<app-appointment-dialog [appointmentId]="appointmentIdToEdit"[isEditMode]="isEditMode" <app-appointment-dialog [appointmentId]="appointmentIdToEdit"[isEditMode]="isEditMode"
[visible]="isModalVisible"*ngIf="isModalVisible" [name]="'Appointment'" (close)="closeDialog()"></app-appointment-dialog> [visible]="isModalVisible"*ngIf="isModalVisible"
[name]="'::appointment' | abpLocalization"
(close)="closeDialog()"></app-appointment-dialog>

View File

@ -1,8 +1,7 @@
import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { NgForm } from '@angular/forms'; import { CreateOrUpdateAppointmentDto } from '@proxy/appoinments/dto';
import { AppointmentDto, CreateOrUpdateAppointmentDto } from '@proxy/appoinments/dto';
import { AppointmentService } from '@proxy/appointments'; import { AppointmentService } from '@proxy/appointments';
import { DoctorService } from '@proxy/doctors'; import { DoctorService } from '@proxy/doctors';
import { PagingSortResultDto } from '@proxy/dto'; import { PagingSortResultDto } from '@proxy/dto';
@ -66,7 +65,6 @@ export class ViewAppointmentComponent {
}; };
appointments = []; appointments = [];
// status = { 1: 'Scheduled', 2: 'Completed', 3: 'Canceled' };
doctors = []; doctors = [];
doctorOptions = []; doctorOptions = [];
@ -76,7 +74,6 @@ export class ViewAppointmentComponent {
constructor( constructor(
private DoctorService: DoctorService, private DoctorService: DoctorService,
private AppointmentService: AppointmentService, private AppointmentService: AppointmentService,
private http: HttpClient,
private confirmation: ConfirmationService, private confirmation: ConfirmationService,
private toaster: ToasterService private toaster: ToasterService
) {} ) {}
@ -136,9 +133,7 @@ export class ViewAppointmentComponent {
} }
const blob = new Blob([bytes], { type: 'application/xlsx' }); const blob = new Blob([bytes], { type: 'application/xlsx' });
const url = window.URL.createObjectURL(blob); const url = window.URL.createObjectURL(blob);
const link = document.createElement('a'); const link = document.createElement('a');
link.href = url; link.href = url;
link.download = result.fileName; link.download = result.fileName;
@ -186,7 +181,7 @@ export class ViewAppointmentComponent {
this.DoctorService.get().subscribe(result => { this.DoctorService.get().subscribe(result => {
this.doctors = result; this.doctors = result;
this.doctorOptions = this.doctors.map(doctor => ({ this.doctorOptions = this.doctors.map(doctor => ({
label: `Dr. ${doctor.firstName} ${doctor.lastName}`, // Combine first and last name label: `Dr. ${doctor.firstName} ${doctor.lastName}`,
value: doctor.id, value: doctor.id,
})); }));
}); });

View File

@ -15,6 +15,7 @@ import { DoctorService } from '@proxy/doctors';
import { InputTextareaModule } from 'primeng/inputtextarea'; import { InputTextareaModule } from 'primeng/inputtextarea';
import { ChipModule } from 'primeng/chip'; import { ChipModule } from 'primeng/chip';
import { AppointmentDialogComponent } from "../appointment-dialog/appointment-dialog.component"; import { AppointmentDialogComponent } from "../appointment-dialog/appointment-dialog.component";
import { SharedModule } from 'src/app/shared/shared.module';
@NgModule({ @NgModule({
declarations: [ViewAppointmentComponent], declarations: [ViewAppointmentComponent],
@ -33,6 +34,7 @@ import { AppointmentDialogComponent } from "../appointment-dialog/appointment-di
RadioButtonModule, RadioButtonModule,
InputTextareaModule, InputTextareaModule,
ChipModule, ChipModule,
SharedModule,
AppointmentDialogComponent AppointmentDialogComponent
], ],
providers:[DoctorService] providers:[DoctorService]

View File

@ -4,70 +4,170 @@
role="dialog" role="dialog"
style="background: rgba(0, 0, 0, 0.5)" style="background: rgba(0, 0, 0, 0.5)"
*ngIf="visible" *ngIf="visible"
aria-label="l('Doctor')" aria-label="{{ '::department' | abpLocalization }}"
> >
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header py-4"> <div class="modal-header py-4">
<h4 class="text-success mb-0 fs-3 fw-normal"> <h4 class="text-success mb-0 fs-3 fw-normal">
{{ isEditMode ? 'Edit ' : 'Create ' }} Doctor {{ isEditMode ? ('::edit' | abpLocalization) : ('::create' | abpLocalization) }}
{{ '::department' | abpLocalization }}
</h4> </h4>
<button <button
tabindex="0" tabindex="0"
type="button" type="button"
(click)="onClose()" (click)="onClose()"
class="btn-close" class="btn-close"
aria-label="Close" aria-label="{{ '::close' | abpLocalization }}"
></button> ></button>
</div> </div>
<form #doctorForm="ngForm" (ngSubmit)="saveDoctor(doctorForm)"> <form #departmentForm="ngForm" (ngSubmit)="saveDepartment(departmentForm)">
<div class="p-fluid grid justify-content-center"> <div class="p-fluid grid justify-content-center">
<div class="field col-md-5" *ngFor="let field of ['firstName', 'lastName', 'mobile', 'email']; let i = index"> <div class="field col-md-5">
<label [for]="field">{{ field | titlecase }} <span class="text-danger">*</span></label> <label for="departmentNo">
{{ '::departmentNo' | abpLocalization }} <span class="text-danger">*</span>
</label>
<span class="p-input-icon-left p-input-icon-right"> <span class="p-input-icon-left p-input-icon-right">
<i class="pi" [ngClass]="{'pi-user': i < 2, 'pi-phone': field === 'mobile', 'pi-envelope': field === 'email'}"></i> <i class="pi pi-hashtag"></i>
<input pInputText [id]="field" [name]="field" [(ngModel)]="doctor[field]" required #ctrl="ngModel" <input
[ngClass]="{'is-valid': ctrl.valid && ctrl.touched, 'is-invalid': ctrl.invalid && ctrl.touched}" /> pInputText
<i *ngIf="ctrl.valid && ctrl.touched" class="pi pi-check text-success"></i> id="departmentNo"
<i *ngIf="ctrl.invalid && ctrl.touched" class="pi pi-times text-danger"></i> name="departmentNo"
[(ngModel)]="department.departmentNo"
#departmentNoCtrl="ngModel"
required
[ngClass]="{
'is-valid': departmentNoCtrl.valid && departmentNoCtrl.touched,
'is-invalid': departmentNoCtrl.invalid && departmentNoCtrl.touched
}"
/>
<i
*ngIf="departmentNoCtrl.valid && departmentNoCtrl.touched"
class="pi pi-check text-success"
></i>
<i
*ngIf="departmentNoCtrl.invalid && departmentNoCtrl.touched"
class="pi pi-times text-danger"
></i>
</span>
<small class="text-danger" *ngIf="departmentNoCtrl.invalid && departmentNoCtrl.touched">
<span *ngIf="departmentNoCtrl.errors?.required">
{{ '::departmentNoRequired' | abpLocalization }}
</span>
</small>
</div>
<div class="field col-md-1"></div>
<div class="field col-md-5">
<label for="departmentName">
{{ '::departmentName' | abpLocalization }} <span class="text-danger">*</span>
</label>
<span class="p-input-icon-left p-input-icon-right">
<i class="pi pi-building"></i>
<input
pInputText
id="departmentName"
name="departmentName"
[(ngModel)]="department.departmentName"
#departmentNameCtrl="ngModel"
required
/>
</span>
<small
class="text-danger"
*ngIf="departmentNameCtrl.invalid && departmentNameCtrl.touched"
>
<span *ngIf="departmentNameCtrl.errors?.required">
{{ '::departmentNameRequired' | abpLocalization }}
</span>
</small>
</div>
<div class="field col-md-5">
<label for="departmentDate">
{{ '::departmentDate' | abpLocalization }}
</label>
<p-calendar
id="departmentDate"
name="departmentDate"
[(ngModel)]="Departmentdate"
[showIcon]="true"
>
</p-calendar>
</div>
<div class="field col-md-1"></div>
<div class="field col-md-5">
<label for="departmentHead">
{{ '::departmentHead' | abpLocalization }}
</label>
<span class="p-input-icon-left">
<i class="pi pi-user"></i>
<input
pInputText
id="departmentHead"
name="departmentHead"
[(ngModel)]="department.departmentHead"
/>
</span> </span>
<small class="text-danger" *ngIf="ctrl.invalid && ctrl.touched">{{ field | titlecase }} is required.</small>
</div> </div>
<div class="field col-md-5"> <div class="field col-md-5">
<label for="specialization">Specialization</label> <label>
<input pInputText id="specialization" name="specialization" [(ngModel)]="doctor.specialization" /> {{ '::status' | abpLocalization }}
</label>
<div class="flex align-items-center p-input-icon-right">
<p-radioButton
name="status"
value="Active"
[(ngModel)]="department.status"
inputId="active"
></p-radioButton>
<label for="active" class="ml-2 mr-3">
{{ '::active' | abpLocalization }}
</label>
<p-radioButton
name="status"
value="Inactive"
[(ngModel)]="department.status"
inputId="inactive"
></p-radioButton>
<label for="inactive" class="ml-2">
{{ '::inactive' | abpLocalization }}
</label>
</div> </div>
<div class="field col-md-5">
<label for="degree">Degree</label>
<input pInputText id="degree" name="degree" [(ngModel)]="doctor.degree" />
</div>
<div class="field col-md-5">
<label for="experience">Experience (Years)</label>
<input type="number" pInputText id="experience" name="experience" [(ngModel)]="doctor.experience" min="0" />
</div>
<div class="field col-md-5">
<label for="consultationFee">Consultation Fee</label>
<input type="number" pInputText id="consultationFee" name="consultationFee" [(ngModel)]="doctor.consultationFee" min="0" />
</div>
<div class="field col-md-5">
<label for="clinicLocation">Clinic Location</label>
<input pInputText id="clinicLocation" name="clinicLocation" [(ngModel)]="doctor.clinicLocation" />
</div>
<div class="field col-md-5">
<label for="rating">Rating</label>
<p-rating [(ngModel)]="doctor.rating" [stars]="4" [cancel]="false" name="rating"></p-rating>
</div>
<div class="field col-md-5">
<label for="availability">Availability</label>
<p-dropdown [options]="workScheduleOptions" [(ngModel)]="doctor.availability" name="availability" placeholder="Select Availability"></p-dropdown>
</div> </div>
<div class="field col-md-6"></div>
<div class="field col-11"> <div class="field col-11">
<label for="description">Description</label> <label for="description">
<textarea id="description" name="description" [(ngModel)]="doctor.description" rows="5" cols="30" pInputTextarea></textarea> {{ '::description' | abpLocalization }}
</label>
<textarea
id="description"
name="description"
[(ngModel)]="department.description"
rows="5"
cols="30"
pInputTextarea
>
</textarea>
</div> </div>
<div class="field col-11 flex justify-content-end"> <div class="field col-11 flex justify-content-end">
<button pButton type="submit" label="Save" class="p-button-success" [disabled]="doctorForm.invalid"></button> <button
<button pButton type="button" label="Cancel" class="p-button-secondary ml-2" (click)="onClose()"></button> pButton
type="submit"
[label]="'::save' | abpLocalization"
class="p-button-success"
[disabled]="departmentForm.invalid"
></button>
<button
pButton
type="button"
[label]="'::cancel' | abpLocalization"
class="p-button-secondary ml-2"
(click)="onClose()"
></button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -11,13 +11,11 @@
border-color: red !important; border-color: red !important;
} }
/* Adjust the z-index of the calendar dropdown */
.p-calendar .p-datepicker { .p-calendar .p-datepicker {
z-index: 1050 !important; /* Make sure it's above other elements */ z-index: 1050 !important;
} }
/* You can also adjust modal z-index if necessary */
.modal { .modal {
z-index: 1040; /* Set lower z-index to ensure modal is behind the calendar */ z-index: 1040;
} }

View File

@ -1,5 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DepartmentsRoutingModule } from './departments-routing.module';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormsModule, NgForm } from '@angular/forms'; import { FormsModule, NgForm } from '@angular/forms';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
@ -13,7 +12,8 @@ import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { CreateDepartmentDto } from '@proxy/dtos'; import { CreateDepartmentDto } from '@proxy/dtos';
import { DepartmentService } from '@proxy/departments'; import { DepartmentService } from '@proxy/departments';
import { ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; import { ToasterService } from '@abp/ng.theme.shared';
import { SharedModule } from '../shared/shared.module';
@Component({ @Component({
selector: 'app-department-dialog', selector: 'app-department-dialog',
@ -32,6 +32,7 @@ import { ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
InputTextareaModule, InputTextareaModule,
ChipModule, ChipModule,
CommonModule, CommonModule,
SharedModule
], ],
templateUrl: './department-dialog.component.html', templateUrl: './department-dialog.component.html',
styleUrl: './department-dialog.component.scss', styleUrl: './department-dialog.component.scss',

View File

@ -16,7 +16,7 @@
> >
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="flex align-items-center justify-content-between mb-3 gap-3"> <div class="flex align-items-center justify-content-between mb-3 gap-3">
<h4 class="m-0">Department List</h4> <h4 class="m-0">{{ '::departmentList' | abpLocalization }}</h4>
<div class="flex-grow-1 flex justify-content-center"> <div class="flex-grow-1 flex justify-content-center">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"><i class="pi pi-search"></i></span> <span class="input-group-text"><i class="pi pi-search"></i></span>
@ -26,7 +26,7 @@
class="form-control" class="form-control"
(input)="dt2.filterGlobal($event.target.value, 'contains')" (input)="dt2.filterGlobal($event.target.value, 'contains')"
[(ngModel)]="globalFilter" [(ngModel)]="globalFilter"
placeholder="Search keyword" placeholder="{{ '::searchKeyword' | abpLocalization }}"
/> />
</div> </div>
</div> </div>
@ -35,6 +35,8 @@
pButton pButton
class="p-button-rounded p-button-secondary ml-2" class="p-button-rounded p-button-secondary ml-2"
(click)="loaddepartments($event)" (click)="loaddepartments($event)"
[title]="'::refresh' | abpLocalization"
> >
<i class="pi pi-refresh"></i> <i class="pi pi-refresh"></i>
</button> </button>
@ -42,7 +44,8 @@
pButton pButton
class="p-button-rounded p-button-success ml-2" class="p-button-rounded p-button-success ml-2"
(click)="openNewDepartmentDialog()" (click)="openNewDepartmentDialog()"
pTooltip="Add Department" pTooltip="{{ '::addDepartment' | abpLocalization }}"
tooltipPosition="left" tooltipPosition="left"
> >
<i class="pi pi-plus-circle"></i> <i class="pi pi-plus-circle"></i>
@ -51,6 +54,8 @@
pButton pButton
class="p-button-rounded p-button-warning ml-2" class="p-button-rounded p-button-warning ml-2"
(click)="exportDepartments()" (click)="exportDepartments()"
[title]="'::export' | abpLocalization"
> >
<i class="pi pi-download"></i> <i class="pi pi-download"></i>
</button> </button>
@ -59,13 +64,31 @@
</ng-template> </ng-template>
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="departmentNo">Department Number <p-sortIcon field="departmentNo" /></th> <th pSortableColumn="departmentNo">
<th pSortableColumn="departmentName">Department Name <p-sortIcon field="departmentName" /></th> {{ '::departmentNumber' | abpLocalization }}
<th pSortableColumn="description">Description <p-sortIcon field="description" /></th> <p-sortIcon field="departmentNo" />
<th pSortableColumn="departmentDate">Date <p-sortIcon field="departmentDate" /></th> </th>
<th pSortableColumn="departmentHead">Department Head<p-sortIcon field="departmentHead" /></th> <th pSortableColumn="departmentName">
<th pSortableColumn="status">Status <p-sortIcon field="status" /></th> {{ '::departmentName' | abpLocalization }}
<th>Actions</th> <p-sortIcon field="departmentName" />
</th>
<th pSortableColumn="description">
{{ '::description' | abpLocalization }}
<p-sortIcon field="description" />
</th>
<th pSortableColumn="departmentDate">
{{ '::date' | abpLocalization }}
<p-sortIcon field="departmentDate" />
</th>
<th pSortableColumn="departmentHead">
{{ '::departmentHead' | abpLocalization }}
<p-sortIcon field="departmentHead" />
</th>
<th pSortableColumn="status">
{{ '::status' | abpLocalization }}
<p-sortIcon field="status" />
</th>
<th>{{ '::actions' | abpLocalization }}</th>
</tr> </tr>
</ng-template> </ng-template>
<ng-template pTemplate="body" let-department> <ng-template pTemplate="body" let-department>
@ -94,4 +117,6 @@
</div> </div>
<app-department-dialog [Id]="DepartmentIdToEdit"[isEditMode]="isEditMode" <app-department-dialog [Id]="DepartmentIdToEdit"[isEditMode]="isEditMode"
[visible]="isModalVisible"*ngIf="isModalVisible" [name]="'Department'" (close)="closeDialog()"></app-department-dialog > [visible]="isModalVisible"*ngIf="isModalVisible"
[name]="'::department' | abpLocalization"
(close)="closeDialog()"></app-department-dialog >

View File

@ -1,5 +1,4 @@
import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { DepartmentService } from '@proxy/departments'; import { DepartmentService } from '@proxy/departments';
import { PagingSortResultDto } from '@proxy/dto'; import { PagingSortResultDto } from '@proxy/dto';
@ -29,7 +28,6 @@ export class DepartmentsComponent implements OnInit {
} }
constructor( constructor(
private DepartmentService: DepartmentService, private DepartmentService: DepartmentService,
private http: HttpClient,
private confirmation: ConfirmationService, private confirmation: ConfirmationService,
private toaster: ToasterService private toaster: ToasterService

View File

@ -14,12 +14,14 @@ import { InputTextareaModule } from 'primeng/inputtextarea';
import { RadioButtonModule } from 'primeng/radiobutton'; import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { DepartmentDialogComponent } from "./department-dialog.component"; import { DepartmentDialogComponent } from "./department-dialog.component";
import { SharedModule } from '../shared/shared.module';
@NgModule({ @NgModule({
declarations: [DepartmentsComponent], declarations: [DepartmentsComponent],
imports: [ imports: [
CommonModule, CommonModule,
SharedModule,
DepartmentsRoutingModule, DepartmentsRoutingModule,
TableModule, TableModule,
DialogModule, DialogModule,

View File

@ -269,7 +269,6 @@
<span *ngIf="joiningDateCtrl.errors?.required">Joining Date is required.</span> <span *ngIf="joiningDateCtrl.errors?.required">Joining Date is required.</span>
</small> </small>
</div> </div>
<!-- Rating -->
<div class="field col-md-5"> <div class="field col-md-5">
<label for="rating">Rating</label><br /> <label for="rating">Rating</label><br />
<p-rating <p-rating
@ -280,7 +279,9 @@
></p-rating> ></p-rating>
</div> </div>
<div class="field col-md-1"></div> <div class="field col-md-1"></div>
<!-- Button to open the popup --> <!-- Button to open the popup -->
<div class="col-md-5">
<div class="button-container"> <div class="button-container">
<button <button
pButton pButton
@ -291,8 +292,11 @@
class="p-mr-2" class="p-mr-2"
></button> ></button>
</div> </div>
</div>
<!-- Popup Dialog -->
<!-- #incomplete -->
<!-- Need to Be Worked on the popup for schedule the time -->
<p-dialog <p-dialog
header="Select Days and Times" header="Select Days and Times"
[(visible)]="displayDialog" [(visible)]="displayDialog"
@ -353,8 +357,7 @@
</div> </div>
</p-footer> </p-footer>
</p-dialog> </p-dialog>
<!-- end -->
<!-- Description -->
<div class="field col-11"> <div class="field col-11">
<label for="description">Description</label> <label for="description">Description</label>
<textarea <textarea
@ -367,7 +370,6 @@
></textarea> ></textarea>
</div> </div>
<!-- Buttons -->
<div class="field col-11 flex justify-content-end"> <div class="field col-11 flex justify-content-end">
<button <button
pButton pButton

View File

@ -15,14 +15,8 @@ import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { RatingModule } from 'primeng/rating'; import { RatingModule } from 'primeng/rating';
import { MultiSelectModule } from 'primeng/multiselect'; import { MultiSelectModule } from 'primeng/multiselect';
import { TimeSlot, timeSlotOptions, WorkSchedule, workScheduleOptions } from '@proxy/global-enum'; import { TimeSlot, WorkSchedule, } from '@proxy/global-enum';
// Define Type for Availability
interface ScheduleOption {
label: string;
value: string;
items?: ScheduleOption[];
}
@Component({ @Component({
selector: 'app-doctor-dialog', selector: 'app-doctor-dialog',
standalone: true, standalone: true,
@ -59,12 +53,10 @@ export class DoctorDialogComponent implements OnInit {
isSchedulePopupVisible = false; isSchedulePopupVisible = false;
selectedDays: { label: string; value: string }[] = []; selectedDays: { label: string; value: string }[] = [];
selectedTimeSlots: { [key: number]: number | null } = {}; selectedTimeSlots: { [key: number]: number | null } = {};
displayDialog: boolean = false; displayDialog: boolean = false;
selectedDay: any = null; selectedDay: any = null;
selectedTime: any = null; selectedTime: any = null;
selectedTimes: { [key: number]: number } = {}; selectedTimes: { [key: number]: number } = {};
workScheduleOptions: { label: string; value: number }[] = []; workScheduleOptions: { label: string; value: number }[] = [];
timeSlotOptions: { label: string; value: number }[] = []; timeSlotOptions: { label: string; value: number }[] = [];

View File

@ -16,7 +16,7 @@
> >
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="flex align-items-center justify-content-between mb-3 gap-3"> <div class="flex align-items-center justify-content-between mb-3 gap-3">
<h4 class="m-0">Doctor List</h4> <h4 class="m-0">{{ '::doctorList' | abpLocalization }}</h4>
<div class="flex-grow-1 flex justify-content-center"> <div class="flex-grow-1 flex justify-content-center">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"><i class="pi pi-search"></i></span> <span class="input-group-text"><i class="pi pi-search"></i></span>
@ -26,18 +26,31 @@
class="form-control" class="form-control"
(input)="dt.filterGlobal($event.target.value, 'contains')" (input)="dt.filterGlobal($event.target.value, 'contains')"
[(ngModel)]="globalFilter" [(ngModel)]="globalFilter"
placeholder="Search keyword" placeholder="{{ '::searchKeyword' | abpLocalization }}"
/> />
</div> </div>
</div> </div>
<div> <div>
<button pButton class="p-button-rounded p-button-secondary ml-2" (click)="loadDoctors($event)"> <button
pButton
class="p-button-rounded p-button-secondary ml-2"
(click)="loadDoctors($event)"
[title]="'::refresh' | abpLocalization"
>
<i class="pi pi-refresh"></i> <i class="pi pi-refresh"></i>
</button> </button>
<button pButton class="p-button-rounded p-button-success ml-2" (click)="openNewDoctorDialog()" pTooltip="Add Doctor" tooltipPosition="left"> <button
pButton
class="p-button-rounded p-button-success ml-2"
(click)="openNewDoctorDialog()"
pTooltip="{{ '::addDoctor' | abpLocalization }}"
tooltipPosition="left"
>
<i class="pi pi-plus-circle"></i> <i class="pi pi-plus-circle"></i>
</button> </button>
<button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportDoctors()"> <button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportDoctors()"
[title]="'::export' | abpLocalization"
>
<i class="pi pi-download"></i> <i class="pi pi-download"></i>
</button> </button>
</div> </div>
@ -45,22 +58,40 @@
</ng-template> </ng-template>
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="firstName">Name <p-sortIcon field="firstName" /></th> <th pSortableColumn="firstName">
<th pSortableColumn="mobile">Mobile <p-sortIcon field="mobile" /></th> {{ '::name' | abpLocalization }}
<th pSortableColumn="email">Email <p-sortIcon field="email" /></th> <p-sortIcon field="firstName" />
<th pSortableColumn="specialization">Specialization <p-sortIcon field="specialization" /></th> </th>
<th pSortableColumn="experience">Experience <p-sortIcon field="experience" /></th> <th pSortableColumn="mobile">
<th pSortableColumn="rating">Rating <p-sortIcon field="rating" /></th> {{ '::mobile' | abpLocalization }}
<th>Actions</th> <p-sortIcon field="mobile" />
</th>
<th pSortableColumn="email">
{{ '::email' | abpLocalization }}
<p-sortIcon field="email" />
</th>
<th pSortableColumn="specialization">
{{ '::specialization' | abpLocalization }}
<p-sortIcon field="specialization" />
</th>
<th pSortableColumn="experience">
{{ '::experience' | abpLocalization }}
<p-sortIcon field="experience" />
</th>
<th pSortableColumn="rating">
{{ '::rating' | abpLocalization }}
<p-sortIcon field="rating" />
</th>
<th>{{ '::actions' | abpLocalization }}</th>
</tr> </tr>
</ng-template> </ng-template>
<ng-template pTemplate="body" let-doctor> <ng-template pTemplate="body" let-doctor>
<tr> <tr>
<td>Dr. {{ doctor.firstName }} {{ doctor.lastName }}</td> <td>{{ '::doctorPrefix' | abpLocalization }} {{ doctor.firstName }} {{ doctor.lastName }}</td>
<td>{{ doctor.mobile }}</td> <td>{{ doctor.mobile }}</td>
<td>{{ doctor.email }}</td> <td>{{ doctor.email }}</td>
<td>{{ doctor.specialization }}</td> <td>{{ doctor.specialization }}</td>
<td>{{ doctor.experience }} years</td> <td>{{ doctor.experience }} {{ '::years' | abpLocalization }}</td>
<td>{{ doctor.rating }}</td> <td>{{ doctor.rating }}</td>
<td class="d-flex"> <td class="d-flex">
<button class="btn btn-warning btn-sm ml-1" (click)="editDoctor(doctor)"> <button class="btn btn-warning btn-sm ml-1" (click)="editDoctor(doctor)">
@ -78,5 +109,11 @@
</p-table> </p-table>
</div> </div>
<app-doctor-dialog [Id]="DoctorIdToEdit"[isEditMode]="isEditMode" <app-doctor-dialog
[visible]="isModalVisible"*ngIf="isModalVisible" [name]="'Doctor'" (close)="closeDialog()"></app-doctor-dialog> [Id]="DoctorIdToEdit"
[isEditMode]="isEditMode"
[visible]="isModalVisible"
*ngIf="isModalVisible"
[name]="'::doctor' | abpLocalization"
(close)="closeDialog()"
></app-doctor-dialog>

View File

@ -1,5 +1,4 @@
import { ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DoctorService } from '@proxy/doctors'; import { DoctorService } from '@proxy/doctors';
@ -31,9 +30,7 @@ export class DoctorsComponent implements OnInit {
} }
constructor( constructor(
private DoctorService: DoctorService, private DoctorService: DoctorService,
private http: HttpClient,
private confirmation: ConfirmationService,
private toaster: ToasterService,
private router: Router private router: Router
) {} ) {}
workSchedule = Object.keys(workScheduleOptions) workSchedule = Object.keys(workScheduleOptions)

View File

@ -15,6 +15,7 @@ import { RadioButtonModule } from 'primeng/radiobutton';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { DoctorDialogComponent } from './doctor-dialog.component'; import { DoctorDialogComponent } from './doctor-dialog.component';
import { ShiftManagementComponent } from './shift-management/shift-management.component'; import { ShiftManagementComponent } from './shift-management/shift-management.component';
import { SharedModule } from '../shared/shared.module';
@NgModule({ @NgModule({
declarations: [DoctorsComponent,ShiftManagementComponent], declarations: [DoctorsComponent,ShiftManagementComponent],
@ -34,6 +35,7 @@ import { ShiftManagementComponent } from './shift-management/shift-management.co
InputTextareaModule, InputTextareaModule,
ChipModule, ChipModule,
DoctorDialogComponent, DoctorDialogComponent,
SharedModule

View File

@ -7,14 +7,22 @@
[list]="list" [list]="list"
></abp-extensible-table> --> ></abp-extensible-table> -->
<div class="flex justify-content-between align-items-center mb-3"> <div class="flex justify-content-between align-items-center mb-3">
<button pButton icon="pi pi-plus" label="Add Roles" class="p-button-success" (click)="add()"></button> <button
pButton
icon="pi pi-plus"
label="{{ '::addRoles' | abpLocalization }}"
class="p-button-success"
(click)="add()"
></button>
</div> </div>
<p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll"> <p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll">
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="name">Role name <p-sortIcon field="name"></p-sortIcon></th> <th pSortableColumn="name">
{{ 'AbpIdentity::RoleName' | abpLocalization }}
<th>Actions</th> <p-sortIcon field="name"></p-sortIcon>
</th>
<th>{{ 'AbpIdentity::Actions' | abpLocalization }}</th>
</tr> </tr>
</ng-template> </ng-template>
@ -22,12 +30,28 @@
<tr> <tr>
<td>{{ role.name }}</td> <td>{{ role.name }}</td>
<td> <td>
<button pButton icon="pi pi-pencil" class="p-button-text p-button-primary" (click)="edit(role.id)"></button> <button
<button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="delete(role.id,role.name)"></button> pButton
<button pButton icon="pi pi-lock" class="p-button-text p-button-success" (click)="openPermissionsModal(role.name)"></button> icon="pi pi-pencil"
class="p-button-text p-button-primary"
(click)="edit(role.id)"
title="{{ 'AbpIdentity::Edit' | abpLocalization }}"
></button>
<button
pButton
icon="pi pi-trash"
class="p-button-text p-button-danger"
(click)="delete(role.id, role.name)"
title="{{ 'AbpIdentity::Delete' | abpLocalization }}"
></button>
<button
pButton
icon="pi pi-lock"
class="p-button-text p-button-success"
(click)="openPermissionsModal(role.name)"
title="{{ 'AbpIdentity::Permissions' | abpLocalization }}"
></button>
</td> </td>
</tr> </tr>
</ng-template> </ng-template>
@ -50,7 +74,7 @@
<form #roleForm="ngForm" (ngSubmit)="save()" validateOnSubmit> <form #roleForm="ngForm" (ngSubmit)="save()" validateOnSubmit>
<!-- Name Field --> <!-- Name Field -->
<div class="form-group"> <div class="form-group">
<label for="name">Name</label> <label for="name">{{ 'AbpIdentity::Name' | abpLocalization }}</label>
<input <input
id="name" id="name"
type="text" type="text"
@ -60,7 +84,9 @@
required required
#nameCtrl="ngModel" #nameCtrl="ngModel"
/> />
<small class="text-danger" *ngIf="nameCtrl.invalid && nameCtrl.touched">Name is required</small> <small class="text-danger" *ngIf="nameCtrl.invalid && nameCtrl.touched">
{{ 'AbpIdentity::NameIsRequired' | abpLocalization }}
</small>
</div> </div>
<!-- Is Default Checkbox --> <!-- Is Default Checkbox -->
@ -72,7 +98,9 @@
[(ngModel)]="selected.isDefault" [(ngModel)]="selected.isDefault"
name="isDefault" name="isDefault"
/> />
<label for="isDefault" class="form-check-label">Default</label> <label for="isDefault" class="form-check-label">
{{ 'AbpIdentity::Default' | abpLocalization }}
</label>
</div> </div>
<!-- Is Public Checkbox --> <!-- Is Public Checkbox -->
@ -84,9 +112,11 @@
[(ngModel)]="selected.isPublic" [(ngModel)]="selected.isPublic"
name="isPublic" name="isPublic"
/> />
<label for="isPublic" class="form-check-label">Public</label> <label for="isPublic" class="form-check-label">
{{ 'AbpIdentity::Public' | abpLocalization }}
</label>
</div> </div>
<br> <br />
<abp-button iconClass="fa fa-check" [disabled]="roleForm.invalid" (click)="save()">{{ <abp-button iconClass="fa fa-check" [disabled]="roleForm.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization 'AbpIdentity::Save' | abpLocalization
}}</abp-button> }}</abp-button>
@ -122,4 +152,3 @@
> >
</abp-permission-management> </abp-permission-management>
</abp-page> </abp-page>

View File

@ -33,6 +33,7 @@ import { PermissionManagementModule } from '@abp/ng.permission-management';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { MenuItem } from 'primeng/api'; import { MenuItem } from 'primeng/api';
import { Dropdown, DropdownModule } from 'primeng/dropdown'; import { Dropdown, DropdownModule } from 'primeng/dropdown';
import { SharedModule } from 'src/app/shared/shared.module';
@Component({ @Component({
selector: 'app-custom-roles', selector: 'app-custom-roles',
@ -50,7 +51,8 @@ import { Dropdown, DropdownModule } from 'primeng/dropdown';
PermissionManagementModule, PermissionManagementModule,
CoreModule, CoreModule,
NgbNavModule, NgbNavModule,
DropdownModule DropdownModule,
SharedModule
], ],
templateUrl: './custom-roles.component.html', templateUrl: './custom-roles.component.html',
providers: [ providers: [

View File

@ -15,7 +15,7 @@
<button <button
pButton pButton
icon="pi pi-plus" icon="pi pi-plus"
label="Add User" label="{{ '::addUser' | abpLocalization }}"
class="p-button-success" class="p-button-success"
(click)="add()" (click)="add()"
></button> ></button>
@ -47,13 +47,28 @@
> >
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="userName">Username <p-sortIcon field="userName"></p-sortIcon></th> <th pSortableColumn="userName">
<th pSortableColumn="name">First Name <p-sortIcon field="name"></p-sortIcon></th> {{ '::username' | abpLocalization }}
<th pSortableColumn="surname">Last Name <p-sortIcon field="surname"></p-sortIcon></th> <p-sortIcon field="userName"></p-sortIcon>
<th pSortableColumn="email">Email <p-sortIcon field="email"></p-sortIcon></th> </th>
<th pSortableColumn="Phone">Phone No <p-sortIcon field="Phone"></p-sortIcon></th> <th pSortableColumn="name">
<th>Status</th> {{ '::firstName' | abpLocalization }}
<th>Actions</th> <p-sortIcon field="name"></p-sortIcon>
</th>
<th pSortableColumn="surname">
{{ '::lastName' | abpLocalization }}
<p-sortIcon field="surname"></p-sortIcon>
</th>
<th pSortableColumn="email">
{{ '::email' | abpLocalization }}
<p-sortIcon field="email"></p-sortIcon>
</th>
<th pSortableColumn="phoneNumber">
{{ '::phoneNumber' | abpLocalization }}
<p-sortIcon field="phoneNumber"></p-sortIcon>
</th>
<th>{{ '::status' | abpLocalization }}</th>
<th>{{ '::actions' | abpLocalization }}</th>
</tr> </tr>
</ng-template> </ng-template>
@ -73,7 +88,7 @@
<td> <td>
<div class="btn-group" dropdown placement="bottom left" container="body"> <div class="btn-group" dropdown placement="bottom left" container="body">
<p-splitButton <p-splitButton
label="Actions" label="{{ '::actions' | abpLocalization }}"
icon="pi pi-cog" icon="pi pi-cog"
class="p-button-sm p-button-primary" class="p-button-sm p-button-primary"
[model]="actionItems" [model]="actionItems"
@ -155,7 +170,9 @@
<a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a> <a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a>
<ng-template ngbNavContent> <ng-template ngbNavContent>
<div class="form-group"> <div class="form-group">
<label for="userName">{{ 'User Name' | abpLocalization }}</label> <label for="userName">
{{ '::userName' | abpLocalization }}
</label>
<input <input
id="userName" id="userName"
type="text" type="text"
@ -166,13 +183,14 @@
#userName="ngModel" #userName="ngModel"
/> />
<div *ngIf="userName.invalid && userName.touched" class="text-danger"> <div *ngIf="userName.invalid && userName.touched" class="text-danger">
User Name is required {{ '::userNameIsRequired' | abpLocalization }}
</div> </div>
</div> </div>
<!-- Password -->
<div class="form-group" *ngIf="!selected.id"> <div class="form-group" *ngIf="!selected.id">
<label for="password">Password</label> <label for="password">
{{ '::password' | abpLocalization }}
</label>
<input <input
id="password" id="password"
type="password" type="password"
@ -183,13 +201,14 @@
#passwordField="ngModel" #passwordField="ngModel"
/> />
<div *ngIf="passwordField.invalid && passwordField.touched" class="text-danger"> <div *ngIf="passwordField.invalid && passwordField.touched" class="text-danger">
Password is required {{ '::passwordIsRequired' | abpLocalization }}
</div> </div>
</div> </div>
<!-- Name -->
<div class="form-group"> <div class="form-group">
<label for="name">{{ 'Name' | abpLocalization }}</label> <label for="name">
{{ '::firstName' | abpLocalization }}
</label>
<input <input
id="name" id="name"
type="text" type="text"
@ -200,9 +219,10 @@
/> />
</div> </div>
<!-- Surname -->
<div class="form-group"> <div class="form-group">
<label for="surname">{{ 'Surname' | abpLocalization }}</label> <label for="surname">
{{ '::lastName' | abpLocalization }}
</label>
<input <input
id="surname" id="surname"
type="text" type="text"
@ -215,7 +235,9 @@
<!-- Email --> <!-- Email -->
<div class="form-group"> <div class="form-group">
<label for="email">{{ 'Email' | abpLocalization }}</label> <label for="email">
{{ '::email' | abpLocalization }}
</label>
<input <input
id="email" id="email"
type="email" type="email"
@ -226,13 +248,14 @@
#email="ngModel" #email="ngModel"
/> />
<div *ngIf="email.invalid && email.touched" class="text-danger"> <div *ngIf="email.invalid && email.touched" class="text-danger">
Valid Email is required {{ '::validEmailIsRequired' | abpLocalization }}
</div> </div>
</div> </div>
<!-- Phone Number -->
<div class="form-group"> <div class="form-group">
<label for="phoneNumber">{{ 'Phone Number' | abpLocalization }}</label> <label for="phoneNumber">
{{ '::phoneNumber' | abpLocalization }}
</label>
<input <input
id="phoneNumber" id="phoneNumber"
type="text" type="text"
@ -243,7 +266,6 @@
/> />
</div> </div>
<!-- Active Account (Checkbox) -->
<div class="form-check"> <div class="form-check">
<input <input
id="isActive" id="isActive"
@ -252,12 +274,11 @@
[(ngModel)]="selected.isActive" [(ngModel)]="selected.isActive"
name="isActive" name="isActive"
/> />
<label for="isActive" class="form-check-label">{{ <label for="isActive" class="form-check-label">
'Active' | abpLocalization {{ '::active' | abpLocalization }}
}}</label> </label>
</div> </div>
<!-- Lockout Enabled (Checkbox) -->
<div class="form-check"> <div class="form-check">
<input <input
id="lockoutEnabled" id="lockoutEnabled"
@ -266,14 +287,13 @@
[(ngModel)]="selected.lockoutEnabled" [(ngModel)]="selected.lockoutEnabled"
name="lockoutEnabled" name="lockoutEnabled"
/> />
<label for="lockoutEnabled" class="form-check-label">{{ <label for="lockoutEnabled" class="form-check-label">
'Lockout Enabled' | abpLocalization {{ '::lockoutEnabled' | abpLocalization }}
}}</label> </label>
</div> </div>
</ng-template> </ng-template>
</li> </li>
<!-- Roles Tab -->
<li ngbNavItem> <li ngbNavItem>
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a> <a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a>
<ng-template ngbNavContent> <ng-template ngbNavContent>
@ -296,14 +316,17 @@
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div> <div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div>
<div class="mt-3"> <div class="mt-3">
<button type="submit" class="btn btn-primary" [disabled]="userForm.invalid">Save</button> <button type="submit" class="btn btn-primary" [disabled]="userForm.invalid">
{{ '::save' | abpLocalization }}
</button>
</div> </div>
</form> </form>
</ng-template> </ng-template>
<ng-template #abpFooter> <ng-template #abpFooter>
<button type="button" class="btn btn-outline-primary" abpClose> <button type="button" class="btn btn-outline-primary" abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }} {{ '::cancel' | abpLocalization }}
</button> </button>
<!-- <abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{ <!-- <abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization 'AbpIdentity::Save' | abpLocalization

View File

@ -59,6 +59,7 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { PaginatorModule } from 'primeng/paginator'; import { PaginatorModule } from 'primeng/paginator';
import { TagModule } from 'primeng/tag'; // For active/inactive status import { TagModule } from 'primeng/tag'; // For active/inactive status
import { SplitButtonModule } from 'primeng/splitbutton'; import { SplitButtonModule } from 'primeng/splitbutton';
import { SharedModule } from 'src/app/shared/shared.module';
@Component({ @Component({
selector: 'app-custom-users', selector: 'app-custom-users',
@ -77,7 +78,7 @@ import { SplitButtonModule } from 'primeng/splitbutton';
CoreModule, CoreModule,
NgbNavModule, NgbNavModule,
PaginatorModule, PaginatorModule,
TagModule,SplitButtonModule TagModule,SplitButtonModule,SharedModule
], ],
templateUrl: './custom-users.component.html', templateUrl: './custom-users.component.html',
providers: [ providers: [

View File

@ -20,3 +20,4 @@
</div> </div>
</div> </div>

View File

@ -5,6 +5,126 @@
"Menu:Home": "Home", "Menu:Home": "Home",
"Welcome": "Welcome", "Welcome": "Welcome",
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.", "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
"PatientHeader": "Patient Records" "PatientHeader": "Patient Records",
"AbpIdentity::Roles": "Roles",
"addRoles": "Add Roles",
"AbpIdentity::RoleName": "Role Name",
"AbpIdentity::Actions": "Actions",
"AbpIdentity::Edit": "Edit",
"AbpIdentity::Delete": "Delete",
"AbpIdentity::Permissions": "Permissions",
"AbpIdentity::NewRole": "New Role",
"AbpIdentity::Name": "Name",
"AbpIdentity::NameIsRequired": "Name is required",
"AbpIdentity::Default": "Default",
"AbpIdentity::Public": "Public",
"AbpIdentity::Save": "Save",
"AbpIdentity::Cancel": "Cancel",
"users": "Users",
"addUser": "Add User",
"pagerSearch": "Search...",
"username": "Username",
"firstName": "First Name",
"lastName": "Last Name",
"email": "Email",
"phoneNumber": "Phone Number",
"status": "Status",
"actions": "Actions",
"active": "Active",
"inactive": "Inactive",
"editUser": "Edit User",
"newUser": "New User",
"userInformations": "User Informations",
"userName": "User Name",
"userNameIsRequired": "User Name is required",
"password": "Password",
"passwordIsRequired": "Password is required",
"validEmailIsRequired": "Valid Email is required",
"lockoutEnabled": "Lockout Enabled",
"save": "Save",
"cancel": "Cancel",
"roles": "Roles",
"edit": "Edit",
"create": "Create",
"gender": "Gender",
"male": "Male",
"female": "Female",
"mobileNo": "Mobile No",
"address": "Address",
"emailId": "Email ID",
"dateOfBirth": "Date of Birth",
"consultingDoctor": "Consulting Doctor",
"dateOfAppointment": "Date of Appointment",
"timeOfAppointment": "Time Of Appointment",
"injuryCondition": "Injury/Condition",
"insuranceProvider": "Insurance Provider",
"appointmentStatus": "Appointment Status",
"visitType": "Visit Type",
"paymentStatus": "Payment Status",
"notes": "Notes",
"selectDoctor": "Select Doctor",
"firstNameRequired": "First Name is required.",
"lastNameRequired": "Last Name is required.",
"genderRequired": "Please select a gender.",
"mobileNoRequired": "Mobile number is required.",
"addressRequired": "Address is required.",
"dobRequired": "DOB is required.",
"mobileNoInvalid": "Enter a valid 10-digit mobile number.",
"minLength": "Minimum {length} characters required.",
"maxLength": "Maximum {length} characters allowed.",
"emailRequired": "Email address is required.",
"emailInvalid": "Enter a valid email address.",
"appointmentList": "Appointment List",
"searchKeyword": "Search keyword",
"refresh": "Refresh",
"addAppointment": "Add Appointment",
"export": "Export",
"name": "Name",
"doctor": "Doctor",
"doctorPrefix": "Dr.",
"date": "Date",
"time": "Time",
"appointment": "Appointment",
"mobile": "Mobile",
"mobileRequired": "Mobile is required.",
"specialization": "Specialization",
"degree": "Degree",
"experience": "Experience",
"years": "Years",
"consultationFee": "Consultation Fee",
"clinicLocation": "Clinic Location",
"rating": "Rating",
"availability": "Availability",
"selectAvailability": "Select Availability",
"description": "Description",
"departmentList": "Department List",
"addDepartment": "Add Department",
"departmentNumber": "Department Number",
"departmentName": "Department Name",
"departmentHead": "Department Head",
"department": "Department",
"close": "Close",
"departmentNo": "Department No",
"departmentNoRequired": "Department No is required.",
"departmentNameRequired": "Department Name is required.",
"departmentDate": "Department Date",
"doctorList": "Doctor List"
} }
} }