From dd4a7d08a07afecdad07936744a90e4e55819fb0 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Fri, 13 Jun 2025 00:17:30 +0200 Subject: [PATCH] Fix TIm Coding. Fix Login CustomerId save in AccountProvider --- 00-backend/datasource/database.sqlite | Bin 2629632 -> 2629632 bytes .../webshop/repository/entities/Account.java | 2 +- .../service/impl/AccountServiceImpl.java | 9 +- .../public/locales/de/translation.json | 4 +- .../public/locales/en/translation.json | 4 +- 01-frontend/src/helper/navbar/LoginDialog.tsx | 13 ++- 01-frontend/src/helper/query/Queries.tsx | 21 ++++- 01-frontend/src/pages/Account.tsx | 81 +++++++++++++----- 8 files changed, 104 insertions(+), 30 deletions(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index a32c59859af56b4e3c556498ac042356c1bcce04..6049a259d37110ba512e0de9f0161af59168be62 100644 GIT binary patch delta 5290 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 XO6GzXAejjwfMgyB+Z31W+Gqa{ZS9et delta 280 zcmWN{FHZt-0LS6`iGp|PeLa;E0R{iwX3{{{d0l3c#C!o7iN{8u7+@Bn`^{o7xC>XD zbFx{9W@q&sT=5g0_Vhm5c0bruW)?x-3+^=|idAN>7_ZFP(PI%S9vW$fiMe zqJd3@HZhn(0rOZu5hX0bg@+|9V+B5hRRmbWIyO*7h)q(CX`*Z0>P0c*SXn%a G-rE1>{A~yT diff --git a/00-backend/src/main/java/de/htwsaar/webshop/repository/entities/Account.java b/00-backend/src/main/java/de/htwsaar/webshop/repository/entities/Account.java index ff12a49..d6f167a 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/repository/entities/Account.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/repository/entities/Account.java @@ -18,7 +18,7 @@ public class Account { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(fetch = FetchType.LAZY, optional = false) + @ManyToOne(fetch = FetchType.EAGER, optional = false, cascade = CascadeType.ALL) @JoinColumn(name = "customer_id", nullable = false) private Customer customer; diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java index 74431cc..cfdeea2 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/AccountServiceImpl.java @@ -1,6 +1,7 @@ package de.htwsaar.webshop.service.impl; import de.htwsaar.webshop.repository.AccountRepository; +import de.htwsaar.webshop.repository.CustomerRepository; import de.htwsaar.webshop.repository.entities.Account; import de.htwsaar.webshop.service.AccountService; import de.htwsaar.webshop.service.PasswordService; @@ -13,11 +14,13 @@ import java.util.List; public class AccountServiceImpl implements AccountService { private final AccountRepository accountRepository; private final PasswordService passwordService; + private final CustomerRepository customerRepository; @Autowired - public AccountServiceImpl(AccountRepository accountRepository, PasswordService passwordService) { + public AccountServiceImpl(AccountRepository accountRepository, PasswordService passwordService, CustomerRepository customerRepository) { this.accountRepository = accountRepository; this.passwordService = passwordService; + this.customerRepository = customerRepository; } @Override @@ -32,6 +35,10 @@ public class AccountServiceImpl implements AccountService { @Override public Account saveNew(Account account) { + if (account.getCustomer() != null) { + account.getCustomer().setId(null); // Ensure new customer + customerRepository.save(account.getCustomer()); + } account.setPassword(passwordService.hashPassword(account.getPassword())); return this.save(account); } diff --git a/01-frontend/public/locales/de/translation.json b/01-frontend/public/locales/de/translation.json index 412a962..e2c1d00 100644 --- a/01-frontend/public/locales/de/translation.json +++ b/01-frontend/public/locales/de/translation.json @@ -97,5 +97,7 @@ "login": "Anmelden", "total": "Insgesamt", "admin": "Admin", - "fsmodel": "Indoor-Farming-Station" + "fsmodel": "Indoor-Farming-Station", + "zip": "Postleitzahl", + "surname": "Nachname" } diff --git a/01-frontend/public/locales/en/translation.json b/01-frontend/public/locales/en/translation.json index f60fd56..148863f 100644 --- a/01-frontend/public/locales/en/translation.json +++ b/01-frontend/public/locales/en/translation.json @@ -97,5 +97,7 @@ "login": "Login", "total": "Total", "admin": "Admin", - "fsmodel": "Indoor farming station" + "fsmodel": "Indoor farming station", + "zip": "Zip code", + "surname": "Surname" } \ No newline at end of file diff --git a/01-frontend/src/helper/navbar/LoginDialog.tsx b/01-frontend/src/helper/navbar/LoginDialog.tsx index fc6409d..b824c74 100644 --- a/01-frontend/src/helper/navbar/LoginDialog.tsx +++ b/01-frontend/src/helper/navbar/LoginDialog.tsx @@ -3,8 +3,8 @@ import { useQuery } from "@tanstack/react-query"; import i18next from "i18next"; import React, { useState } from "react"; import AccountType from "../../components/Account"; -import { submitLogin, submitRegister } from "../query/Queries"; // Importiere die Funktion für die Registrierung import { useAccount } from "../AccountProvider"; +import { fetchAccount, submitLogin, submitRegister } from "../query/Queries"; // Importiere die Funktion für die Registrierung type LoginDialogProps = { open: boolean; @@ -30,6 +30,14 @@ const LoginDialog: React.FC = ({ open, onClose, loginData, set enabled: false, }); + const { refetch: refetchAccount } = useQuery({ + queryKey: ["fetchAccount", loginData], + queryFn: () => fetchAccount(loginData), + retry: 0, + retryDelay: 1000, + enabled: false, + }); + // useQuery für Registrierung const { refetch: refetchRegister, isLoading: isLoadingRegister, error: errorRegister } = useQuery({ queryKey: ["submitRegister", registerData], @@ -45,7 +53,8 @@ const LoginDialog: React.FC = ({ open, onClose, loginData, set const response = await refetchLogin(); // Anfrage auslösen if (response.status === "success") { const userData = response.data; // Extrahiere die Benutzerdaten aus der Antwort - login({ email: userData.email, customerId: userData.token, password: userData.password }); // Speichere die Benutzerdaten im AccountProvider + const customerData = (await refetchAccount()).data; // Hole die Account-Daten + login({ email: userData.email, customerId: customerData.customer.id, password: userData.password }); // Speichere die Benutzerdaten im AccountProvider setShowRegister(false); // Zurück zum Login wechseln onSubmit(); // Dialog schließen } else { diff --git a/01-frontend/src/helper/query/Queries.tsx b/01-frontend/src/helper/query/Queries.tsx index cffe389..d677c79 100644 --- a/01-frontend/src/helper/query/Queries.tsx +++ b/01-frontend/src/helper/query/Queries.tsx @@ -11,7 +11,6 @@ export const fetchItemList = async () => { throw new Error('Fehler beim Laden der Items'); } const data = await response.json(); - console.log("Fetched Items:", data); return data; }; @@ -29,7 +28,6 @@ export const submitRating = async (ratingData: RatingSubmitType) => { } const data = await response.json(); - console.log("Rating Submitted:", data); return data; } @@ -40,7 +38,6 @@ export const fetchRatingList = async (itemId: string) => { throw new Error('Fehler beim Laden der Items'); } const data = await response.json(); - console.log("Fetched Items:", data); return data; }; @@ -106,6 +103,14 @@ export const submitLogin = async (loginData: SubmitLogin) => { return response.json(); }; +export const fetchAccount = async (loginData: SubmitLogin) => { + const response = await fetch("http://localhost:8085/account?email=" + loginData.email + "&password=" + loginData.password); + if (!response.ok) { + throw new Error("Login failed"); + } + return response.json(); +}; + export const submitRegister = async (registerData: AccountType) => { const response = await fetch("http://localhost:8085/account", { method: "POST", @@ -118,4 +123,14 @@ export const submitRegister = async (registerData: AccountType) => { throw new Error("Login failed"); } return response.json(); +}; + +export const fetchCustomer = async (userId: number) => { + const response = await fetch('http://localhost:8085/customer?id=' + userId); + console.log("API Response:", response); + if (!response.ok) { + throw new Error('Fehler beim Laden des Customers'); + } + const data = await response.json(); + return data; }; \ No newline at end of file diff --git a/01-frontend/src/pages/Account.tsx b/01-frontend/src/pages/Account.tsx index 5ce75a2..dfa3729 100644 --- a/01-frontend/src/pages/Account.tsx +++ b/01-frontend/src/pages/Account.tsx @@ -1,25 +1,57 @@ -import { Box, Typography, Button, TextField, Paper, Divider, Stack } from "@mui/material"; +import { Box, Button, Divider, Paper, Stack, TextField, Typography } from "@mui/material"; +import { useQuery } from "@tanstack/react-query"; +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; +import { CustomerType } from "../components/Account"; +import { useAccount } from "../helper/AccountProvider"; +import { fetchCustomer } from "../helper/query/Queries"; import "./pages.css"; -import { useState } from "react"; -import {useTranslation} from "react-i18next"; export default function Account() { const { t } = useTranslation(); const navigate = useNavigate(); + const { user: userData, logout } = useAccount(); // Beispielhafte Userdaten (könnten aus Context/Backend kommen) - const [user, setUser] = useState({ - name: "Max Mustermann", - email: "max.mustermann@email.de", - phone: "+49 123 456789", - address: "Musterstraße 1, 12345 Musterstadt" + const [user, setUser] = useState({ + name: "", + surname: "", + address: "", + country: "", + zip: "", + id: userData?.customerId || 0, // Initialwert }); + // Aktualisiere den `user`-State, wenn sich `userData` ändert + useEffect(() => { + console.log("UserData changed:", userData); + if (userData?.customerId) { + setUser((prev) => ({ + ...prev, + id: userData.customerId, // Aktualisiere die ID + })); + } + }, [userData]); + const [edit, setEdit] = useState(false); const [form, setForm] = useState(user); + const { data } = useQuery({ + queryKey: ['fetchCustomer', userData?.customerId], + queryFn: () => fetchCustomer(userData?.customerId || 0), // Funktion zum Abrufen der Kundendaten + retry: 3, // Versucht es 3-mal erneut + retryDelay: 1000, // Wartezeit zwischen den Versuchen (in ms) + }); + + useEffect(() => { + if (data) { + setUser(data); // Aktualisiere den user-State mit den abgerufenen Daten + setForm(data); // Optional: Aktualisiere auch den form-State + } + }, [data]); + const handleEdit = () => setEdit(true); const handleCancel = () => { setForm(user); @@ -33,9 +65,8 @@ export default function Account() { setEdit(false); }; const handleDelete = () => { - // Hier ggf. Dialog oder API-Call zum Löschen - alert(t('accountDeleted')); navigate("/"); + logout(); // Logout nach dem Löschen }; return ( @@ -55,17 +86,9 @@ export default function Account() { fullWidth /> - + + {edit ? (