diff options
Diffstat (limited to 'frontend/src/app/_pages/profile')
4 files changed, 371 insertions, 0 deletions
diff --git a/frontend/src/app/_pages/profile/profile.component.css b/frontend/src/app/_pages/profile/profile.component.css new file mode 100644 index 00000000..5565d105 --- /dev/null +++ b/frontend/src/app/_pages/profile/profile.component.css @@ -0,0 +1,44 @@ +body{margin-top:20px; +background-color:#f2f6fc; +color:#69707a; +} +.img-account-profile { + height: 10rem; + border: 1px solid lightgray; +} +.rounded-circle { + border-radius: 50% !important; +} +.card .card-header { + font-weight: 500; +} +.card-header:first-child { + border-radius: 0.35rem 0.35rem 0 0; +} +.card-header { + padding: 1rem 1.35rem; + margin-bottom: 0; + background-color: rgba(33, 40, 50, 0.03); + border-bottom: 1px solid rgba(33, 40, 50, 0.125); +} +.form-control, .dataTable-input { + display: block; + width: 100%; + padding: 0.875rem 1.125rem; + font-size: 0.875rem; + font-weight: 400; + line-height: 1; + color: #69707a; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #c5ccd6; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 0.35rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +.selectedPicture { + border: 2px solid darkgray; +} diff --git a/frontend/src/app/_pages/profile/profile.component.html b/frontend/src/app/_pages/profile/profile.component.html new file mode 100644 index 00000000..d082a003 --- /dev/null +++ b/frontend/src/app/_pages/profile/profile.component.html @@ -0,0 +1,137 @@ +<div class="container-xl px-4 mt-1"> + <hr class="mt-0 mb-4"> + + <div class="row"> + <div class="col-xl-4"> + <!-- Profile picture card--> + <div class="card mb-4 mb-xl-0"> + <div class="card-header">Moj profil</div> + <div class="card-body text-center"> + <div class=" image d-flex flex-column justify-content-center align-items-center"> + <!-- Profile picture image--> + <img class="img-account-profile rounded-circle mb-2" src="{{this.photoPath}}" alt="profilePicture"> + <!-- User's info --> + <span>@ {{this.user.username}}</span> + <span class="mt-3" style="font-weight: bold;">{{this.user.firstName}} {{this.user.lastName}}</span> + </div> + </div> + </div> + + <!-- Password Change card --> + <div class="card mt-3"> + <div class="card-header">Promena lozinke</div> + <div class="card-body"> + <form> + <div class="row"> + <!-- Form Row--> + <div class="row gx-3 mb-3"> + <!-- Form Group (password)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputPassword">Važeća lozinka</label> + <input class="form-control" id="inputPassword" name="inputPassword" type="password" [(ngModel)]="this.oldPass" placeholder="Trenutna lozinka"> + <small *ngIf="wrongPassBool" class="form-text text-danger">Neispravna lozinka.</small> + </div> + <!-- Form Group (new password)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputNewPassword">Nova lozinka</label> + <input class="form-control" id="inputNewPassword" name="inputNewPassword" type="password" [(ngModel)]="this.newPass1" placeholder="Ukucaj novu lozinku"> + <small *ngIf="wrongNewPassBool" class="form-text text-danger">Lozinke se ne podudaraju.</small> + </div> + </div> + + <!-- Form Row--> + <div class="row gx-3 mb-3"> + <div class="col-md-6"> + <div class="col text-center"> + <!-- Save changes button--> + <button class="btn btn-primary text-center mt-4" type="button" (click)="savePasswordChanges()">Promeni lozinku</button> + </div> + </div> + <!-- Form Group (new password again)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputNewPasswordAgain">Ponovo nova lozinka</label> + <input class="form-control" id="inputNewPasswordAgain" name="inputNewPasswordAgain" type="password" [(ngModel)]="this.newPass2" placeholder="Ukucaj novu lozinku"> + <small *ngIf="wrongNewPassBool" class="form-text text-danger">Lozinke se ne podudaraju.</small> + </div> + </div> + </div> + </form> + </div> + </div> + </div> + + <!-- Info Change card --> + <div class="col-xl-8"> + <!-- Account details card--> + <div class="card mb-4"> + <div class="card-header">Osnovni podaci</div> + <div class="card-body"> + <form> + <!-- Form Row--> + <div class="row gx-3 mb-3"> + <!-- Form Group (username)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputUsername">Korisničko ime (kako će ostali korisnici videti tvoje ime)</label> + <input class="form-control" id="inputUsername" name="inputUsername" type="text" [(ngModel)]="this.username"> + </div> + <!-- Form Group (email address)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputEmailAddress">Email adresa</label> + <input class="form-control" id="inputEmailAddress" name="inputEmailAddress" type="email" [(ngModel)]="this.email"> + </div> + </div> + + <!-- Form Row--> + <div class="row gx-3 mb-3"> + <!-- Form Group (first name)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputFirstName">Ime</label> + <input class="form-control" id="inputFirstName" name="inputFirstName" type="text" [(ngModel)]="this.firstName"> + </div> + <!-- Form Group (last name)--> + <div class="col-md-6"> + <label class="small mb-1" for="inputLastName">Prezime</label> + <input class="form-control" id="inputLastName" name="inputLastName" type="text" [(ngModel)]="this.lastName"> + </div> + </div> + + <div> + <label class="small mt-2 mb-3">Kliknite na sliku kako biste je odabrali za profilnu:</label> + + <div class="container"> + <div class="card-group"> + <!--bootstrap card with 3 horizontal images--> + <div class="row overflow-auto" style="max-height: 200px;"> + <div class="card col-md-3" *ngFor="let picture of this.pictures" (click)="this.photoId = picture.photoId.toString()" + [ngClass]="{'selectedPicture': this.photoId == picture.photoId.toString()}"> + <img src="{{picture.path}}"> + </div> + </div> + </div> + </div> + </div> + + <div class="row mt-5"> + <div class="col text-center"> + <!-- Save changes button--> + <button class="btn btn-primary text-center" type="button" (click)="saveInfoChanges()">Sačuvaj izmene</button> + </div> + </div> + </form> + </div> + </div> + </div> + </div> + + + <div class="row"> + <div class="col-xl-4"> + + </div> + </div> + + + + + +</div>
\ No newline at end of file diff --git a/frontend/src/app/_pages/profile/profile.component.spec.ts b/frontend/src/app/_pages/profile/profile.component.spec.ts new file mode 100644 index 00000000..e88012e7 --- /dev/null +++ b/frontend/src/app/_pages/profile/profile.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture<ProfileComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ProfileComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_pages/profile/profile.component.ts b/frontend/src/app/_pages/profile/profile.component.ts new file mode 100644 index 00000000..3e9a0d11 --- /dev/null +++ b/frontend/src/app/_pages/profile/profile.component.ts @@ -0,0 +1,165 @@ +import { Component, OnInit } from '@angular/core'; +import User from 'src/app/_data/User'; +import { UserInfoService } from 'src/app/_services/user-info.service'; +import { AuthService } from 'src/app/_services/auth.service'; +import { Router } from '@angular/router'; +import { PICTURES } from 'src/app/_data/ProfilePictures'; +import { Picture } from 'src/app/_data/ProfilePictures'; +import shared from '../../Shared'; + + +@Component({ + selector: 'app-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.css'] +}) +export class ProfileComponent implements OnInit { + + user: User = new User(); + pictures: Picture[] = PICTURES; + + username: string = ''; + email: string = ''; + firstName : string = ''; + lastName : string = ''; + oldPass: string = ''; + newPass1: string = ''; + newPass2: string = ''; + photoId: string = ''; + photoPath: string = ''; + + wrongPassBool: boolean = false; + wrongNewPassBool: boolean = false; + + wrongFirstNameBool: boolean = false; + wrongLastNameBool: boolean = false; + wrongUsernameBool: boolean = false; + wrongEmailBool: boolean = false; + wrongOldPassBool: boolean = false; + wrongNewPass1Bool: boolean = false; + wrongNewPass2Bool: boolean = false; + + pattName: RegExp = /^[a-zA-ZšŠđĐčČćĆžŽ]+([ \-][a-zA-ZšŠđĐčČćĆžŽ]+)*$/; + pattUsername: RegExp = /^[a-zA-Z0-9]{6,18}$/; + pattTwoSpaces: RegExp = / /; + pattEmail: RegExp = /^[a-zA-Z0-9]+([\.\-\+][a-zA-Z0-9]+)*\@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$/; + pattPassword: RegExp = /.{6,30}$/; + + + constructor(private userInfoService: UserInfoService, private authService: AuthService, private router: Router) { } + + ngOnInit(): void { + this.userInfoService.getUserInfo().subscribe((response) => { + + this.user = response; + shared.photoId = this.user.photoId; + + this.username = this.user.username; + this.email = this.user.email; + this.firstName = this.user.firstName; + this.lastName = this.user.lastName; + this.photoId = this.user.photoId; + + for (let i = 0; i < this.pictures.length; i++) { + if (this.pictures[i].photoId.toString() === this.photoId) { + this.photoPath = this.pictures[i].path; + break; + } + } + console.log(this.user); + }); + } + + saveInfoChanges() { + let editedUser: User = { + _id: this.user._id, + username: this.username, + email: this.email, + password: this.user.password, + firstName: this.firstName, + lastName: this.lastName, + photoId: this.photoId + } + + this.userInfoService.changeUserInfo(editedUser).subscribe((response: any) =>{ + if (this.user.username != editedUser.username) { //promenio username, ide logout + this.user = editedUser; + alert("Nakon promene korisničkog imena, moraćete ponovo da se ulogujete."); + this.authService.logOut(); + this.router.navigate(['']); + return; + } + this.user = editedUser; + console.log(this.user); + this.resetInfo(); + }, (error: any) =>{ + if (error.error == "Username already exists!") { + alert("Ukucano korisničko ime je već zauzeto!\nIzaberite neko drugo."); + (<HTMLSelectElement>document.getElementById("inputUsername")).focus(); + //poruka obavestenja ispod inputa + this.resetInfo(); + } + }); + } + + savePasswordChanges() { + if (this.newPass1 == '' && this.newPass2 == '') //ne zeli da promeni lozinku + return; + console.log("zeli da promeni lozinku"); + + if (this.newPass1 != this.newPass2) { //netacno ponovio novu lozinku + this.wrongNewPassBool = true; + this.resetNewPassInputs(); + console.log("Netacno ponovljena lozinka"); + return; + } + + this.wrongPassBool = false; + this.wrongNewPassBool = false; + + let passwordArray: string[] = [this.oldPass, this.newPass1]; + this.userInfoService.changeUserPassword(passwordArray).subscribe((response: any) => { + console.log("PROMENIO LOZINKU"); + this.resetNewPassInputs(); + alert("Nakon promene lozinke, moraćete ponovo da se ulogujete."); + this.authService.logOut(); + this.router.navigate(['']); + }, (error: any) => { + console.log("error poruka: ", error.error); + if (error.error == 'Wrong old password!') { + this.wrongPassBool = true; + (<HTMLSelectElement>document.getElementById("inputPassword")).focus(); + return; + } + else if (error.error == 'Identical password!') { + alert("Stara i nova lozinka su identične."); + this.resetNewPassInputs(); + (<HTMLSelectElement>document.getElementById("inputNewPassword")).focus(); + return; + } + }); + } + + resetNewPassInputs() { + this.newPass1 = ''; + this.newPass2 = ''; + } + + resetInfo() { + this.username = this.user.username; + this.email = this.user.email; + this.firstName = this.user.firstName; + this.lastName = this.user.lastName; + this.photoId = this.user.photoId; + + for (let i = 0; i < this.pictures.length; i++) { + if (this.pictures[i].photoId.toString() === this.photoId) { + this.photoPath = this.pictures[i].path; + break; + } + } + shared.photoId = this.photoId; + } + + +} |