diff options
| author | Gunther6070 <haydenhartman10@yahoo.com> | 2025-04-05 13:44:33 -0400 | 
|---|---|---|
| committer | Gunther6070 <haydenhartman10@yahoo.com> | 2025-04-05 13:44:33 -0400 | 
| commit | ef52495d781a3adcec79bfbc9067f70f5ec3c8ab (patch) | |
| tree | e16e8cf36f1cafcf198d21d57a0b3a908116b3df /ufund-ui/src/app/components/need-list | |
| parent | d7c974a98de42f41f3ca16f961d2dee96a3c4313 (diff) | |
| parent | 0103ffc6f84d04433943c644ab759c1d04b5e681 (diff) | |
| download | JellySolutions-ef52495d781a3adcec79bfbc9067f70f5ec3c8ab.tar.gz JellySolutions-ef52495d781a3adcec79bfbc9067f70f5ec3c8ab.tar.bz2 JellySolutions-ef52495d781a3adcec79bfbc9067f70f5ec3c8ab.zip  | |
Merge branch 'main' into checkout-improvement
# Conflicts:
#	ufund-ui/src/app/components/funding-basket/funding-basket.component.html
#	ufund-ui/src/app/components/funding-basket/funding-basket.component.ts
Diffstat (limited to 'ufund-ui/src/app/components/need-list')
3 files changed, 39 insertions, 339 deletions
diff --git a/ufund-ui/src/app/components/need-list/need-list.component.css b/ufund-ui/src/app/components/need-list/need-list.component.css index e17609b..622b64a 100644 --- a/ufund-ui/src/app/components/need-list/need-list.component.css +++ b/ufund-ui/src/app/components/need-list/need-list.component.css @@ -1,9 +1,3 @@ -#header { -    display: flex; -    flex-direction: column; -    gap: 10px -} -  .needEntry {      background-color: #2e2e2e;      display: flex; @@ -17,33 +11,6 @@      gap: 15px  } -select { -    font-size: 14pt; -    padding: 5px; -} - -#searchArea { -    display: flex; - -    form { -        display: flex; -        width: 100%; -        gap: 10px; -    } - -    input[type=text] { -        display: flex; -        width: 100%; -    } -} - -#sortArea { -    display: flex; -    flex-direction: row; -    gap: 10px; -    align-items: center; -} -  .needName {      font-weight: bold;  } @@ -105,6 +72,10 @@ select {      gap: 5px;  } +.actionArea:empty { +    padding: 0; +} +  #page-selector {      display: flex;      align-items: center; 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 84f80dc..406bfa0 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)="editNeedsPerPage()" 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"> @@ -46,19 +20,9 @@                  <span>{{need.type.toString() == 'MONETARY' ? '$' : ''}}{{need.current}}/{{need.type.toString() == 'MONETARY' ? '$' : ''}}{{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 *ngIf="actionArea" class="actionArea"> +            <ng-container [ngTemplateOutlet]="actionArea" [ngTemplateOutletContext]="{$implicit: need}"/>          </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 ae6bc99..40af9f5 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,293 +1,58 @@ -import {Component, EventEmitter, Output} from '@angular/core'; +import {Component, Input, OnChanges, TemplateRef} from '@angular/core';  import {GoalType, 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; -}  @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); +export class NeedListComponent implements OnChanges { -  getPrefix(need: Need) { -      return (need.type === GoalType.MONETARY) ? "$" : ""; -  } +    @Input({required: true}) needs!: Need[] +    @Input() itemsPerPage: number = 5; +    @Input() actionArea: TemplateRef<any> | null = null -  decrementPage() { -    this.currentPage--; -    this.updateVisibleNeeds(); -  } +    visibleNeeds: Need[] = []; +    currentPage: number = 0; +    totalPages: number = 0; -  incrementPage() { -    this.currentPage++; -    this.updateVisibleNeeds(); -  } +    constructor( -  lastPage() { -      this.currentPage = this.totalPages - 1 -      this.updateVisibleNeeds() -  } +    ) {} -  firstPage() { -      this.currentPage = 0 -      this.updateVisibleNeeds() -  } - -  editNeedsPerPage() { -    if (this.itemsPerPage > this.searchResults.length) { -      this.itemsPerPage = this.searchResults.length; -    } -    if (this.itemsPerPage < 1) { -      this.itemsPerPage = 1; +    ngOnChanges() { +        this.updateVisibleNeeds()      } -    this.resetVisibleNeeds(); -  } - -  updateVisibleNeeds() { -    this.totalPages = Math.ceil(this.searchResults.length / this.itemsPerPage); -    this.visibleNeeds = this.searchResults.slice(this.currentPage * this.itemsPerPage, (this.currentPage + 1) * this.itemsPerPage); -  } - -  resetVisibleNeeds() { -    this.currentPage = 0; -    this.updateVisibleNeeds(); -  } -  currentSortAlgo: sortAlgo = sortByPriority; -  sortSelection: string = 'sortByPriority'; - -  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); +    getPrefix(need: Need) { +        return (need.type === GoalType.MONETARY) ? "$" : "";      } -  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); -  } - -  changeText(id : number, text : string) { -    const span = document.getElementById('hover-status-label-' + id); -    if (span) { -      span.innerHTML = ' ' + text; +    lastPage() { +        this.currentPage = this.totalPages - 1 +        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.toastService.sendToast(ToastType.INFO, "Need added to your basket!") -        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!") -      } +    firstPage() { +        this.currentPage = 0 +        this.updateVisibleNeeds()      } -  } - -  back() { -    this.searchResults = this.needs; -  } -  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'; -      } +    updateVisibleNeeds() { +        this.totalPages = Math.ceil(this.needs.length / this.itemsPerPage); +        this.visibleNeeds = this.needs.slice(this.currentPage * this.itemsPerPage, (this.currentPage + 1) * this.itemsPerPage);      } -      //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'; -      } -  }      protected readonly GoalType = GoalType;  }  | 
