import React, { useState, useEffect, useCallback } from "react"; import { useNavigate } from "react-router-dom"; import { withI18n } from "../../i18n/withTranslation.js"; import { Box, Paper, Alert, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, IconButton, Tooltip, CircularProgress, Typography, Dialog, DialogTitle, DialogContent, DialogActions, Button, } from "@mui/material"; import SearchIcon from "@mui/icons-material/Search"; import CancelIcon from "@mui/icons-material/Cancel"; import OrderDetailsDialog from "./OrderDetailsDialog.js"; // Constants const getStatusTranslation = (status, t) => { const statusMap = { new: t ? t('orders.status.new') : "in Bearbeitung", pending: t ? t('orders.status.pending') : "Neu", processing: t ? t('orders.status.processing') : "in Bearbeitung", paid: t ? t('orders.status.paid') : "Bezahlt", cancelled: t ? t('orders.status.cancelled') : "Storniert", shipped: t ? t('orders.status.shipped') : "Verschickt", delivered: t ? t('orders.status.delivered') : "Geliefert", }; return statusMap[status] || status; }; const statusEmojis = { new: "โš™๏ธ", pending: "โณ", processing: "๐Ÿ”„", paid: "๐Ÿฆ", cancelled: "โŒ", shipped: "๐Ÿšš", delivered: "โœ…", }; const statusColors = { new: "#ed6c02", // orange pending: "#ff9800", // orange for pending processing: "#2196f3", // blue for processing paid: "#2e7d32", // green cancelled: "#d32f2f", // red for cancelled shipped: "#2e7d32", // green delivered: "#2e7d32", // green }; const currencyFormatter = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR", }); // Orders Tab Content Component const OrdersTab = ({ orderIdFromHash, t }) => { const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedOrder, setSelectedOrder] = useState(null); const [isDetailsDialogOpen, setIsDetailsDialogOpen] = useState(false); const [cancelConfirmOpen, setCancelConfirmOpen] = useState(false); const [orderToCancel, setOrderToCancel] = useState(null); const [isCancelling, setIsCancelling] = useState(false); const navigate = useNavigate(); const handleViewDetails = useCallback( (orderId) => { const orderToView = orders.find((order) => order.orderId === orderId); if (orderToView) { setSelectedOrder(orderToView); setIsDetailsDialogOpen(true); // Update the hash to include the order ID navigate(`/profile#${orderId}`, { replace: true }); } }, [orders, navigate] ); const fetchOrders = useCallback(() => { setLoading(true); setError(null); window.socketManager.emit("getOrders", (response) => { if (response.success) { setOrders(response.orders); } else { setError(response.error || "Failed to fetch orders."); } setLoading(false); }); }, []); useEffect(() => { fetchOrders(); }, [fetchOrders]); useEffect(() => { if (orderIdFromHash && orders.length > 0) { handleViewDetails(orderIdFromHash); } }, [orderIdFromHash, orders, handleViewDetails]); const getStatusDisplay = (status) => { return getStatusTranslation(status, t); }; const getStatusEmoji = (status) => { return statusEmojis[status] || "โ“"; }; const getStatusColor = (status) => { return statusColors[status] || "#757575"; // default gray }; const handleCloseDetailsDialog = () => { setIsDetailsDialogOpen(false); setSelectedOrder(null); navigate("/profile#orders", { replace: true }); }; // Check if order can be cancelled const isOrderCancelable = (order) => { const cancelableStatuses = ['new', 'pending', 'processing']; return cancelableStatuses.includes(order.status); }; // Handle cancel button click const handleCancelClick = (order) => { setOrderToCancel(order); setCancelConfirmOpen(true); }; // Handle cancel confirmation const handleConfirmCancel = () => { if (!orderToCancel) return; setIsCancelling(true); window.socketManager.emit('cancelOrder', { orderId: orderToCancel.orderId }, (response) => { setIsCancelling(false); setCancelConfirmOpen(false); if (response.success) { console.log('Order cancelled:', response.orderId); // Refresh orders list fetchOrders(); } else { setError(response.error || 'Failed to cancel order'); } setOrderToCancel(null); }); }; // Handle cancel dialog close const handleCancelDialogClose = () => { if (!isCancelling) { setCancelConfirmOpen(false); setOrderToCancel(null); } }; if (loading) { return ( ); } if (error) { return ( {error} ); } return ( {orders.length > 0 ? ( {t ? t('orders.table.orderNumber') : 'Bestellnummer'} {t ? t('orders.table.date') : 'Datum'} {t ? t('orders.table.status') : 'Status'} {t ? t('orders.table.items') : 'Artikel'} {t ? t('orders.table.total') : 'Summe'} {t ? t('orders.table.actions') : 'Aktionen'} {orders.map((order) => { const displayStatus = getStatusDisplay(order.status); const total = order.items.reduce( (acc, item) => acc + item.price * item.quantity_ordered, 0 ); return ( {order.orderId} {new Date(order.created_at).toLocaleDateString()} {getStatusEmoji(order.status)} {displayStatus} {order.items .filter(item => { // Exclude delivery items - backend uses deliveryMethod ID as item name const itemName = item.name || ''; return itemName !== 'DHL' && itemName !== 'DPD' && itemName !== 'Sperrgut' && itemName !== 'Abholung'; }) .reduce( (acc, item) => acc + item.quantity_ordered, 0 )} {currencyFormatter.format(total)} handleViewDetails(order.orderId)} aria-label={t ? t('orders.tooltips.viewDetails') : 'Details anzeigen'} > {isOrderCancelable(order) && ( handleCancelClick(order)} aria-label={t ? t('orders.tooltips.cancelOrder') : 'Bestellung stornieren'} > )} ); })}
) : ( {t ? t('orders.noOrders') : 'Sie haben noch keine Bestellungen aufgegeben.'} )} {/* Cancel Confirmation Dialog */} {t ? t('orders.cancelConfirm.title') : 'Bestellung stornieren'} {t ? t('orders.cancelConfirm.message') : 'Sind Sie sicher, dass Sie diese Bestellung stornieren mรถchten?'} {orderToCancel && ( {t ? t('orders.table.orderNumber') : 'Bestellnummer'}: {orderToCancel.orderId} )}
); }; export default withI18n()(OrdersTab);