From ef46ddd082bb91d0262363536d46fe3eb4da47be Mon Sep 17 00:00:00 2001 From: benal01 Date: Tue, 18 Mar 2025 09:42:05 -0400 Subject: back button on need page --- ufund-ui/src/app/components/need-page/need-page.component.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ufund-ui/src/app/components/need-page/need-page.component.html b/ufund-ui/src/app/components/need-page/need-page.component.html index 90fd459..e9c23bd 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.html +++ b/ufund-ui/src/app/components/need-page/need-page.component.html @@ -1,6 +1,5 @@ - +

Viewing Need: {{need?.name}}

-internal id: {{need?.id}}

Looking for

{{need?.type}}

-- cgit v1.2.3 From bc9d3417795d841b4cb3e9fb022f8d61448af946 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Tue, 1 Apr 2025 07:47:13 -0400 Subject: Added updated acceptance test plan --- etc/Acceptance Test Plan.xlsx | Bin 30698 -> 71297 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/etc/Acceptance Test Plan.xlsx b/etc/Acceptance Test Plan.xlsx index dd55e20..396cc1c 100644 Binary files a/etc/Acceptance Test Plan.xlsx and b/etc/Acceptance Test Plan.xlsx differ -- cgit v1.2.3 From 095e637a24e609cc21ef3ad446e20e520da12445 Mon Sep 17 00:00:00 2001 From: Akash Keshav <112591754+domesticchores@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:25:19 -0400 Subject: improved "OO Design Principles" section of the Design Doc. -ak --- docs/DesignDoc.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/DesignDoc.md b/docs/DesignDoc.md index 0a92bac..7f1c457 100644 --- a/docs/DesignDoc.md +++ b/docs/DesignDoc.md @@ -167,9 +167,13 @@ In our model tier we have a Need class, a User class, and a UserAuth class. The > _**[Sprint 1]** Name and describe the initial OO Principles that your team has considered in support of your design (and implementation) for this first Sprint._ - Law of Demeter: Classes only talk to nearby classes. + - This principle is used to ensure that unintended behavior is minimal, by making each class only talk to others that make sense in the scope of the application. For example, the `dashboard` component interacts with the `need-list` and `funding-basket` components because they are needed to display needs on the dashboard, but it does not interact with the `login` or `signup` components, as they are not needed in order to ensure the functionality of the dashboard. These are located in the ViewModel and Model Tiers. - Low Coupling: Limit the number of classes connected to each individual class. + - We use Low Coupling principles to ensure that only classes related in function are actually interacting with each other. In our Angular setup, classes interact with their respective services instead of sharing the data with other classes. `NeedService` connects to `need-page`, `need-list`, `funding-basket`, and `cupboard`, but the components themselves do not interact with each other. This is more efficient and prevents one component from stalling if another errors. Because the service exclusively handles CRUD operations, it will not cause the connected components to stall if it encounters an error. These examples are located in the ViewModel Tier. - Pure Fabrication: Using helper functions to split up larger classes into more managable chunks. + - For example, this principle is showcased in our `AuthService`. Instead of having the `UserService` handle user management and user authorization at the same time, we have split the authorization part into a new AuthService class to handle login, while the UserService handles just the CRUD operations pertaining to the user. These classes are located in the ViewModel Tier. - Single Responsibility: Each function should only have one function to prevent unintended errors. + - This principle is used in our `CupboardController`, as it's only functionality is to connect the front-end and back-end through our REST API. This means that cupboard-related operations are not backlogged by any other classes, which is efficient and prevents unintended behavior in the application. This can be seen in the Model Tier. > _**[Sprint 2, 3 & 4]** Will eventually address upto **4 key OO Principles** in your final design. Follow guidance in augmenting those completed in previous Sprints as indicated to you by instructor. Be sure to include any diagrams (or clearly refer to ones elsewhere in your Tier sections above) to support your claims._ -- cgit v1.2.3 From 91e8835b84b00bffc6db350f7cf6641c0d128a93 Mon Sep 17 00:00:00 2001 From: benal01 Date: Wed, 2 Apr 2025 10:27:48 -0400 Subject: negative and large input handling for need page amount --- .../src/app/components/need-list/need-list.component.html | 2 +- ufund-ui/src/app/components/need-list/need-list.component.ts | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) 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 c0501ba..c166152 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 @@ -16,7 +16,7 @@ {{sortMode === 'Ascending' ? 'arrow_upward': 'arrow_downward'}} - +
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 cd3d9bd..ed14d6a 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 @@ -82,9 +82,14 @@ export class NeedListComponent { this.updateVisibleNeeds(); } - editNeedsPerPage(amount: number) { - this.itemsPerPage = amount; - this.updateVisibleNeeds(); + editNeedsPerPage() { + if (this.itemsPerPage > this.searchResults.length) { + this.itemsPerPage = this.searchResults.length; + } + if (this.itemsPerPage < 1) { + this.itemsPerPage = 1; + } + this.resetVisibleNeeds(); } updateVisibleNeeds() { -- cgit v1.2.3 From 81414e1ce9223801585214d8d7a3bbf51f0ac5a7 Mon Sep 17 00:00:00 2001 From: benal01 Date: Wed, 2 Apr 2025 10:31:11 -0400 Subject: dollar label for monetary needs --- ufund-ui/src/app/components/need-list/need-list.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c166152..0d64c99 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 @@ -44,7 +44,7 @@
- {{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%) + {{need.type.toString() == 'MONETARY' ? '$' : ''}}{{need.current}}/{{need.type.toString() == 'MONETARY' ? '$' : ''}}{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%)
-- cgit v1.2.3 From 2b7c42ffacaaf884bc9497e975c0c3274e9f966e Mon Sep 17 00:00:00 2001 From: benal01 Date: Wed, 2 Apr 2025 10:33:13 -0400 Subject: dollar label in need page --- ufund-ui/src/app/components/need-page/need-page.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ufund-ui/src/app/components/need-page/need-page.component.html b/ufund-ui/src/app/components/need-page/need-page.component.html index 958dfa6..12e9b74 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.html +++ b/ufund-ui/src/app/components/need-page/need-page.component.html @@ -11,9 +11,9 @@ This goal is {{(((need?.current ?? 0)*100) / (need?.maxGoal ?? 0)).toFixed(0)}}% complete! - Target Goal: {{need.maxGoal}} + Target Goal: {{need.type.toString() == 'MONETARY' ? '$' : ''}}{{need.maxGoal}} - Amount Currently Collected: {{need.current}} + Amount Currently Collected: {{need.type.toString() == 'MONETARY' ? '$' : ''}}{{need.current}} Location: {{need.location}} -- cgit v1.2.3 From 4d382ccf9de889e4b339dd13220c3f761497e419 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Wed, 2 Apr 2025 16:08:52 -0400 Subject: Added dollar signs and other small additions to needs --- ufund-ui/src/app/components/cupboard/cupboard.component.ts | 8 ++------ ufund-ui/src/app/components/need-list/need-list.component.ts | 9 ++++++++- ufund-ui/src/app/models/Need.ts | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ufund-ui/src/app/components/cupboard/cupboard.component.ts b/ufund-ui/src/app/components/cupboard/cupboard.component.ts index 2230cd3..a4706b3 100644 --- a/ufund-ui/src/app/components/cupboard/cupboard.component.ts +++ b/ufund-ui/src/app/components/cupboard/cupboard.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import { CupboardService } from '../../services/cupboard.service'; -import { Need, GoalType } from '../../models/Need'; +import { Need } from '../../models/Need'; import { userType } from '../../models/User'; import { catchError, of } from 'rxjs'; import { NeedListComponent } from '../need-list/need-list.component'; @@ -90,7 +90,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 @@ -120,8 +120,4 @@ export class CupboardComponent implements OnInit { ); } - - destroy() { - - } } 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..2ec850e 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,5 +1,5 @@ import {Component, EventEmitter, Output} from '@angular/core'; -import {Need} from '../../models/Need'; +import {GoalType, Need} from '../../models/Need'; import {CupboardService} from '../../services/cupboard.service'; import {UsersService} from '../../services/users.service'; import {userType} from '../../models/User'; @@ -72,6 +72,10 @@ export class NeedListComponent { itemsPerPage: number = 5; totalPages: number = Math.ceil(this.needs.length / this.itemsPerPage); + getPrefix(need: Need) { + return (need.type === GoalType.MONETARY) ? "$" : ""; + } + decrementPage() { this.currentPage--; this.updateVisibleNeeds(); @@ -229,6 +233,7 @@ export class NeedListComponent { 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); @@ -278,5 +283,7 @@ export class NeedListComponent { button.style.visibility = 'hidden'; } } + + protected readonly GoalType = GoalType; } diff --git a/ufund-ui/src/app/models/Need.ts b/ufund-ui/src/app/models/Need.ts index 6cf7e76..588e745 100644 --- a/ufund-ui/src/app/models/Need.ts +++ b/ufund-ui/src/app/models/Need.ts @@ -12,6 +12,6 @@ export interface Need { } export enum GoalType { - MONETARY, - PHYSICAL + MONETARY = 'MONETARY', + PHYSICAL = 'PHYSICAL' } -- cgit v1.2.3 From bc23c624a760b33bb67b3c0df5fd3d8f39f36e77 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Wed, 2 Apr 2025 16:09:24 -0400 Subject: Added dollar signs and other small additions to needs --- ufund-ui/src/app/components/need-list/need-list.component.html | 2 +- ufund-ui/src/app/components/need-page/need-page.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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..593aebf 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 @@ -42,7 +42,7 @@
- {{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%) + {{getPrefix(need)}}{{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%)
diff --git a/ufund-ui/src/app/components/need-page/need-page.component.html b/ufund-ui/src/app/components/need-page/need-page.component.html index 522b710..3d362f5 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.html +++ b/ufund-ui/src/app/components/need-page/need-page.component.html @@ -11,7 +11,7 @@ This goal is {{(((need.current)*100) / (need.maxGoal)).toFixed(0)}}% complete! - Target Goal: {{need.maxGoal}} + Target Goal: {{(need.type === GoalType.MONETARY) ? "$" : ""}}{{need.maxGoal}} Amount Currently Collected: {{need.current}} -- cgit v1.2.3 From c561e9a5b36bafbb5e6f277b04f112941c2231a5 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Wed, 2 Apr 2025 16:56:27 -0400 Subject: Implemented new endpoint to get total number of users --- .../api/ufundapi/controller/UserController.java | 26 ++++++++++++++++++++++ .../ufund/api/ufundapi/persistence/UserDAO.java | 10 +++++++++ .../api/ufundapi/persistence/UserFileDAO.java | 7 ++++++ .../ufund/api/ufundapi/service/UserService.java | 10 +++++++++ 4 files changed, 53 insertions(+) diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java index a34e891..653a925 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java @@ -94,6 +94,32 @@ public class UserController { } + /** + * Responds to the GET request with the total number of users + * + * @param key The authentication key of the user + * @return ResponseEntity with amount and HTTP status of OK
+ * ResponseEntity with HTTP status of UNAUTHORIZED if user is not aa manager
+ * ResponseEntity with HTTP status of INTERNAL_SERVER_ERROR otherwise + */ + @GetMapping("/userCount") + public ResponseEntity getUserCount(@RequestHeader("jelly-api-key") String key) { + LOG.log(Level.INFO, "GET /userAmount"); + + try { + authService.keyHasAccessToCupboard(key); + int count = userService.getUserCount(); + return new ResponseEntity<>(count, HttpStatus.OK); + } catch (IllegalAccessException ex) { + LOG.log(Level.WARNING, ex.getLocalizedMessage()); + return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); + } catch (IOException ex) { + LOG.log(Level.SEVERE, ex.getLocalizedMessage()); + return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + + } + /** * Updates a User with the provided one * diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java index 29d46cf..27ba0b9 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java @@ -33,6 +33,16 @@ public interface UserDAO { */ User getUser(String username) throws IOException; + /** + * Retrieves the total count of users + * + * @return a {@link int amount} number of users + *
+ * + * @throws IOException if an issue with underlying storage + */ + int getUserCount() throws IOException; + /** * Creates and saves a {@linkplain User user} * diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java index ec94da8..7f1fadd 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java @@ -57,6 +57,13 @@ public class UserFileDAO implements UserDAO { } } + @Override + public int getUserCount() { + synchronized (users) { + return users.size(); + } + } + @Override public User getUser(String username) { synchronized (users) { diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java index 6e27f50..8b34e68 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java @@ -55,6 +55,16 @@ public class UserService { return userDAO.getUser(username); } + /** + * Returns the total number of users + * + * @return The number of users + * @throws IOException If there was any problem saving the file + */ + public int getUserCount() throws IOException { + return userDAO.getUserCount(); + } + /** * Updates a user * -- cgit v1.2.3 From f8641c164ddc3a0ae4e8e81aa8f5595ce751b17c Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Wed, 2 Apr 2025 16:57:07 -0400 Subject: Implemented new endpoint to get total number of users --- .../src/main/java/com/ufund/api/ufundapi/controller/UserController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java index 653a925..c6e622c 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java @@ -102,7 +102,7 @@ public class UserController { * ResponseEntity with HTTP status of UNAUTHORIZED if user is not aa manager
* ResponseEntity with HTTP status of INTERNAL_SERVER_ERROR otherwise */ - @GetMapping("/userCount") + @GetMapping("/count") public ResponseEntity getUserCount(@RequestHeader("jelly-api-key") String key) { LOG.log(Level.INFO, "GET /userAmount"); -- cgit v1.2.3 From f88e5d727ae42d0e27ae7949d0f0d4189dda464d Mon Sep 17 00:00:00 2001 From: sowgro Date: Wed, 2 Apr 2025 21:08:38 -0400 Subject: [incomplete] checkout flow improvement --- .../funding-basket/funding-basket.component.html | 39 +------------- .../funding-basket/funding-basket.component.ts | 60 ++++++---------------- 2 files changed, 18 insertions(+), 81 deletions(-) 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..bba66a3 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,36 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Funding Basket

@@ -56,14 +23,10 @@ {{need.current}}/{{need.maxGoal}} ({{((need.current / need.maxGoal) * 100).toFixed(0)}}%)
- - - -
- + 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..18bb9b8 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 @@ -23,7 +23,6 @@ export class FundingBasketComponent implements OnInit { ) {} @ViewChild("contribution") contribution?: Input; - @Input() isValid: boolean = true; // this is for login rerouting ngOnInit(): void { @@ -37,58 +36,33 @@ export class FundingBasketComponent implements OnInit { } async checkout() { - this.isValid = true; - for (let c of document.querySelectorAll('.contribution')!) { - let contribution = c as HTMLInputElement; - contribution.setAttribute("style", ""); - if (contribution.value == '' || contribution.valueAsNumber <= 0) { - this.isValid = false; + let order: { id: number, quantity: number }[] = [] + for (let contribution of document.querySelectorAll('.contribution')!) { + if (contribution.value == '' || contribution.valueAsNumber <= 0) { contribution.setAttribute("style", "border-color: #ff0000"); this.toastService.sendToast(ToastType.ERROR, "Invalid input in funding basket!") - - setTimeout(() => { - contribution.setAttribute("style", "border-color: #ffffff"); - }, 3000); + return; } + order.push({id: +contribution.id, quantity: contribution.valueAsNumber}); } - // if (this.usersService.getBasket().value != await firstValueFrom(this.usersService.getUser(1)) - // for (let c of this.usersService.getBasket().value) { - // if (c == null) { - // this.isValid = false; - // this.statusText.next("One or more needs have been deleted") - // } else { - // this.statusText.next("test") - // } - // } - if (this.isValid) { - for (let c of document.querySelectorAll('.contribution')!) { - let contribution = c as HTMLInputElement; + + for (let c of document.querySelectorAll('.contribution')!) { + let contribution = c as HTMLInputElement; + try { let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id)); + await firstValueFrom(this.cupboardService.checkoutNeed(need.id, +contribution.value)); need.current += +contribution.value; this.usersService.removeNeed(+need.id); - this.cupboardService.checkoutNeed(need.id, +contribution.value) - .pipe(catchError((ex, _) => { - if (ex.status == 500) { - this.toastService.sendToast(ToastType.ERROR, 'Fields cannot be blank'); - } else if (ex.status == 400) { - this.toastService.sendToast(ToastType.ERROR, ex.error); - } else { - this.toastService.sendToast(ToastType.ERROR, 'Error on creating need'); - } - return new Observable(); - })) - .subscribe((result) => { - if (result) { - //this.needList?.refresh() - } else { - console.log('need update failed'); - } - this.toastService.sendToast(ToastType.INFO, "Checkout successful"); - }); + this.toastService.sendToast(ToastType.INFO, "Checkout successful"); + } catch (ex: any) { + this.toastService.sendToast(ToastType.ERROR, ex.error); } } } - + resetColor(ev: any) { + console.log(ev); + (ev.target as HTMLInputElement).setAttribute("style", "border-color: unset") + } } -- cgit v1.2.3 From 5be753d9826629bdcaff5a7e48ba6b81e8e1e7cf Mon Sep 17 00:00:00 2001 From: benal01 Date: Wed, 2 Apr 2025 22:25:11 -0400 Subject: placeholder for unset need images --- ufund-ui/public/placeholder.png | Bin 0 -> 605690 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ufund-ui/public/placeholder.png diff --git a/ufund-ui/public/placeholder.png b/ufund-ui/public/placeholder.png new file mode 100644 index 0000000..5b86fb7 Binary files /dev/null and b/ufund-ui/public/placeholder.png differ -- cgit v1.2.3 From 010d2ed677e1fca33cee0963a897492f5902cb89 Mon Sep 17 00:00:00 2001 From: benal01 Date: Wed, 2 Apr 2025 22:25:30 -0400 Subject: need image support in need page --- .../components/need-page/need-page.component.css | 11 +++++++ .../components/need-page/need-page.component.html | 35 ++++++++++++---------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/ufund-ui/src/app/components/need-page/need-page.component.css b/ufund-ui/src/app/components/need-page/need-page.component.css index 844410f..e634c8f 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.css +++ b/ufund-ui/src/app/components/need-page/need-page.component.css @@ -31,6 +31,7 @@ .left { display: flex; flex-direction: column; + width : 50%; } .right { @@ -40,6 +41,16 @@ } } +.need-image { + width: 80%; + height: auto; + aspect-ratio: 16/9; + object-fit: cover; + border-radius: 10px; + box-shadow: rgb(0, 40, 70) 0 0 50px; + +} + .urgent { font-size: 11pt; background-color: rgba(255, 165, 0, 0.27); diff --git a/ufund-ui/src/app/components/need-page/need-page.component.html b/ufund-ui/src/app/components/need-page/need-page.component.html index 3d362f5..210e444 100644 --- a/ufund-ui/src/app/components/need-page/need-page.component.html +++ b/ufund-ui/src/app/components/need-page/need-page.component.html @@ -1,9 +1,6 @@

{{need.name}}

{{need.type}} GOAL - - Need image -

{{need.description}}

@@ -11,25 +8,33 @@ This goal is {{(((need.current)*100) / (need.maxGoal)).toFixed(0)}}% complete!
+
+
Target Goal: {{(need.type === GoalType.MONETARY) ? "$" : ""}}{{need.maxGoal}} Amount Currently Collected: {{need.current}} Location: {{need.location}} - Urgency: - Not urgent - URGENT - - -
- Tags: -
    -
  • -

    {{tag}}

    -
  • -
+ Urgency: + Not urgent + URGENT + + +
+ Tags: +
    +
  • +

    {{tag}}

    +
  • +
+
+
+
+ Need image +
+
- Need image + Need image
-- cgit v1.2.3 From cb6463630446503d441b37f3d62ec2d064b00269 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 07:56:54 -0400 Subject: Added dashboard statistics --- .../api/ufundapi/controller/UserController.java | 2 +- .../components/dashboard/dashboard.component.ts | 37 +++++++++++++++------- ufund-ui/src/app/services/users.service.ts | 13 ++++++++ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java index c6e622c..6953276 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java @@ -108,7 +108,7 @@ public class UserController { try { authService.keyHasAccessToCupboard(key); - int count = userService.getUserCount(); + String count = String.valueOf(userService.getUserCount()); return new ResponseEntity<>(count, HttpStatus.OK); } catch (IllegalAccessException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.ts b/ufund-ui/src/app/components/dashboard/dashboard.component.ts index c94b5c6..8c397ff 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.ts +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.ts @@ -1,10 +1,10 @@ import {Component, OnInit} from '@angular/core'; import {AuthService} from '../../services/auth.service'; import {Router} from '@angular/router'; -import {Need} from '../../models/Need'; import {CupboardService} from '../../services/cupboard.service'; -import {firstValueFrom} from 'rxjs'; import {UsersService} from '../../services/users.service'; +import {BehaviorSubject} from 'rxjs'; +import {GoalType, Need} from '../../models/Need'; @Component({ selector: 'app-dashboard', @@ -14,9 +14,10 @@ import {UsersService} from '../../services/users.service'; }) export class DashboardComponent implements OnInit{ - topNeeds?: Need[] - almostThere?: Need[] - inBasket?: Need[] + protected count = new BehaviorSubject(undefined) + protected totalDonations = new BehaviorSubject(undefined) + protected fulfilledNeeds = new BehaviorSubject(undefined) + protected mostFulfilledNeeds = new BehaviorSubject(undefined) constructor( protected authService: AuthService, @@ -32,14 +33,28 @@ export class DashboardComponent implements OnInit{ return } - firstValueFrom(this.cupboardService.getNeeds()).then(r => { - this.topNeeds = r.sort((a, b) => b.current - a.current) - this.almostThere = r.sort((a, b) => a.current/a.maxGoal - b.current/b.maxGoal) - }) + this.userService.getCount().subscribe(count => this.count.next(count)) + this.cupboardService.getNeeds().subscribe(needs => { + let fulfilledNeeds = 0 + let totalValue = 0 + for (let need of needs) { + let needPercent = need.current / need.maxGoal + if (needPercent >= 1) { + fulfilledNeeds++ + this.fulfilledNeeds.next(fulfilledNeeds) + } + if (need.type === GoalType.MONETARY) { + totalValue += need.current + this.totalDonations.next(totalValue) + } - this.userService.getBasket().subscribe(r => { - this.inBasket = r; + } + needs.sort((a, b) => b.current/b.maxGoal - a.current/a.maxGoal) + needs = needs.filter(a => a.current != 0) + this.mostFulfilledNeeds.next(needs.slice(0, 5)) }) + + } } diff --git a/ufund-ui/src/app/services/users.service.ts b/ufund-ui/src/app/services/users.service.ts index 4080ebf..080c394 100644 --- a/ufund-ui/src/app/services/users.service.ts +++ b/ufund-ui/src/app/services/users.service.ts @@ -21,6 +21,15 @@ export class UsersService { }) }); + httpOptions2 = () => ({ + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + "jelly-api-key": this.authService.getApiKey() + }), + 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, @@ -35,6 +44,10 @@ export class UsersService { return this.http.get(`${this.url}/${id}`, this.httpOptions()) } + getCount(): Observable { + return this.http.get(`${this.url}/count`, this.httpOptions2()) + } + updateUser(user: User): Observable { console.log(`${this.url}/${user.username}`, user, this.httpOptions) return this.http.put(`${this.url}/${user.username}`, user, this.httpOptions()) -- cgit v1.2.3 From 27b70a790a6418aa6702f950a0f85f1d23f38ff6 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 07:58:13 -0400 Subject: Added dollar signs and other small additions to needs --- ufund-ui/src/app/components/dashboard/dashboard.component.html | 7 ++++++- .../src/app/components/mini-need-list/mini-need-list.component.css | 2 +- .../app/components/mini-need-list/mini-need-list.component.html | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.html b/ufund-ui/src/app/components/dashboard/dashboard.component.html index 2d7b4c3..69ae66e 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.html +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.html @@ -4,7 +4,12 @@ _ Registered users + {{count | async}} _ Needs with overflow -_ Needs in peoples baskets +_ Fulfilled needs + {{fulfilledNeeds | async}} +_ Most fulfilled needs + _ Total monetary contributions +${{totalDonations | async}} _ diff --git a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css index ac456ab..090bea9 100644 --- a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css +++ b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css @@ -23,7 +23,7 @@ padding: 10px; gap: 10px; justify-content: start; - overflow: clip; + overflow: auto; } .needEntry { diff --git a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html index a2de9e5..9febfa5 100644 --- a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html +++ b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html @@ -1,6 +1,6 @@
-- cgit v1.2.3 From d7cbf88df5d8cb9e5b8feb563b787a3ac20816aa Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 07:58:13 -0400 Subject: Updated statistics on dashboard --- ufund-ui/src/app/components/dashboard/dashboard.component.html | 7 ++++++- .../src/app/components/mini-need-list/mini-need-list.component.css | 2 +- .../app/components/mini-need-list/mini-need-list.component.html | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.html b/ufund-ui/src/app/components/dashboard/dashboard.component.html index 2d7b4c3..69ae66e 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.html +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.html @@ -4,7 +4,12 @@ _ Registered users + {{count | async}} _ Needs with overflow -_ Needs in peoples baskets +_ Fulfilled needs + {{fulfilledNeeds | async}} +_ Most fulfilled needs + _ Total monetary contributions +${{totalDonations | async}} _ diff --git a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css index ac456ab..090bea9 100644 --- a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css +++ b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.css @@ -23,7 +23,7 @@ padding: 10px; gap: 10px; justify-content: start; - overflow: clip; + overflow: auto; } .needEntry { diff --git a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html index a2de9e5..9febfa5 100644 --- a/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html +++ b/ufund-ui/src/app/components/mini-need-list/mini-need-list.component.html @@ -1,6 +1,6 @@
-- cgit v1.2.3 From 8cdf84ae4a6765db8f462cc71e2685c1d3514f08 Mon Sep 17 00:00:00 2001 From: benal01 Date: Thu, 3 Apr 2025 08:08:08 -0400 Subject: re-adding resources folder --- ufund-api/src/main/resources/application.properties | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ufund-api/src/main/resources/application.properties diff --git a/ufund-api/src/main/resources/application.properties b/ufund-api/src/main/resources/application.properties new file mode 100644 index 0000000..c742063 --- /dev/null +++ b/ufund-api/src/main/resources/application.properties @@ -0,0 +1,11 @@ +server.error.include-message=always + +cupboard.file=data/cupboard.json +users.file=data/users.json +authKeys.file=data/userAuths.json + +spring.jackson.mapper.auto-detect-getters=false +spring.jackson.mapper.auto-detect-setters=false +spring.jackson.mapper.auto-detect-is-getters=false +spring.jackson.mapper.auto-detect-creators=false +spring.jackson.mapper.auto-detect-fields=false \ No newline at end of file -- cgit v1.2.3 From 84cb4b31da27c0db49b933a56a1de563121ceb60 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 12:59:54 -0400 Subject: Updated styling on signup page --- .../src/app/components/signup/signup.component.css | 27 +++++++++++++++++----- .../app/components/signup/signup.component.html | 9 ++++---- .../src/app/components/signup/signup.component.ts | 9 ++++---- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/ufund-ui/src/app/components/signup/signup.component.css b/ufund-ui/src/app/components/signup/signup.component.css index 429bc42..aa90e04 100644 --- a/ufund-ui/src/app/components/signup/signup.component.css +++ b/ufund-ui/src/app/components/signup/signup.component.css @@ -3,15 +3,26 @@ align-items: center; justify-content: center; height: 100%; - margin-top: -66px + margin-top: -66px; + background: rgba(0, 0, 0, .65) url("https://4kwallpapers.com/images/walls/thumbs_2t/13136.png"); + background-blend-mode: darken; + background-size: cover; } #box { display: flex; flex-direction: column; - /*max-width: 300px;*/ + max-width: 500px; gap: 10px; + backdrop-filter: blur(25px); + background-color: rgba(0, 0, 0, 0.1); + padding: 30px; + color: white; + border-radius: 5px; + border-style: solid; + border-width: 1px; + border-color: rgb(140, 140, 255); & > div { display: flex; @@ -19,6 +30,11 @@ } } +#password { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + .border { border-style: solid; border-width: 1px; @@ -34,6 +50,8 @@ width: 100%; appearance: none; overflow: hidden; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; /*margin-top: -5px;*/ } @@ -57,13 +75,10 @@ #passReq { display: flex; flex-direction: column; + margin-top: 10px; } #box > div { - display: flex; - flex-direction: row; - align-items: start; - gap: 20px; div { display: flex; diff --git a/ufund-ui/src/app/components/signup/signup.component.html b/ufund-ui/src/app/components/signup/signup.component.html index 84f15e4..ef2fc27 100644 --- a/ufund-ui/src/app/components/signup/signup.component.html +++ b/ufund-ui/src/app/components/signup/signup.component.html @@ -7,13 +7,12 @@
- + {{passwordStatusText | async}} -
- -
- {{requirement.value?"check":"close"}} {{requirement.title}} +
+ {{requirement.value?"check":"close"}} {{requirement.title}} +
diff --git a/ufund-ui/src/app/components/signup/signup.component.ts b/ufund-ui/src/app/components/signup/signup.component.ts index 9c37211..2762d03 100644 --- a/ufund-ui/src/app/components/signup/signup.component.ts +++ b/ufund-ui/src/app/components/signup/signup.component.ts @@ -1,4 +1,4 @@ -import {Component} from '@angular/core'; +import {Component, ElementRef, ViewChild} from '@angular/core'; import {UsersService} from '../../services/users.service'; import {Router} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; @@ -29,6 +29,7 @@ export class SignupComponent { protected ableToCreateAccount = new BehaviorSubject(false) protected passwordRequirements: PasswordRequirements = new PasswordRequirements() protected strength = new BehaviorSubject(0) + @ViewChild("username") usernameInput!: ElementRef constructor( protected usersService: UsersService, @@ -56,11 +57,11 @@ export class SignupComponent { validate(username: string, passConfirm:string, password: string) { this.passwordsMatch.next(false) - this.usernameStatusText.next("") + this.usernameInput.nativeElement.setAttribute("style", "") this.checkPasswordStrength(password); if (username === "") { - this.usernameStatusText.next("Username field can't be blank") + this.usernameInput.nativeElement.setAttribute("style", "border-color: #ff0000") } if (passConfirm && password === passConfirm) { @@ -105,8 +106,6 @@ export class SignupComponent { this.passwordStatusText.next("") } else if (strength == 0) { this.passwordStatusText.next("") - } else { - this.passwordStatusText.next("Password must meet requirements") } this.strength.next(strength) -- cgit v1.2.3 From 2423f4ee67e7e9079e12ecde51326472308cf22f Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 13:00:38 -0400 Subject: Added fulfilled needs list dashboard --- .../src/app/components/dashboard/dashboard.component.html | 3 +-- ufund-ui/src/app/components/dashboard/dashboard.component.ts | 12 +++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.html b/ufund-ui/src/app/components/dashboard/dashboard.component.html index 69ae66e..2af467c 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.html +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.html @@ -5,9 +5,8 @@ _ Registered users {{count | async}} -_ Needs with overflow _ Fulfilled needs - {{fulfilledNeeds | async}} + _ Most fulfilled needs _ Total monetary contributions diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.ts b/ufund-ui/src/app/components/dashboard/dashboard.component.ts index 8c397ff..9bf7627 100644 --- a/ufund-ui/src/app/components/dashboard/dashboard.component.ts +++ b/ufund-ui/src/app/components/dashboard/dashboard.component.ts @@ -16,7 +16,8 @@ export class DashboardComponent implements OnInit{ protected count = new BehaviorSubject(undefined) protected totalDonations = new BehaviorSubject(undefined) - protected fulfilledNeeds = new BehaviorSubject(undefined) + protected totalNeeds = new BehaviorSubject(undefined) + protected fulfilledNeeds = new BehaviorSubject(undefined) protected mostFulfilledNeeds = new BehaviorSubject(undefined) constructor( @@ -35,22 +36,19 @@ export class DashboardComponent implements OnInit{ this.userService.getCount().subscribe(count => this.count.next(count)) this.cupboardService.getNeeds().subscribe(needs => { - let fulfilledNeeds = 0 let totalValue = 0 for (let need of needs) { - let needPercent = need.current / need.maxGoal - if (needPercent >= 1) { - fulfilledNeeds++ - this.fulfilledNeeds.next(fulfilledNeeds) - } if (need.type === GoalType.MONETARY) { totalValue += need.current this.totalDonations.next(totalValue) } } + this.fulfilledNeeds.next(needs.filter(a => ((a.current / a.maxGoal)) >= 1)) needs.sort((a, b) => b.current/b.maxGoal - a.current/a.maxGoal) + needs = needs.filter(a => a.current != 0) + this.totalNeeds.next(needs.length) this.mostFulfilledNeeds.next(needs.slice(0, 5)) }) -- cgit v1.2.3 From 26b4a37cb91dfe5551f3e227512cd5ceff897d54 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 14:49:04 -0400 Subject: Changes to cupboard on front end and back end to try and fix bugs --- .../ufundapi/controller/CupboardController.java | 21 +++++++++++---- .../funding-basket/funding-basket.component.ts | 30 +++++++++++++--------- ufund-ui/src/app/services/cupboard.service.ts | 5 ++-- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java index 12fb0a9..2cf8647 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java @@ -1,6 +1,7 @@ package com.ufund.api.ufundapi.controller; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -189,12 +190,22 @@ public class CupboardController { * @return OK if successful, other statuses if failure */ @PutMapping("/checkout") - public ResponseEntity checkoutNeeds(@RequestBody Map data, @RequestHeader("jelly-api-key") String key) { - int needID = data.get("needID"); - int checkoutAmount = data.get("amount"); - LOG.log(Level.INFO, "PUT /need/checkout body={0}", data); + public ResponseEntity checkoutNeeds(@RequestBody List> data, @RequestHeader("jelly-api-key") String key) { + LOG.log(Level.INFO, "PUT /cupboard/checkout body={0}", data); try { - cupboardService.checkoutNeed(needID, checkoutAmount, key); + authService.keyIsValid(key); + + for (Map map : data) { + int needID = map.get("needID"); + if (cupboardService.getNeed(needID) != null) { + return new ResponseEntity<>("One or more need is invalid, please refresh.", HttpStatus.BAD_REQUEST); + } + } + for (Map map : data) { + int needID = map.get("needID"); + int checkoutAmount = map.get("amount"); + cupboardService.checkoutNeed(needID, checkoutAmount, key); + } return new ResponseEntity<>(HttpStatus.OK); } catch (IllegalArgumentException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); 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 18bb9b8..015d5b5 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 @@ -47,22 +47,28 @@ export class FundingBasketComponent implements OnInit { order.push({id: +contribution.id, quantity: contribution.valueAsNumber}); } - for (let c of document.querySelectorAll('.contribution')!) { - let contribution = c as HTMLInputElement; - try { - let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id)); - await firstValueFrom(this.cupboardService.checkoutNeed(need.id, +contribution.value)); - need.current += +contribution.value; - this.usersService.removeNeed(+need.id); - this.toastService.sendToast(ToastType.INFO, "Checkout successful"); - } catch (ex: any) { - this.toastService.sendToast(ToastType.ERROR, ex.error); - } + try { + this.cupboardService.checkoutNeed(order) + } catch (ex:any) { + this.toastService.sendToast(ToastType.ERROR, ex.error); + return } + + console.log(order) + + for (let contribution of order) { + let need = await firstValueFrom(this.cupboardService.getNeed(contribution.id)) + need.current += contribution.quantity; + this.usersService.removeNeed(need.id); + this.toastService.sendToast(ToastType.INFO, "Checkout successful"); + } + + // this.usersService.getBasket().subscribe(console.log) + // this.usersService.refreshBasket() } resetColor(ev: any) { - console.log(ev); + // console.log(ev); (ev.target as HTMLInputElement).setAttribute("style", "border-color: unset") } } diff --git a/ufund-ui/src/app/services/cupboard.service.ts b/ufund-ui/src/app/services/cupboard.service.ts index 9232c0c..786973e 100644 --- a/ufund-ui/src/app/services/cupboard.service.ts +++ b/ufund-ui/src/app/services/cupboard.service.ts @@ -47,7 +47,8 @@ export class CupboardService { return this.http.delete(`${this.url}/${id}`, this.httpOptions()) } - checkoutNeed(id: number, quantity: number) { - return this.http.put(`${this.url}/checkout`, {needID: id, amount: quantity}, this.httpOptions()) + checkoutNeed(data: {id: number, quantity: number}[]) { + console.log("GOT HERE") + return this.http.put(`${this.url}/checkout`, data, this.httpOptions()) } } -- cgit v1.2.3 From 75f5ad5fb154811d7acd236687bb7f30bb7c10aa Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 15:35:12 -0400 Subject: Fixed incognito race condition and checkout bugs --- .../ufundapi/controller/CupboardController.java | 4 ++-- .../funding-basket/funding-basket.component.ts | 23 ++++++---------------- .../src/app/components/toast/toast.component.ts | 1 - ufund-ui/src/app/services/cupboard.service.ts | 3 +-- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java index 2cf8647..075878a 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java @@ -197,13 +197,13 @@ public class CupboardController { for (Map map : data) { int needID = map.get("needID"); - if (cupboardService.getNeed(needID) != null) { + if (cupboardService.getNeed(needID) == null) { return new ResponseEntity<>("One or more need is invalid, please refresh.", HttpStatus.BAD_REQUEST); } } for (Map map : data) { int needID = map.get("needID"); - int checkoutAmount = map.get("amount"); + int checkoutAmount = map.get("quantity"); cupboardService.checkoutNeed(needID, checkoutAmount, key); } return new ResponseEntity<>(HttpStatus.OK); 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 015d5b5..5d94124 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 {firstValueFrom} from 'rxjs'; import {AuthService} from '../../services/auth.service'; import {ToastsService, ToastType} from '../../services/toasts.service'; @@ -32,11 +32,10 @@ export class FundingBasketComponent implements OnInit { } this.usersService.refreshBasket(); - // this.usersService.removeNeed(); <- call this to remove } async checkout() { - let order: { id: number, quantity: number }[] = [] + let order: { needID: number, quantity: number }[] = [] for (let contribution of document.querySelectorAll('.contribution')!) { if (contribution.value == '' || contribution.valueAsNumber <= 0) { @@ -44,31 +43,21 @@ export class FundingBasketComponent implements OnInit { this.toastService.sendToast(ToastType.ERROR, "Invalid input in funding basket!") return; } - order.push({id: +contribution.id, quantity: contribution.valueAsNumber}); + order.push({needID: +contribution.id, quantity: contribution.valueAsNumber}); } try { - this.cupboardService.checkoutNeed(order) + await firstValueFrom(this.cupboardService.checkoutNeed(order)) } catch (ex:any) { this.toastService.sendToast(ToastType.ERROR, ex.error); return } - console.log(order) - - for (let contribution of order) { - let need = await firstValueFrom(this.cupboardService.getNeed(contribution.id)) - need.current += contribution.quantity; - this.usersService.removeNeed(need.id); - this.toastService.sendToast(ToastType.INFO, "Checkout successful"); - } - - // this.usersService.getBasket().subscribe(console.log) - // this.usersService.refreshBasket() + order.forEach(contribution => this.usersService.removeNeed(contribution.needID)) + this.toastService.sendToast(ToastType.INFO, "Checkout successful"); } resetColor(ev: any) { - // console.log(ev); (ev.target as HTMLInputElement).setAttribute("style", "border-color: unset") } } diff --git a/ufund-ui/src/app/components/toast/toast.component.ts b/ufund-ui/src/app/components/toast/toast.component.ts index 47fd7ff..6bbae34 100644 --- a/ufund-ui/src/app/components/toast/toast.component.ts +++ b/ufund-ui/src/app/components/toast/toast.component.ts @@ -21,7 +21,6 @@ export class ToastComponent implements OnInit{ } hide() { - console.log(this.toastDiv, typeof this.toastDiv) this.toastDiv.nativeElement.classList.add('hide') } diff --git a/ufund-ui/src/app/services/cupboard.service.ts b/ufund-ui/src/app/services/cupboard.service.ts index 786973e..1060476 100644 --- a/ufund-ui/src/app/services/cupboard.service.ts +++ b/ufund-ui/src/app/services/cupboard.service.ts @@ -47,8 +47,7 @@ export class CupboardService { return this.http.delete(`${this.url}/${id}`, this.httpOptions()) } - checkoutNeed(data: {id: number, quantity: number}[]) { - console.log("GOT HERE") + checkoutNeed(data: {needID: number, quantity: number}[]) { return this.http.put(`${this.url}/checkout`, data, this.httpOptions()) } } -- cgit v1.2.3 From 8c38792e8e257cf264d5739e80e085c824ccecd8 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Thu, 3 Apr 2025 15:54:36 -0400 Subject: Fixed broken tests --- .../controller/CupboardControllerTest.java | 48 +++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java index 8572ec6..7ea4455 100644 --- a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java +++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java @@ -1,6 +1,7 @@ package com.ufund.api.ufundapi.controller; import java.io.IOException; +import java.util.List; import java.util.Map; import static java.util.Map.entry; @@ -418,12 +419,14 @@ public class CupboardControllerTest { @Test public void checkoutNeeds() throws IOException, IllegalAccessException { + when(mockCupboardService.getNeed(0)).thenReturn(new Need("name", "image", "location", 0, 10, GoalType.MONETARY, true, "a")); doNothing().when(mockCupboardService).checkoutNeed(0, 20, key); - - Map needMap = Map.ofEntries( - entry("needID", 0), - entry("amount", 20) + var needMap = List.of( + Map.ofEntries( + entry("needID", 0), + entry("quantity", 20) + ) ); var res = cupboardController.checkoutNeeds(needMap, key); @@ -435,9 +438,15 @@ public class CupboardControllerTest { public void checkoutNeedsBadRequest() throws IOException, IllegalAccessException { doThrow(new IllegalArgumentException()).when(mockCupboardService).checkoutNeed(0, 20, key); - Map needMap = Map.ofEntries( - entry("needID", 0), - entry("amount", 20) + var needMap = List.of( + Map.ofEntries( + entry("needID", 0), + entry("quantity", 20) + ), + Map.ofEntries( + entry("needID", 2), + entry("quantity", 30) + ) ); var res = cupboardController.checkoutNeeds(needMap, key); @@ -447,11 +456,17 @@ public class CupboardControllerTest { @Test public void checkoutNeedsUnauthorized() throws IOException, IllegalAccessException { - doThrow(new IllegalAccessException()).when(mockCupboardService).checkoutNeed(0, 20, key); - - Map needMap = Map.ofEntries( - entry("needID", 0), - entry("amount", 20) + doThrow(new IllegalAccessException()).when(mockAuthService).keyIsValid(key); + + var needMap = List.of( + Map.ofEntries( + entry("needID", 0), + entry("quantity", 20) + ), + Map.ofEntries( + entry("needID", 2), + entry("quantity", 30) + ) ); var res = cupboardController.checkoutNeeds(needMap, key); @@ -461,11 +476,14 @@ public class CupboardControllerTest { @Test public void checkoutNeedsInternalError() throws IOException, IllegalAccessException { + when(mockCupboardService.getNeed(0)).thenReturn(new Need("name", "image", "location", 0, 10, GoalType.MONETARY, true, "a")); doThrow(new IOException()).when(mockCupboardService).checkoutNeed(0, 20, key); - Map needMap = Map.ofEntries( - entry("needID", 0), - entry("amount", 20) + var needMap = List.of( + Map.ofEntries( + entry("needID", 0), + entry("quantity", 20) + ) ); var res = cupboardController.checkoutNeeds(needMap, key); -- cgit v1.2.3 From 0a876b31609144c62f312ea59f074f5f79b67ae7 Mon Sep 17 00:00:00 2001 From: Gunther6070 Date: Fri, 4 Apr 2025 16:13:25 -0400 Subject: Made every invalid need input in basket turn red when invalid --- .../components/funding-basket/funding-basket.component.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 5d94124..a39b4f3 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 @@ -36,16 +36,21 @@ export class FundingBasketComponent implements OnInit { async checkout() { let order: { needID: number, quantity: number }[] = [] + let isNotValid = false for (let contribution of document.querySelectorAll('.contribution')!) { if (contribution.value == '' || contribution.valueAsNumber <= 0) { + isNotValid = true contribution.setAttribute("style", "border-color: #ff0000"); - this.toastService.sendToast(ToastType.ERROR, "Invalid input in funding basket!") - return; } order.push({needID: +contribution.id, quantity: contribution.valueAsNumber}); } + if (isNotValid) { + this.toastService.sendToast(ToastType.ERROR, "Invalid input in funding basket!") + return; + } + try { await firstValueFrom(this.cupboardService.checkoutNeed(order)) } catch (ex:any) { @@ -58,6 +63,9 @@ export class FundingBasketComponent implements OnInit { } resetColor(ev: any) { + for (let contribution of document.querySelectorAll('.contribution')!) { + + } (ev.target as HTMLInputElement).setAttribute("style", "border-color: unset") } } -- cgit v1.2.3