Fixed ORders Page

This commit is contained in:
FlorianSpeicher
2025-06-15 21:29:48 +02:00
parent f8bb5fc82a
commit 570b64750e
5 changed files with 58 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
type Item = { type Item = {
id: string; id: number;
uuid: string; uuid: string;
name: string; name: string;
description: string; description: string;

View File

@@ -1,18 +1,18 @@
export const enum OrderStatusEnum { export enum OrderStatusEnum {
CANCELLED, CANCELLED = 'CANCELLED',
ISSUES, ISSUES = 'ISSUES',
DELIVERED, DELIVERED = 'DELIVERED',
ORDERED, ORDERED = 'ORDERED',
IN_PROGRESS IN_PROGRESS = 'IN_PROGRESS',
}; };
type OrderType = { type OrderType = {
id: string; id: number;
date: string; customerId: number;
time: number;
status: OrderStatusEnum; status: OrderStatusEnum;
items: { name: string; quantity: number; price: number }[]; orderItems: { id: number; amount: number; article: string }[];
total: number; total: number;
address: string;
}; };
export default OrderType; export default OrderType;
@@ -34,10 +34,7 @@ export type OrderItem = {
article: string; // UUID of the item article: string; // UUID of the item
}; };
export type SubmitOrder = { export type OrderPatch = {
id: number; id: number;
customerId: number; status: OrderStatusEnum;
time: number; };
status: OrderStatusEnum;
orderItems: OrderItem[];
}

View File

@@ -1,7 +1,7 @@
// api/queries.js // api/queries.js
import AccountType, { CustomerType, SubmitLogin, User } from "../../components/Account"; import AccountType, { CustomerType, SubmitLogin, User } from "../../components/Account";
import { SubmitOrder } from "../../components/Order"; import OrderType, { OrderPatch } from "../../components/Order";
import RatingSubmitType from "../../components/RatingSubmit"; import RatingSubmitType from "../../components/RatingSubmit";
export const fetchItemList = async () => { export const fetchItemList = async () => {
@@ -39,7 +39,7 @@ export const fetchRatingList = async (itemId: string) => {
return data; return data;
}; };
export const submitOrder = async (data: SubmitOrder) => { export const submitOrder = async (data: OrderType) => {
const response = await fetch('http://localhost:8085/order', { const response = await fetch('http://localhost:8085/order', {
method: 'POST', method: 'POST',
headers: { headers: {
@@ -143,7 +143,7 @@ export const deleteAccount = async (user: User) => {
}; };
export const fetchOrders = async (customerId: number) => { export const fetchOrders = async (customerId: number) => {
const response = await fetch('http://localhost:8085/order/all?sutomerId=' + customerId); const response = await fetch('http://localhost:8085/order/all?customerId=' + customerId);
if (!response.ok) { if (!response.ok) {
throw new Error('Fehler beim Laden des Customers'); throw new Error('Fehler beim Laden des Customers');
} }
@@ -179,4 +179,15 @@ export const editAccount = async (customer: CustomerType) => {
throw new Error('Fehler beim Löschen des Accounts'); throw new Error('Fehler beim Löschen des Accounts');
} }
return await response.json(); return await response.json();
};
export const orderPatch = async (order: OrderPatch) => {
const response = await fetch("http://localhost:8085/order?id=" + order.id + "&status=" + order.status, {
method: "PATCH",
}
);
if (!response.ok) {
throw new Error("Order patch failed");
}
return response.json();
}; };

View File

@@ -5,14 +5,14 @@ import { useTranslation } from "react-i18next";
import OrderType, { OrderStatusEnum } from "../components/Order"; import OrderType, { OrderStatusEnum } from "../components/Order";
import "./pages.css"; import "./pages.css";
import { useAccount } from "../helper/AccountProvider"; import { useAccount } from "../helper/AccountProvider";
import { fetchOrders } from "../helper/query/Queries"; import { fetchOrders, orderPatch } from "../helper/query/Queries";
export default function Orders() { export default function Orders() {
const {user} = useAccount(); const {user} = useAccount();
const [orders, setOrders] = useState<OrderType[]>([]) const [orders, setOrders] = useState<OrderType[]>([])
const { data: accountOrders } = useQuery<OrderType[]>({ const { data: accountOrders, refetch } = useQuery<OrderType[]>({
queryKey: ['fetchOrders', user?.customerId], // Hier sollte die tatsächliche Kunden-ID verwendet werden queryKey: ['fetchOrders', user?.customerId], // Hier sollte die tatsächliche Kunden-ID verwendet werden
queryFn: () => user ? fetchOrders(user.customerId) : Promise.resolve([]), // Simulierte API-Antwort queryFn: () => user ? fetchOrders(user.customerId) : Promise.resolve([]), // Simulierte API-Antwort
enabled: !!user, // Nur ausführen, wenn user existiert enabled: !!user, // Nur ausführen, wenn user existiert
@@ -22,6 +22,7 @@ export default function Orders() {
useEffect(() => { useEffect(() => {
setOrders(accountOrders ?? []); setOrders(accountOrders ?? []);
console.log("Orders fetched:", accountOrders);
}, [accountOrders]); }, [accountOrders]);
const { t } = useTranslation(); const { t } = useTranslation();
@@ -34,10 +35,19 @@ export default function Orders() {
const handleTabChange = (_: React.SyntheticEvent, newValue: number) => setTab(newValue); const handleTabChange = (_: React.SyntheticEvent, newValue: number) => setTab(newValue);
const handleCancelOrder = (orderId: string) => {
// Hier API-Call zum Stornieren einbauen const { refetch: cancleOrder } = useQuery({
alert(`${t('orderCancelled')} #${orderId}`); queryKey: ["orderPatch", {id: selectedOrder?.id || -1, status: OrderStatusEnum.CANCELLED}],
queryFn: () => orderPatch({id: selectedOrder?.id || -1, status: OrderStatusEnum.CANCELLED}),
retry: 0,
retryDelay: 1000,
enabled: false,
});
const handleCancelOrder = async() => {
await cancleOrder();
setSelectedOrder(null); setSelectedOrder(null);
refetch();
}; };
return ( return (
@@ -57,8 +67,8 @@ export default function Orders() {
{activeOrders.map(order => ( {activeOrders.map(order => (
<ListItemButton key={order.id} onClick={() => setSelectedOrder(order)}> <ListItemButton key={order.id} onClick={() => setSelectedOrder(order)}>
<ListItemText <ListItemText
primary={`${t('order')} #${order.id}${order.date}`} primary={`${t('order')} #${order.id}${order.status}${new Date(order.time).toUTCString()}`}
secondary={`${t('sum')}: ${order.total.toFixed(2)} € • ${order.items.length} ${t('items')}`} secondary={`${t('sum')}: ${order.total.toFixed(2)} € • ${order.orderItems.length} ${t('items')}`}
/> />
</ListItemButton> </ListItemButton>
))} ))}
@@ -72,8 +82,8 @@ export default function Orders() {
{inactiveOrders.map(order => ( {inactiveOrders.map(order => (
<ListItemButton key={order.id} onClick={() => setSelectedOrder(order)}> <ListItemButton key={order.id} onClick={() => setSelectedOrder(order)}>
<ListItemText <ListItemText
primary={`${t('order')} #${order.id}${order.date}`} primary={`${t('order')} #${order.id}${order.status}${order.time}`}
secondary={`${t('sum')}: ${order.total.toFixed(2)} € • ${order.items.length} ${t('items')}`} secondary={`${t('sum')}: ${order.total.toFixed(2)} € • ${order.orderItems.length} ${t('items')}`}
/> />
</ListItemButton> </ListItemButton>
))} ))}
@@ -90,16 +100,14 @@ export default function Orders() {
<DialogContent dividers> <DialogContent dividers>
{selectedOrder && ( {selectedOrder && (
<Stack spacing={2}> <Stack spacing={2}>
<Typography variant="subtitle1">{`${t('orderDate')}: ${selectedOrder.date}`}</Typography> <Typography variant="subtitle1">{`${t('orderDate')}: ${selectedOrder.time}`}</Typography>
<Typography variant="subtitle1">{`${t('shippingAddress')}: ${selectedOrder.address}`}</Typography>
<Divider /> <Divider />
<Typography variant="subtitle2">{t('orderedItems')}:</Typography> <Typography variant="subtitle2">{t('orderedItems')}:</Typography>
<List dense> <List dense>
{selectedOrder.items.map((item, idx) => ( {selectedOrder.orderItems.map((item, idx) => (
<ListItemText <ListItemText
key={idx} key={idx}
primary={`${item.name} x${item.quantity}`} primary={`${item.article} x${item.amount}`}
secondary={`${t('pricePerItem')}: ${item.price.toFixed(2)}`}
/> />
))} ))}
</List> </List>
@@ -109,8 +117,8 @@ export default function Orders() {
)} )}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
{selectedOrder?.status === OrderStatusEnum.IN_PROGRESS && ( {(selectedOrder?.status === OrderStatusEnum.ISSUES || selectedOrder?.status === OrderStatusEnum.IN_PROGRESS || selectedOrder?.status === OrderStatusEnum.ORDERED) && (
<Button color="error" onClick={() => handleCancelOrder(selectedOrder.id)}> <Button color="error" onClick={() => handleCancelOrder()}>
{t('cancelOrder')} {t('cancelOrder')}
</Button> </Button>
)} )}

View File

@@ -22,7 +22,7 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { CustomerType } from '../components/Account'; import { CustomerType } from '../components/Account';
import Item from '../components/Item'; import Item from '../components/Item';
import { OrderStatusEnum, SubmitOrder } from '../components/Order'; import OrderType, { OrderStatusEnum } from '../components/Order';
import { useAccount } from '../helper/AccountProvider'; import { useAccount } from '../helper/AccountProvider';
import { BasketItem, useBasket } from '../helper/BasketProvider'; import { BasketItem, useBasket } from '../helper/BasketProvider';
import { fetchCustomer, submitCustomer, submitOrder } from '../helper/query/Queries'; import { fetchCustomer, submitCustomer, submitOrder } from '../helper/query/Queries';
@@ -82,7 +82,7 @@ export default function Payment() {
const steps = [t('reviewCart'), t('shippingDetails'), t('payment'), t('orderSummary')]; const steps = [t('reviewCart'), t('shippingDetails'), t('payment'), t('orderSummary')];
const { user } = useAccount(); const { user } = useAccount();
const submitOrderData: SubmitOrder = { const submitOrderData: OrderType = {
id: 0, // This will be set by the backend id: 0, // This will be set by the backend
customerId: user ? user.customerId : 0, // Use user ID if logged in, otherwise 0 customerId: user ? user.customerId : 0, // Use user ID if logged in, otherwise 0
time: Date.now(), time: Date.now(),
@@ -92,6 +92,7 @@ export default function Payment() {
amount: item.quantity, amount: item.quantity,
article: item.item.uuid, // Assuming UUID is the identifier for the item article: item.item.uuid, // Assuming UUID is the identifier for the item
})), })),
total: basket.reduce((total, item) => total + (item.quantity * getDiscountedPrice(item.item)), 0),
}; };
const { refetch: refetchCustomer } = useQuery({ const { refetch: refetchCustomer } = useQuery({
@@ -132,7 +133,7 @@ export default function Payment() {
// Verwende useMutation statt useQuery für submitOrder // Verwende useMutation statt useQuery für submitOrder
const { mutateAsync: submitOrderMutation } = useMutation({ const { mutateAsync: submitOrderMutation } = useMutation({
mutationFn: (orderData: SubmitOrder) => submitOrder(orderData), mutationFn: (orderData: OrderType) => submitOrder(orderData),
}); });
const handleNext = async () => { const handleNext = async () => {
@@ -150,7 +151,7 @@ export default function Payment() {
} }
// Erzeuge die Orderdaten mit der richtigen customerId // Erzeuge die Orderdaten mit der richtigen customerId
const orderData: SubmitOrder = { const orderData: OrderType = {
...submitOrderData, ...submitOrderData,
customerId, customerId,
}; };