From a35b0d9809fe2d7c1a2beecef5b02ffd56aed462 Mon Sep 17 00:00:00 2001 From: Robert Stolz Date: Tue, 11 Mar 2025 18:55:36 +0100 Subject: [PATCH 01/18] before change --- frontend/src/components/Play.tsx | 1 - frontend/src/components/styles/HighScore.css | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Play.tsx b/frontend/src/components/Play.tsx index d342895..9340f58 100644 --- a/frontend/src/components/Play.tsx +++ b/frontend/src/components/Play.tsx @@ -42,7 +42,6 @@ export default function Play(props: Readonly) { const [showPopup, setShowPopup] = useState(false); const [popupMessage, setPopupMessage] = useState(""); - const handleSaveHighScore = () => { if (playerName.trim().length < 3) { setPopupMessage("Dein Name muss mindestens 3 Zeichen lang sein!"); diff --git a/frontend/src/components/styles/HighScore.css b/frontend/src/components/styles/HighScore.css index 68482dc..f71231a 100644 --- a/frontend/src/components/styles/HighScore.css +++ b/frontend/src/components/styles/HighScore.css @@ -15,7 +15,8 @@ width: 100%; /* Jetzt auf 100%, sodass die Tabellen untereinander passen */ max-width: 800px; /* Optional: Limitiert die maximale Breite für bessere Darstellung */ background-color: #f9f9f9; - padding: 5px; + padding-left: 5px; + padding-right: 5px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); margin-bottom: 20px; /* Fügt Abstand zwischen den Tabellen hinzu */ From 88cd6e49d1f7eecf1918d25d6bc4f7a4d100feba Mon Sep 17 00:00:00 2001 From: Robert Stolz Date: Tue, 11 Mar 2025 19:41:33 +0100 Subject: [PATCH 02/18] new endpoint and tests --- .../backend/controller/MemoryController.java | 8 ++- .../ropold/backend/service/MemoryService.java | 9 +++ .../MemoryControllerIntegrationTest.java | 9 +++ .../backend/service/MemoryServiceTest.java | 67 +++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/ropold/backend/controller/MemoryController.java b/backend/src/main/java/ropold/backend/controller/MemoryController.java index 184cb47..d66686c 100644 --- a/backend/src/main/java/ropold/backend/controller/MemoryController.java +++ b/backend/src/main/java/ropold/backend/controller/MemoryController.java @@ -27,11 +27,17 @@ public class MemoryController { private final CloudinaryService cloudinaryService; private final AppUserService appUserService; - @GetMapping("active/match-id/{numberOfMatchId}") + @GetMapping("/active/match-id/{numberOfMatchId}") public List getActiveMemoriesFilterByMatchId(@PathVariable int numberOfMatchId) { return memoryService.getActiveMemoriesFilterByMatchId(numberOfMatchId); } + @GetMapping("/active/match-ids") + public List getActiveMemoriesMatchIds() { + return memoryService.getActiveMemoriesMatchIds(); + } + + @GetMapping("/favorites") public List getUserFavorites(@AuthenticationPrincipal OAuth2User authentication) { List favoriteMemoryIds = appUserService.getUserFavorites(authentication.getName()); diff --git a/backend/src/main/java/ropold/backend/service/MemoryService.java b/backend/src/main/java/ropold/backend/service/MemoryService.java index 86b668d..866ebde 100644 --- a/backend/src/main/java/ropold/backend/service/MemoryService.java +++ b/backend/src/main/java/ropold/backend/service/MemoryService.java @@ -162,4 +162,13 @@ public List getMemoriesForGithubUser(String githubId) { .toList(); } + public List getActiveMemoriesMatchIds() { + return memoryRepository.findAll().stream() // Alle MemoryModel-Objekte laden + .filter(MemoryModel::isActive) // Nur aktive Einträge filtern + .map(MemoryModel::matchId) // matchId extrahieren + .distinct() // Duplikate entfernen + .sorted() // Sortieren + .toList(); // Mit Stream.toList() die Liste zurückgeben + } + } diff --git a/backend/src/test/java/ropold/backend/controller/MemoryControllerIntegrationTest.java b/backend/src/test/java/ropold/backend/controller/MemoryControllerIntegrationTest.java index b592c7f..6562c95 100644 --- a/backend/src/test/java/ropold/backend/controller/MemoryControllerIntegrationTest.java +++ b/backend/src/test/java/ropold/backend/controller/MemoryControllerIntegrationTest.java @@ -203,6 +203,15 @@ void getAllMemories_shouldReturnAllMemories() throws Exception { """)); } + @Test + void getActiveMatchIds_shouldReturnListOfIntWithMatchIds() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/api/memory-hub/active/match-ids") + .with(oidcLogin().idToken(i -> i.claim("sub", "user"))) + ) + .andExpect(status().isOk()) + .andExpect(content().json("[101]")); + } + @Test void getActiveMemoriesFilterByMatchId_shouldReturnFilteredMemories() throws Exception { // Beispiel für eine 'matchId' (z.B. 101) diff --git a/backend/src/test/java/ropold/backend/service/MemoryServiceTest.java b/backend/src/test/java/ropold/backend/service/MemoryServiceTest.java index 11c8029..d4d3d29 100644 --- a/backend/src/test/java/ropold/backend/service/MemoryServiceTest.java +++ b/backend/src/test/java/ropold/backend/service/MemoryServiceTest.java @@ -579,7 +579,74 @@ void getMemoriesForGithubUser_NoMemoriesForGithubId() { verify(memoryRepository, times(1)).findAll(); // Verify all memories were fetched } + @Test + void getActiveMemoriesMatchIds_Success() { + // Given + List expectedMatchIds = List.of(101); // Erwartete sortierte matchId-Liste + when(memoryRepository.findAll()).thenReturn(memories); + + // When + List actualMatchIds = memoryService.getActiveMemoriesMatchIds(); + + // Then + assertEquals(expectedMatchIds, actualMatchIds); // Verifizieren, dass die zurückgegebene Liste korrekt ist + } + + @Test + void getActiveMemoriesMatchIds_MultipleMatches() { + // Given + MemoryModel avatarMemory = new MemoryModel( + "1", + "Avatar Erinnerung", + 101, + Category.GITHUB_AVATAR, + "Eine Erinnerung, die mit einem GitHub-Avatar verknüpft ist", + true, + "github123", + "user1", + "https://avatars.example.com/user1.png", + "https://github.com/user1", + "https://example.com/image1.jpg" + ); + + MemoryModel cloudinaryMemory = new MemoryModel( + "2", + "Cloudinary Erinnerung", + 102, + Category.CLOUDINARY_IMAGE, + "Eine Erinnerung, die mit einem Cloudinary-Bild gespeichert ist", + false, + "github456", + "user2", + "https://avatars.example.com/user2.png", + "https://github.com/user2", + "https://example.com/image2.jpg" + ); + + MemoryModel additionalMemory = new MemoryModel( + "3", + "Neue Erinnerung", + 103, + Category.GITHUB_AVATAR, + "Eine weitere Erinnerung", + true, + "github789", + "user3", + "https://avatars.example.com/user3.png", + "https://github.com/user3", + "https://example.com/image3.jpg" + ); + + // Speichern der Erinnerungen + when(memoryRepository.findAll()).thenReturn(List.of(avatarMemory, cloudinaryMemory, additionalMemory)); + + // When + List actualMatchIds = memoryService.getActiveMemoriesMatchIds(); + // Then + List expectedMatchIds = List.of(101, 103); // Erwartete Liste mit matchIds der aktiven Erinnerungen + assertEquals(expectedMatchIds, actualMatchIds); // Verifizieren, dass die Liste korrekt ist + } } From eeaadfeb2915ced346e6ced1fcca4884e8a35489 Mon Sep 17 00:00:00 2001 From: Robert Stolz Date: Wed, 12 Mar 2025 09:37:14 +0100 Subject: [PATCH 03/18] not using get allmemories anymore --- frontend/src/App.tsx | 4 +-- frontend/src/components/Play.tsx | 53 ++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 433659a..d729826 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -161,7 +161,7 @@ export default function App() { useEffect(() => { getUser(); - getActiveMemories(); + //getActiveMemories(); getAllMemories(); getHighScoresFor10Cards(); getHighScoresFor20Cards(); @@ -186,7 +186,7 @@ export default function App() { } /> } /> } /> - } /> + } /> } /> } /> diff --git a/frontend/src/components/Play.tsx b/frontend/src/components/Play.tsx index 9340f58..8c07c52 100644 --- a/frontend/src/components/Play.tsx +++ b/frontend/src/components/Play.tsx @@ -6,7 +6,6 @@ import axios from "axios"; type PlayProps = { - activeMemories: MemoryModel[]; highScores10: HighScoreModel[]; highScores20: HighScoreModel[]; highScores32: HighScoreModel[]; @@ -41,10 +40,12 @@ export default function Play(props: Readonly) { const [showNameInput, setShowNameInput] = useState(false); const [showPopup, setShowPopup] = useState(false); const [popupMessage, setPopupMessage] = useState(""); + const [activeMatchIds, setActiveMatchIds] = useState([]); + const [activeMemories, setActiveMemories] = useState([]); // Daten für das ausgewählte matchId const handleSaveHighScore = () => { if (playerName.trim().length < 3) { - setPopupMessage("Dein Name muss mindestens 3 Zeichen lang sein!"); + setPopupMessage("Your name must be at least 3 characters long!"); setShowPopup(true); return; } @@ -52,6 +53,41 @@ export default function Play(props: Readonly) { postHighScore(); }; + const getActiveMemoriesMatchIds = () => { + axios + .get("api/memory-hub/active/match-ids") + .then((response) => { + const matchIds = response.data; + setActiveMatchIds(matchIds); + }) + .catch((error) => { + console.error(error); + }); + } + + useEffect(() => { + getActiveMemoriesMatchIds(); + }, []); + + const getActiveMemoriesByMatchId = (matchId: number) => { + axios + .get(`api/memory-hub/active/match-id/${matchId}`) + .then((response) => { + setActiveMemories(response.data); // Speichert die abgerufenen Erinnerungen + }) + .catch((error) => { + console.error("Error retrieving memories:", error); + }); + }; + +// useEffect, um die Erinnerungen zu laden, wenn die `selectedMatchId` geändert wird + useEffect(() => { + if (selectedMatchId !== null) { + getActiveMemoriesByMatchId(selectedMatchId); + } + }, [selectedMatchId]); + + // Timer starten, wenn das Spiel beginnt useEffect(() => { if (isGameStarted) { @@ -77,7 +113,7 @@ export default function Play(props: Readonly) { // Vorschau der Karten (neu laden, wenn MatchId oder Anzahl sich ändert) useEffect(() => { if (selectedMatchId !== null) { - let filteredCards = props.activeMemories.filter(memory => memory.matchId === selectedMatchId); + let filteredCards = activeMemories.filter(memory => memory.matchId === selectedMatchId); // Zufällig mischen, bevor die Vorschau angezeigt wird filteredCards = shuffleArray(filteredCards); @@ -97,7 +133,7 @@ export default function Play(props: Readonly) { setShowAnimation(false); // Win-Animation zurücksetzen setHasStarted(false); // Spielstatus zurücksetzen } - }, [selectedMatchId, cardCount, props.activeMemories]); + }, [selectedMatchId, cardCount, activeMemories]); // Win-Animation auslösen useEffect(() => { @@ -116,7 +152,7 @@ export default function Play(props: Readonly) { setHasStarted(true); - let filteredCards = props.activeMemories.filter(memory => memory.matchId === selectedMatchId); + let filteredCards = activeMemories.filter(memory => memory.matchId === selectedMatchId); // Karten vorher mischen, damit nicht immer dieselben zuerst genommen werden filteredCards = shuffleArray(filteredCards); @@ -135,7 +171,7 @@ export default function Play(props: Readonly) { setCards([...allCards]); setFlippedCards([]); setMatchedCards([]); - }, [selectedMatchId, cardCount, isGameStarted, props.activeMemories]); + }, [selectedMatchId, cardCount, isGameStarted, activeMemories]); // Karte umdrehen const flipCard = (uniqueId: string) => { @@ -200,7 +236,7 @@ export default function Play(props: Readonly) { setShowNameInput(false); // Eingabefeld nach dem Speichern ausblenden }) .catch((error) => { - console.error("Fehler beim Speichern des Highscores:", error); + console.error("Error saving the high score:", error); }); }; @@ -267,12 +303,11 @@ export default function Play(props: Readonly) { onChange={(e) => setSelectedMatchId(Number(e.target.value))} > - {[...new Set(props.activeMemories.map(m => m.matchId))].sort((a, b) => a - b).map(matchId => ( + {activeMatchIds.sort((a, b) => a - b).map(matchId => ( ))} - From 9d878cc191718cb36c56a21a07f21065db6f8307 Mon Sep 17 00:00:00 2001 From: Robert Stolz Date: Wed, 12 Mar 2025 10:34:29 +0100 Subject: [PATCH 04/18] before new profile --- frontend/src/App.tsx | 13 ++++--------- frontend/src/components/HighScore.tsx | 11 +++++++++++ frontend/src/components/MyMemories.tsx | 6 ++++++ frontend/src/components/Navbar.tsx | 2 -- frontend/src/components/Profile.tsx | 14 ++++++++++++++ 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d729826..1bcbde9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -161,11 +161,6 @@ export default function App() { useEffect(() => { getUser(); - //getActiveMemories(); - getAllMemories(); - getHighScoresFor10Cards(); - getHighScoresFor20Cards(); - getHighScoresFor32Cards(); }, []); useEffect(() => { @@ -181,20 +176,20 @@ export default function App() { return ( <> - + } /> } /> } /> } /> } /> - } /> + } /> }> } /> - } /> + } /> } /> - } /> + } />