Skip to content

Commit

Permalink
Interview status with feedback and reschedule option
Browse files Browse the repository at this point in the history
  • Loading branch information
shivaneej committed Jul 13, 2020
1 parent 122fecc commit 4c4170f
Show file tree
Hide file tree
Showing 17 changed files with 346 additions and 31 deletions.
8 changes: 8 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { EditUserGuard } from './services/guards/edit-user-guard.service';
import { ViewCandidateGuard } from './services/guards/view-candidate-guard.service';
import { EditCandidateGuard } from './services/guards/edit-candidate-guard.service';
import { InterviewCardComponent } from './interview-card/interview-card.component';
import { RescheduleComponent } from './interview-form/reschedule/reschedule.component';
import { FeedbackComponent } from './feedback/feedback.component';


@NgModule({
Expand All @@ -50,6 +52,8 @@ import { InterviewCardComponent } from './interview-card/interview-card.componen
EditUserComponent,
StatisticsCardComponent,
InterviewCardComponent,
RescheduleComponent,
FeedbackComponent,
],
imports: [
BrowserModule,
Expand Down Expand Up @@ -81,6 +85,10 @@ import { InterviewCardComponent } from './interview-card/interview-card.componen
multi: true,
}
],
entryComponents: [
FeedbackComponent,
RescheduleComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
4 changes: 2 additions & 2 deletions src/app/dashboard/dashboard.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

<mat-divider *ngIf="showInterviews && showStatistics"></mat-divider>

<mat-grid-list cols="3" rowHeight="250px" *ngIf="showInterviews">
<mat-grid-list cols="3" rowHeight="300px" *ngIf="showInterviews">
<mat-grid-tile *ngFor="let interview of interviews">
<interview-card [interview]="interview">
<interview-card [interview]="interview" [currentUser]="user.role.roleString">
</interview-card>
</mat-grid-tile>
</mat-grid-list>
1 change: 0 additions & 1 deletion src/app/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export class DashboardComponent implements OnInit {
if(this.showInterviews)
this.interviewService.fetchInterviews().subscribe(interviews => {
this.interviews = interviews;
console.log(this.interviews);
});
}

Expand Down
11 changes: 11 additions & 0 deletions src/app/feedback/feedback.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div mat-dialog-content>
<form [formGroup] = "form" (ngSubmit)="save()">
<h1>Feedback</h1>
<mat-form-field appearance="outline">
<mat-label>Give feedback</mat-label>
<textarea matInput required formControlName="feedback"></textarea>
</mat-form-field>
<mat-error *ngIf="feedback.errors?.required">Feedback is required</mat-error>
<button mat-raised-button color="primary" [disabled]="!form.valid" (click)="save()" class="full-width-button">Save</button>
</form>
</div>
7 changes: 7 additions & 0 deletions src/app/feedback/feedback.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
div {
width: 500px;
}

mat-form-field {
display: block;
}
25 changes: 25 additions & 0 deletions src/app/feedback/feedback.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { FeedbackComponent } from './feedback.component';

describe('FeedbackComponent', () => {
let component: FeedbackComponent;
let fixture: ComponentFixture<FeedbackComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FeedbackComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(FeedbackComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
40 changes: 40 additions & 0 deletions src/app/feedback/feedback.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Component, Inject } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

@Component({
selector: 'feedback',
templateUrl: './feedback.component.html',
styleUrls: ['./feedback.component.scss']
})
export class FeedbackComponent {

interview;
form;
constructor(
public dialogRef: MatDialogRef<FeedbackComponent>,
private builder : FormBuilder,
@Inject(MAT_DIALOG_DATA) public data: any) {
this.interview = {...data};
this.form = builder.group({
feedback : [this.interview.feedback, [Validators.required]]
});
}

save(){
if(this.feedback.value.trim() !== this.interview.feedback.trim()) {
this.interview.feedback = this.feedback.value;
this.dialogRef.close({ event: 'Feedback', data: this.interview });
} else
this.dialogRef.close({ event: 'Feedback', data: null });
}

closeDialog(){
this.dialogRef.close({event: 'Cancel'});
}

get feedback() {
return this.form.get('feedback');
}

}
15 changes: 5 additions & 10 deletions src/app/interview-card/interview-card.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@
</div>
</mat-card-content>
<mat-divider></mat-divider>
<!-- <mat-card-actions>
<mat-button-toggle-group #group="matButtonToggleGroup" [(value)]="statsMode">
<mat-button-toggle value="overall">
Overall
</mat-button-toggle>
<mat-button-toggle value="user">
My Stats
</mat-button-toggle>
</mat-button-toggle-group>
</mat-card-actions> -->
<mat-card-actions>
<button [style.visibility]="showAction == 2 ? 'visible' : 'hidden'" mat-button color="accent">Accept</button>
<button (click)="openDialog(1)" [style.visibility]="showAction == 2 ? 'visible' : 'hidden'" mat-button color="accent">Reschedule</button>
<button (click)="openDialog(2)" [style.visibility]="showAction == 1 ? 'visible' : 'hidden'" mat-button color="accent">Give Feedback</button>
</mat-card-actions>
</mat-card>
2 changes: 1 addition & 1 deletion src/app/interview-card/interview-card.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
width: 100%;
}
mat-card {
// max-width: 300px;

margin: 2em;

table {
Expand Down
76 changes: 67 additions & 9 deletions src/app/interview-card/interview-card.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { Component, OnInit, Input } from '@angular/core';
import { InterviewStatus } from './interview-status';
import { MatDialog } from '@angular/material/dialog';
import { RescheduleComponent } from '../interview-form/reschedule/reschedule.component';
import { FeedbackComponent } from '../feedback/feedback.component';
import { MatSnackBar } from '@angular/material/snack-bar';

enum Footer {
None,
Feedback,
Actions
}

@Component({
selector: 'interview-card',
Expand All @@ -9,27 +19,75 @@ import { InterviewStatus } from './interview-status';
export class InterviewCardComponent implements OnInit {

@Input('interview') interview;
@Input('currentUser') currentUser;
status;
statusColor;
date;
startTime;
endTime;
constructor() { }
showAction : Footer ;
constructor(public dialog: MatDialog, private snackbar : MatSnackBar) { }

openDialog(value : number) {
let dialogRef;
if(value === 1)
dialogRef = this.dialog.open(RescheduleComponent, { data : this.interview });
else if(value === 2)
dialogRef = this.dialog.open(FeedbackComponent, { data : this.interview });


dialogRef.afterClosed().subscribe(result => {
if(result?.event == 'Feedback'){
this.saveFeedback(result.data);
} else if(result?.event == 'Reschedule'){
this.reschedule(result.data);
}
});
}

ngOnInit(): void {
let dateObject = new Date(this.interview.start_time);
this.date = dateObject.toDateString();
this.startTime = dateObject.toLocaleString('en-US', { hour: '2-digit', minute: 'numeric', hour12: true });
this.endTime = new Date(this.interview.end_time).toLocaleString('en-US', { hour: '2-digit', minute: 'numeric', hour12: true });
if(this.interview.recruiter_approved) {
let intStatus = (this.interview.interviewer_approved) ? InterviewStatus.Confirmed : InterviewStatus.Pending;
this.status = intStatus.message;
this.statusColor = intStatus.color;
} else {
this.status = InterviewStatus.Reschedule.message; // Need clarification
this.statusColor = InterviewStatus.Reschedule.color;
let otherUser = (this.currentUser === 'Interviewer') ? 'Recruiter' : 'Interviewer';

let status = this.interview.status as string;
if(status.startsWith('BOTH')) { // Both have approved - option to update feedback AFTER endtime
this.status = InterviewStatus.Confirmed.message;
this.statusColor = InterviewStatus.Confirmed.color;
let endTimeObj = new Date(this.interview.end_time);
this.showAction = (this.currentUser === 'Interviewer' && (new Date()).valueOf() > endTimeObj.valueOf()) ? Footer.Feedback : Footer.None ;
} else if(status.startsWith(otherUser.toUpperCase())) { // Show accept/reschedule button
this.status = InterviewStatus.New.message;
this.statusColor = InterviewStatus.New.color;
this.showAction = Footer.Actions ;
} else { // Show no action
this.status = InterviewStatus.Pending.message;
this.statusColor = InterviewStatus.Pending.color;
this.showAction = Footer.None ;
}
}


saveFeedback(formData) {
console.log("Save " + JSON.stringify(formData));
if(formData !== null) {
// Method to update feedback
// this.interviewService.save(processedFormData);
this.snackbar.open("Feedback saved!", "Dismiss", {
duration: 2000,
});
}
}

reschedule(formData) {
console.log("Save " + JSON.stringify(formData));
if(formData !== null) {
// Method to update feedback
// this.interviewService.save(processedFormData);
this.snackbar.open("Reschedule requested", "Dismiss", {
duration: 2000,
});
}
}
}
6 changes: 3 additions & 3 deletions src/app/interview-card/interview-status.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export class InterviewStatus {
static readonly Confirmed = new InterviewStatus('Confirmed', '#8BC34A');
static readonly Pending = new InterviewStatus('Pending', '#FFC107');
static readonly Reschedule = new InterviewStatus('Reschedule', '#F44336');
static readonly Confirmed = new InterviewStatus('Confirmed', '#8BC34A'); // Both approved
static readonly New = new InterviewStatus('New', '#FFC107'); // Approved by current user, yet to be approved by the other person
static readonly Pending = new InterviewStatus('Pending', '#F44336');

// private to disallow creating other instances of this type
private constructor(public readonly message: string, public readonly color: any) {
Expand Down
33 changes: 33 additions & 0 deletions src/app/interview-form/reschedule/reschedule.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<mat-card>
<mat-card-content>
<form [formGroup] = "form" (ngSubmit)="save()">
<h2>Reschedule interview</h2>
<mat-form-field appearance="outline">
<mat-label>Choose a date</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepickerFilter]="filter" [matDatepicker]="datePicker" formControlName="date">
<mat-datepicker-toggle matSuffix [for]="datePicker"></mat-datepicker-toggle>
<mat-datepicker #datePicker></mat-datepicker>
</mat-form-field>

<mat-form-field appearance="outline">
<mat-label>Choose start time</mat-label>
<input matInput [ngxTimepicker]="startTimePicker" formControlName="startTime">
<ngx-material-timepicker #startTimePicker [disableAnimation]="true"
timepickerClass="timePicker"></ngx-material-timepicker>
<ngx-material-timepicker-toggle matSuffix [for]="startTimePicker"></ngx-material-timepicker-toggle>
</mat-form-field>

<mat-form-field appearance="outline">
<mat-label>Choose end time</mat-label>
<input matInput [ngxTimepicker]="endTimePicker" formControlName="endTime" [min]="startTime.value">
<ngx-material-timepicker #endTimePicker [disableAnimation]="true"
timepickerClass="timePicker"></ngx-material-timepicker>
<ngx-material-timepicker-toggle matSuffix [for]="endTimePicker"></ngx-material-timepicker-toggle>
</mat-form-field>
<mat-error *ngIf = "endTime.valid && form.invalid && form.errors?.invalidDuration">
End time should be greater than start time
</mat-error>
<button mat-raised-button color="primary" type="submit" [disabled]="!form.valid" class="full-width-button">Save</button>
</form>
</mat-card-content>
</mat-card>
21 changes: 21 additions & 0 deletions src/app/interview-form/reschedule/reschedule.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
mat-card {
max-width: 800px;
margin: 2em auto;
text-align: center;
padding: 2em 5em;
}

mat-form-field {
display: block;
}

.form-group {
display: flex;
mat-form-field {
margin-right: 0.5em;
box-sizing: border-box;
}
mat-form-field:last-of-type {
margin-right: 0em;
}
}
25 changes: 25 additions & 0 deletions src/app/interview-form/reschedule/reschedule.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { RescheduleComponent } from './reschedule.component';

describe('RescheduleComponent', () => {
let component: RescheduleComponent;
let fixture: ComponentFixture<RescheduleComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RescheduleComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(RescheduleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 4c4170f

Please sign in to comment.