Skip to content

Commit 2754e58

Browse files
vdamovVladimir Damov
authored and
Vladimir Damov
committed
Adding toastr and documentation.
1 parent a5862e9 commit 2754e58

21 files changed

+175
-103
lines changed

angular-fundamentals/Project Defense/Quinder/README.md

+20-17
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
11
# Quinder
22

3-
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.3.6.
3+
**Quinder** is a dating application designed for people who are looking for a partner. In **Quinder** you can choose people you like by swiping and if they like you too, you can start a chat.
44

5-
## Development server
5+
Project URL - [http://quinder-8e428.firebaseapp.com/](http://quinder-8e428.firebaseapp.com/)
66

7-
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
7+
**Guest** privileges
88

9-
## Code scaffolding
9+
- Can view the home page.
10+
- Can Login/Register.
1011

11-
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12+
**User** privileges
1213

13-
## Build
14+
- Can swipe for a match.
15+
- Can chat with a matched partner.
16+
- Can delete their own messages in the chat.
17+
- Can view their own profile.
18+
- Can edit their own profile.
19+
- Can use the side navigation.
1420

15-
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
21+
**Admin** privileges
1622

17-
## Running unit tests
23+
- Can swipe for a match.
24+
- Can chat with a matched partner.
25+
- Can delete their own messages in the chat.
26+
- Has access to the Admin Panel.
27+
- Can view all profiles.
28+
- Can edit all profiles.
29+
- Can use the side navigation.
1830

19-
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20-
21-
## Running end-to-end tests
22-
23-
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
24-
25-
## Further help
26-
27-
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

angular-fundamentals/Project Defense/Quinder/angular.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"src/assets"
2424
],
2525
"styles": [
26-
"src/styles.css"
26+
"src/styles.css",
27+
"node_modules/ngx-toastr/toastr.css"
2728
],
2829
"scripts": [],
2930
"es5BrowserSupport": true
@@ -133,4 +134,4 @@
133134
}
134135
},
135136
"defaultProject": "Quinder"
136-
}
137+
}

angular-fundamentals/Project Defense/Quinder/package-lock.json

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

angular-fundamentals/Project Defense/Quinder/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@angular/router": "~7.2.0",
2525
"core-js": "^2.5.4",
2626
"hammerjs": "^2.0.8",
27+
"ngx-toastr": "^10.0.2",
2728
"rxjs": "~6.3.3",
2829
"tslib": "^1.9.0",
2930
"zone.js": "~0.8.26"

angular-fundamentals/Project Defense/Quinder/src/app/app.component.html

+2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
class="example-sidenav-container">
55
<mat-sidenav #sidenav [fixedInViewport]="mobileQuery.matches" [mode]="mobileQuery.matches ? 'over' : 'side'"
66
fixedTopGap="70" position="end">
7+
78
<app-sidenav (sidenavToggle)="sidenav.toggle()" *ngIf="authService.isAuthenticated()"></app-sidenav>
89
</mat-sidenav>
910
<mat-sidenav-content>
11+
1012
<router-outlet></router-outlet>
1113
</mat-sidenav-content>
1214
</mat-sidenav-container>

angular-fundamentals/Project Defense/Quinder/src/app/app.component.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import {AuthService} from './core/services/auth.service';
1010
export class AppComponent implements OnDestroy {
1111
title = 'Quinder';
1212
mobileQuery: MediaQueryList;
13-
1413
private mobileQueryListener: () => void;
1514

16-
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, private authService: AuthService) {
15+
constructor(
16+
changeDetectorRef: ChangeDetectorRef,
17+
media: MediaMatcher,
18+
public authService: AuthService) {
19+
1720
this.mobileQuery = media.matchMedia('(max-width: 600px)');
1821
this.mobileQueryListener = () => changeDetectorRef.detectChanges();
1922
this.mobileQuery.addListener(this.mobileQueryListener);

angular-fundamentals/Project Defense/Quinder/src/app/app.module.ts

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
1313
import {ReactiveFormsModule} from '@angular/forms';
1414
import {HttpClientModule} from '@angular/common/http';
1515
import {MaterialModule} from './material.module';
16+
import {ToastrModule} from 'ngx-toastr';
1617

1718
@NgModule({
1819
declarations: [
@@ -25,6 +26,9 @@ import {MaterialModule} from './material.module';
2526
BrowserModule,
2627
AppRoutingModule,
2728
BrowserAnimationsModule,
29+
ToastrModule.forRoot({
30+
positionClass: 'toast-bottom-right',
31+
}),
2832
HttpClientModule,
2933
ReactiveFormsModule,
3034
FlexLayoutModule,
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1-
import {Component, OnInit} from '@angular/core';
1+
import {Component, OnDestroy, OnInit} from '@angular/core';
22
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
33
import {AuthService} from '../../../core/services/auth.service';
44
import {Router} from '@angular/router';
5+
import {Subscription} from 'rxjs';
6+
import {ToastrService} from 'ngx-toastr';
57

68
@Component({
79
selector: 'app-login',
810
templateUrl: './login.component.html',
911
styleUrls: ['./login.component.css']
1012
})
11-
export class LoginComponent implements OnInit {
13+
export class LoginComponent implements OnInit, OnDestroy {
1214
loginForm: FormGroup;
15+
private subscription: Subscription = new Subscription();
1316

1417
constructor(
1518
private fb: FormBuilder,
1619
private authService: AuthService,
17-
private router: Router
20+
private router: Router,
21+
private toastr: ToastrService
1822
) {
1923
}
2024

@@ -26,10 +30,14 @@ export class LoginComponent implements OnInit {
2630
}
2731

2832
login() {
29-
this.authService.login(this.loginForm.value).subscribe((user) => {
30-
console.log(user);
33+
this.subscription.add(this.authService.login(this.loginForm.value).subscribe((user) => {
34+
this.toastr.success(`Welcome back, ${user.username}!`, 'Logged In');
3135
this.router.navigate(['match']);
32-
});
36+
}));
37+
}
38+
39+
ngOnDestroy(): void {
40+
this.subscription.unsubscribe();
3341
}
3442

3543
}

angular-fundamentals/Project Defense/Quinder/src/app/components/authentication/register/register.component.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
import {Component, OnInit} from '@angular/core';
1+
import {Component, OnDestroy, OnInit} from '@angular/core';
22
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
3-
import {Observable} from 'rxjs';
3+
import {Observable, Subscription} from 'rxjs';
44
import {map, startWith} from 'rxjs/operators';
55
import {AuthService} from '../../../core/services/auth.service';
66
import {Router} from '@angular/router';
7+
import {ToastrService} from 'ngx-toastr';
78

89

910
@Component({
1011
selector: 'app-register',
1112
templateUrl: './register.component.html',
1213
styleUrls: ['./register.component.css']
1314
})
14-
export class RegisterComponent implements OnInit {
15+
export class RegisterComponent implements OnInit, OnDestroy {
1516
registerForm: FormGroup;
1617
filteredOptions: Observable<string[]>;
18+
private subscription: Subscription = new Subscription();
1719
private readonly imagePattern = /^(http:\/\/|https:\/\/).+$/;
1820
private cities: string[] = [
1921
'Sofia',
@@ -41,7 +43,8 @@ export class RegisterComponent implements OnInit {
4143
constructor(
4244
private fb: FormBuilder,
4345
private authService: AuthService,
44-
private router: Router
46+
private router: Router,
47+
private toastr: ToastrService
4548
) {
4649
}
4750

@@ -66,9 +69,10 @@ export class RegisterComponent implements OnInit {
6669
}
6770

6871
register() {
69-
this.authService.signUp(this.registerForm.value).subscribe(() => {
72+
this.subscription.add(this.authService.signUp(this.registerForm.value).subscribe(() => {
73+
this.toastr.success(`You can login with your credentials.`, 'Successful registration');
7074
this.router.navigate(['/login']);
71-
});
75+
}));
7276
}
7377

7478
private _filter(value: object): string[] {
@@ -78,4 +82,8 @@ export class RegisterComponent implements OnInit {
7882
return this.cities.filter(option => option.toLowerCase().includes(filterValue));
7983
}
8084

85+
ngOnDestroy(): void {
86+
this.subscription.unsubscribe();
87+
}
88+
8189
}
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,50 @@
1-
import {AfterViewChecked, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
1+
import {AfterViewChecked, Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
22
import {ActivatedRoute} from '@angular/router';
33
import {FormBuilder, FormGroup} from '@angular/forms';
44
import {MessageService} from '../../../core/services/message.service';
55
import {IMessage} from '../../shared/interfaces/message.interface';
66
import {IUser} from '../../shared/interfaces/user.interface';
77
import {UserService} from '../../../core/services/user.service';
8+
import {Subscription} from 'rxjs';
89

910
@Component({
1011
selector: 'app-conversation',
1112
templateUrl: './conversation.component.html',
1213
styleUrls: ['./conversation.component.css']
1314
})
14-
export class ConversationComponent implements OnInit, AfterViewChecked {
15+
export class ConversationComponent implements OnInit, AfterViewChecked, OnDestroy {
1516
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
16-
private messageForm: FormGroup;
17-
private readonly matchId: string;
17+
public messageForm: FormGroup;
18+
public allMessages: IMessage[];
1819
private userId: string;
19-
private allMessages: IMessage[];
20+
private matchId: string;
2021
private user: IUser;
2122
private partner: IUser;
23+
private subscription: Subscription = new Subscription();
2224

2325
constructor(
2426
private route: ActivatedRoute,
2527
private fb: FormBuilder,
2628
private messageService: MessageService,
2729
private userService: UserService
2830
) {
29-
this.matchId = this.route.snapshot.paramMap.get('id');
3031
this.userId = localStorage.getItem('userId');
31-
32-
this.userService.getUserById(this.route.snapshot.paramMap.get('partnerId')).subscribe((partner) => this.partner = partner);
33-
this.userService.getUserById(this.userId).subscribe((user) => this.user = user);
34-
3532
this.messageForm = fb.group({
3633
content: [null]
3734
});
3835
}
3936

4037
ngOnInit() {
41-
this.getAllMessages();
42-
this.messageService.refreshNeeded$.subscribe(() => {
38+
this.route.params.subscribe((params) => {
39+
this.matchId = params.id;
4340
this.getAllMessages();
4441
});
42+
this.subscription.add(this.userService.getUserById(this.userId).subscribe((user) => this.user = user));
43+
this.getAllMessages();
44+
this.subscription.add(this.messageService.refreshNeeded$.subscribe(() => {
45+
this.getAllMessages();
46+
}));
47+
4548
}
4649

4750
ngAfterViewChecked() {
@@ -52,23 +55,29 @@ export class ConversationComponent implements OnInit, AfterViewChecked {
5255
try {
5356
this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
5457
} catch (err) {
58+
console.log(err);
5559
}
5660
}
5761

5862
getAllMessages() {
59-
this.messageService.getAllMessages(this.matchId).subscribe((messages: IMessage[]) => {
63+
this.subscription.add(this.userService.getUserById(this.route.snapshot.paramMap.get('partnerId')).subscribe((partner) => this.partner = partner));
64+
this.subscription.add(this.messageService.getAllMessages(this.matchId).subscribe((messages: IMessage[]) => {
6065
this.allMessages = messages;
61-
});
66+
}));
6267
}
6368

6469
addMessage() {
6570
const content = this.messageForm.get('content').value;
66-
this.messageService.postMessage(this.matchId, this.userId, content).subscribe(() => {
71+
this.subscription.add(this.messageService.postMessage(this.matchId, this.userId, content).subscribe(() => {
6772
this.messageForm.reset();
68-
});
73+
}));
6974
}
7075

7176
deleteMessage(messageId: string) {
72-
this.messageService.deleteMessage(messageId).subscribe();
77+
this.subscription.add(this.messageService.deleteMessage(messageId).subscribe());
78+
}
79+
80+
ngOnDestroy(): void {
81+
this.subscription.unsubscribe();
7382
}
7483
}

0 commit comments

Comments
 (0)