From 1c4e3d52f5e4969ee46b89df4cc0bb8ad08f0957 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 26 Oct 2025 20:40:47 -0400 Subject: [PATCH 1/5] refactor:updates get user Invtes method to get the images --- .../api/demo/controllers/UserController.java | 8 ++++++++ .../java/com/api/demo/dtos/DTOConverter.java | 11 +++++++++++ .../java/com/api/demo/dtos/UserInviteDTO.java | 7 +++++-- .../com/api/demo/repos/UserRepository.java | 18 +++++++++--------- .../com/api/demo/services/UserServiceTest.java | 8 ++++---- 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java index adc62193..0808a689 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java @@ -5,6 +5,7 @@ import com.api.demo.dtos.EventDTO; import com.api.demo.dtos.LoginRequest; import com.api.demo.dtos.UserDTO; +import com.api.demo.dtos.UserInviteDTO; import com.api.demo.models.EventModel; import com.api.demo.models.User; import com.api.demo.services.UserService; @@ -116,4 +117,11 @@ public ResponseEntity loginUser(@RequestBody LoginRequest loginRequest) return ResponseEntity.ok(userDTO); } + + @GetMapping("/{id}/invites") + public ResponseEntity> getUserInvited(@PathVariable Long id) { + + return ResponseEntity.ok(userService.getAllInvitedEvents(id)); + } + } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java index 3168d3e2..e7455a37 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java @@ -43,4 +43,15 @@ public static EventModel mapToModel(CreateEventWithGuestsRequest request) { createdEvent.setLocation(request.getAddress()); return createdEvent; } + + public static EventDTO mapDto(UserInviteDTO userInvite) { + return EventDTO.builder() + .description(userInvite.getDescription()) + .address(userInvite.getLocation()) + .eventType("private") + .startTime(userInvite.getStartTime()) + .imageURL(userInvite.getImageUrl()).build() + ; + + } } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java index 9fdc982b..d042d964 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java @@ -12,7 +12,10 @@ public class UserInviteDTO { private String email; private String name; private String description; - private Boolean is_public; - private LocalDateTime start_time; + private Boolean isPublic; + private LocalDateTime startTime; private String title; + private Long eventId; + private String location; + private String imageUrl; } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java index e8e7d0f7..a1b427b9 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java @@ -18,14 +18,14 @@ public interface UserRepository extends JpaRepository { Optional findByClerkId(String clerkId); - @Query( - """ - SELECT - u.email, u.name, e.title, e.description, e.isPublic, e.startTime - FROM EventGuest eg - JOIN eg.guest u - JOIN eg.event e - WHERE u.id = :userId - """) + @Query(""" + SELECT new com.api.demo.dtos.UserInviteDTO( + u.email, u.name, e.description, e.startTime, e.title,e.id,e.location,e.imageURL + ) + FROM EventGuest eg + JOIN eg.guest u + JOIN eg.event e + WHERE u.id = :userId +""") List findAllUserInvitedEvents(Long userId); } diff --git a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java index 96b3fcf5..c152e598 100644 --- a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java +++ b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java @@ -234,16 +234,16 @@ public void getUserInvitedEvents() { .email("john.doe@example.com") .description("Description 1") .title("Event 1") - .is_public(true) - .start_time(LocalDateTime.now().plusDays(1)) + .isPublic(true) + .startTime(LocalDateTime.now().plusDays(1)) .name("John Doe") .build(), UserInviteDTO.builder() .email("john.doe@example.com") .description("Description 2") .title("Event 2") - .is_public(false) - .start_time(LocalDateTime.now().plusDays(2)) + .isPublic(false) + .startTime(LocalDateTime.now().plusDays(2)) .name("John Doe") .build()); From b4c0d46b60c5c92882c8b9d9ea045a2a8b2c9386 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 26 Oct 2025 20:59:09 -0400 Subject: [PATCH 2/5] refactor:changed DTO to only return the title and id of the event --- .../api/demo/controllers/UserController.java | 6 +-- .../java/com/api/demo/dtos/DTOConverter.java | 42 +++++++++++-------- .../java/com/api/demo/dtos/UserInviteDTO.java | 7 ---- .../com/api/demo/repos/UserRepository.java | 2 +- .../api/demo/services/UserServiceTest.java | 16 +++---- 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java index 0808a689..e634a0de 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java @@ -119,9 +119,9 @@ public ResponseEntity loginUser(@RequestBody LoginRequest loginRequest) } @GetMapping("/{id}/invites") - public ResponseEntity> getUserInvited(@PathVariable Long id) { - - return ResponseEntity.ok(userService.getAllInvitedEvents(id)); + public ResponseEntity> getUserInvites(@PathVariable Long id) { + List userInvites = userService.getAllInvitedEvents(id); + return ResponseEntity.ok(userInvites); } } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java index e7455a37..939d6831 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java @@ -1,22 +1,18 @@ package com.api.demo.dtos; import com.api.demo.models.EventModel; +import com.api.demo.models.User; + import java.util.HashSet; +import java.util.List; import java.util.Set; public class DTOConverter { public static EventDTO mapToDTO(EventModel event) { // Handle null organizer case - UserDTO organizerDTO = null; - if (event.getOrganizer() != null) { - organizerDTO = - UserDTO.builder() - .id(event.getOrganizer().getId()) - .name(event.getOrganizer().getName()) - .email(event.getOrganizer().getEmail()) - .build(); - } + UserDTO organizerDTO = mapToDTO(event.getOrganizer()); + Set guests = new HashSet<>(); EventDTO model = @@ -33,6 +29,19 @@ public static EventDTO mapToDTO(EventModel event) { .build(); return model; } + public static UserDTO mapToDTO(User user) { + UserDTO userDTO = null; + if (user!= null) { + userDTO = + UserDTO.builder() + .id(user.getId()) + .name(user.getName()) + .email(user.getEmail()) + .build(); + } + return userDTO; + + } public static EventModel mapToModel(CreateEventWithGuestsRequest request) { EventModel createdEvent = new EventModel(); @@ -44,14 +53,13 @@ public static EventModel mapToModel(CreateEventWithGuestsRequest request) { return createdEvent; } - public static EventDTO mapDto(UserInviteDTO userInvite) { + public static EventDTO mapToDTO(UserInviteDTO userInvite) { return EventDTO.builder() - .description(userInvite.getDescription()) - .address(userInvite.getLocation()) - .eventType("private") - .startTime(userInvite.getStartTime()) - .imageURL(userInvite.getImageUrl()).build() - ; - + .title(userInvite.getTitle()) + .id(userInvite.getEventId()).build(); + + } + public static List mapListToDTO(List list) { + return list.stream().map(DTOConverter::mapToDTO).toList(); } } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java index d042d964..a81acbd7 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java @@ -9,13 +9,6 @@ @Builder @Data public class UserInviteDTO { - private String email; - private String name; - private String description; - private Boolean isPublic; - private LocalDateTime startTime; private String title; private Long eventId; - private String location; - private String imageUrl; } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java index a1b427b9..4b1deffd 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java @@ -20,7 +20,7 @@ public interface UserRepository extends JpaRepository { @Query(""" SELECT new com.api.demo.dtos.UserInviteDTO( - u.email, u.name, e.description, e.startTime, e.title,e.id,e.location,e.imageURL + e.title,e.id ) FROM EventGuest eg JOIN eg.guest u diff --git a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java index c152e598..85d1717f 100644 --- a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java +++ b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java @@ -231,20 +231,12 @@ public void getUserInvitedEvents() { List expectedInvites = List.of( UserInviteDTO.builder() - .email("john.doe@example.com") - .description("Description 1") .title("Event 1") - .isPublic(true) - .startTime(LocalDateTime.now().plusDays(1)) - .name("John Doe") + .eventId(1L) .build(), UserInviteDTO.builder() - .email("john.doe@example.com") - .description("Description 2") .title("Event 2") - .isPublic(false) - .startTime(LocalDateTime.now().plusDays(2)) - .name("John Doe") + .eventId(2L) .build()); when(userRepository.findAllUserInvitedEvents(userId)).thenReturn(expectedInvites); @@ -256,8 +248,10 @@ public void getUserInvitedEvents() { verify(userRepository, times(1)).findAllUserInvitedEvents(userId); assertThat(result).hasSize(2); assertThat(result).isEqualTo(expectedInvites); - assertThat(result.get(0).getEmail()).isEqualTo("john.doe@example.com"); + assertThat(result.get(0).getTitle()).isEqualTo("Event 1"); assertThat(result.get(1).getTitle()).isEqualTo("Event 2"); + assertThat(result.get(0).getEventId()).isEqualTo(1L); + assertThat(result.get(1).getEventId()).isEqualTo(2L); } @Test From 58d47f2e0c626aeb1a08d32ab78e5eced05902c8 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 26 Oct 2025 21:33:48 -0400 Subject: [PATCH 3/5] feat:adds fetch calls to frontend --- .../invitations/InvitationsList.tsx | 3 +- .../src/components/navigation/Navigation.tsx | 1 + .../src/pages/invitations/Invitations.tsx | 49 ++++++++++++++++++- .../frontend/src/service/apicalls.ts | 16 ++++++ 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 event-planner/frontend/src/service/apicalls.ts diff --git a/event-planner/frontend/src/components/invitations/InvitationsList.tsx b/event-planner/frontend/src/components/invitations/InvitationsList.tsx index 7007714c..dec9da3b 100644 --- a/event-planner/frontend/src/components/invitations/InvitationsList.tsx +++ b/event-planner/frontend/src/components/invitations/InvitationsList.tsx @@ -12,7 +12,8 @@ type InvitationsListProps = { const InvitationsList: React.FC = ({ events, onSelect }) => (
    {/* Render a button for each event; clicking sets the selected event in the parent */} - {events.map((event, idx) => ( + { + events.map((event, idx) => (
  • diff --git a/event-planner/frontend/src/components/navigation/Navigation.tsx b/event-planner/frontend/src/components/navigation/Navigation.tsx index d3901a07..0effd27e 100644 --- a/event-planner/frontend/src/components/navigation/Navigation.tsx +++ b/event-planner/frontend/src/components/navigation/Navigation.tsx @@ -51,6 +51,7 @@ const Navigation: React.FC = () => {
    • Discover
    • About Us
    • +
    • Invites
    )} diff --git a/event-planner/frontend/src/pages/invitations/Invitations.tsx b/event-planner/frontend/src/pages/invitations/Invitations.tsx index b8b09815..53cd85e5 100644 --- a/event-planner/frontend/src/pages/invitations/Invitations.tsx +++ b/event-planner/frontend/src/pages/invitations/Invitations.tsx @@ -1,16 +1,54 @@ -import React, { useState } from "react"; +import React, { use, useEffect, useState } from "react"; import './Invitations.css'; import { type PrivateEventDetails, invitedEvents } from "../../types/types"; import InvitationsList from "../../components/invitations/InvitationsList"; import InvitationDetails from "../../components/invitations/InvitationDetails"; - +import { useUser } from "@clerk/clerk-react"; +import { fetchUser } from "../../service/apicalls"; // Main Invitations page component // Manages the list of invited events, selected event, and RSVP state const Invitations: React.FC = () => { // Index of the currently selected event in the events array (null if none selected) const [selectedEventIdx, setSelectedEventIdx] = useState(null); const [events, setEvents] = useState(invitedEvents); + const { isSignedIn, user } = useUser(); + const apiUrl = import.meta.env.VITE_API_URL; + const [backendUser,setBackendUser] = useState(); + if (!isSignedIn) { + alert("You must be signed in to view your invitations."); + window.location.href = "/login"; + } + const fetchUserData = async () => { + if (user) { + const userData = await fetchUser(user.id); + console.log("Fetched user data:", userData); + setBackendUser(userData); + } + }; + useEffect(() => { + fetchUserData(); + }, [user]); + + useEffect(() => { + const fetchInvitedEvents = async () => { + + try { + const response = await fetch(`${apiUrl}/users/${backendUser.id}/invites`); + if (response.ok) { + const data = await response.json(); + console.log("Fetched invited events:", data); + setEvents(data); + } else { + console.error("Failed to fetch invited events", response.status); + } + } catch (err) { + console.error("Error fetching invited events:", err); + } + }; + fetchInvitedEvents(); + }, [backendUser, apiUrl]); + // Updates RSVP status for the selected event // Only updates if an event is selected const handleRSVP = (status: "accepted" | "declined") => { @@ -22,6 +60,9 @@ const Invitations: React.FC = () => { }; setEvents(updatedEvents); }; + useEffect(() => { + fetch(`${apiUrl}/users//invites`) + }, []) // Get the currently selected event object, or null if none selected const selectedEvent = selectedEventIdx !== null ? events[selectedEventIdx] : null; @@ -41,3 +82,7 @@ const Invitations: React.FC = () => { }; export default Invitations; +function useffect(arg0: () => void, arg1: never[]) { + throw new Error("Function not implemented."); +} + diff --git a/event-planner/frontend/src/service/apicalls.ts b/event-planner/frontend/src/service/apicalls.ts new file mode 100644 index 00000000..89c39416 --- /dev/null +++ b/event-planner/frontend/src/service/apicalls.ts @@ -0,0 +1,16 @@ +const BASE_API_URL = import.meta.env.VITE_API_URL +export const fetchUser = async(clerkId: string)=> { + try { + const response = await fetch(`${BASE_API_URL}/users/clerk/${clerkId}`) + if (response.ok) { + const json = await response.json(); + return json; + + + } else { + console.error("Failed to fetch user", response.status); + } + } catch (err) { + console.error("Error fetching user:", err); + } + } \ No newline at end of file From 51ef406f68d9a45285f6514f06d1b6b5e6405279 Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 26 Oct 2025 21:39:13 -0400 Subject: [PATCH 4/5] chore:spotless Apply --- .../api/demo/controllers/UserController.java | 1 - .../java/com/api/demo/dtos/DTOConverter.java | 18 +++++------------- .../java/com/api/demo/dtos/UserInviteDTO.java | 1 - .../com/api/demo/repos/UserRepository.java | 3 ++- .../com/api/demo/services/UserServiceTest.java | 10 ++-------- 5 files changed, 9 insertions(+), 24 deletions(-) diff --git a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java index e634a0de..7483f962 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/controllers/UserController.java @@ -123,5 +123,4 @@ public ResponseEntity> getUserInvites(@PathVariable Long id) List userInvites = userService.getAllInvitedEvents(id); return ResponseEntity.ok(userInvites); } - } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java index 939d6831..ec81c4ac 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/DTOConverter.java @@ -2,7 +2,6 @@ import com.api.demo.models.EventModel; import com.api.demo.models.User; - import java.util.HashSet; import java.util.List; import java.util.Set; @@ -12,7 +11,6 @@ public class DTOConverter { public static EventDTO mapToDTO(EventModel event) { // Handle null organizer case UserDTO organizerDTO = mapToDTO(event.getOrganizer()); - Set guests = new HashSet<>(); EventDTO model = @@ -29,18 +27,14 @@ public static EventDTO mapToDTO(EventModel event) { .build(); return model; } + public static UserDTO mapToDTO(User user) { UserDTO userDTO = null; - if (user!= null) { + if (user != null) { userDTO = - UserDTO.builder() - .id(user.getId()) - .name(user.getName()) - .email(user.getEmail()) - .build(); + UserDTO.builder().id(user.getId()).name(user.getName()).email(user.getEmail()).build(); } return userDTO; - } public static EventModel mapToModel(CreateEventWithGuestsRequest request) { @@ -54,11 +48,9 @@ public static EventModel mapToModel(CreateEventWithGuestsRequest request) { } public static EventDTO mapToDTO(UserInviteDTO userInvite) { - return EventDTO.builder() - .title(userInvite.getTitle()) - .id(userInvite.getEventId()).build(); - + return EventDTO.builder().title(userInvite.getTitle()).id(userInvite.getEventId()).build(); } + public static List mapListToDTO(List list) { return list.stream().map(DTOConverter::mapToDTO).toList(); } diff --git a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java index a81acbd7..932df4cf 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/dtos/UserInviteDTO.java @@ -1,6 +1,5 @@ package com.api.demo.dtos; -import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java index 4b1deffd..d17ad3d4 100644 --- a/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java +++ b/event-planner/api/demo/src/main/java/com/api/demo/repos/UserRepository.java @@ -18,7 +18,8 @@ public interface UserRepository extends JpaRepository { Optional findByClerkId(String clerkId); - @Query(""" + @Query( + """ SELECT new com.api.demo.dtos.UserInviteDTO( e.title,e.id ) diff --git a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java index 85d1717f..aabe27d4 100644 --- a/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java +++ b/event-planner/api/demo/src/test/java/com/api/demo/services/UserServiceTest.java @@ -230,14 +230,8 @@ public void getUserInvitedEvents() { Long userId = 1L; List expectedInvites = List.of( - UserInviteDTO.builder() - .title("Event 1") - .eventId(1L) - .build(), - UserInviteDTO.builder() - .title("Event 2") - .eventId(2L) - .build()); + UserInviteDTO.builder().title("Event 1").eventId(1L).build(), + UserInviteDTO.builder().title("Event 2").eventId(2L).build()); when(userRepository.findAllUserInvitedEvents(userId)).thenReturn(expectedInvites); From 95e0af922e1201dbd8b3c51af3f5d245d8b51e6a Mon Sep 17 00:00:00 2001 From: Daniel Boyce Date: Sun, 26 Oct 2025 21:42:42 -0400 Subject: [PATCH 5/5] chore:removes unused import --- .../frontend/src/pages/invitations/Invitations.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/event-planner/frontend/src/pages/invitations/Invitations.tsx b/event-planner/frontend/src/pages/invitations/Invitations.tsx index 53cd85e5..5bc7ebb1 100644 --- a/event-planner/frontend/src/pages/invitations/Invitations.tsx +++ b/event-planner/frontend/src/pages/invitations/Invitations.tsx @@ -1,4 +1,4 @@ -import React, { use, useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import './Invitations.css'; import { type PrivateEventDetails, invitedEvents } from "../../types/types"; import InvitationsList from "../../components/invitations/InvitationsList"; @@ -82,7 +82,5 @@ const Invitations: React.FC = () => { }; export default Invitations; -function useffect(arg0: () => void, arg1: never[]) { - throw new Error("Function not implemented."); -} +