diff --git a/01-frontend/src/components/Account.tsx b/01-frontend/src/components/Account.tsx index add147d..01b0d43 100644 --- a/01-frontend/src/components/Account.tsx +++ b/01-frontend/src/components/Account.tsx @@ -1,8 +1,27 @@ type AccountType = { - id: string; - name: string; + id: number; + customer: { + id: number; + name: string; + surname: string; + address: string; + country: string; + zip: string; + }; + password: string; + langI18n: string; + admin: boolean; email: string; - status: "active" | "inactive"; }; -export default AccountType; \ No newline at end of file +export default AccountType; + +export type CustomerType = +{ + id: number; + name: string; + surname: string; + address: string; + country: string; + zip: string; +} \ No newline at end of file diff --git a/01-frontend/src/components/Order.tsx b/01-frontend/src/components/Order.tsx index 42c388e..af86f4f 100644 --- a/01-frontend/src/components/Order.tsx +++ b/01-frontend/src/components/Order.tsx @@ -8,3 +8,28 @@ type OrderType = { }; export default OrderType; + + +export type ShippingDetails = { + firstName: string; + lastName: string; + telefon: string; + address: string; + postalCode: string; + city: string; + country: string; +}; + +export type OrderItem = { + id: string; + amount: number; + article: string; // UUID of the item +}; + +export type SubmitOrder = { + id: number; + customerId: number; + time: number; + status: "active" | "inactive" | "running" | "cancelled"; + orderItems: OrderItem[]; +} diff --git a/01-frontend/src/helper/AccountProvider.tsx b/01-frontend/src/helper/AccountProvider.tsx index 8a22135..3507e89 100644 --- a/01-frontend/src/helper/AccountProvider.tsx +++ b/01-frontend/src/helper/AccountProvider.tsx @@ -3,6 +3,7 @@ import { createContext, ReactNode, useContext, useState } from "react"; type User = { password: string; email: string; + customerId: number; // weitere Felder nach Bedarf }; diff --git a/01-frontend/src/helper/navbar/LoginDialog.tsx b/01-frontend/src/helper/navbar/LoginDialog.tsx index 0356ade..3af0e48 100644 --- a/01-frontend/src/helper/navbar/LoginDialog.tsx +++ b/01-frontend/src/helper/navbar/LoginDialog.tsx @@ -1,4 +1,4 @@ -import { Dialog, DialogTitle, DialogContent, DialogActions, TextField, Button, Box, Link } from "@mui/material"; +import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Link, TextField } from "@mui/material"; import React, { useState } from "react"; type LoginDialogProps = { @@ -6,7 +6,7 @@ type LoginDialogProps = { onClose: () => void; onSubmit: () => void; loginData: { email: string; password: string }; - setLoginData: React.Dispatch>; + setLoginData: React.Dispatch>; }; const LoginDialog: React.FC = ({ open, onClose, onSubmit, loginData, setLoginData }) => { diff --git a/01-frontend/src/helper/navbar/NavBar.tsx b/01-frontend/src/helper/navbar/NavBar.tsx index 0736a37..ee0a7d7 100644 --- a/01-frontend/src/helper/navbar/NavBar.tsx +++ b/01-frontend/src/helper/navbar/NavBar.tsx @@ -32,7 +32,7 @@ export default function NavBar() { const { user, login, logout } = useAccount(); const [loginOpen, setLoginOpen] = React.useState(false); - const [loginData, setLoginData] = React.useState({ password: '', email: '' }); + const [loginData, setLoginData] = React.useState({ password: '', email: '', customerId: 0 }); const [itemNames, setItemNames] = React.useState([]); // Für Autocomplete @@ -83,7 +83,7 @@ export default function NavBar() { const handleLoginSubmit = () => { login(loginData); setLoginOpen(false); - setLoginData({ password: '', email: '' }); + setLoginData({ password: '', email: '', customerId: 0 }); }; // useQuery, um die Item-Namen zu laden diff --git a/01-frontend/src/helper/query/Queries.tsx b/01-frontend/src/helper/query/Queries.tsx index 7fbbc88..0dd32b9 100644 --- a/01-frontend/src/helper/query/Queries.tsx +++ b/01-frontend/src/helper/query/Queries.tsx @@ -1,5 +1,7 @@ // api/queries.js +import AccountType, { CustomerType } from "../../components/Account"; +import { SubmitOrder } from "../../components/Order"; import RatingSubmitType from "../../components/RatingSubmit"; export const fetchItemList = async () => { @@ -40,4 +42,70 @@ export const fetchRatingList = async (itemId: string) => { const data = await response.json(); console.log("Fetched Items:", data); return data; -}; \ No newline at end of file +}; + +export const submitLogin = async (ratingData: RatingSubmitType) => { + const response = await fetch('http://localhost:8085/account?uuid=' + ratingData.articleId + '&rating=' + ratingData.rating * 2, { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: ratingData.content, + }); + + if (!response.ok) { + throw new Error('Fehler beim Senden der Bewertung'); + } + + const data = await response.json(); + console.log("Rating Submitted:", data); + return data; +} + +export const submitOrder = async (data: SubmitOrder) => { + const response = await fetch('http://localhost:8085/order', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error('Fehler beim Senden der Bestellung'); + } + + return await response.json(); +} + +export const submitAccount = async (data: AccountType) => { + const response = await fetch('http://localhost:8085/account', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error('Fehler beim Senden des Accounts'); + } + + return await response.json(); +} + +export const submitCustomer = async (data: CustomerType) => { + const response = await fetch('http://localhost:8085/customer', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }); + + if (!response.ok) { + throw new Error('Fehler beim Senden des Accounts'); + } + + return await response.json(); +} \ No newline at end of file diff --git a/01-frontend/src/pages/Payment.tsx b/01-frontend/src/pages/Payment.tsx index 182d68a..1cc8c8d 100644 --- a/01-frontend/src/pages/Payment.tsx +++ b/01-frontend/src/pages/Payment.tsx @@ -20,16 +20,11 @@ import { useTranslation } from "react-i18next"; import { useNavigate } from 'react-router-dom'; import Item from '../components/Item'; import { BasketItem, useBasket } from '../helper/BasketProvider'; - -type ShippingDetails = { - firstName: string; - lastName: string; - telefon: string; - address: string; - postalCode: string; - city: string; - country: string; -}; +import { ShippingDetails, SubmitOrder } from '../components/Order'; +import { useAccount } from '../helper/AccountProvider'; +import { useQuery } from '@tanstack/react-query'; +import { submitCustomer, submitOrder } from '../helper/query/Queries'; +import { CustomerType } from '../components/Account'; function getDiscountedPrice(item: Item): number { return (item.price100 / 100 * (100-item.discount100)/100); @@ -85,12 +80,57 @@ export default function Payment() { }); 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 handleNext = () => { + const submitOrderData: SubmitOrder = { + id: 0, // This will be set by the backend + customerId: user ? user.customerId : 0, // Use user ID if logged in, otherwise 0 + time: Date.now(), + status: "active", + orderItems: basket.map(item => ({ + id: item.item.id, + amount: item.quantity, + article: item.item.uuid, // Assuming UUID is the identifier for the item + })), + }; + + const { refetch: refetchCustomer } = useQuery({ + queryKey: ["submitCustomer", customerData], + queryFn: () => submitCustomer(customerData), + retry: 3, + retryDelay: 1000, + enabled: false, + }); + + const { refetch: refetchSubmit } = useQuery({ + queryKey: ["submitOrder", submitOrderData], + queryFn: () => submitOrder(submitOrderData), + retry: 3, + retryDelay: 1000, + enabled: false, + }); + + const handleNext = async () => { if (activeStep === steps.length - 2) { // Simulate order placement and generate order number const generatedOrderNumber = `ORD-${Math.floor(Math.random() * 1000000)}`; setOrderNumber(generatedOrderNumber); + if (user) { + submitOrderData.customerId = user.customerId; // Use logged-in user's customer ID + } else { + void refetchCustomer(); // Submit customer data if not logged in + submitOrderData.customerId = JSON.parse((await refetchCustomer()).data as string).customerId; // Get the customer ID from the response + } + //TODO Wenn nicht eingeloggt Customer anlegen, ansosnten Accountdaten laden + void refetchSubmit(); // Submit order data } setActiveStep((prevStep) => prevStep + 1); };