diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2025-04-02 23:27:27 -0400 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2025-04-02 23:27:27 -0400 |
commit | 3e5422b90a09d1ed2cfffae56abf8dbe361f6c27 (patch) | |
tree | 3b3fdbd99a4b2a4f990b2f8d8543a80614492142 /ufund-ui | |
parent | 6b7c830eeefb6a6a28136a3faacf7713953a6138 (diff) | |
download | JellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.tar.gz JellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.tar.bz2 JellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.zip |
[incomplete] rearrange code to begin need-list abstraction
Diffstat (limited to 'ufund-ui')
7 files changed, 350 insertions, 414 deletions
diff --git a/ufund-ui/src/app/components/cupboard/cupboard.component.html b/ufund-ui/src/app/components/cupboard/cupboard.component.html index 37954bb..bdc8a0e 100644 --- a/ufund-ui/src/app/components/cupboard/cupboard.component.html +++ b/ufund-ui/src/app/components/cupboard/cupboard.component.html @@ -3,36 +3,64 @@ <h1> Cupboard </h1> <button *ngIf="isManager()" class="button2" (click)="this.selectForm('create')"><span class="icon">add</span>Create Need</button> </div> - <app-need-list (currentNeed) = populateForm($event) #needList></app-need-list> -</div> -<ng-template [ngIf]="isManager()" > -<div> - <app-need-edit *ngIf="selectedForm === 'update'" [selectedNeed]="selectedNeed" (refreshNeedList)="needList.refresh()"></app-need-edit> - <div> - <div id="create-form" *ngIf="selectedForm === 'create'"> - <h1> Create Need </h1> - <form #cupboardForm="ngForm" (ngSubmit)="submit(cupboardForm.value)"> - <label>Name:</label><br> - <input type="text" name="name" ngModel><br> - <label>Image:</label><br> - <input type="text" name="image" ngModel><br> - <label>Location:</label><br> - <input type="text" name="location" ngModel><br> - <label>Max Goal:</label><br> - <input type="number" name="maxGoal" ngModel><br> - <label>Type</label><br> - <input type="radio" name="type" value="MONETARY" ngModel> - <label>Monetary</label><br> - <input type="radio" name="type" value="PHYSICAL" ngModel> - <label>Physical</label><br> - <input type="checkbox" name="urgent" value="false" ngModel> - <label>Urgent</label><br> - <label>Description</label><br> - <textarea name="description"></textarea><br> - <input type="submit" value="Submit"> - </form> - </div> + <div id="header2"> + <div id="searchArea"> + <form id="search-form" #searchForm="ngForm"> + <input type="text" name="search" class="wide-input" placeholder="Search in {{needs.length}} needs..." (input)="search(searchForm.value)" ngModel> + <input type="reset" value="Clear" (click)="search(null)"> <br> + </form> + </div> + <div id="sortArea"> + <label for="sort">Sort by: </label> + <select id='sort' [(ngModel)] = "currentSortAlgo" class="wide-input" (change)="search(searchForm.value)" [value]="currentSortAlgo"> + <option *ngFor="let algorithm of Object.values(SortingAlgoArrays)" value="{{algorithm}}"> + {{algorithm.display[sortMode === 'Ascending' ? 0 : 1]}} + </option> + </select> + <button (click)="changeSortMode(searchForm.value)"> + <span class="icon">{{sortMode === 'Ascending' ? 'arrow_upward': 'arrow_downward'}}</span> + </button> + <label>Needs per page: </label> +<!-- <input type ="number" [(ngModel)]="itemsPerPage" min="1" max="{{searchResults.length}}">--> + </div> + <!--<button (click)="close()">Close</button>--> </div> + <h2 *ngIf="(searchResults | async)?.length < needs.length && (searchResults | async)?.length != 0"> Search Results({{needs.length - (searchResults | async)?.length}} needs filtered): </h2> + <h2 *ngIf="(searchResults | async)?.length == needs.length"> All Needs </h2> + <h2 *ngIf="(searchResults | async)?.length == 0"> No Results Found </h2> + + <app-need-list [needs]="searchResults" #needList></app-need-list> </div> -</ng-template> + +<!--<ng-template [ngIf]="isManager()" >--> +<!--<div>--> +<!-- <app-need-edit *ngIf="selectedForm === 'update'" [selectedNeed]="selectedNeed" (refreshNeedList)="needList.refresh()"></app-need-edit>--> +<!-- <div>--> +<!-- <div id="create-form" *ngIf="selectedForm === 'create'">--> +<!-- <h1> Create Need </h1>--> +<!-- <form #cupboardForm="ngForm" (ngSubmit)="submit(cupboardForm.value)">--> +<!-- <label>Name:</label><br>--> +<!-- <input type="text" name="name" ngModel><br>--> +<!-- <label>Image:</label><br>--> +<!-- <input type="text" name="image" ngModel><br>--> +<!-- <label>Location:</label><br>--> +<!-- <input type="text" name="location" ngModel><br>--> +<!-- <label>Max Goal:</label><br>--> +<!-- <input type="number" name="maxGoal" ngModel><br>--> +<!-- <label>Type</label><br>--> +<!-- <input type="radio" name="type" value="MONETARY" ngModel>--> +<!-- <label>Monetary</label><br>--> +<!-- <input type="radio" name="type" value="PHYSICAL" ngModel>--> +<!-- <label>Physical</label><br>--> +<!-- <input type="checkbox" name="urgent" value="false" ngModel>--> +<!-- <label>Urgent</label><br>--> +<!-- <label>Description</label><br>--> +<!-- <textarea name="description"></textarea><br>--> +<!-- <input type="submit" value="Submit">--> + +<!-- </form>--> +<!-- </div>--> +<!-- </div>--> +<!--</div>--> +<!--</ng-template>--> diff --git a/ufund-ui/src/app/components/cupboard/cupboard.component.ts b/ufund-ui/src/app/components/cupboard/cupboard.component.ts index 2230cd3..95845e7 100644 --- a/ufund-ui/src/app/components/cupboard/cupboard.component.ts +++ b/ufund-ui/src/app/components/cupboard/cupboard.component.ts @@ -2,10 +2,12 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import { CupboardService } from '../../services/cupboard.service'; import { Need, GoalType } from '../../models/Need'; import { userType } from '../../models/User'; -import { catchError, of } from 'rxjs'; +import {BehaviorSubject, catchError, of} from 'rxjs'; import { NeedListComponent } from '../need-list/need-list.component'; import {AuthService} from '../../services/auth.service'; import {ToastsService, ToastType} from '../../services/toasts.service'; +import {UsersService} from '../../services/users.service'; +import {SortingAlgoArrays} from './sorting'; @Component({ selector: 'app-cupboard', @@ -13,17 +15,36 @@ import {ToastsService, ToastType} from '../../services/toasts.service'; templateUrl: './cupboard.component.html', styleUrl: './cupboard.component.css' }) - export class CupboardComponent implements OnInit { selectedForm?: string = undefined; - needs: any; + // needs: any; @ViewChild("needList") needList?: NeedListComponent + private searchDelay: any; + selectedNeed: Need | null = null; + needs: Need[] = []; + searchResults = new BehaviorSubject<Need[]>([]); + sortMode: 'Ascending' | 'Descending' = 'Ascending' + // selectedNeed: any = { + // name: '', + // location:'', + // id: null, + // maxGoal: null, + // type: '', + // urgent: false + // }; + selectedNeedId: number | null = null; + // searchResults: any[] = []; + + currentSortAlgo = SortingAlgoArrays.sortByPriority; + // sortSelection: string = 'sortByPriority'; + constructor( private cupboardService: CupboardService, private authService: AuthService, - private toastService: ToastsService + private toastService: ToastsService, + private usersService: UsersService ) {} ngOnInit(): void { @@ -35,21 +56,26 @@ export class CupboardComponent implements OnInit { } } - selectedNeed: any = { - name: '', - location:'', - id: null, - maxGoal: null, - type: '', - urgent: false - }; - selectedNeedId: number | null = null; - searchResults: any[] = []; + refresh() { + this.cupboardService.getNeeds().subscribe(n => { + if (this.sortMode == 'Ascending') { + this.needs = n.sort(this.currentSortAlgo.func); + } else { + this.needs = n.sort(this.currentSortAlgo.func).reverse(); + } + this.searchResults.next(this.needs); + // this.updateVisibleNeeds(); + }); + + const form = document.getElementById('search-form') as HTMLFormElement; + form.reset(); + this.search(null); + } selectForm(name: string) { //get search results from the need list if (this.needList) { - this.searchResults = this.needList.searchResults; + // this.searchResults = this.needList.searchResults; } console.log(this.searchResults) this.selectedForm = name; @@ -63,10 +89,72 @@ export class CupboardComponent implements OnInit { } } + 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 + + //remove previous search if it exists + if (this.searchDelay) { + clearTimeout(this.searchDelay); + } + if (form) { + this.searchDelay = setTimeout(() => { + + if (form) { + //sorting based on algo selected + // SortingAlgoArrays.forEach(algo => { + // if(algo.name === this.sortSelection) { + // this.currentSortAlgo = SortingAlgoArrays[this.sort]; + // console.log("changed sorting algorithm to: ", algo.name + this.sortMode) + // return + // } + // }); + + const currentSearchValue = form.search; //latest value of the search + this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => { + if (this.sortMode == 'Ascending') { + this.searchResults.next(n.sort(this.currentSortAlgo.func)); + } else { + this.searchResults.next(n.sort(this.currentSortAlgo.func).reverse()); + } + // this.updateVisibleNeeds(); + }); + } + }, 250); + } else { + //user has cleared the search bar, we can skip the timeout for a 1/4 second faster response + //clear timeout to stop pending search + clearTimeout(this.searchDelay); + this.searchResults.next(this.needs); + } + } + + changeSortMode(form : any) { + if (this.sortMode == 'Ascending'){ + this.sortMode = 'Descending' + } else { + this.sortMode = 'Ascending' + } + this.search(form) + } + + + + isHelper() { + const type = this.authService.getCurrentUser()?.type; + return type === ("HELPER" as unknown as userType); + } + + changeText(id : number, text : string) { + const span = document.getElementById('hover-status-label-' + id); + if (span) { + span.innerHTML = ' ' + text; + } + } + async updateSearchResults() { if (this.needList) { while (this.selectedForm == 'update') { - this.searchResults = this.needList.searchResults + // this.searchResults = this.needList.searchResults await new Promise(resolve => setTimeout(resolve, 100)); } } @@ -82,6 +170,40 @@ export class CupboardComponent implements OnInit { return type === ("MANAGER" as unknown as userType); } + // -------------- DISPLAY FUNCTIONS -------------- // + + select(need : Need) { + //emit value + // this.currentNeed.emit(need); + if (this.selectedNeed) { + //revert already selected need to previous style + console.log(need.id); + let button = document.getElementById('need-button-' + this.selectedNeed.id); + if (button) { + console.log(button) + button.style.background = 'lightgray'; + button.style.marginLeft = '0%'; + button.style.width = '98%'; + } + button = document.getElementById('need-edit-button-' + this.selectedNeed.id); + if (button) { + button.style.visibility = 'visible'; + } + } + //change selected need to selected style + this.selectedNeed = need; + let button = document.getElementById('need-button-' + need.id); + if (button) { + button.style.background = 'white'; + button.style.marginLeft = '4%'; + button.style.width = '100%'; + } + button = document.getElementById('need-edit-button-' + need.id); + if (button) { + button.style.visibility = 'hidden'; + } + } + submit(form: any) { const need: Need = { name: form.name, @@ -90,7 +212,7 @@ export class CupboardComponent implements OnInit { id: 0, maxGoal: form.maxGoal, type: form.type, - urgent: form.urgent ? true : false, + urgent: !!form.urgent, filterAttributes: [], current: 0, description: form.description @@ -112,7 +234,7 @@ export class CupboardComponent implements OnInit { (result) => { if (result) { console.log("need created successfully"); - this.needList?.refresh() + // this.needList?.refresh() } else { console.log("need creation failed"); } @@ -121,7 +243,36 @@ export class CupboardComponent implements OnInit { ); } - destroy() { + // -------------- CRUD OPERATIONS -------------- // + delete(id : number) { + this.cupboardService.deleteNeed(id).subscribe(() => { + this.toastService.sendToast(ToastType.INFO, "Need deleted.") + this.needs = this.needs.filter(n => n.id !== id) + }) + this.refresh(); } + + 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, _) => { + console.error(err); + return of(); + })) + .subscribe(() => { + this.usersService.refreshBasket(); + }); + } else { + this.toastService.sendToast(ToastType.ERROR, "This need is already in your basket!") + } + } + } + + protected readonly SortingAlgoArrays = SortingAlgoArrays; + protected readonly Object = Object; } diff --git a/ufund-ui/src/app/components/cupboard/sorting.ts b/ufund-ui/src/app/components/cupboard/sorting.ts new file mode 100644 index 0000000..a512f22 --- /dev/null +++ b/ufund-ui/src/app/components/cupboard/sorting.ts @@ -0,0 +1,58 @@ +import {Need} from '../../models/Need'; + +interface sortAlgo { + (a: Need, b: Need): number; +} + +// sort functions +const sortByName: sortAlgo = (a: Need, b: Need): number => { + if(a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) { + return -1; + } + return 1; +} + +const sortByGoal: sortAlgo = (a: Need, b: Need): number => { + if(a.maxGoal == b.maxGoal) { + return sortByName(a,b); + } + else if(a.maxGoal > b.maxGoal) { + return -1; + } + return 1; +} + +const sortByCompletion: sortAlgo = (a: Need, b: Need): number => { + if(a.current == b.current) { + return sortByGoal(a,b); + } + else if(a.current > b.current) { + return -1; + } + return 1; +} + +const sortByPriority: sortAlgo = (a: Need, b: Need): number => { + if(a.urgent == b.urgent) { + return sortByGoal(a,b); + } + else if(a.urgent && !b.urgent) { + return -1; + } + return 1; +} + +const sortByLocation: sortAlgo = (a: Need, b: Need): number => { + if(a.location.toLocaleLowerCase() < b.location.toLocaleLowerCase()) { + return -1; + } + return 1; +} + +export const SortingAlgoArrays = { + sortByPriority: { func: sortByPriority, display: ["Highest Priority", "Lowest Priority" ] }, + sortByName: { func: sortByName, display: ["Name (A to Z)", "Name (Z to A)" ] }, + sortByLocation: { func: sortByLocation, display: ["Location (A to Z)", "Location (Z to A)" ] }, + sortByCompletion: { func: sortByCompletion, display: ["Most Completed", "Least Completed" ] }, + sortByGoal: { func: sortByGoal, display: ["Largest Maximum Goal", "Smallest Maximum Goal" ] }, +}; diff --git a/ufund-ui/src/app/components/funding-basket/funding-basket.component.html b/ufund-ui/src/app/components/funding-basket/funding-basket.component.html index 52b35c1..a53b47c 100644 --- a/ufund-ui/src/app/components/funding-basket/funding-basket.component.html +++ b/ufund-ui/src/app/components/funding-basket/funding-basket.component.html @@ -1,75 +1,7 @@ - -<!--<div id="needCount">--> -<!-- <label for="needCount">Needs in Basket:</label>--> -<!-- <span>{{ this.usersService.getBasket().getValue().length }}</span>--> -<!--</div>--> - -<!--<div *ngIf="this.usersService.getBasket().getValue().length == 0">--> -<!-- <h2>There are no needs in the basket</h2>--> -<!--</div>--> - -<!--<table class="needs" id="funding-basket" *ngIf="this.usersService.getBasket().getValue().length != 0">--> -<!-- <thead>--> -<!-- <tr>--> -<!-- <th class="need"></th>--> -<!-- </tr>--> -<!-- </thead>--> -<!-- <tbody>--> -<!-- <tr *ngFor="let need of usersService.getBasket().getValue()">--> -<!-- <td>--> -<!-- <a routerLink="/need/{{need.id}}">{{need.name}}</a>--> -<!-- <p>Goal: {{need.maxGoal}}</p>--> -<!-- <p>Current: {{(need.current).toFixed(2)}}</p>--> -<!-- <p>How much to Contribute: <input type="number" placeholder="insert value" min="1" id={{need.id}} class="contribution"></p>--> -<!-- <br>--> -<!-- <div>--> -<!-- <button type="button" class="removeNeed" title="delete need"--> -<!-- (click)="this.usersService.removeNeed(need.id)">Remove Need</button>--> -<!-- </div>--> -<!-- </td>--> -<!-- </tr>--> -<!-- </tbody>--> -<!--</table>--> -<!--<br>--> <div id="box"> <h1>Funding Basket</h1> <ng-template [ngIf]="usersService.getBasket().getValue().length"> - <div id="needList"> - <div *ngFor="let need of usersService.getBasket().getValue()" class="needEntry"> - <div [routerLink]="'/need/' + need.id" class="clickable"> - <div class="split"> - <div class="left"> - <span class="needName">{{need.name}}</span> - <span class="needType">{{need.type}}</span> - </div> - - <div class="right"> - <span *ngIf="need.urgent" class="urgent">URGENT</span> - <span *ngIf="need.location"><span class="icon">location_on</span>{{need.location}}</span> - </div> - </div> - - <br> - - <div class="prog"> - <span id="hover-status-label-{{need.id}}"> </span> - <span>{{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%)</span> - <progress [value]="need.current" [max]="need.maxGoal"></progress> - </div> - - <!-- <div class="description">--> - <!-- {{need.description}}--> - <!-- </div>--> - </div> - - <div class="actionArea"> - <input type="number" placeholder="Quantity" min="1" id={{need.id}} class="contribution"> - <button class="removeNeed" title="delete need" (click)="this.usersService.removeNeed(need.id)"> - <span class="icon">delete</span> Remove from Basket - </button> - </div> - </div> - </div> + <app-need-list [needs]="of(usersService.getBasket().getValue())"/> <br> <div id="footer"> <button class="button2" title="checkout" (click)="checkout()">Checkout</button> 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 847baee..0b3b9f3 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 @@ -2,7 +2,7 @@ import {Component, Input, OnInit, ViewChild} from '@angular/core'; import {UsersService} from '../../services/users.service'; import {Router} from '@angular/router'; import {CupboardService} from '../../services/cupboard.service'; -import {catchError, firstValueFrom, Observable} from 'rxjs'; +import {catchError, firstValueFrom, Observable, of} from 'rxjs'; import {AuthService} from '../../services/auth.service'; import {ToastsService, ToastType} from '../../services/toasts.service'; @@ -91,4 +91,5 @@ export class FundingBasketComponent implements OnInit { } + protected readonly of = of; } diff --git a/ufund-ui/src/app/components/need-list/need-list.component.html b/ufund-ui/src/app/components/need-list/need-list.component.html index 88317dd..b19c33d 100644 --- a/ufund-ui/src/app/components/need-list/need-list.component.html +++ b/ufund-ui/src/app/components/need-list/need-list.component.html @@ -1,30 +1,4 @@ -<div id="header"> - <div id="searchArea"> - <form id="search-form" #searchForm="ngForm"> - <input type="text" name="search" class="wide-input" placeholder="Search in {{needs.length}} needs..." (input)="search(searchForm.value)" ngModel> - <input type="reset" value="Clear" (click)="search(null)"> <br> - </form> - </div> - <div id="sortArea"> - <label for="sort">Sort by: </label> - <select id='sort' [(ngModel)] = "sortSelection" class="wide-input" (change)="search(searchForm.value)" [value]="sortSelection"> - <option *ngFor="let algorithm of SortingAlgoArrays" value="{{algorithm.name}}"> - {{algorithm.display[sortMode === 'Ascending' ? 0 : 1]}} - </option> - </select> - <button (click)="changeSortMode(searchForm.value)"> - <span class="icon">{{sortMode === 'Ascending' ? 'arrow_upward': 'arrow_downward'}}</span> - </button> - <label>Needs per page: </label> - <input type ="number" [(ngModel)]="itemsPerPage" (change)="resetVisibleNeeds()" min="1" max="{{searchResults.length}}"> - </div> - <!--<button (click)="close()">Close</button>--> -</div> - <!-- display for when results are present and filtered--> -<h2 *ngIf="searchResults.length < needs.length && searchResults.length != 0"> Search Results({{needs.length - searchResults.length}} needs filtered): </h2> -<h2 *ngIf="searchResults.length == needs.length"> All Needs </h2> -<h2 *ngIf="searchResults.length == 0"> No Results Found </h2> <div id="needList"> <div *ngFor="let need of visibleNeeds" class="needEntry"> <div [routerLink]="'/need/' + need.id" class="clickable"> @@ -45,20 +19,25 @@ <span>{{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%)</span> <progress [value]="need.current" [max]="need.maxGoal"></progress> </div> - </div> - <div class="actionArea"> - <button *ngIf="isHelper()" (click)="add(need)"> - <span class="icon">add</span>Add To Basket - </button> - <button *ngIf="isManager()" (click)="select(need)"> - <span class="icon">edit</span>Edit Need - </button> - <button *ngIf="isManager()" (click)="delete(need.id)" > - <span class="icon">delete</span>Delete Need - </button> - </div> +<!-- <div class="actionArea">--> +<!-- <button *ngIf="isHelper()" (click)="add(need)">--> +<!-- <span class="icon">add</span>Add To Basket--> +<!-- </button>--> +<!-- <button *ngIf="isManager()" (click)="select(need)">--> +<!-- <span class="icon">edit</span>Edit Need--> +<!-- </button>--> +<!-- <button *ngIf="isManager()" (click)="delete(need.id)" >--> +<!-- <span class="icon">delete</span>Delete Need--> +<!-- </button>--> +<!-- </div>--> +<!-- <div class="actionArea">--> +<!-- <input type="number" placeholder="Quantity" min="1" id={{need.id}} class="contribution">--> +<!-- <button class="removeNeed" title="delete need" (click)="this.usersService.removeNeed(need.id)">--> +<!-- <span class="icon">delete</span> Remove from Basket--> +<!-- </button>--> +<!-- </div>--> </div> </div> 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 06a612e..d637005 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,282 +1,69 @@ -import {Component, EventEmitter, Output} from '@angular/core'; +import {Component, Input, OnInit} 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 {AuthService} from '../../services/auth.service'; -import {catchError, of} from 'rxjs'; -import {ToastsService, ToastType} from '../../services/toasts.service'; - -interface sortAlgo { - (a: Need,b: Need): number; -} - -// sort functions -const sortByName: sortAlgo = (a: Need, b: Need): number => { - if(a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) { - return -1; - } - return 1; -} - -const sortByGoal: sortAlgo = (a: Need, b: Need): number => { - if(a.maxGoal == b.maxGoal) { - return sortByName(a,b); - } - else if(a.maxGoal > b.maxGoal) { - return -1; - } - return 1; -} - -const sortByCompletion: sortAlgo = (a: Need, b: Need): number => { - if(a.current == b.current) { - return sortByGoal(a,b); - } - else if(a.current > b.current) { - return -1; - } - return 1; -} - -const sortByPriority: sortAlgo = (a: Need, b: Need): number => { - if(a.urgent == b.urgent) { - return sortByGoal(a,b); - } - else if(a.urgent && !b.urgent) { - return -1; - } - return 1; -} - -const sortByLocation: sortAlgo = (a: Need, b: Need): number => { - if(a.location.toLocaleLowerCase() < b.location.toLocaleLowerCase()) { - return -1; - } - return 1; -} +import {BehaviorSubject, Observable} from 'rxjs'; @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 { - selectedNeed: Need | null = null; - needs: Need[] = []; - searchResults: Need[] = []; - visibleNeeds: Need[] = []; - sortMode: 'Ascending' | 'Descending' = 'Ascending' - currentPage: number = 0; - itemsPerPage: number = 5; - totalPages: number = Math.ceil(this.needs.length / this.itemsPerPage); - - decrementPage() { - this.currentPage--; - this.updateVisibleNeeds(); - } - - incrementPage() { - this.currentPage++; - this.updateVisibleNeeds(); - } - - lastPage() { - this.currentPage = this.totalPages - 1 - this.updateVisibleNeeds() - } +export class NeedListComponent implements OnInit { - firstPage() { - this.currentPage = 0 - this.updateVisibleNeeds() - } + @Input({required: true}) needs!: Observable<Need[]> - editNeedsPerPage(amount: number) { - this.itemsPerPage = amount; - this.updateVisibleNeeds(); - } + visibleNeeds: Need[] = []; + currentPage: number = 0; + itemsPerPage: number = 5; + totalPages: number = 0; - updateVisibleNeeds() { - this.totalPages = Math.ceil(this.searchResults.length / this.itemsPerPage); - this.visibleNeeds = this.searchResults.slice(this.currentPage * this.itemsPerPage, (this.currentPage + 1) * this.itemsPerPage); - } + constructor( - resetVisibleNeeds() { - this.currentPage = 0; - this.updateVisibleNeeds(); - } + ) {} - currentSortAlgo: sortAlgo = sortByPriority; - sortSelection: string = 'sortByPriority'; + ngOnInit() { + this.needs.subscribe(needs => { + this.totalPages = Math.ceil(needs.length / this.itemsPerPage); + this.totalPages = Math.ceil(needs.length / this.itemsPerPage); + this.visibleNeeds = needs.slice(this.currentPage * this.itemsPerPage, (this.currentPage + 1) * this.itemsPerPage); + console.log(needs.length) + }) - SortingAlgoArrays: {func:sortAlgo,name:string, display:string[]}[] = [ - {func:sortByPriority,name:"sortByPriority", display:["Highest Priority", "Lowest Priority"]}, - {func:sortByName,name:"sortByName", display:["Name (A to Z)", "Name (Z to A)"]}, - {func:sortByLocation,name:"sortByLocation", display:["Location (A to Z)", "Location (Z to A)"]}, - {func:sortByCompletion,name:"sortByCompletion", display:["Most Completed", "Least Completed"]}, - {func:sortByGoal,name:"sortByGoal", display:["Largest Maximum Goal", "Smallest Maximum Goal"]}, - ]; - - @Output() currentNeed = new EventEmitter<Need>(); - - constructor( - private cupboardService: CupboardService, - private usersService: UsersService, - private authService: AuthService, - private toastService: ToastsService - ) {} - - refresh() { - this.cupboardService.getNeeds().subscribe(n => { - if (this.sortMode == 'Ascending') { - this.needs = n.sort(this.currentSortAlgo); - } else { - this.needs = n.sort(this.currentSortAlgo).reverse(); - } - this.searchResults = this.needs; - this.updateVisibleNeeds(); - }); - - const form = document.getElementById('search-form') as HTMLFormElement; - form.reset(); - this.search(null); } - ngOnInit(): void { - this.refresh() - - } - - changeSortMode(form : any) { - if (this.sortMode == 'Ascending'){ - this.sortMode = 'Descending' - } else { - this.sortMode = 'Ascending' + decrementPage() { + this.currentPage--; + this.updateVisibleNeeds(); } - this.search(form) - } - - private searchDelay: any; - 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 - - //remove previous search if it exists - if (this.searchDelay) { - clearTimeout(this.searchDelay); + incrementPage() { + this.currentPage++; + this.updateVisibleNeeds(); } - if (form) { - this.searchDelay = setTimeout(() => { - - if (form) { - //sorting based on algo selected - this.SortingAlgoArrays.forEach(algo => { - if(algo.name === this.sortSelection) { - this.currentSortAlgo = algo.func; - console.log("changed sorting algorithm to: ", algo.name + this.sortMode) - return - } - }); - - const currentSearchValue = form.search; //latest value of the search - this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => { - if (this.sortMode == 'Ascending') { - this.searchResults = n.sort(this.currentSortAlgo); - } else { - this.searchResults = n.sort(this.currentSortAlgo).reverse(); - } - this.updateVisibleNeeds(); - }); - } - }, 250); - } else { - //user has cleared the search bar, we can skip the timeout for a 1/4 second faster response - //clear timeout to stop pending search - clearTimeout(this.searchDelay); - this.searchResults = this.needs; - } - } - - delete(id : number) { - this.cupboardService.deleteNeed(id).subscribe(() => { - this.toastService.sendToast(ToastType.INFO, "Need deleted.") - this.needs = this.needs.filter(n => n.id !== id) - }) - this.refresh(); - } - 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); - } + lastPage() { + this.currentPage = this.totalPages - 1 + this.updateVisibleNeeds() + } - changeText(id : number, text : string) { - const span = document.getElementById('hover-status-label-' + id); - if (span) { - span.innerHTML = ' ' + text; + firstPage() { + this.currentPage = 0 + this.updateVisibleNeeds() } - } - 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, _) => { - console.error(err); - return of(); - })) - .subscribe(() => { - this.usersService.refreshBasket(); - }); - } else { - this.toastService.sendToast(ToastType.ERROR, "This need is already in your basket!") - } + editNeedsPerPage(amount: number) { + this.itemsPerPage = amount; + this.updateVisibleNeeds(); } - } - back() { - this.searchResults = this.needs; - } + updateVisibleNeeds() { + // this.totalPages = Math.ceil(this.needs.length / this.itemsPerPage); + // this.visibleNeeds = this.needs.slice(this.currentPage * this.itemsPerPage, (this.currentPage + 1) * this.itemsPerPage); + } - select(need : Need) { - //emit value - this.currentNeed.emit(need); - if (this.selectedNeed) { - //revert already selected need to previous style - console.log(need.id); - let button = document.getElementById('need-button-' + this.selectedNeed.id); - if (button) { - console.log(button) - button.style.background = 'lightgray'; - button.style.marginLeft = '0%'; - button.style.width = '98%'; - } - button = document.getElementById('need-edit-button-' + this.selectedNeed.id); - if (button) { - button.style.visibility = 'visible'; - } + resetVisibleNeeds() { + this.currentPage = 0; + this.updateVisibleNeeds(); } - //change selected need to selected style - this.selectedNeed = need; - let button = document.getElementById('need-button-' + need.id); - if (button) { - button.style.background = 'white'; - button.style.marginLeft = '4%'; - button.style.width = '100%'; - } - button = document.getElementById('need-edit-button-' + need.id); - if (button) { - button.style.visibility = 'hidden'; - } - } } |