From f46dc1af332904acd5496f41915d3853169a8685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9ESophia?= <„sophia.haupt@mni.thm.de“> Date: Tue, 28 Jan 2025 14:20:55 +0100 Subject: [PATCH] push --- userman_all/client/index.html | 48 ++++--- userman_all/client/src/client.ts | 136 +++++++++++++++++- userman_all/client/stylesheet.css | 21 +++ userman_all/server/doc/index.html | 2 +- userman_all/server/src/server.ts | 89 +++++++++++- userman_all/server/test/horizon_changers.http | 73 ++++++---- 6 files changed, 317 insertions(+), 52 deletions(-) diff --git a/userman_all/client/index.html b/userman_all/client/index.html index 43138b6..2dad744 100644 --- a/userman_all/client/index.html +++ b/userman_all/client/index.html @@ -669,34 +669,32 @@ </aside> <div class="reiseberichtFormular"> <h1>Wie war Deine Reise mit Uns?</h1> - <form> + <form id="reiseberichtForm"> <label for="country">Land auswählen</label> <select id="country" name="country"> <option value="">-- Bitte wählen --</option> - <option value="de">Spanien</option> - <option value="fr" >Peru</option> - <option value="it">Indien</option> - <option value="it">Kenia</option> + <option value="spanien">Spanien</option> + <option value="peru" >Peru</option> + <option value="indien">Indien</option> + <option value="kenia">Kenia</option> </select> - <label for="firstname">Vorname</label> - <input type="text" id="firstname" name="firstname" placeholder="Vorname"> + <div class="rating" id="ratingReisebericht"> + <span id="stern1">★</span> + <span id="stern2">★</span> + <span id="stern3">★</span> + <span id="stern4">★</span> + <span id="stern5">★</span> + </div> - <label for="lastname">Nachname</label> - <input type="text" id="lastname" name="lastname" placeholder="Nachname"> + <label for="titleReisebericht">Titel</label> + <input type="text" id="titleReisebericht" name="title" placeholder="titel"> - <div class="rating"> - <span>★</span> - <span>★</span> - <span>★</span> - <span>★</span> - <span>★</span> - </div> <label for="feedback">Feedback</label> <textarea id="feedback" name="feedback" placeholder="Schreibe hier dein Feedback..."></textarea> - <button type="submit" class="reiseberichtAbsenden" onclick="showPage('meineReiseberichte')">Absenden</button> + <button type="submit" class="reiseberichtAbsenden">Absenden</button> </form> </div> @@ -715,16 +713,30 @@ <li><a>Mein Profil</a></li> <li><a>Merkliste</a></li> <li><a>Meine Supportanfragen</a></li> - <li><a onclick="showPage ('meineReiseberichte')">Meine Reiseberichte </a></li> + <li><a onclick="showPage ('meineReiseberichte')" id="meineReiseberichteSeite" >Meine Reiseberichte </a></li> <div id="logout-form4"> <li><a id="logout-button4" onclick="showPage('startseite')">Abmelden</a></li> </div> </ul> </nav> </aside> + <main class="content"> + <section id="sectionNewReisebericht"> + <h2>Meine Reiseberichte</h2> + <div class="reisebericht-card" id="reisebericht-card"> + <h3 id="titelReise">Meine Reise in Indien</h3> + <h5 id="reiseland"> ...</h5> + <p id="reisebeschreibung">Das Projekt setzt sich dafür ein, Frauen in benachteiligten Regionen Indiens Zugang zu Bildung und beruflichen Chancen zu ermöglichen. Schon bei meiner Ankunft wurde deutlich, wie wichtig diese Arbeit ist: Die strahlenden Augen der Teilnehmerinnen und ihre Geschichten zeigten, dass Bildung für sie ein Tor zu einem besseren Leben bedeutet.</p> + <button class="details-button">Reisebericht löschen</button> + <button class="report-button" onclick="showPage('reiseberichtSchreiben')">Reisebericht bearbeiten</button> + </div> + </section> + </main> </div> + + <!--Footer--> <footer class="footer"> <div class="footer-container"> diff --git a/userman_all/client/src/client.ts b/userman_all/client/src/client.ts index 67b8d78..46b510d 100644 --- a/userman_all/client/src/client.ts +++ b/userman_all/client/src/client.ts @@ -35,6 +35,16 @@ interface User { role: string; } +// Reiseberichte schreiben +interface Review { + reviews_id: number; + title: string; + description: string; + rating: number; + country: string; + user_id: number; +} + // Ein Modal-Objekt von Bootstrap wird hier deklariert, aber initialisiert erst später im DOMContentLoaded Event. let modalEl: bootstrap.Modal let modalTest: bootstrap.Modal @@ -54,6 +64,7 @@ document.addEventListener("DOMContentLoaded", (): void => { checkLogin(); // --- Initialisierung der Benutzeranzeige --- readUsers(); + readReviews(); // --- Registrierungsformular Eventhandler --- //Registrierung des Event-Listeners @@ -109,6 +120,7 @@ document.addEventListener("DOMContentLoaded", (): void => { addMessage(data.message); showLoggedInStatus(data.user); userDataInProfile(data.user); + reviewDataInProfile(data.user); } else { addMessage(data.message); showPage('registrieren'); @@ -124,6 +136,7 @@ document.addEventListener("DOMContentLoaded", (): void => { }); + const modalDeleteButton = document.getElementById("saveButtonDelete") as HTMLButtonElement; modalDeleteButton.addEventListener("click", async () => { deleteUser() @@ -164,6 +177,7 @@ document.addEventListener("DOMContentLoaded", (): void => { showPage('profil')// Modal schließen addMessage(data.message || "Profil wurde erfolgreich aktualisiert."); userDataInProfile(data.user); + reviewDataInProfile(data.user); } else { console.error ("Fehler beim Aktualisieren des Profils."); } @@ -252,6 +266,7 @@ document.addEventListener("DOMContentLoaded", (): void => { } showLoggedInStatus(data.user); userDataInProfile(data.user); + reviewDataInProfile(data.user); } else { console.warn(`Unhandled response code (${response.status}).`) } @@ -267,7 +282,76 @@ document.addEventListener("DOMContentLoaded", (): void => { ); /*showLoggedOutStatus()*/ }); + + // create Reisebericht + document.getElementById("reiseberichtForm")!.addEventListener("submit", async (event: SubmitEvent): Promise<void> => { + //Verhindern des Standartverhaltens + event.preventDefault(); + console.log('test'); + + //Eingabefelder durch ihre IDs (grün) auslesen + const countryEl: HTMLInputElement = document.getElementById("country") as HTMLInputElement; + const titleEl: HTMLInputElement = document.getElementById("titleReisebericht") as HTMLInputElement; + const descriptionEl: HTMLInputElement = document.getElementById("feedback") as HTMLInputElement; + const ratingEl: HTMLInputElement = document.getElementById("ratingReisebericht") as HTMLInputElement; + +//Die Werte der Eingabefelder werden in Variablen gespeichert + const country: string = countryEl.value; + const title: string = titleEl.value; + const description: string = descriptionEl.value; + const rating: string = ratingEl.value; + + // Validieren der Eingaben + if (!country|| !title || !description) { + addMessage("Bitte alle Felder ausfüllen!"); + showPage('reiseberichtSchreiben'); + return; + } + + // Sende User Daten an Server - asynchrone HTTP-POST-Anfrage - await sorgt dafür, dass die Ausführung wartet, bis die Anfrage abgeschlossen + // ist und eine Antwort vom Server erhalten wurde + const res: Response = await fetch('/reviews', { + method: 'POST', + headers: { + "Content-type": "application/json", + }, + body: JSON.stringify({country, title, description, rating: Number(rating) }), + }); + + //Antwort vom Server verarbeiten + const data: any = await res.json(); + + addMessage(data.message); + +//Verarbeiten des Antwortstatus + if (res.status === 201) { + addMessage(data.message); + showPage('meineReiseberichte' || "Deine Bewertung wurde erfolgreich erstellt. Danke für dein Feedback! :)."); + } else { + addMessage(data.message || "Fehler beim Erstellen deines Berichts, versuche es später erneut."); + showPage('reiseberichtSchreiben'); + } + + // Zurücksetzen der Eingabefelder, sodass Vorlage wieder leer ist + countryEl.value = ""; + titleEl.value = ""; + descriptionEl.value = ""; + ratingEl.value = ""; + + }); + ///Read Reisebericht + document.getElementById("meineReiseberichteSeite")!.addEventListener("click", async (): Promise<void> => { + showPage('meineReiseberichte'); + readReviews(); + + }) + + + }); + + + /** * Checks if user might be logged */ @@ -281,6 +365,7 @@ async function checkLogin(): Promise<void> { const data: any = await response.json(); showLoggedInStatus(data.user); userDataInProfile(data.user); + reviewDataInProfile(data.user); } } @@ -296,6 +381,28 @@ async function readUsers(): Promise<void> { renderList(data.userList); } +async function readReviews(): Promise<void> { + const res: Response = await fetch('/reviews', { + method: "GET" + } + ); + const data: any = await res.json(); + renderReviews(data.reviewsList); +} + +//Funktion für get REVIEW + +function reviewDataInProfile (reviews: Review): void { + const countryEl: HTMLInputElement = document.getElementById("reiseland") as HTMLInputElement; + const titleEl: HTMLInputElement = document.getElementById('titelReise') as HTMLInputElement; + const descriptionEl: HTMLInputElement = document.getElementById('reisebeschreibung') as HTMLInputElement; + //const ratingEl: HTMLInputElement = document.getElementById('edit-user-email') as HTMLInputElement; + + countryEl.value = reviews.country; + titleEl.value = reviews.title; + descriptionEl.value = reviews.description; + //ratingEl.value = reviews.rating; +} /** * Displays the logged in username */ @@ -371,6 +478,34 @@ function showLoggedOutStatus(): void { * 1) Clears the user table. * 2) Adds all users to the table. */ +function renderReviews(reviewsList: Review[]): void { + let reviewsListEl: HTMLElement = document.getElementById("sectionNewReisebericht")!; + + // Remove all entries from the table + reviewsListEl.replaceChildren(); + + for (let reviews of reviewsList) { + // The new h3 überschrift + let container: HTMLElement = document.createElement("div"); + container.className = "reisebericht-card" + + let h3: HTMLElement = document.createElement("h3"); + h3.textContent = reviews.title.toString(); + + // New country element h5 + let h5: HTMLElement = document.createElement("h5"); + h5.textContent = reviews.country.toString(); + + // new description + let p: HTMLElement = document.createElement("p"); + p.textContent = reviews.description.toString(); + + container.append(h3, h5, p); + + reviewsListEl.appendChild(container); + + } +} //** function renderList(userList: User[]): void { @@ -509,4 +644,3 @@ function addMessage(message: string): void { alert.close(); }, 5000); } - diff --git a/userman_all/client/stylesheet.css b/userman_all/client/stylesheet.css index dd162c9..d844338 100644 --- a/userman_all/client/stylesheet.css +++ b/userman_all/client/stylesheet.css @@ -1380,4 +1380,25 @@ textarea { .reiseberichtAbsenden:hover { background-color: #e36c20; +} + + +.reisebericht-card { + width: 662px; + height: auto; + display: flex; + flex-direction: column; + align-items: normal; + background-color: #FCF3E4; + border-radius: 30px; + padding: 15px; + margin-bottom: 20px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.reisebericht-info { + font-family: 'DM Sans', sans-serif; + color: #03355C; + font-size: 20px; + flex-grow: 1; } \ No newline at end of file diff --git a/userman_all/server/doc/index.html b/userman_all/server/doc/index.html index e8a7a9c..9e997c1 100644 --- a/userman_all/server/doc/index.html +++ b/userman_all/server/doc/index.html @@ -1042,6 +1042,6 @@ </div> </div> -<script src="assets/main.bundle.js?v=1737968153982"></script> +<script src="assets/main.bundle.js?v=1737724955109"></script> </body> </html> diff --git a/userman_all/server/src/server.ts b/userman_all/server/src/server.ts index 87823e4..df05f0b 100644 --- a/userman_all/server/src/server.ts +++ b/userman_all/server/src/server.ts @@ -79,6 +79,15 @@ export interface User { role: string; eMail: string; } + +export interface Review { + reviews_id: number; + title: string; + description: string; + rating: number; + country: string; + user_id: number; +} //Middleware: Login-Status prüfen --Prüft, ob ein Benutzer eingeloggt ist. Falls nicht, wird ein HTTP-Status 401 (Unauthorized) zurückgegeben. function isLoggedIn(req: Request, res: Response, next: NextFunction) { // Abstract middleware route for checking login state of the user @@ -380,7 +389,6 @@ app.post('/user', async (req: Request, res: Response): Promise<void> => { } }); -//Benutzer abrufen, aktualisieren, löschen /***************************************************************************** * HTTP ROUTES: USER, USERS * @@ -859,7 +867,86 @@ app.get('/users', isLoggedIn, async (req: Request, res: Response): Promise<void> } }); +//Reisebericht schreiben +app.post('/reviews', isLoggedIn, async (req: Request, res: Response): Promise<void> => { + const country: string = req.body.country; + const title: string = req.body.title; + const description: string = req.body.description; + const rating: number = req.body.rating; + const user_id: number = Number(req.session.user?.user_id); //user_id wird zu Number gemacht weil könnte "theoretisch" undefined sein,. aber eig wegen isloggedin nicht + + // Check, if any given value is empty + if (!country || !title || !description) { + res.status(400).send({ + message: "Bitte alle Felder ausfüllen!", + }); + return; + } + +//aufrufen titel, beschreibung, land, rating, userid + const data: [string, string, string, number, number] = [ + title, + description, + country, + Number(rating), + user_id, + ]; +//soll in review tabelle gespeichert werden + const query: string = 'INSERT INTO reviews (title, description, country, rating, user_id) VALUES (?, ?, ?, ?, ?);'; + try { + const [rows] = await database.query<RowDataPacket[]>(query, data); + // Check if database response contains exactly one entry + res.status(201).send({ + message: 'Deine Bewertung wurde erfolgreich erstellt. Danke für dein Feedback! :).', + }); + } catch (error: unknown) { + // Unknown error + res.status(500).send({ + message: 'Database request failed: ' + error, + }); + } +}); + +/// Read Review + +app.get('/reviews', isLoggedIn, async (req: Request, res: Response): Promise<void> => { + // Die `user_id` wird aus der Middleware `isLoggedIn` bereitgestellt + const user_id: number = Number(req.session.user?.user_id); + + // SQL-Query für alle Reviews des Users + const query: string = 'SELECT * FROM reviews WHERE user_id = ?;'; + + try { + // Daten aus der Datenbank abrufen + const [rows] = await database.query<RowDataPacket[]>(query, [user_id]); + + // Alle Reviews sammeln und formatieren + const reviewsList: Review[] = []; + for (const row of rows) { + const reviews: Review = { + reviews_id: row.reviews_id, + user_id: row.user_id, + country: row.country, + title: row.title, + description: row.description, + rating: row.rating, + }; + reviewsList.push(reviews); + } + // Erfolgsantwort senden + res.status(200).send({ + reviewsList: reviewsList, // Alle Reviews zurückgeben + message: 'Erfolgreicher Zugriff auf Review.', + }); + } catch (error) { + // Fehlerbehandlung bei Datenbankoperationen + console.error('Database error: ', error); + res.status(500).send({ + message: 'Database request failed: ' + error, + }); + } +}); /***************************************************************************** diff --git a/userman_all/server/test/horizon_changers.http b/userman_all/server/test/horizon_changers.http index 86e670f..5f7ee50 100644 --- a/userman_all/server/test/horizon_changers.http +++ b/userman_all/server/test/horizon_changers.http @@ -3,8 +3,20 @@ POST http://localhost:8080/login HTTP/1.1 Content-Type: application/json { - "eMail": "jens@badeke.de", - "password": "123" + "eMail": "amelieenders@gmail.com", + "password": "amelie" +} + +### Update specific user admin +PUT http://localhost:8080/user/10 HTTP/1.1 +Content-Type: application/json + +{ + "firstName": "Bruce", + "lastName": "Kayne", + "eMail": "bato", + "adress": "Fetzwiesen 4", + "role": "user" } ### Update user @@ -12,16 +24,16 @@ PUT http://localhost:8080/user HTTP/1.1 Content-Type: application/json { - "firstName": "Selina", - "lastName": "Kyle", - "eMail": "otto@gmail.com", - "password": "otto" + "firstName": "Amelie", + "lastName": "Dralle", + "eMail": "amelie@gmail.com", + "password": "amelie" } -### Read User - User -GET http://localhost:8080/user/31 HTTP/1.1 +### Read User +GET http://localhost:8080/user/76 HTTP/1.1 -### Read User - Fehlerfall User gibt es nicht +### Read User GET http://localhost:8080/user/500 HTTP/1.1 @@ -30,35 +42,35 @@ POST http://localhost:8080/login HTTP/1.1 Content-Type: application/json { - "eMail": "jens@badeke.de", + "eMail": "lilith@fa.gmx.de", "password": "passwort" } -### Create a new user - Registrieren +### Create a new user richtige Route POST http://localhost:8080/user HTTP/1.1 Content-Type: application/json { - "firstName": "Felix", - "lastName": "Blau", - "eMail": "felix@blau.de", + "firstName": "Daria", + "lastName": "Krawtschenko", + "eMail": "daria@gmail.com", "password": "1234", "repeatPassword": "1234" } -### Create a new user Fehlermeldung Passwort unterschiedlich +### Create a new user verschiedene Paswörter POST http://localhost:8080/user HTTP/1.1 Content-Type: application/json { - "firstName": "Bruce", - "lastName": "Wayne", - "eMail": "bat@mail.de", + "firstName": "Leonie", + "lastName": "Lutz", + "eMail": "lutzleo@gmail.com", "password": "1234", "repeatPassword": "123456" } -### Create a new user Fehlermeldung Email fehlt +### Create a new user eMail fehlt POST http://localhost:8080/user HTTP/1.1 Content-Type: application/json @@ -72,29 +84,28 @@ Content-Type: application/json ### Logout POST http://localhost:8080/logout HTTP/1.1 - ### Delete user Nutzer DELETE http://localhost:8080/user HTTP/1.1 -####Read Users Admin +####Read Users Nutzerliste Admin GET http://localhost:8080/users HTTP/1.1 ### Update specific user Admin -PUT http://localhost:8080/user/31 HTTP/1.1 +PUT http://localhost:8080/user/70 HTTP/1.1 Content-Type: application/json { - "firstName": "Felix", - "lastName": "Blau", - "eMail": "felix@blau.de", + "firstName": "Minette", + "lastName": "Stark", + "eMail": "minette@gmail.com", "adress": "Fetzwiesen 4", "role": "user" } -### Update specific user - fehlerfall -PUT http://localhost:8080/user/1 HTTP/1.1 +### Update specific user +PUT http://localhost:8080/user/79 HTTP/1.1 Content-Type: application/json { @@ -102,12 +113,12 @@ Content-Type: application/json "familyName": "Kyle" } -### Delete specific user Admin -DELETE http://localhost:8080/user/31 HTTP/1.1 +### Delete specific user +DELETE http://localhost:8080/user/80 HTTP/1.1 -### Delete specific user admin fehlerfall -DELETE http://localhost:8080/user/1 HTTP/1.1 +### Delete specific user +DELETE http://localhost:8080/user/76 HTTP/1.1 -- GitLab