From ffe7f1d1cd4dc1093641e5ff155d9cd48031f6f1 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:50:19 +0200 Subject: [PATCH 01/15] Mismades were taken --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes .../service/impl/SessionServiceImpl.java | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index 1e004847de9474bc9b2b4e49fa09b475d76d317d..a70f9a1e5bba68fb4126d95f2cacb7209c5b2ad9 100644 GIT binary patch delta 166 zcmWm0Ia0y^06@`1z= System.currentTimeMillis()) { + if (session.getTimeout() <= System.currentTimeMillis()) { log.info("Session with email {} is expired", email); delete(session); return false; From 6ebc610f414c232c9f172d137ae563a89da20242 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:53:51 +0200 Subject: [PATCH 02/15] Fix Database Graveyards --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index a70f9a1e5bba68fb4126d95f2cacb7209c5b2ad9..7a4bf65c307ead6c5f56fe37e325cb172e80ae55 100644 GIT binary patch delta 758 zcmbWzPe_w-9LMqBZ_o2=`P1z?OH19%nayX64jWM+;U7@y5V7b%1d+KX8@QAu+dMyF zP(q-^6AZkBqR+vTy2GGLgXj<)oY0{TLV1u5UcLJn?st*A#KQ~TeE2;N{GNr1!x!LP zfJfg4hk0}-wKnLbw@jk}M!#r_21>r680lff%{afWdBlU+m${6Y4H9hSwm{*xj>uCZGh|NMRDo9FlA ny^W>S&D#;h;l<)#PsAl~BTmPRj?1E=ACdq3xz|OEN delta 722 zcmZ|MKWGzS9LDkYP405Z``+E}(m&UxNvv&bu1LXzq7pK+peRl$2A3LYt{Rk5idY3f z;i`fn3Mz-Xs>5NO)F4?L0wO3b85KvxSrpOHN9;RP?C^mv55M6(Zmk>fHMpJS#XGru zy!fp7aK>Vc>C|HMfu7Kfwmn;-aL)0$YfXSvR%^wfp1lMi0+ qKJ+;J_2%Ny?#)Gh|N7U`4}s78bDn(L5nb;KIscwr?RimeviBPa0ov67 From f2ad893adc52c1e9a7a7de03745678133b5f0bcd Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 15:57:03 +0200 Subject: [PATCH 03/15] Fix warning --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes 01-frontend/src/helper/AccountProvider.tsx | 1 + 01-frontend/src/helper/BasketProvider.tsx | 1 + 3 files changed, 2 insertions(+) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index 7a4bf65c307ead6c5f56fe37e325cb172e80ae55..2e0e78e6385c406172e3f0b1352bb31a6cb61595 100644 GIT binary patch delta 235 zcmZ9@yD|e&0Eh8C%M!7iMdFqf#O0XDF+hEq27NsEAnXiK^Ha2jWoF#F01_C*t%C_w-Wm?a;FmJ50k@_hGBC zA9#(xTwnE~(R(|;zy18a`DtF7B$;+D{AAL1wb?TE?AT7zaNsf<{kIQ!=F&VnD}Vg~ D2NPEF delta 235 zcmZ9@txp1B0LSrr&{JMcAAAA9LsWcu9Ao|q1cQ-o{w5QN#)fXcIht;66obK8Wn=Da zlBlQ2&3F}p$t>CMZJ%#%{A_yjZbMVQtDO0D@3hmuLKu+}3u00DVo5BEw8)68$caF# zh*e=lUaX0Au^~1^K@`Q7D2cMz7NMw!9Z?m#Vo&Ugnm7=L;z%67;vQep#wMOk>?8_? z?#)&&OJU0Q8h)nL`i&nN=cDWP*Y{KR{=y9UKc9o--PPvH%(JsxGYZBow)y|^W*WO_ J8lMzC{s8&aSJeOj diff --git a/01-frontend/src/helper/AccountProvider.tsx b/01-frontend/src/helper/AccountProvider.tsx index 2f21d00..73ab17c 100644 --- a/01-frontend/src/helper/AccountProvider.tsx +++ b/01-frontend/src/helper/AccountProvider.tsx @@ -21,6 +21,7 @@ export const AccountProvider = ({ children }: { children: ReactNode }) => { ); }; +// eslint-disable-next-line react-refresh/only-export-components export const useAccount = () => { const context = useContext(AccountContext); if (!context) { diff --git a/01-frontend/src/helper/BasketProvider.tsx b/01-frontend/src/helper/BasketProvider.tsx index 32e8674..1bd52b7 100644 --- a/01-frontend/src/helper/BasketProvider.tsx +++ b/01-frontend/src/helper/BasketProvider.tsx @@ -44,6 +44,7 @@ export const BasketProvider: React.FC<{ children: React.ReactNode }> = ({ childr ); }; +// eslint-disable-next-line react-refresh/only-export-components export const useBasket = () => { const context = useContext(BasketContext); if (!context) { From 3ff4e757165aa6c0386cd66798f9b97c040fd867 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 15:58:04 +0200 Subject: [PATCH 04/15] Image on ProductInfo page --- 01-frontend/src/helper/productpage/ProductInfo.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/01-frontend/src/helper/productpage/ProductInfo.tsx b/01-frontend/src/helper/productpage/ProductInfo.tsx index 01a3325..877e76a 100644 --- a/01-frontend/src/helper/productpage/ProductInfo.tsx +++ b/01-frontend/src/helper/productpage/ProductInfo.tsx @@ -59,11 +59,14 @@ export default function ProductInfo({ item }: { item: Item }) { const fetchImage = async () => { try { const response = await fetch(`http://localhost:8085/image?uuid=${item.uuid}`); - const data = await response.text(); + var data = await response.text(); if(data.length == 0) { console.error("Got emtpy picture for article ", item.uuid); } - setImageUrl("data:image/jpeg;base64," + data); + if(!data.startsWith("data:image/")) { + data = "data:image/jpeg;base64," + data + } + setImageUrl(data); } catch (error) { console.error("Fehler beim Laden des Bildes:", error); } From 3dddcdf860fe6f4bff9ad8ccd7d7990fa21a3117 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 16:04:40 +0200 Subject: [PATCH 05/15] Cronjob for deleting expired Sessions --- .../de/htwsaar/webshop/repository/SessionRepository.java | 2 ++ .../main/java/de/htwsaar/webshop/service/SessionService.java | 2 ++ .../de/htwsaar/webshop/service/impl/SessionServiceImpl.java | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/00-backend/src/main/java/de/htwsaar/webshop/repository/SessionRepository.java b/00-backend/src/main/java/de/htwsaar/webshop/repository/SessionRepository.java index d200c65..6d5f2ca 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/repository/SessionRepository.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/repository/SessionRepository.java @@ -13,4 +13,6 @@ public interface SessionRepository extends JpaRepository { Session findByAccount(Account account); Session getSessionByToken(UUID token); + + void deleteSessionsByTimeoutBefore(Long timeoutBefore); } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/SessionService.java b/00-backend/src/main/java/de/htwsaar/webshop/service/SessionService.java index 71fe2ae..169b09d 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/service/SessionService.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/SessionService.java @@ -19,4 +19,6 @@ public interface SessionService { boolean isValid(UUID token, String email); boolean isAdmin(UUID token, String email); + + void deleteExpired(); } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/SessionServiceImpl.java b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/SessionServiceImpl.java index 17d04a9..e718d08 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/SessionServiceImpl.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/SessionServiceImpl.java @@ -92,4 +92,9 @@ public class SessionServiceImpl implements SessionService { log.info("Session with email {} allowed to access Admin Services", email); return true; } + + @Override + public void deleteExpired() { + sessionRepository.deleteSessionsByTimeoutBefore(System.currentTimeMillis()); + } } From e7169e4317eac307d40098ccaaf3b8926aa60f72 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 16:04:50 +0200 Subject: [PATCH 06/15] Fix timeutil epoch/milli --- 00-backend/src/main/java/de/htwsaar/webshop/util/TimeUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/00-backend/src/main/java/de/htwsaar/webshop/util/TimeUtil.java b/00-backend/src/main/java/de/htwsaar/webshop/util/TimeUtil.java index f9fd439..0cc9549 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/util/TimeUtil.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/util/TimeUtil.java @@ -46,7 +46,7 @@ public class TimeUtil { } public static long nowMonthsAgo(long months) { - return LocalDateTime.now().minusMonths(months).atZone(ZoneId.systemDefault()).toEpochSecond(); + return LocalDateTime.now().minusMonths(months).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } public static long monthLength(long epoch) { From 3c7a0ea6f6f1ddf91fe9826910cc8075ef99f327 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 16:18:45 +0200 Subject: [PATCH 07/15] Added win start script. --- start.ps1 | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 start.ps1 diff --git a/start.ps1 b/start.ps1 new file mode 100644 index 0000000..0a3311f --- /dev/null +++ b/start.ps1 @@ -0,0 +1,60 @@ +# Funktion zur Bereinigung beim Beenden +function OnExit { + Write-Host "`n[DPS] Cleaning up..." + if ($backendProcess -and !$backendProcess.HasExited) { + $backendProcess.Kill() + } + if ($frontendProcess -and !$frontendProcess.HasExited) { + $frontendProcess.Kill() + } + Write-Host "[DPS] Cleaned up..." + + # Einen Ordner höher gehen + Set-Location (Resolve-Path "..").Path + Write-Host "[DPS] Returned to parent directory: $(Get-Location)" + + exit +} + +Write-Host "[DPS] trapped" + +# Backend starten +Set-Location ./00-backend +$backendOutLog = "../backend_latest.out.log" +$backendErrLog = "../backend_latest.err.log" +$backendProcess = Start-Process "java" -ArgumentList "-jar", "target/webshop-0.0.1-SNAPSHOT.jar" ` + -RedirectStandardOutput $backendOutLog ` + -RedirectStandardError $backendErrLog ` + -NoNewWindow -PassThru +Write-Host "[DPS] Backend started with PID $($backendProcess.Id)" + +# Frontend starten (ohne cmd.exe) +Set-Location ../01-frontend +$frontendOutLog = "../frontend_latest.out.log" +$frontendErrLog = "../frontend_latest.err.log" + +$frontendProcess = Start-Process "node" ` + -ArgumentList "node_modules/.bin/react-scripts", "start" ` + -RedirectStandardOutput $frontendOutLog ` + -RedirectStandardError $frontendErrLog ` + -NoNewWindow -PassThru + +Write-Host "[DPS] Frontend started with PID $($frontendProcess.Id)" + +Write-Host "[DPS] Ctrl+C to stop" + +Register-EngineEvent PowerShell.Exiting -Action { OnExit } -SupportEvent + +try { + while ($true) { + Start-Sleep -Seconds 1 + if ($backendProcess.HasExited -and $frontendProcess.HasExited) { + break + } +} +} +catch { + if ($_.Exception -is [System.Management.Automation.PipelineStoppedException]) { + # This block will not execute on CTRL-C + } +} From e73c828a2bd17afb5e00c47051d36bc39a854339 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 16:20:31 +0200 Subject: [PATCH 08/15] Updated Readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6a3b1d5..6381b7d 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ Webshop-Projekt für htw saar Digitale Produktionssysteme ### 🤮 Windows -- TODO: make script +- Check if in parent folder, because after exit script is in frontend folder. So retry after cd .. only possible ```shell - + ./start.ps1 ``` # Contributors From d3cb4bd493e5dc0cda71eb60af87cb65cfe6ca04 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 16:42:56 +0200 Subject: [PATCH 09/15] Loading Customer data on payment. --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes 01-frontend/src/pages/Payment.tsx | 95 ++++++++++++-------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index 2e0e78e6385c406172e3f0b1352bb31a6cb61595..ee07ab439ef3832a017bad5567283e80ad11debf 100644 GIT binary patch delta 543 zcmZ9`J!lhg9LDkcU+!|r`SPntn$+ghtF4}B44h&Mf?$oHgD>Z(2tL8ayGlrPQ z*YNOgOxAr#_vyoAhqG?k$}=J9g452i)Ip+XFrrf*~^^427XGq701@W5gLcV;N&PV+CU+ zgBTr*Rg459$w)Ce8EHm_(ZyKJ=w@UY24f9lEn^+SWb`oBGkO_)j17#9&tWM}LZiGy z-)Wv^=q8<}1C+0)pIKdW+0axerwYw!dhYdtTT@f|#ng2AZ?|kj+d6UE`}xTn z{OsRHPvc6a8fdaEWJCS0Uz^#b+Mrwg{qj%bj(@kM2e-(E($;+SP2YQW|I=6czK^#k zbt2Gs?tyGX+M2m^D0U=!vCw#N^vAA8zY?W@6>m|VntyHW4yr2>Rp<#V(p$Pp)3j7i o&soQ5D4eUMA~_MRjJD5EoZ33WO-kzwm)uxrSoMX*rp;ge0o;SRX8-^I delta 496 zcmZ9`O-K}R9LDkayYsTUrhnUPR~t2_(y4Y2*5*+t^`IoUNC%0)N6=G;jzLAqt~^=< z6?@nY-V~`&(gfE%hzd(y1Vu>;Z-R$RiSptLL^FGw!|(EZ4!`ff;4u&gNf3f4B7B5OXoOA}gr5iy zL86#ALzEDuge1y{vqXqEN0bxii7*i%Du_zr0$~zWL^V-ETqJ4({ - firstName: '', - lastName: '', - telefon: '', + const [shippingDetails, setShippingDetails] = useState({ + id: 0, // This will be set by the backend or user data + name: '', + surname: '', address: '', - postalCode: '', - city: '', + zip: '', country: 'Deutschland', }); const [orderNumber, setOrderNumber] = useState(null); const steps = [t('reviewCart'), t('shippingDetails'), t('payment'), t('orderSummary')]; const { user } = useAccount(); - const customerData: CustomerType = { - id: 0, - name: shippingDetails.firstName, - surname: shippingDetails.lastName, - address: shippingDetails.address, - country: shippingDetails.country, - zip: shippingDetails.postalCode, - }; const submitOrderData: SubmitOrder = { id: 0, // This will be set by the backend @@ -104,8 +95,8 @@ export default function Payment() { }; const { refetch: refetchCustomer } = useQuery({ - queryKey: ["submitCustomer", customerData], - queryFn: () => submitCustomer(customerData), + queryKey: ["submitCustomer", shippingDetails], + queryFn: () => submitCustomer(shippingDetails), retry: 0, retryDelay: 1000, enabled: false, @@ -117,6 +108,28 @@ export default function Payment() { }; + const { refetch: customerData } = useQuery({ + queryKey: ['fetchCustomer', user?.customerId], + queryFn: () => fetchCustomer(user?.customerId || 0), // Funktion zum Abrufen der Kundendaten + enabled: false + }); + + useEffect(() => { + const fetchShippingDetails = async () => { + if (user) { + try { + const userShippingDetails = (await customerData()).data; + setShippingDetails(userShippingDetails || shippingDetails); + } catch (error) { + console.error("Fehler beim Laden der Kundendaten:", error); + } + } + }; + + fetchShippingDetails(); + }, [user, customerData, shippingDetails]); + + // Verwende useMutation statt useQuery für submitOrder const { mutateAsync: submitOrderMutation } = useMutation({ mutationFn: (orderData: SubmitOrder) => submitOrder(orderData), @@ -174,11 +187,10 @@ export default function Payment() { // Hilfsfunktion prüfen, ob alle Pflichtfelder ausgefüllt sind const isShippingDetailsValid = () => { return ( - shippingDetails.firstName.trim() !== '' && - shippingDetails.lastName.trim() !== '' && + shippingDetails.name.trim() !== '' && + shippingDetails.surname.trim() !== '' && shippingDetails.address.trim() !== '' && - shippingDetails.postalCode.trim() !== '' && - shippingDetails.city.trim() !== '' && + shippingDetails.zip.trim() !== '' && shippingDetails.country.trim() !== '' ); }; @@ -211,7 +223,7 @@ export default function Payment() { fullWidth label={t('firstName')} name="firstName" - value={shippingDetails.firstName} + value={shippingDetails.name} onChange={handleInputChange} required /> @@ -220,20 +232,11 @@ export default function Payment() { fullWidth label={t('lastName')} name="lastName" - value={shippingDetails.lastName} + value={shippingDetails.surname} onChange={handleInputChange} required /> - - - - {t('shippingDetails')}: - {shippingDetails.firstName} {shippingDetails.lastName}
+ {shippingDetails.name} {shippingDetails.surname}
{shippingDetails.address}
- {shippingDetails.postalCode} {shippingDetails.city}
- {shippingDetails.country} + {shippingDetails.zip} {shippingDetails.country}
{t('orderedItems')}: From 648683c2339dbe9d8b2e971cbdfa64e3b1ff46d8 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 16:45:19 +0200 Subject: [PATCH 10/15] Midmades were taken --- 01-frontend/src/pages/Payment.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/01-frontend/src/pages/Payment.tsx b/01-frontend/src/pages/Payment.tsx index 65c15cf..e67a10c 100644 --- a/01-frontend/src/pages/Payment.tsx +++ b/01-frontend/src/pages/Payment.tsx @@ -222,7 +222,7 @@ export default function Payment() { Date: Sun, 15 Jun 2025 16:45:27 +0200 Subject: [PATCH 11/15] i forgor --- .../cronjob/ExpiredSessionDeleteJob.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 00-backend/src/main/java/de/htwsaar/webshop/cronjob/ExpiredSessionDeleteJob.java diff --git a/00-backend/src/main/java/de/htwsaar/webshop/cronjob/ExpiredSessionDeleteJob.java b/00-backend/src/main/java/de/htwsaar/webshop/cronjob/ExpiredSessionDeleteJob.java new file mode 100644 index 0000000..8a00b40 --- /dev/null +++ b/00-backend/src/main/java/de/htwsaar/webshop/cronjob/ExpiredSessionDeleteJob.java @@ -0,0 +1,36 @@ +package de.htwsaar.webshop.cronjob; + +import de.htwsaar.webshop.service.SessionService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import static de.htwsaar.webshop.util.TimeUtil.MILLIS_TO_WEEK; + +/** + * CronJob for deleting expired sessions in fixed intervals + */ +@Component +@Slf4j +public class ExpiredSessionDeleteJob { + + private final SessionService sessionService; + + /** + * Constructor of the class + * @param sessionService used in the class + */ + public ExpiredSessionDeleteJob(SessionService sessionService) { + this.sessionService = sessionService; + } + + /** + * Method running the job calling the referring service method + */ + @Scheduled(fixedRate = MILLIS_TO_WEEK) + public void runFixedRateTask() { + log.info("Deleting expired sessions..."); + sessionService.deleteExpired(); + log.info("Deleted expired sessions."); + } +} \ No newline at end of file From c1cab06596062954ef6b6a0122734d19b890cb44 Mon Sep 17 00:00:00 2001 From: Tim <47184194+imgde@users.noreply.github.com> Date: Sun, 15 Jun 2025 16:46:47 +0200 Subject: [PATCH 12/15] ItemsInfo add REST call 1, missing category --- .../src/helper/adminpanel/ItemsInfo.tsx | 57 +++++++++---------- 01-frontend/src/helper/query/Queries.tsx | 8 +++ 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/01-frontend/src/helper/adminpanel/ItemsInfo.tsx b/01-frontend/src/helper/adminpanel/ItemsInfo.tsx index d5f8d3d..8da52b7 100644 --- a/01-frontend/src/helper/adminpanel/ItemsInfo.tsx +++ b/01-frontend/src/helper/adminpanel/ItemsInfo.tsx @@ -4,8 +4,13 @@ import {Box, Button, IconButton, Toolbar, useTheme} from "@mui/material"; import Item from "../../components/Item"; import {useTranslation} from "react-i18next"; import {DataGrid, GridColDef, GridRowId, GridRowSelectionModel} from "@mui/x-data-grid"; -import {useState} from "react"; +import {useEffect, useState} from "react"; import {Gauge, gaugeClasses} from "@mui/x-charts"; +import {useAccount} from "../AccountProvider.tsx"; +import {useQuery} from "@tanstack/react-query"; +import {fetchItems} from "../query/Queries.tsx"; +import Select from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; export default function ItemsInfo() { const theme = useTheme(); @@ -56,37 +61,25 @@ export default function ItemsInfo() { console.log("IconEdit", item); } - const _rows: Item[] = [ - { - id: "1", - uuid: "uuid123", - name: "Item", - description: "Super duper geil wichtiger text ", - price100: 1000, - stock: 100, - stockExpected: 1200, - category: "garden", - rating: 7, - discount100: 21, - }, - { - id: "2", - uuid: "uuid12312412", - name: "Schlauch", - description: "Schlauchiger Schlauch für Schlauchige Angelegenheiten", - price100: 10, - stock: 50, - stockExpected: 100, - category: "technicalComponents", - rating: 10, - discount100: 21, - }, - ] - //TODO: get per REST - const [rows, setRows] = useState(_rows); + const [rows, setRows] = useState([]); const [selectedRows, setSelectedRows] = useState>(new Set()); + const {user: loginData} = useAccount(); + + const { data } = useQuery({ + queryKey: ["fetchItems", loginData], + queryFn: () => fetchItems(loginData? loginData : {email: "", password: "", session: "", customerId: -1}), + retry: 3, + retryDelay: 1000, + }); + + useEffect(() => { + if (data) { + setRows(data); + } + }, [data]); + const handleSelectionChange = (newSelection: GridRowSelectionModel) => { setSelectedRows(newSelection.ids); }; @@ -112,7 +105,7 @@ export default function ItemsInfo() { { field: 'name', headerName: t('name'), - width: 150, + width: 200, editable: true, }, { @@ -120,6 +113,7 @@ export default function ItemsInfo() { headerName: t('category'), width: 150, editable: true, + valueFormatter: (val) => t(val), }, { field: 'description', @@ -132,7 +126,8 @@ export default function ItemsInfo() { headerName: t('price100'), width: 100, editable: true, - type: 'number' + type: 'number', + valueFormatter: (val) => (val / 100).toFixed(2), }, { field: 'discount100', diff --git a/01-frontend/src/helper/query/Queries.tsx b/01-frontend/src/helper/query/Queries.tsx index a3e1242..99b718b 100644 --- a/01-frontend/src/helper/query/Queries.tsx +++ b/01-frontend/src/helper/query/Queries.tsx @@ -157,4 +157,12 @@ export const fetchAccounts = async (loginData: User) => { throw new Error("Login failed"); } return response.json(); +}; + +export const fetchItems = async (loginData: User) => { + const response = await fetch("http://localhost:8085/article/all?email=" + loginData.email + "&session=" + loginData.session); + if (!response.ok) { + throw new Error("Login failed"); + } + return response.json(); }; \ No newline at end of file From adfcfefd3bb1432ec6b16225017f7c97248ff4b3 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 16:56:54 +0200 Subject: [PATCH 13/15] Added dynmic avatar name loading --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes 01-frontend/src/helper/navbar/NavBar.tsx | 10 +++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index ee07ab439ef3832a017bad5567283e80ad11debf..073b1b4a17bf267125c6039a99eb45c58f64af4b 100644 GIT binary patch delta 255 zcmZ9@y)Od+9LM3ia-5g;cPNgYDy3(T4oxg3iP$X0Zl76Fo4q36FjfrhAJ8;02#Lr| zqQqVkgUxJUk&ZeWp7E)7J8pfTk#j2-(XLxLLAW9%hQzS&#E2Lbz8DkZVnR%cw8#h( zftV80Vn$@ete6w?A`}Z^QRGAQ^FV1VnzfaFJ?tS%!zriAQnYYEQw{Y@xVKqCj zU5m_*{m1YpQ`lQ~>ZiZS^T2ZxYi|1X?DgjTZo7HBRqVF+%k}6v{OIkKgjMXpKCNv> ac5UC@PVBeBP0RlCUnk{G7?(S%S8sn(null); const [anchorElUser, setAnchorElUser] = React.useState(null); + const [avatarName, setAvatarName] = React.useState(''); // Für Avatar-Tooltip const { user, logout } = useAccount(); @@ -96,6 +97,13 @@ export default function NavBar() { setItemNames(items.map((item) => item.name)); }, [items]); + React.useEffect(() => { + // Setze den Avatar-Namen, wenn der Benutzer angemeldet ist + if (user) { + setAvatarName(user.email.toUpperCase()); + } + }, [user]); + const handleSearch = (_: React.SyntheticEvent, value: string | null) => { if (!value) { @@ -216,7 +224,7 @@ export default function NavBar() { - + Date: Sun, 15 Jun 2025 17:06:04 +0200 Subject: [PATCH 14/15] Added logged in username display --- 00-backend/datasource/database.sqlite | Bin 2727936 -> 2727936 bytes .../public/locales/de/translation.json | 3 ++- .../public/locales/en/translation.json | 3 ++- 01-frontend/src/helper/navbar/NavBar.tsx | 15 +++++++++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index 073b1b4a17bf267125c6039a99eb45c58f64af4b..246d0e038c1dcec972b7894d519398bc0ec8182a 100644 GIT binary patch delta 314 zcmZ9^zb^xE9LDkcUVG@_K8MnB=eIi1MwgCEBnTinod_MP_~HYKjfmR!oaJjkBpWl0*6l6c9jcp-_j Vp3R^yrdo&l$*NaMR%b5W{s1l_bVvXI delta 314 zcmZ9FJuCxp9ER_&N?Urr!&R$ysE<04#?YCN2$Mw8MA8PyyI4e+3>K-#>uX}F$wVVW z7%FF?5wTWcuyqil#K3|`G&Y83dXneK7V|1wVaHO*U3)|&S3xMEitrHCgqNrxY6&0V zCjvwrQBMR3oe;tx8i+=si7<%}(M*Ji2+=}B35&3aR-%n)Ct^eg(Mfa>-9((|xqx$U z7V(Lp$&=hlUN&V;#-(2j{Yx*q_PKMZ5A@BaR#a}=oc^`~UM=DE&+b33r`|@#u9ls_ zr9v#Ka$BDt50?K|-UXwt<)MjV_wZygw3sulo%hNhqsfAt%A?%Kn(WDoWPAmE#+pd8|jkcrc1p?_dk(nZT$cM diff --git a/01-frontend/public/locales/de/translation.json b/01-frontend/public/locales/de/translation.json index 92ff8fe..4332fc3 100644 --- a/01-frontend/public/locales/de/translation.json +++ b/01-frontend/public/locales/de/translation.json @@ -107,5 +107,6 @@ "discount100": "Rabatt in %", "deleteProduct": "Produkt löschen", "description": "Beschreibung", - "images": "Bilder" + "images": "Bilder", + "loggedInAs": "Angemeldet als" } diff --git a/01-frontend/public/locales/en/translation.json b/01-frontend/public/locales/en/translation.json index 83d0cad..faa6f6a 100644 --- a/01-frontend/public/locales/en/translation.json +++ b/01-frontend/public/locales/en/translation.json @@ -107,5 +107,6 @@ "discount100": "Discount in %", "deleteProduct": "Delete Product", "description": "Description", - "images": "Images" + "images": "Images", + "loggedInAs": "Logged in as" } \ No newline at end of file diff --git a/01-frontend/src/helper/navbar/NavBar.tsx b/01-frontend/src/helper/navbar/NavBar.tsx index f590119..eaac097 100644 --- a/01-frontend/src/helper/navbar/NavBar.tsx +++ b/01-frontend/src/helper/navbar/NavBar.tsx @@ -43,6 +43,11 @@ export default function NavBar() { const pages = pageKeys.map(key => ({ key, label: t(key) })); const settings = user ? [ + { + key: 'email', + label: `${t('loggedInAs')}: ${user.email}`, + disabled: true // wir nutzen dieses Flag gleich zur Erkennung + }, { key: 'account', label: t('account') }, { key: 'orders', label: t('orders') }, { key: 'logout', label: t('logout') } @@ -234,8 +239,14 @@ export default function NavBar() { open={Boolean(anchorElUser)} onClose={() => setAnchorElUser(null)} > - {settings.map(({ key, label }) => ( - handleCloseUserMenu(key)}> + {settings.map(({ key, label, disabled }) => ( + { + if (!disabled) handleCloseUserMenu(key); + }} + disabled={disabled} + > {label} ))} From 6b74bf772238d24b611757e0908407a7db18ff05 Mon Sep 17 00:00:00 2001 From: FlorianSpeicher Date: Sun, 15 Jun 2025 17:10:28 +0200 Subject: [PATCH 15/15] Added badge for item count in basket --- 01-frontend/src/helper/navbar/NavBar.tsx | 47 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/01-frontend/src/helper/navbar/NavBar.tsx b/01-frontend/src/helper/navbar/NavBar.tsx index eaac097..e003dfb 100644 --- a/01-frontend/src/helper/navbar/NavBar.tsx +++ b/01-frontend/src/helper/navbar/NavBar.tsx @@ -1,7 +1,7 @@ import AdbIcon from '@mui/icons-material/Adb'; import MenuIcon from '@mui/icons-material/Menu'; import SearchIcon from '@mui/icons-material/Search'; -import { Autocomplete, TextField } from '@mui/material'; +import { Autocomplete, Badge, TextField } from '@mui/material'; import AppBar from '@mui/material/AppBar'; import Avatar from '@mui/material/Avatar'; import Box from '@mui/material/Box'; @@ -22,6 +22,7 @@ import { useAccount } from '../AccountProvider'; import { fetchItemList } from '../query/Queries'; import LoginDialog from './LoginDialog'; import './NavBar.css'; +import { useBasket } from '../BasketProvider'; export default function NavBar() { const { t } = useTranslation(); @@ -32,6 +33,11 @@ export default function NavBar() { const { user, logout } = useAccount(); + const { basket } = useBasket(); + + const totalQuantity = basket?.reduce((sum, item) => sum + item.quantity, 0) ?? 0; + + const [loginOpen, setLoginOpen] = React.useState(false); const [loginData, setLoginData] = React.useState({ password: '', email: '', customerId: 0 }); @@ -191,15 +197,36 @@ export default function NavBar() { - {pages.map(({ key, label }) => ( - - ))} + {pages.map(({ key, label }) => { + if (key === 'checkout') { + return ( + + ); + } + + return ( + + ); + })}