diff --git a/public/Scheunenfest.png b/public/Scheunenfest.png new file mode 100644 index 0000000..d140bcb Binary files /dev/null and b/public/Scheunenfest.png differ diff --git a/public/index.html b/public/index.html index aa069f2..f1636b4 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,7 @@ - React App + Kellner Rechner diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..74a5ae9 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Scheunenfestrechner", + "name": "Kellnerrechner für das Scheunenfest", "icons": [ { "src": "favicon.ico", diff --git a/src/App.tsx b/src/App.tsx index 484390e..cacdecc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import HomePage from './pages/HomePage'; import ProductDetailsPage from './pages/ProductDetailsPage'; +import ChangeCalculatorPage from './pages/ChangeCalculatorPage'; import { CartProvider } from './contexts/CartContext'; import './App.css'; @@ -13,6 +14,7 @@ function App() { } /> } /> + } /> diff --git a/src/components/CartOverview.css b/src/components/CartOverview.css index 166da2d..557bf2e 100644 --- a/src/components/CartOverview.css +++ b/src/components/CartOverview.css @@ -40,6 +40,26 @@ cursor: pointer; transition: background-color 0.2s; } +.calculate-change-button { + width: 100%; + padding: 12px; + background-color: #2c7be5; + color: white; + border: none; + border-radius: 8px; + font-weight: bold; + cursor: pointer; + transition: background-color 0.2s; +} +.cart-actions { + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 20px; +} +.calculate-change-button:active { + background-color: #1b5eb5; +} .clear-cart-button:active { background-color: #e53935; diff --git a/src/components/CartOverview.tsx b/src/components/CartOverview.tsx index a589bb6..a4b77bb 100644 --- a/src/components/CartOverview.tsx +++ b/src/components/CartOverview.tsx @@ -1,22 +1,24 @@ import React from 'react'; import { useCart } from '../contexts/CartContext'; +import { useNavigate } from 'react-router-dom'; import './CartOverview.css'; const CartOverview: React.FC = () => { - const { - cartItems, - incrementQuantity, - decrementQuantity, + const navigate = useNavigate(); // <-- Move here + const { + cartItems, + incrementQuantity, + decrementQuantity, getTotalPrice, getFoodCount, getDrinksCount, clearCart } = useCart(); - + if (cartItems.length === 0) { return
Warenkorb ist leer
; } - + return (
@@ -26,11 +28,23 @@ const CartOverview: React.FC = () => {
Gesamtpreis: {getTotalPrice().toFixed(2)} €
- - - + +
+ + + +
+
{cartItems.map((item) => (
@@ -51,4 +65,4 @@ const CartOverview: React.FC = () => { ); }; -export default CartOverview; +export default CartOverview; \ No newline at end of file diff --git a/src/pages/ChangeCalculatorPage.css b/src/pages/ChangeCalculatorPage.css new file mode 100644 index 0000000..613e225 --- /dev/null +++ b/src/pages/ChangeCalculatorPage.css @@ -0,0 +1,120 @@ +.change-calculator-page { + height: 100vh; + display: flex; + flex-direction: column; +} + +.calculator-container { + padding: 15px; + flex: 1; + display: flex; + flex-direction: column; + gap: 20px; +} + +.totals-section { + background-color: white; + padding: 15px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.total-item { + display: flex; + justify-content: space-between; + padding: 8px 0; + font-size: 1.1rem; + border-bottom: 1px solid #eee; +} + +.total-item:last-child { + border-bottom: none; +} + +.total-item.highlight { + font-weight: bold; + font-size: 1.2rem; + color: #2c7be5; +} + +.denominations-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; +} + +.denomination-button { + background-color: #2c7be5; + color: white; + border: none; + border-radius: 8px; + padding: 15px 5px; + font-size: 1.1rem; + font-weight: 500; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: background-color 0.2s; +} + +.denomination-button:active { + background-color: #1a68d1; +} + +.selected-denominations { + background-color: white; + padding: 15px; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.selected-denominations h3 { + margin-top: 0; + margin-bottom: 15px; + font-size: 1.1rem; + color: #333; + padding-left: 10px; + border-left: 4px solid #2c7be5; +} + +.selected-denominations ul { + list-style: none; + padding: 0; + margin: 0; +} + +.denomination-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 0; + border-bottom: 1px solid #eee; +} + +.denomination-item:last-child { + border-bottom: none; +} + +.item-controls { + display: flex; + gap: 5px; +} + +.item-controls button { + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + background-color: #f5f5f5; + border: 1px solid #ddd; + border-radius: 4px; +} + +.reset-button { + width: 100%; + padding: 10px; + margin-top: 15px; + background-color: #f5f5f5; + border: 1px solid #ddd; + border-radius: 4px; + font-weight: 500; +} diff --git a/src/pages/ChangeCalculatorPage.tsx b/src/pages/ChangeCalculatorPage.tsx new file mode 100644 index 0000000..1f3b6c0 --- /dev/null +++ b/src/pages/ChangeCalculatorPage.tsx @@ -0,0 +1,147 @@ +import React, { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useCart } from '../contexts/CartContext'; +import './ChangeCalculatorPage.css'; + +interface MoneyItem { + value: number; + label: string; + count: number; +} + +const ChangeCalculatorPage: React.FC = () => { + const navigate = useNavigate(); + const { getTotalPrice, clearCart } = useCart(); + const cartTotal = getTotalPrice(); + + const initialDenominations: MoneyItem[] = [ + { value: 0.5, label: '0,50 €', count: 0 }, + { value: 1, label: '1 €', count: 0 }, + { value: 2, label: '2 €', count: 0 }, + { value: 5, label: '5 €', count: 0 }, + { value: 10, label: '10 €', count: 0 }, + { value: 20, label: '20 €', count: 0 }, + { value: 50, label: '50 €', count: 0 }, + { value: 100, label: '100 €', count: 0 }, + { value: 200, label: '200 €', count: 0 }, + ]; + + const [moneyItems, setMoneyItems] = useState(initialDenominations); + const [customerTotal, setCustomerTotal] = useState(0); + const [changeAmount, setChangeAmount] = useState(0); + + // Calculate totals whenever money items change + useEffect(() => { + const total = moneyItems.reduce((sum, item) => sum + item.value * item.count, 0); + setCustomerTotal(total); + setChangeAmount(Math.max(0, total - cartTotal)); + }, [moneyItems, cartTotal]); + + const handleDenominationClick = (index: number) => { + const updatedItems = [...moneyItems]; + updatedItems[index].count += 1; + setMoneyItems(updatedItems); + }; + + const resetDenomination = (index: number) => { + const updatedItems = [...moneyItems]; + updatedItems[index].count = 0; + setMoneyItems(updatedItems); + }; + + const decreaseDenomination = (index: number) => { + if (moneyItems[index].count > 0) { + const updatedItems = [...moneyItems]; + updatedItems[index].count -= 1; + setMoneyItems(updatedItems); + } + }; + + const resetAllDenominations = () => { + setMoneyItems(initialDenominations.map(item => ({ ...item, count: 0 }))); + }; + + const handleDoneClick = () => { + clearCart(); + navigate('/'); + }; + + return ( +
+
+ +

Restgeld

+ +
+ +
+
+
+ Warenkorb: + {cartTotal.toFixed(2)} € +
+
+ Erhalten: + {customerTotal.toFixed(2)} € +
+
+ Restgeld: + {changeAmount.toFixed(2)} € +
+
+ +
+ {moneyItems.map((item, index) => ( + + ))} +
+ +
+

Ausgewählte Münzen/Scheine

+ {moneyItems.some(item => item.count > 0) ? ( +
    + {moneyItems + .filter(item => item.count > 0) + .map((item, index) => ( +
  • + {item.count}x {item.label} +
    + + +
    +
  • + ))} +
+ ) : ( +

Keine Auswahl

+ )} + + {moneyItems.some(item => item.count > 0) && ( + + )} +
+
+
+ ); +}; + +export default ChangeCalculatorPage; diff --git a/src/pages/ProductDetailsPage.css b/src/pages/ProductDetailsPage.css index 3ad1a5a..e0912b7 100644 --- a/src/pages/ProductDetailsPage.css +++ b/src/pages/ProductDetailsPage.css @@ -25,6 +25,16 @@ left: 15px; } +.done-button { + background: none; + border: none; + color: white; + font-size: 1.2rem; + cursor: pointer; + padding: 0; + position: absolute; + right: 15px; +} .details-header h1 { flex: 1; text-align: center;