diff --git a/src/components/profile/OrderDetailsDialog.js b/src/components/profile/OrderDetailsDialog.js
index 414ef1f..ee2f2dd 100644
--- a/src/components/profile/OrderDetailsDialog.js
+++ b/src/components/profile/OrderDetailsDialog.js
@@ -26,14 +26,25 @@ const OrderDetailsDialog = ({ open, onClose, order }) => {
const currencyFormatter = new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" });
+ // Helper function to translate payment methods
+ const getPaymentMethodDisplay = (paymentMethod) => {
+ if (!paymentMethod) return t('orders.details.notSpecified');
+
+ switch (paymentMethod.toLowerCase()) {
+ case 'wire':
+ return t('payment.methods.bankTransfer');
+ default:
+ return paymentMethod;
+ }
+ };
+
const handleCancelOrder = () => {
// Implement order cancellation logic here
console.log(`Cancel order: ${order.orderId}`);
onClose(); // Close the dialog after action
};
- const subtotal = order.items.reduce((acc, item) => acc + item.price * item.quantity_ordered, 0);
- const total = subtotal + order.delivery_cost;
+ const total = order.items.reduce((acc, item) => acc + item.price * item.quantity_ordered, 0);
// Calculate VAT breakdown similar to CartDropdown
const vatCalculations = order.items.reduce((acc, item) => {
@@ -83,7 +94,7 @@ const OrderDetailsDialog = ({ open, onClose, order }) => {
{t('orders.details.paymentMethod')}
- {order.paymentMethod || order.payment_method || t('orders.details.notSpecified')}
+ {getPaymentMethodDisplay(order.paymentMethod || order.payment_method)}
@@ -96,6 +107,7 @@ const OrderDetailsDialog = ({ open, onClose, order }) => {
{t('orders.details.item')}
{t('orders.details.quantity')}
{t('orders.details.price')}
+ {t('product.vatShort')}
{t('orders.details.total')}
@@ -105,12 +117,12 @@ const OrderDetailsDialog = ({ open, onClose, order }) => {
{item.name}
{item.quantity_ordered}
{currencyFormatter.format(item.price)}
+ {item.vat}%
{currencyFormatter.format(item.price * item.quantity_ordered)}
))}
-
-
+
{t ? t('tax.totalNet') : 'Gesamtnettopreis'}
@@ -119,35 +131,18 @@ const OrderDetailsDialog = ({ open, onClose, order }) => {
{vatCalculations.vat7 > 0 && (
-
- {t ? t('tax.vat7') : '7% Mehrwertsteuer'}
+ {t ? t('tax.vat7') : '7% Mehrwertsteuer'}
{currencyFormatter.format(vatCalculations.vat7)}
)}
{vatCalculations.vat19 > 0 && (
-
- {t ? t('tax.vat19') : '19% Mehrwertsteuer'}
+ {t ? t('tax.vat19') : '19% Mehrwertsteuer'}
{currencyFormatter.format(vatCalculations.vat19)}
)}
-
-
- {t ? t('tax.subtotal') : 'Zwischensumme'}
-
-
- {currencyFormatter.format(subtotal)}
-
-
-
-
- {t ? t('cart.summary.shippingCosts') : 'Lieferkosten'}
- {currencyFormatter.format(order.delivery_cost)}
-
-
-
-
+
{t ? t('cart.summary.total') : 'Gesamtsumme'}
diff --git a/src/components/profile/OrdersTab.js b/src/components/profile/OrdersTab.js
index 017d6a8..23a5809 100644
--- a/src/components/profile/OrdersTab.js
+++ b/src/components/profile/OrdersTab.js
@@ -15,8 +15,14 @@ import {
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 SocketContext from "../../contexts/SocketContext.js";
import OrderDetailsDialog from "./OrderDetailsDialog.js";
@@ -71,6 +77,9 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
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 {socket} = useContext(SocketContext);
const navigate = useNavigate();
@@ -121,11 +130,7 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
useEffect(() => {
if (orderIdFromHash && orders.length > 0) {
- console.log('OrdersTab: Attempting to open order from hash:', orderIdFromHash);
- console.log('OrdersTab: Available orders:', orders.map(o => o.orderId));
handleViewDetails(orderIdFromHash);
- } else if (orderIdFromHash && orders.length === 0) {
- console.log('OrdersTab: Order ID from hash but no orders loaded yet:', orderIdFromHash);
}
}, [orderIdFromHash, orders, handleViewDetails]);
@@ -147,6 +152,47 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
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 || !socket) return;
+
+ setIsCancelling(true);
+ socket.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 (
@@ -181,11 +227,10 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
{orders.map((order) => {
const displayStatus = getStatusDisplay(order.status);
- const subtotal = order.items.reduce(
+ const total = order.items.reduce(
(acc, item) => acc + item.price * item.quantity_ordered,
0
);
- const total = subtotal + order.delivery_cost;
return (
{order.orderId}
@@ -223,15 +268,28 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
{currencyFormatter.format(total)}
-
- handleViewDetails(order.orderId)}
- >
-
-
-
+
+
+ handleViewDetails(order.orderId)}
+ >
+
+
+
+ {isOrderCancelable(order) && (
+
+ handleCancelClick(order)}
+ >
+
+
+
+ )}
+
);
@@ -249,6 +307,47 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
onClose={handleCloseDetailsDialog}
order={selectedOrder}
/>
+
+ {/* Cancel Confirmation Dialog */}
+
);
};
diff --git a/src/i18n/locales/bg/orders.js b/src/i18n/locales/bg/orders.js
index 3b67a94..25392fd 100644
--- a/src/i18n/locales/bg/orders.js
+++ b/src/i18n/locales/bg/orders.js
@@ -17,14 +17,14 @@ export default {
"items": "Артикули",
"total": "Общо",
"actions": "Действия",
- "viewDetails": "Виж подробности"
+ "viewDetails": "Виж детайли"
},
"noOrders": "Все още не сте направили поръчки.",
"details": {
- "title": "Подробности за поръчка: {{orderId}}",
+ "title": "Детайли за поръчка: {{orderId}}",
"deliveryAddress": "Адрес за доставка",
"invoiceAddress": "Адрес за фактура",
- "orderDetails": "Подробности за поръчката",
+ "orderDetails": "Детайли за поръчката",
"deliveryMethod": "Начин на доставка:",
"paymentMethod": "Начин на плащане:",
"notSpecified": "Не е посочено",
@@ -35,5 +35,11 @@ export default {
"total": "Общо",
"cancelOrder": "Отмени поръчката"
},
+ "cancelConfirm": {
+ "title": "Отмяна на поръчка",
+ "message": "Сигурни ли сте, че искате да отмените тази поръчка?",
+ "confirm": "Отмени поръчката",
+ "cancelling": "Отмяна..."
+ },
"processing": "Поръчката се обработва...",
};
diff --git a/src/i18n/locales/cs/orders.js b/src/i18n/locales/cs/orders.js
index 1d11444..a902f26 100644
--- a/src/i18n/locales/cs/orders.js
+++ b/src/i18n/locales/cs/orders.js
@@ -35,5 +35,11 @@ export default {
"total": "Celkem",
"cancelOrder": "Zrušit objednávku"
},
- "processing": "Objednávka se dokončuje..."
+ "cancelConfirm": {
+ "title": "Zrušit objednávku",
+ "message": "Opravdu chcete tuto objednávku zrušit?",
+ "confirm": "Zrušit objednávku",
+ "cancelling": "Rušení..."
+ },
+ "processing": "Objednávka se dokončuje...",
};
diff --git a/src/i18n/locales/de/orders.js b/src/i18n/locales/de/orders.js
index 0607749..c7e6a44 100644
--- a/src/i18n/locales/de/orders.js
+++ b/src/i18n/locales/de/orders.js
@@ -19,6 +19,10 @@ export default {
"actions": "Aktionen",
"viewDetails": "Details anzeigen"
},
+ "tooltips": {
+ "viewDetails": "Details anzeigen",
+ "cancelOrder": "Bestellung stornieren"
+ },
"noOrders": "Sie haben noch keine Bestellungen aufgegeben.",
"details": {
"title": "Bestelldetails: {{orderId}}",
@@ -35,5 +39,11 @@ export default {
"total": "Gesamt",
"cancelOrder": "Bestellung stornieren"
},
+ "cancelConfirm": {
+ "title": "Bestellung stornieren",
+ "message": "Sind Sie sicher, dass Sie diese Bestellung stornieren möchten?",
+ "confirm": "Stornieren",
+ "cancelling": "Wird storniert..."
+ },
"processing": "Bestellung wird abgeschlossen..."
};
\ No newline at end of file
diff --git a/src/i18n/locales/en/orders.js b/src/i18n/locales/en/orders.js
index 054ae79..f0839cc 100644
--- a/src/i18n/locales/en/orders.js
+++ b/src/i18n/locales/en/orders.js
@@ -19,6 +19,10 @@ export default {
"actions": "Actions", // Aktionen
"viewDetails": "View details" // Details anzeigen
},
+ "tooltips": {
+ "viewDetails": "View details", // Details anzeigen
+ "cancelOrder": "Cancel order" // Bestellung stornieren
+ },
"noOrders": "You have not placed any orders yet.", // Sie haben noch keine Bestellungen aufgegeben.
"details": {
"title": "Order details: {{orderId}}", // Bestelldetails: {{orderId}}
@@ -32,8 +36,15 @@ export default {
"item": "Item", // Artikel
"quantity": "Quantity", // Menge
"price": "Price", // Preis
+ "vat": "VAT", // MwSt.
"total": "Total", // Gesamt
"cancelOrder": "Cancel order" // Bestellung stornieren
},
+ "cancelConfirm": {
+ "title": "Cancel Order",
+ "message": "Are you sure you want to cancel this order?",
+ "confirm": "Cancel Order",
+ "cancelling": "Cancelling..."
+ },
"processing": "Order is being completed...", // Bestellung wird abgeschlossen...
};
diff --git a/src/i18n/locales/es/orders.js b/src/i18n/locales/es/orders.js
index c7b26cf..6ed4381 100644
--- a/src/i18n/locales/es/orders.js
+++ b/src/i18n/locales/es/orders.js
@@ -35,5 +35,11 @@ export default {
"total": "Total",
"cancelOrder": "Cancelar pedido"
},
- "processing": "El pedido se está completando..."
+ "cancelConfirm": {
+ "title": "Cancelar pedido",
+ "message": "¿Estás seguro de que deseas cancelar este pedido?",
+ "confirm": "Cancelar pedido",
+ "cancelling": "Cancelando..."
+ },
+ "processing": "El pedido se está completando...",
};
diff --git a/src/i18n/locales/fr/orders.js b/src/i18n/locales/fr/orders.js
index 21ca801..ebc7019 100644
--- a/src/i18n/locales/fr/orders.js
+++ b/src/i18n/locales/fr/orders.js
@@ -19,7 +19,7 @@ export default {
"actions": "Actions",
"viewDetails": "Voir les détails"
},
- "noOrders": "Vous n'avez encore passé aucune commande.",
+ "noOrders": "Vous n'avez pas encore passé de commandes.",
"details": {
"title": "Détails de la commande : {{orderId}}",
"deliveryAddress": "Adresse de livraison",
@@ -35,5 +35,11 @@ export default {
"total": "Total",
"cancelOrder": "Annuler la commande"
},
+ "cancelConfirm": {
+ "title": "Annuler la commande",
+ "message": "Êtes-vous sûr de vouloir annuler cette commande ?",
+ "confirm": "Annuler la commande",
+ "cancelling": "Annulation en cours..."
+ },
"processing": "La commande est en cours de traitement...",
};
diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js
index 3a8e51f..22aaf34 100644
--- a/src/pages/ProfilePage.js
+++ b/src/pages/ProfilePage.js
@@ -94,21 +94,17 @@ const ProfilePage = (props) => {
useEffect(() => {
const hash = location.hash;
- console.log('ProfilePage: Processing hash:', hash);
switch (hash) {
case '#cart':
- console.log('ProfilePage: Switching to cart tab');
setTabValue(0);
setOrderIdFromHash(null);
break;
case '#orders':
- console.log('ProfilePage: Switching to orders tab');
setTabValue(1);
setOrderIdFromHash(null);
break;
case '#settings':
- console.log('ProfilePage: Switching to settings tab');
setTabValue(2);
setOrderIdFromHash(null);
break;
@@ -117,18 +113,15 @@ const ProfilePage = (props) => {
// Check if it's a potential order ID (starts with # and has alphanumeric characters with dashes)
const potentialOrderId = hash.substring(1);
if (/^[A-Z0-9]+-[A-Z0-9]+$/i.test(potentialOrderId)) {
- console.log('ProfilePage: Detected order ID from hash:', potentialOrderId);
setOrderIdFromHash(potentialOrderId);
setTabValue(1); // Switch to Orders tab
} else {
- console.log('ProfilePage: Hash does not match order ID pattern:', potentialOrderId);
setOrderIdFromHash(null);
}
} else {
setOrderIdFromHash(null);
// If no hash is present, set default to cart tab
if (!hash) {
- console.log('ProfilePage: No hash present, redirecting to cart');
navigate('/profile#cart', { replace: true });
}
}