-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Todays special component Updated #190
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,24 +11,25 @@ import caesar_salad from '../../assets/TSimg/caesar_salad.webp'; | |
|
||
const menuItems = { | ||
coffee: [ | ||
{ name: "Espresso", description: "Rich and bold coffee shot.", image: espresso }, | ||
{ name: "Cappuccino", description: "Creamy coffee with frothy milk.", image: cappuccino }, | ||
{ name: "Latte", description: "Smooth coffee with steamed milk.", image: latte }, | ||
{ name: "Espresso", description: "Rich and bold coffee shot.", image: espresso, originalPrice: "$3.00", offerPrice: "$2.50" }, | ||
{ name: "Cappuccino", description: "Creamy coffee with frothy milk.", image: cappuccino, originalPrice: "$3.50", offerPrice: "$3.00" }, | ||
{ name: "Latte", description: "Smooth coffee with steamed milk.", image: latte, originalPrice: "$4.00", offerPrice: "$3.50" }, | ||
], | ||
drinks: [ | ||
{ name: "Mango Smoothie", description: "Refreshing mango blend.", image: mango_smoothie }, | ||
{ name: "Lemonade", description: "Zesty and chilled lemonade.", image: lemonade }, | ||
{ name: "Iced Tea", description: "Cool iced tea with lemon.", image: iced_tea }, | ||
{ name: "Mango Smoothie", description: "Refreshing mango blend.", image: mango_smoothie, originalPrice: "$4.50", offerPrice: "$4.00" }, | ||
{ name: "Lemonade", description: "Zesty and chilled lemonade.", image: lemonade, originalPrice: "$2.50", offerPrice: "$2.00" }, | ||
{ name: "Iced Tea", description: "Cool iced tea with lemon.", image: iced_tea, originalPrice: "$2.00", offerPrice: "$1.50" }, | ||
], | ||
food: [ | ||
{ name: "Cheese Sandwich", description: "Toasted sandwich with cheese.", image: cheese_sandwich }, | ||
{ name: "Pasta Primavera", description: "Veggies and pasta in a light sauce.", image: pasta_primavera }, | ||
{ name: "Caesar Salad", description: "Crispy salad with Caesar dressing.", image: caesar_salad }, | ||
{ name: "Cheese Sandwich", description: "Toasted sandwich with cheese.", image: cheese_sandwich, originalPrice: "$3.50", offerPrice: "$3.00" }, | ||
{ name: "Pasta Primavera", description: "Veggies and pasta in a light sauce.", image: pasta_primavera, originalPrice: "$5.50", offerPrice: "$5.00" }, | ||
{ name: "Caesar Salad", description: "Crispy salad with Caesar dressing.", image: caesar_salad, originalPrice: "$5.00", offerPrice: "$4.50" }, | ||
], | ||
}; | ||
|
||
const TodaysSpecial = () => { | ||
const [todaysSpecial, setTodaysSpecial] = useState({ coffee: {}, drink: {}, food: {} }); | ||
const [hoveredItem, setHoveredItem] = useState(null); // State to track the hovered item | ||
|
||
// Function to update today's special (cycling through 3 items) | ||
const updateTodaysSpecial = () => { | ||
|
@@ -51,20 +52,61 @@ const TodaysSpecial = () => { | |
<div className="mt-10"> | ||
<h2 className="text-5xl font-bold text-center mb-9">Today's Special</h2> | ||
<div className="flex flex-col md:flex-row justify-around items-center mb-8 space-y-8 md:space-y-0 md:space-x-4"> | ||
<div className="card bg-pink-100 p-4 rounded-lg shadow-lg max-w-xs text-center"> | ||
{/* Coffee Card */} | ||
<div | ||
className="bg-pink-100 p-4 rounded-lg shadow-lg max-w-xs text-center transition-transform duration-300 ease-in-out transform hover:scale-105 mx-2" | ||
style={{ minHeight: '300px' }} // Ensure a minimum height for the card | ||
onMouseEnter={() => setHoveredItem('coffee')} | ||
onMouseLeave={() => setHoveredItem(null)} | ||
> | ||
<img className="w-64 h-48 object-cover object-center rounded-md mb-4" src={todaysSpecial.coffee.image} alt={todaysSpecial.coffee.name} /> | ||
<h3 className="text-xl font-semibold">{todaysSpecial.coffee.name}</h3> | ||
<p className="text-gray-600">{todaysSpecial.coffee.description}</p> | ||
{/* Show prices below the image and description */} | ||
{hoveredItem === 'coffee' && ( | ||
<div className="mt-4"> | ||
<p className="text-lg font-bold text-red-700 line-through">{todaysSpecial.coffee.originalPrice}</p> | ||
<p className="text-xl font-bold text-red-500">{todaysSpecial.coffee.offerPrice}</p> | ||
</div> | ||
)} | ||
Comment on lines
+55
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Refactor repeated card components into a reusable component The code for the Coffee Card, Food Card, and Drink Card is largely similar, with differences only in data and styling classes. To adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability, consider creating a reusable Create a new component const MenuItemCard = ({ item, backgroundClass, itemKey, hoveredItem, setHoveredItem }) => (
<div
className={`${backgroundClass} p-4 rounded-lg shadow-lg max-w-xs text-center transition-transform duration-300 ease-in-out transform hover:scale-105 mx-2`}
style={{ minHeight: '300px' }}
onMouseEnter={() => setHoveredItem(itemKey)}
onMouseLeave={() => setHoveredItem(null)}
>
<img
className="w-64 h-48 object-cover object-center rounded-md mb-4"
src={item.image}
alt={item.name}
/>
<h3 className="text-xl font-semibold">{item.name}</h3>
<p className="text-gray-600">{item.description}</p>
{hoveredItem === itemKey && (
<div className="mt-4">
<p className="text-lg font-bold text-red-700 line-through">
${item.originalPrice.toFixed(2)}
</p>
<p className="text-xl font-bold text-red-500">
${item.offerPrice.toFixed(2)}
</p>
</div>
)}
</div>
); Then, use this component in your <div className="flex flex-col md:flex-row justify-around items-center mb-8 space-y-8 md:space-y-0 md:space-x-4">
<MenuItemCard
item={todaysSpecial.coffee}
backgroundClass="bg-pink-100"
itemKey="coffee"
hoveredItem={hoveredItem}
setHoveredItem={setHoveredItem}
/>
<MenuItemCard
item={todaysSpecial.food}
backgroundClass="bg-teal-100"
itemKey="food"
hoveredItem={hoveredItem}
setHoveredItem={setHoveredItem}
/>
<MenuItemCard
item={todaysSpecial.drink}
backgroundClass="bg-pink-100"
itemKey="drink"
hoveredItem={hoveredItem}
setHoveredItem={setHoveredItem}
/>
</div> This refactoring reduces code duplication and makes future updates easier. Also applies to: 75-90, 94-109
Comment on lines
+65
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure price information is accessible on touch devices Currently, the price information is displayed on hover using Consider making the price information always visible or implementing a touch-friendly interaction, such as displaying the prices on tap or by default. This will improve accessibility and ensure all users can view the pricing regardless of their device. For example, you could modify the condition to check for touch devices: const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
{(hoveredItem === itemKey || isTouchDevice) && (
/* Price information */
)} Or simplify by always showing the prices. Also applies to: 84-90, 103-109 |
||
</div> | ||
<div className="card bg-teal-100 p-4 rounded-lg shadow-lg max-w-xs text-center"> | ||
|
||
{/* Food Card */} | ||
<div | ||
className="bg-teal-100 p-4 rounded-lg shadow-lg max-w-xs text-center transition-transform duration-300 ease-in-out transform hover:scale-105 mx-2" | ||
style={{ minHeight: '300px' }} // Ensure a minimum height for the card | ||
onMouseEnter={() => setHoveredItem('food')} | ||
onMouseLeave={() => setHoveredItem(null)} | ||
> | ||
<img className="w-64 h-48 object-cover object-center rounded-md mb-4" src={todaysSpecial.food.image} alt={todaysSpecial.food.name} /> | ||
<h3 className="text-xl font-semibold">{todaysSpecial.food.name}</h3> | ||
<p className="text-gray-600">{todaysSpecial.food.description}</p> | ||
{/* Show prices below the image and description */} | ||
{hoveredItem === 'food' && ( | ||
<div className="mt-4"> | ||
<p className="text-lg font-bold text-red-700 line-through">{todaysSpecial.food.originalPrice}</p> | ||
<p className="text-xl font-bold text-red-500">{todaysSpecial.food.offerPrice}</p> | ||
</div> | ||
)} | ||
</div> | ||
<div className="card bg-pink-100 p-4 rounded-lg shadow-lg max-w-xs text-center"> | ||
|
||
{/* Drink Card */} | ||
<div | ||
className="bg-pink-100 p-4 rounded-lg shadow-lg max-w-xs text-center transition-transform duration-300 ease-in-out transform hover:scale-105 mx-2" | ||
style={{ minHeight: '300px' }} // Ensure a minimum height for the card | ||
onMouseEnter={() => setHoveredItem('drink')} | ||
onMouseLeave={() => setHoveredItem(null)} | ||
> | ||
<img className="w-64 h-48 object-cover object-center rounded-md mb-4" src={todaysSpecial.drink.image} alt={todaysSpecial.drink.name} /> | ||
<h3 className="text-xl font-semibold">{todaysSpecial.drink.name}</h3> | ||
<p className="text-gray-600">{todaysSpecial.drink.description}</p> | ||
{/* Show prices below the image and description */} | ||
{hoveredItem === 'drink' && ( | ||
<div className="mt-4"> | ||
<p className="text-lg font-bold text-red-700 line-through">{todaysSpecial.drink.originalPrice}</p> | ||
<p className="text-xl font-bold text-red-500">{todaysSpecial.drink.offerPrice}</p> | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Store price values as numbers and format them when rendering
The
originalPrice
andofferPrice
are currently stored as strings with currency symbols, e.g.,"$3.00"
. It's better practice to store price values as numeric types without currency symbols and format them when displaying. This allows for easier calculations, accurate sorting, and consistent formatting across the application.Update the
menuItems
data to use numeric values:Then, format the prices when rendering:
Apply similar changes for the food and drink items to ensure consistency.