diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2025-03-27 18:55:39 -0400 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2025-03-27 18:55:39 -0400 |
commit | d6f4aad157baad7d9b25d56ce056b80805e88f5f (patch) | |
tree | 1b4a3df94389afb1637ea59fe47ba3a327c89561 /ufund-ui/src | |
parent | 96f833352eff7b9428daf2add988ecd0a2b41d92 (diff) | |
parent | ddbd1cc688aa98fb275ad72a750fbaaf53e6c0ae (diff) | |
download | JellySolutions-d6f4aad157baad7d9b25d56ce056b80805e88f5f.tar.gz JellySolutions-d6f4aad157baad7d9b25d56ce056b80805e88f5f.tar.bz2 JellySolutions-d6f4aad157baad7d9b25d56ce056b80805e88f5f.zip |
Merge branch 'main' into css
Diffstat (limited to 'ufund-ui/src')
-rw-r--r-- | ufund-ui/src/app/app.component.ts | 8 | ||||
-rw-r--r-- | ufund-ui/src/app/components/cupboard/cupboard.component.ts | 58 | ||||
-rw-r--r-- | ufund-ui/src/app/components/dashboard/dashboard.component.ts | 20 | ||||
-rw-r--r-- | ufund-ui/src/app/components/funding-basket/funding-basket.component.ts | 122 | ||||
-rw-r--r-- | ufund-ui/src/app/components/home-page/home-page.component.ts | 10 | ||||
-rw-r--r-- | ufund-ui/src/app/components/login/login.component.ts | 14 | ||||
-rw-r--r-- | ufund-ui/src/app/components/need-list/need-list.component.ts | 212 | ||||
-rw-r--r-- | ufund-ui/src/app/components/need-page/need-page.component.ts | 38 | ||||
-rw-r--r-- | ufund-ui/src/app/models/Need.ts | 16 | ||||
-rw-r--r-- | ufund-ui/src/app/models/User.ts | 2 | ||||
-rw-r--r-- | ufund-ui/src/app/services/auth.service.ts | 57 | ||||
-rw-r--r-- | ufund-ui/src/app/services/cupboard.service.ts | 30 | ||||
-rw-r--r-- | ufund-ui/src/app/services/users.service.ts | 73 |
13 files changed, 331 insertions, 329 deletions
diff --git a/ufund-ui/src/app/app.component.ts b/ufund-ui/src/app/app.component.ts index 7dc8ffb..86717c4 100644 --- a/ufund-ui/src/app/app.component.ts +++ b/ufund-ui/src/app/app.component.ts @@ -1,7 +1,7 @@ import {Component, OnInit, Inject} from '@angular/core'; -import {UsersService} from './services/users.service'; import {BehaviorSubject} from 'rxjs'; import { DOCUMENT } from '@angular/common'; +import {AuthService} from './services/auth.service'; @Component({ selector: 'app-root', @@ -14,16 +14,16 @@ export class AppComponent implements OnInit { currentUser$: BehaviorSubject<string> = new BehaviorSubject<string>("Logged out."); constructor( - private userService: UsersService, + private authService: AuthService, @Inject(DOCUMENT) private document: Document ) {} reloadPage() { this.document.defaultView?.location.reload(); - } + } ngOnInit() { - this.userService.getCurrentUserSubject().subscribe(r => { + this.authService.getCurrentUserSubject().subscribe(r => { this.currentUser$?.next(r ? "Logged in as " + r.username : "Logged out." diff --git a/ufund-ui/src/app/components/cupboard/cupboard.component.ts b/ufund-ui/src/app/components/cupboard/cupboard.component.ts index 24b3e2d..a812baf 100644 --- a/ufund-ui/src/app/components/cupboard/cupboard.component.ts +++ b/ufund-ui/src/app/components/cupboard/cupboard.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { CupboardService } from '../../services/cupboard.service'; -import { UsersService } from '../../services/users.service'; import { Need, GoalType } from '../../models/Need'; import { userType } from '../../models/User'; import { BehaviorSubject, catchError, of } from 'rxjs'; import { NeedListComponent } from '../need-list/need-list.component'; +import {AuthService} from '../../services/auth.service'; @Component({ selector: 'app-cupboard', @@ -20,7 +20,10 @@ export class CupboardComponent implements OnInit { needs: any; @ViewChild("needList") needList?: NeedListComponent - constructor(private cupboardService: CupboardService, private usersService: UsersService) { } + constructor( + private cupboardService: CupboardService, + private authService: AuthService + ) {} ngOnInit(): void { this.cupboardService.getNeeds().subscribe(n => this.needs = n); @@ -88,7 +91,7 @@ export class CupboardComponent implements OnInit { } isManager() { - const type = this.usersService.getCurrentUser()?.type; + const type = this.authService.getCurrentUser()?.type; return type === ("MANAGER" as unknown as userType); } @@ -105,7 +108,7 @@ export class CupboardComponent implements OnInit { console.log("need:", need); console.log(need.id, need, "need updated"); this.cupboardService.updateNeed(need.id, need) - .pipe(catchError((ex, r) => { + .pipe(catchError((ex, _) => { if (ex.status == 500) { this.statusText.next("Fields cannot be blank"); } else if (ex.status == 400) { @@ -140,7 +143,7 @@ export class CupboardComponent implements OnInit { console.log("need:", need); console.log("form submitted. creating need: ", need); this.cupboardService.createNeed(need) - .pipe(catchError((ex, r) => { + .pipe(catchError((ex, _) => { if (ex.status == 500) { this.statusText.next("Fields cannot be blank"); } else if (ex.status == 400) { @@ -167,48 +170,3 @@ export class CupboardComponent implements OnInit { } } - -let friendlyHttpStatus: { [key: number]: string } = { - 200: 'OK', - 201: 'Created', - 202: 'Accepted', - 203: 'Non-Authoritative Information', - 204: 'No Content', - 205: 'Reset Content', - 206: 'Partial Content', - 300: 'Multiple Choices', - 301: 'Moved Permanently', - 302: 'Found', - 303: 'See Other', - 304: 'Not Modified', - 305: 'Use Proxy', - 306: 'Unused', - 307: 'Temporary Redirect', - 400: 'Bad Request', - 401: 'Unauthorized', - 402: 'Payment Required', - 403: 'Forbidden', - 404: 'Not Found', - 405: 'Method Not Allowed', - 406: 'Not Acceptable', - 407: 'Proxy Authentication Required', - 408: 'Request Timeout', - 409: 'Conflict', - 410: 'Gone', - 411: 'Length Required', - 412: 'Precondition Required', - 413: 'Request Entry Too Large', - 414: 'Request-URI Too Long', - 415: 'Unsupported Media Type', - 416: 'Requested Range Not Satisfiable', - 417: 'Expectation Failed', - 418: 'I\'m a teapot', - 422: 'Unprocessable Entity', - 429: 'Too Many Requests', - 500: 'Internal Server Error', - 501: 'Not Implemented', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - 504: 'Gateway Timeout', - 505: 'HTTP Version Not Supported', -}; diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.ts b/ufund-ui/src/app/components/dashboard/dashboard.component.ts index b9faefa..a0ad566 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.ts +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.ts @@ -1,21 +1,21 @@ -import { Component } from '@angular/core'; -import { UsersService } from '../../services/users.service'; -import { userType } from '../../models/User'; +import {Component} from '@angular/core'; +import {userType} from '../../models/User'; +import {AuthService} from '../../services/auth.service'; @Component({ - selector: 'app-dashboard', - standalone: false, - templateUrl: './dashboard.component.html', - styleUrl: './dashboard.component.css' + selector: 'app-dashboard', + standalone: false, + templateUrl: './dashboard.component.html', + styleUrl: './dashboard.component.css' }) export class DashboardComponent { constructor( - protected usersService: UsersService, + protected authService: AuthService, ) {} isManager() { - const type = this.usersService.getCurrentUser()?.type; + const type = this.authService.getCurrentUser()?.type; return type === ("MANAGER" as unknown as userType); - } + } } diff --git a/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts b/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts index e654711..faa7e0b 100644 --- a/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts +++ b/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts @@ -1,11 +1,9 @@ import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {User} from '../../models/User'; -import { UsersService } from '../../services/users.service'; -import { Need } from '../../models/Need'; -import { NeedListComponent } from '../need-list/need-list.component'; -import { Router } from '@angular/router'; -import { CupboardService } from '../../services/cupboard.service'; -import { BehaviorSubject, catchError, firstValueFrom, Observable } from 'rxjs'; +import {UsersService} from '../../services/users.service'; +import {Router} from '@angular/router'; +import {CupboardService} from '../../services/cupboard.service'; +import {catchError, firstValueFrom, Observable} from 'rxjs'; +import {AuthService} from '../../services/auth.service'; @Component({ selector: 'app-funding-basket', @@ -14,67 +12,67 @@ import { BehaviorSubject, catchError, firstValueFrom, Observable } from 'rxjs'; styleUrl: './funding-basket.component.css' }) export class FundingBasketComponent implements OnInit { - statusText: any; + statusText: any; - constructor( - private router: Router, - protected cupboardService: CupboardService, - protected usersService: UsersService - ) {} + constructor( + private router: Router, + protected cupboardService: CupboardService, + protected usersService: UsersService, + private authService: AuthService + ) {} - @ViewChild("contribution") contribution?: Input; - @Input() isValid: boolean = true; + @ViewChild("contribution") contribution?: Input; + @Input() isValid: boolean = true; - // this is for login rerouting - ngOnInit(): void { - if (!this.usersService.getCurrentUser()) { - this.router.navigate(['/login'], {queryParams: {redir: this.router.url}}); - return; - } - - this.usersService.refreshBasket(); - // this.usersService.removeNeed(); <- call this to remove - } + // this is for login rerouting + ngOnInit(): void { + if (!this.authService.getCurrentUser()) { + this.router.navigate(['/login'], {queryParams: {redir: this.router.url}}); + return; + } - async checkout() { - this.isValid = true; - for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) { - let contribution = c as HTMLInputElement; - contribution.setAttribute("style",""); - if ( contribution.value == '' || contribution.valueAsNumber <= 0) { - this.isValid = false; - contribution.setAttribute("style","color: #ff0000"); - } + this.usersService.refreshBasket(); + // this.usersService.removeNeed(); <- call this to remove } - if (this.isValid) { - for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) { - let contribution = c as HTMLInputElement; - let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id)); - need.current +=+ contribution.value; - this.usersService.removeNeed(+need.id); - this.cupboardService.updateNeed(need.id, need) - .pipe(catchError((ex, r) => { - if (ex.status == 500) { - this.statusText.next('Fields cannot be blank'); - } else if (ex.status == 400) { - this.statusText.next('Goal must be greater than 0'); - } else { - this.statusText.next('Error on creating need'); - } - return new Observable<string>(); - })) - .subscribe((result) => { - if (result) { - console.log('need updated successfully'); - //this.needList?.refresh() - } else { - console.log('need update failed'); - } - }); - } - } - } + async checkout() { + this.isValid = true; + for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) { + let contribution = c as HTMLInputElement; + contribution.setAttribute("style", ""); + if (contribution.value == '' || contribution.valueAsNumber <= 0) { + this.isValid = false; + contribution.setAttribute("style", "color: #ff0000"); + } + } + if (this.isValid) { + for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) { + let contribution = c as HTMLInputElement; + let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id)); + need.current += +contribution.value; + this.usersService.removeNeed(+need.id); + this.cupboardService.checkoutNeed(need.id, +contribution.value) + .pipe(catchError((ex, _) => { + if (ex.status == 500) { + this.statusText.next('Fields cannot be blank'); + } else if (ex.status == 400) { + this.statusText.next('Goal must be greater than 0'); + } else { + this.statusText.next('Error on creating need'); + } + return new Observable<string>(); + })) + .subscribe((result) => { + if (result) { + console.log('need updated successfully'); + //this.needList?.refresh() + } else { + console.log('need update failed'); + } + }); + } + } + } } diff --git a/ufund-ui/src/app/components/home-page/home-page.component.ts b/ufund-ui/src/app/components/home-page/home-page.component.ts index 5b2277c..95e8962 100644 --- a/ufund-ui/src/app/components/home-page/home-page.component.ts +++ b/ufund-ui/src/app/components/home-page/home-page.component.ts @@ -1,10 +1,10 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; @Component({ - selector: 'app-home-page', - standalone: false, - templateUrl: './home-page.component.html', - styleUrl: './home-page.component.css' + selector: 'app-home-page', + standalone: false, + templateUrl: './home-page.component.html', + styleUrl: './home-page.component.css' }) export class HomePageComponent { diff --git a/ufund-ui/src/app/components/login/login.component.ts b/ufund-ui/src/app/components/login/login.component.ts index 9d806f5..f6a2996 100644 --- a/ufund-ui/src/app/components/login/login.component.ts +++ b/ufund-ui/src/app/components/login/login.component.ts @@ -2,12 +2,13 @@ import {Component, OnInit} from '@angular/core' import {UsersService} from '../../services/users.service'; import {ActivatedRoute, Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; +import {AuthService} from '../../services/auth.service'; @Component({ - selector: 'app-login', - standalone: false, - templateUrl: './login.component.html', - styleUrl: './login.component.css' + selector: 'app-login', + standalone: false, + templateUrl: './login.component.html', + styleUrl: './login.component.css' }) export class LoginComponent implements OnInit { @@ -17,7 +18,8 @@ export class LoginComponent implements OnInit { constructor( protected usersService: UsersService, protected router: Router, - private route: ActivatedRoute + private route: ActivatedRoute, + private authService: AuthService ) {} ngOnInit() { @@ -31,7 +33,7 @@ export class LoginComponent implements OnInit { return; } - this.usersService.login(username, password).then(() => { + this.authService.login(username, password).then(() => { this.router.navigate([next]); }).catch(ex => { this.statusText.next("Unable to login: " + friendlyHttpStatus[ex.status]) diff --git a/ufund-ui/src/app/components/need-list/need-list.component.ts b/ufund-ui/src/app/components/need-list/need-list.component.ts index 25f05d6..3a89a20 100644 --- a/ufund-ui/src/app/components/need-list/need-list.component.ts +++ b/ufund-ui/src/app/components/need-list/need-list.component.ts @@ -1,132 +1,138 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; import {Need} from '../../models/Need'; import {CupboardService} from '../../services/cupboard.service'; -import { UsersService } from '../../services/users.service'; -import { userType } from '../../models/User'; +import {UsersService} from '../../services/users.service'; +import {userType} from '../../models/User'; +import {catchError, of} from 'rxjs'; +import {AuthService} from '../../services/auth.service'; + @Component({ - selector: 'app-need-list', - standalone: false, - templateUrl: './need-list.component.html', - styleUrl: './need-list.component.css' + selector: 'app-need-list', + standalone: false, + templateUrl: './need-list.component.html', + styleUrl: './need-list.component.css' }) export class NeedListComponent { - needs: Need[] = []; - searchResults: Need[] = []; + needs: Need[] = []; + searchResults: Need[] = []; - constructor( - private cupboardService: CupboardService, - private usersService: UsersService - ) {} + constructor( + private cupboardService: CupboardService, + private usersService: UsersService, + private authService: AuthService + ) {} refresh() { this.cupboardService.getNeeds().subscribe(n => this.needs = n) } - ngOnInit(): void { - this.refresh() - - this.close(); - } + ngOnInit(): void { + this.refresh() - private showElement(element: any) { - if (element){ - element.style.visibility = 'visible'; - element.style.position = 'relative'; + this.close(); } - } - private hideElement(element: any) { - if (element){ - element.style.visibility = 'hidden'; - element.style.position = 'absolute'; + private showElement(element: any) { + if (element) { + element.style.visibility = 'visible'; + element.style.position = 'relative'; + } } - } - private updateSearchStatus(text: string) { - let element = document.getElementById('search-status'); - if (element) { - element.innerHTML = text; + private hideElement(element: any) { + if (element) { + element.style.visibility = 'hidden'; + element.style.position = 'absolute'; + } } - } - open() { - this.hideElement(document.getElementById('search-button')); - this.showElement(document.getElementById('search-form')); - } + private updateSearchStatus(text: string) { + let element = document.getElementById('search-status'); + if (element) { + element.innerHTML = text; + } + } - close() { - this.hideElement(document.getElementById('search-form')); - this.showElement(document.getElementById('search-button')); - this.hideElement(document.getElementById('search-status')); - } + open() { + this.hideElement(document.getElementById('search-button')); + this.showElement(document.getElementById('search-form')); + } - private searchDelay: any; + close() { + this.hideElement(document.getElementById('search-form')); + this.showElement(document.getElementById('search-button')); + this.hideElement(document.getElementById('search-status')); + } - async search(form: any) { - //wait .25 seconds before searching but cancel if another search is made during the wait to prevent too many api calls + private searchDelay: any; - //remove previous search if it exists - if (this.searchDelay) { - clearTimeout(this.searchDelay); - } + async search(form: any) { + //wait .25 seconds before searching but cancel if another search is made during the wait to prevent too many api calls - this.searchDelay = setTimeout(() => { - const currentSearchValue = form.search; //latest value of the search - this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => { - this.searchResults = n; - console.log(currentSearchValue, this.searchResults); - this.showElement(document.getElementById('search-results')); - this.showElement(document.getElementById('search-status')); - if (this.searchResults.length === this.needs.length) { - this.updateSearchStatus("Please refine your search"); - this.searchResults = []; - } else if (this.searchResults.length === 0) { - this.updateSearchStatus("No results found"); - } else { - this.updateSearchStatus("Search results:"); + //remove previous search if it exists + if (this.searchDelay) { + clearTimeout(this.searchDelay); } - }); - }, 250); - } - - delete(id : number) { - this.cupboardService.deleteNeed(id).subscribe(() => { - this.needs = this.needs.filter(n => n.id !== id) - }) - } - - isManager() { - const type = this.usersService.getCurrentUser()?.type; - return type === ("MANAGER" as unknown as userType); - } - - isHelper() { - const type = this.usersService.getCurrentUser()?.type; - return type === ("HELPER" as unknown as userType); - } - - add(need: Need) { - const currentUser = this.usersService.getCurrentUser(); - //console.log("get current user in angular:", currentUser) - if (currentUser) { - if (!currentUser.basket.includes(need.id)) { - currentUser.basket.push(need.id); - this.usersService.updateUser(currentUser).subscribe(() => { - this.usersService.refreshBasket(); - error: (err: any) => { - console.error(err); - } - }); - } else { - window.alert("This need is already in your basket!") - } - + this.searchDelay = setTimeout(() => { + const currentSearchValue = form.search; //latest value of the search + this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => { + this.searchResults = n; + console.log(currentSearchValue, this.searchResults); + this.showElement(document.getElementById('search-results')); + this.showElement(document.getElementById('search-status')); + if (this.searchResults.length === this.needs.length) { + this.updateSearchStatus("Please refine your search"); + this.searchResults = []; + } else if (this.searchResults.length === 0) { + this.updateSearchStatus("No results found"); + } else { + this.updateSearchStatus("Search results:"); + } + }); + }, 250); + } + + delete(id: number) { + this.cupboardService.deleteNeed(id).subscribe(() => { + this.needs = this.needs.filter(n => n.id !== id) + }) } - } + isManager() { + const type = this.authService.getCurrentUser()?.type; + return type === ("MANAGER" as unknown as userType); + } + + isHelper() { + const type = this.authService.getCurrentUser()?.type; + return type === ("HELPER" as unknown as userType); + } + + add(need: Need) { + const currentUser = this.authService.getCurrentUser(); + //console.log("get current user in angular:", currentUser) + if (currentUser) { + if (!currentUser.basket.includes(need.id)) { + currentUser.basket.push(need.id); + this.usersService.updateUser(currentUser) + .pipe(catchError((err: any, _) => { + console.error(err); + return of(); + })) + .subscribe(() => { + this.usersService.refreshBasket(); + }); + } else { + window.alert("This need is already in your basket!") + } + - back() { - this.searchResults = []; - } + } + + } + + back() { + this.searchResults = []; + } } diff --git a/ufund-ui/src/app/components/need-page/need-page.component.ts b/ufund-ui/src/app/components/need-page/need-page.component.ts index 597d0e0..e38554c 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.ts +++ b/ufund-ui/src/app/components/need-page/need-page.component.ts @@ -2,30 +2,30 @@ import {Component, Input} from '@angular/core'; import {GoalType, Need} from '../../models/Need'; import {ActivatedRoute} from "@angular/router"; import {CupboardService} from "../../services/cupboard.service"; -import { NgFor } from '@angular/common'; +import {NgFor} from '@angular/common'; @Component({ - selector: 'app-need-page', - standalone: false, - templateUrl: './need-page.component.html', - styleUrl: './need-page.component.css' + selector: 'app-need-page', + standalone: false, + templateUrl: './need-page.component.html', + styleUrl: './need-page.component.css' }) export class NeedPageComponent { - constructor( - private route: ActivatedRoute, - private cupboardService: CupboardService, - ) {} + constructor( + private route: ActivatedRoute, + private cupboardService: CupboardService, + ) {} - public GoalType = GoalType; + public GoalType = GoalType; - @Input() need?: Need; + @Input() need?: Need; - ngOnInit(): void { - const id = Number(this.route.snapshot.paramMap.get('id')); - this.cupboardService.getNeed(id).subscribe(n => this.need = n); - } + ngOnInit(): void { + const id = Number(this.route.snapshot.paramMap.get('id')); + this.cupboardService.getNeed(id).subscribe(n => this.need = n); + } - back() { - window.history.back(); - } -}
\ No newline at end of file + back() { + window.history.back(); + } +} diff --git a/ufund-ui/src/app/models/Need.ts b/ufund-ui/src/app/models/Need.ts index 9e97fd4..5cd4e39 100644 --- a/ufund-ui/src/app/models/Need.ts +++ b/ufund-ui/src/app/models/Need.ts @@ -1,13 +1,13 @@ export interface Need { - name: string, - id: number, - filterAttributes: string[], - type: GoalType; - maxGoal: number; - current: number; + name: string, + id: number, + filterAttributes: string[], + type: GoalType; + maxGoal: number; + current: number; } export enum GoalType { - MONETARY, - PHYSICAL + MONETARY, + PHYSICAL } diff --git a/ufund-ui/src/app/models/User.ts b/ufund-ui/src/app/models/User.ts index f4396f6..e6848fa 100644 --- a/ufund-ui/src/app/models/User.ts +++ b/ufund-ui/src/app/models/User.ts @@ -1,5 +1,3 @@ -import {Need} from './Need'; - export enum userType { HELPER, MANAGER diff --git a/ufund-ui/src/app/services/auth.service.ts b/ufund-ui/src/app/services/auth.service.ts new file mode 100644 index 0000000..6bc7145 --- /dev/null +++ b/ufund-ui/src/app/services/auth.service.ts @@ -0,0 +1,57 @@ +import {Injectable} from '@angular/core'; +import {BehaviorSubject, firstValueFrom} from 'rxjs'; +import {User} from '../models/User'; +import {HttpClient, HttpHeaders} from '@angular/common/http'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + + private authUrl = "http://localhost:8080/auth" + private userUrl = "http://localhost:8080/users" + + private currentUser : BehaviorSubject<User | null> = new BehaviorSubject<User | null>(null); + private apiKey: string = ""; + + httpOptions2 = () => ({ + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + "jelly-api-key": this.apiKey + }), + responseType: "text" as "json" // don't ask me how or why this works, bc i have no clue... + // see the relevant angular bug report https://github.com/angular/angular/issues/18586 + }); + + constructor( + private http: HttpClient + ) {} + + async login(username: string, password: string) { + let res = this.http.post<string>(this.authUrl, {username: username, password: password}, this.httpOptions2()); + this.apiKey = await firstValueFrom(res); + console.log("apikey: "+this.apiKey) + let res2 = this.http.get<User>(`${this.userUrl}/${username}`, { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + "jelly-api-key": this.apiKey + }) + }) + let currentU = await firstValueFrom(res2); + this.currentUser.next(currentU); + // this.currentUser.subscribe(r => console.log("currentUser: "+r.username)) + } + + getCurrentUserSubject() { + return this.currentUser; + } + + getCurrentUser() { + return this.currentUser.getValue() + } + + getApiKey() { + return this.apiKey; + } + +} diff --git a/ufund-ui/src/app/services/cupboard.service.ts b/ufund-ui/src/app/services/cupboard.service.ts index 9e14106..9232c0c 100644 --- a/ufund-ui/src/app/services/cupboard.service.ts +++ b/ufund-ui/src/app/services/cupboard.service.ts @@ -2,6 +2,7 @@ import {Injectable} from '@angular/core'; import {HttpClient, HttpHeaders} from '@angular/common/http'; import {Need} from '../models/Need'; import {Observable} from 'rxjs'; +import {AuthService} from './auth.service'; @Injectable({ providedIn: 'root' @@ -9,35 +10,44 @@ import {Observable} from 'rxjs'; export class CupboardService { private url = "http://localhost:8080/cupboard" - private httpOptions = { - headers: new HttpHeaders({'Content-Type': 'application/json'}) - }; + + httpOptions = () => ({ + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + "jelly-api-key": this.authService.getApiKey() + }) + }); constructor( - private http: HttpClient + private http: HttpClient, + private authService: AuthService ) {} createNeed(need: Need): Observable<boolean> { - return this.http.post<boolean>(this.url, need, this.httpOptions) + return this.http.post<boolean>(this.url, need, this.httpOptions()) } getNeeds(): Observable<Need[]> { - return this.http.get<Need[]>(this.url, this.httpOptions) + return this.http.get<Need[]>(this.url, this.httpOptions()) } searchNeeds(name: String): Observable<Need[]> { - return this.http.get<Need[]>(`${this.url}/?name=${name}`, this.httpOptions) + return this.http.get<Need[]>(`${this.url}/?name=${name}`, this.httpOptions()) } getNeed(id: number): Observable<Need> { - return this.http.get<Need>(`${this.url}/${id}`, this.httpOptions) + return this.http.get<Need>(`${this.url}/${id}`, this.httpOptions()) } updateNeed(id: number, data: Need): Observable<boolean> { - return this.http.put<boolean>(`${this.url}/${id}`, data, this.httpOptions) + return this.http.put<boolean>(`${this.url}/${id}`, data, this.httpOptions()) } deleteNeed(id: number): Observable<boolean> { - return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions) + return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions()) + } + + checkoutNeed(id: number, quantity: number) { + return this.http.put(`${this.url}/checkout`, {needID: id, amount: quantity}, this.httpOptions()) } } diff --git a/ufund-ui/src/app/services/users.service.ts b/ufund-ui/src/app/services/users.service.ts index dba8185..4080ebf 100644 --- a/ufund-ui/src/app/services/users.service.ts +++ b/ufund-ui/src/app/services/users.service.ts @@ -1,96 +1,69 @@ import { Injectable } from '@angular/core'; import {HttpClient, HttpHeaders} from '@angular/common/http'; -import {BehaviorSubject, firstValueFrom, Observable} from 'rxjs'; +import {BehaviorSubject, catchError, firstValueFrom, Observable, of} from 'rxjs'; import {User} from '../models/User'; import { Need } from '../models/Need'; import { CupboardService } from './cupboard.service'; +import {AuthService} from './auth.service'; @Injectable({ providedIn: 'root' }) export class UsersService { - private currentUser : BehaviorSubject<User | null> = new BehaviorSubject<User | null>(null); - private apiKey: string = ""; private basket = new BehaviorSubject<Need[]>([]); - private url = "http://localhost:8080/users" - private authUrl = "http://localhost:8080/auth" - private httpOptions = { + + httpOptions = () => ({ headers: new HttpHeaders({ 'Content-Type': 'application/json', - "jelly-api-key": this.apiKey + "jelly-api-key": this.authService.getApiKey() }) - }; - private httpOptions2 = { - headers: new HttpHeaders({ - 'Content-Type': 'application/json', - "jelly-api-key": this.apiKey - }), - responseType: "text" as "json" // don't ask me how or why this works, bc i have no clue... - // see the relevant angular bug report https://github.com/angular/angular/issues/18586 - }; + }); constructor( private http: HttpClient, private cupboardService: CupboardService, + private authService: AuthService ) {} async createUser(username:string, password:string) { - await firstValueFrom(this.http.post<User>(this.url, {username: username, password: password}, this.httpOptions)) + await firstValueFrom(this.http.post<User>(this.url, {username: username, password: password}, this.httpOptions())) } getUser(id: string): Observable<User> { - return this.http.get<User>(`${this.url}/${id}`, this.httpOptions) + return this.http.get<User>(`${this.url}/${id}`, this.httpOptions()) } updateUser(user: User): Observable<User> { - return this.http.put<User>(`${this.url}/${user.username}`,user, this.httpOptions2) + console.log(`${this.url}/${user.username}`, user, this.httpOptions) + return this.http.put<User>(`${this.url}/${user.username}`, user, this.httpOptions()) } deleteUser(id: number): Observable<boolean> { - return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions) - } - - getCurrentUserSubject() { - return this.currentUser; - } - - getCurrentUser() { - return this.currentUser.getValue() - } - - async login(username: string, password: string) { - let res = this.http.post<string>(this.authUrl, {username: username, password: password}, this.httpOptions2); - this.apiKey = await firstValueFrom(res); - console.log("apikey: "+this.apiKey) - let res2 = this.http.get<User>(`${this.url}/${username}`, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json', - "jelly-api-key": this.apiKey - }) - }) - let currentU = await firstValueFrom(res2); - this.currentUser.next(currentU); - // this.currentUser.subscribe(r => console.log("currentUser: "+r.username)) + return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions()) } refreshBasket() { - let promiseArr = this.getCurrentUser()!.basket.map(async needID => { + let promiseArr = this.authService.getCurrentUser()!.basket.map(async needID => { return await firstValueFrom(this.cupboardService.getNeed(needID)); }) Promise.all(promiseArr).then(r => this.basket.next(r)); } - + removeNeed(id: number) { let newArr = this.basket.getValue().filter(v => v.id != id); this.basket.next(newArr); - this.getCurrentUser()!.basket = newArr.map(need => need.id); - this.updateUser(this.getCurrentUser()!).subscribe(() => { + this.authService.getCurrentUser()!.basket = newArr.map(need => need.id); + this.updateUser(this.authService.getCurrentUser()!) + .pipe( + catchError((err: any, _) => { + console.error(err); + return of(); + }) + ) + .subscribe(() => { this.refreshBasket(); - error: (err: any) => { - console.error(err); - } }); } |