aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsowgro <tpoke.ferrari@gmail.com>2025-04-02 23:27:27 -0400
committersowgro <tpoke.ferrari@gmail.com>2025-04-02 23:27:27 -0400
commit3e5422b90a09d1ed2cfffae56abf8dbe361f6c27 (patch)
tree3b3fdbd99a4b2a4f990b2f8d8543a80614492142
parent6b7c830eeefb6a6a28136a3faacf7713953a6138 (diff)
downloadJellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.tar.gz
JellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.tar.bz2
JellySolutions-3e5422b90a09d1ed2cfffae56abf8dbe361f6c27.zip
[incomplete] rearrange code to begin need-list abstraction
-rw-r--r--ufund-ui/src/app/components/cupboard/cupboard.component.html88
-rw-r--r--ufund-ui/src/app/components/cupboard/cupboard.component.ts189
-rw-r--r--ufund-ui/src/app/components/cupboard/sorting.ts58
-rw-r--r--ufund-ui/src/app/components/funding-basket/funding-basket.component.html70
-rw-r--r--ufund-ui/src/app/components/funding-basket/funding-basket.component.ts3
-rw-r--r--ufund-ui/src/app/components/need-list/need-list.component.html55
-rw-r--r--ufund-ui/src/app/components/need-list/need-list.component.ts301
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';
- }
- }
}