dev #2
@ -1,64 +1,64 @@
|
|||||||
.cart-overview {
|
.cart-overview {
|
||||||
padding: 15px;
|
padding: 8px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-summary {
|
.cart-summary {
|
||||||
background-color: #f5f5f5;
|
background-color: #f7f9fc;
|
||||||
border-radius: 8px;
|
border-radius: 6px;
|
||||||
padding: 15px;
|
padding: 12px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 16px;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.count-info {
|
.count-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.food-count, .drink-count {
|
.food-count, .drink-count {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.total-price {
|
.total-price {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.2rem;
|
font-size: 1.1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 10px;
|
margin-top: 8px;
|
||||||
color: #2c7be5;
|
color: #2c7be5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-cart-button {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
background-color: #ff5252;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
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 {
|
.cart-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calculate-change-button, .clear-cart-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculate-change-button {
|
||||||
|
background-color: #2c7be5;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-cart-button {
|
||||||
|
background-color: #ff5252;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.calculate-change-button:active {
|
.calculate-change-button:active {
|
||||||
background-color: #1b5eb5;
|
background-color: #1b5eb5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-cart-button:active {
|
.clear-cart-button:active {
|
||||||
@ -68,49 +68,51 @@
|
|||||||
.cart-items {
|
.cart-items {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 15px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-item {
|
.cart-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: white;
|
background-color: #f7f9fc;
|
||||||
padding: 15px;
|
padding: 12px;
|
||||||
border-radius: 8px;
|
border-radius: 6px;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-info {
|
.item-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 5px;
|
gap: 3px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-name {
|
.item-name {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-option {
|
.item-option {
|
||||||
font-size: 0.9rem;
|
font-size: 0.85rem;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-price {
|
.item-price {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #2c7be5;
|
color: #2c7be5;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-quantity {
|
.item-quantity {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-quantity button {
|
.item-quantity button {
|
||||||
width: 30px;
|
width: 26px;
|
||||||
height: 30px;
|
height: 26px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #2c7be5;
|
background-color: #2c7be5;
|
||||||
@ -126,7 +128,8 @@
|
|||||||
|
|
||||||
.empty-cart {
|
.empty-cart {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 30px;
|
padding: 20px;
|
||||||
color: #666;
|
color: #888;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,9 @@ const ProductDetails: React.FC<ProductDetailsProps> = ({ product, category }) =>
|
|||||||
const { addToCart } = useCart();
|
const { addToCart } = useCart();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Check if all options have the same price
|
||||||
|
const hasSamePrice = product.options.every(option => option.price === product.options[0].price);
|
||||||
|
|
||||||
const handleAddToCart = () => {
|
const handleAddToCart = () => {
|
||||||
addToCart({
|
addToCart({
|
||||||
productId: product.id,
|
productId: product.id,
|
||||||
@ -26,12 +29,6 @@ const ProductDetails: React.FC<ProductDetailsProps> = ({ product, category }) =>
|
|||||||
navigate('/');
|
navigate('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
const incrementQuantity = () => setQuantity(prev => prev + 1);
|
|
||||||
const decrementQuantity = () => setQuantity(prev => Math.max(1, prev - 1));
|
|
||||||
|
|
||||||
// Check if all options have the same price
|
|
||||||
const hasSamePrice = product.options.every(option => option.price === product.options[0].price);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="product-details"
|
className="product-details"
|
||||||
@ -53,18 +50,16 @@ const ProductDetails: React.FC<ProductDetailsProps> = ({ product, category }) =>
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{hasSamePrice && (
|
{hasSamePrice && (
|
||||||
<div className="uniform-price">
|
<div className="uniform-price">Preis: {product.options[0].price.toFixed(2)} €</div>
|
||||||
Preis: {product.options[0].price.toFixed(2)} €
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="quantity-controls">
|
<div className="quantity-controls">
|
||||||
<h3>Menge:</h3>
|
<h3>Menge:</h3>
|
||||||
<div className="quantity-buttons">
|
<div className="quantity-buttons">
|
||||||
<button onClick={decrementQuantity}>-</button>
|
<button onClick={() => setQuantity(prev => Math.max(1, prev - 1))}>-</button>
|
||||||
<span>{quantity}</span>
|
<span>{quantity}</span>
|
||||||
<button onClick={incrementQuantity}>+</button>
|
<button onClick={() => setQuantity(prev => prev + 1)}>+</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -1,34 +1,35 @@
|
|||||||
.product-list {
|
.product-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
padding: 10px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-item {
|
.product-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 15px;
|
padding: 14px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 8px;
|
border-radius: 6px;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #333;
|
color: #333;
|
||||||
transition: transform 0.2s, box-shadow 0.2s;
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-item:active {
|
.product-item:active {
|
||||||
transform: scale(0.98);
|
transform: scale(0.99);
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-name {
|
.product-name {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 1.1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-price {
|
.product-price {
|
||||||
font-weight: bold;
|
font-weight: 600;
|
||||||
color: #2c7be5;
|
color: #2c7be5;
|
||||||
font-size: 1.1rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,61 @@
|
|||||||
.home-page {
|
.home-page {
|
||||||
padding-bottom: 20px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f9fafb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-header {
|
.app-header {
|
||||||
background-color: #2c7be5;
|
background-color: #2c7be5;
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 15px;
|
padding: 12px;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-header h1 {
|
.app-header h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.5rem;
|
font-size: 1.4rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
padding-left: 8px;
|
||||||
|
border-left: 3px solid #2c7be5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-tabs {
|
.category-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 10px;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-tabs button {
|
.category-tabs button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 15px;
|
padding: 12px;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 1.1rem;
|
font-size: 1rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.2s;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-tabs button.active {
|
.category-tabs button.active {
|
||||||
@ -39,14 +63,22 @@
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.products-section, .cart-section {
|
.products-container {
|
||||||
margin: 20px 0;
|
background-color: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 12px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.products-section h2, .cart-section h2 {
|
.cart-container {
|
||||||
margin: 0 10px 10px 10px;
|
background-color: white;
|
||||||
font-size: 1.3rem;
|
border-radius: 10px;
|
||||||
color: #333;
|
padding: 12px;
|
||||||
padding-left: 10px;
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
border-left: 4px solid #2c7be5;
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.main-container {
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,23 +9,11 @@ const HomePage: React.FC = () => {
|
|||||||
const [activeTab, setActiveTab] = useState<'food' | 'drinks'>('drinks');
|
const [activeTab, setActiveTab] = useState<'food' | 'drinks'>('drinks');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadProducts = async () => {
|
import('../data/products.json')
|
||||||
try {
|
.then(data => {
|
||||||
const data = await import('../data/products.json');
|
setProductsData(data);
|
||||||
|
})
|
||||||
// Sort both food and drinks by name
|
.catch(error => console.error('Failed to load products:', error));
|
||||||
const sortedData = {
|
|
||||||
food: [...data.food].sort((a, b) => a.name.localeCompare(b.name)),
|
|
||||||
drinks: [...data.drinks].sort((a, b) => a.name.localeCompare(b.name))
|
|
||||||
};
|
|
||||||
|
|
||||||
setProductsData(sortedData);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load products:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loadProducts();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -34,31 +22,34 @@ const HomePage: React.FC = () => {
|
|||||||
<h1>Preis Rechner</h1>
|
<h1>Preis Rechner</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="category-tabs">
|
<div className="main-container">
|
||||||
<button
|
<div className="products-container">
|
||||||
className={activeTab === 'drinks' ? 'active' : ''}
|
<div className="category-tabs">
|
||||||
onClick={() => setActiveTab('drinks')}
|
<button
|
||||||
>
|
className={activeTab === 'drinks' ? 'active' : ''}
|
||||||
Trinken
|
onClick={() => setActiveTab('drinks')}
|
||||||
</button>
|
>
|
||||||
<button
|
Getränke
|
||||||
className={activeTab === 'food' ? 'active' : ''}
|
</button>
|
||||||
onClick={() => setActiveTab('food')}
|
<button
|
||||||
>
|
className={activeTab === 'food' ? 'active' : ''}
|
||||||
Essen
|
onClick={() => setActiveTab('food')}
|
||||||
</button>
|
>
|
||||||
|
Essen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<h2 className="section-title">{activeTab === 'food' ? 'Essen' : 'Getränke'}</h2>
|
||||||
|
<ProductList
|
||||||
|
products={productsData[activeTab]}
|
||||||
|
category={activeTab}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="products-section">
|
<div className="cart-container">
|
||||||
<h2>{activeTab === 'food' ? 'Essen' : 'Getränke'}</h2>
|
<h2 className="section-title">Warenkorb</h2>
|
||||||
{activeTab === 'food' && <ProductList products={productsData.food} category="food" />}
|
<CartOverview />
|
||||||
{activeTab === 'drinks' && <ProductList products={productsData.drinks} category="drinks" />}
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="cart-section">
|
|
||||||
<h2>Warenkorb</h2>
|
|
||||||
<CartOverview />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user