Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions src/components/Dashboard/DashboardHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { useState, useRef, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { FiBell, FiCheckCircle, FiAlertCircle, FiClock, FiInfo, FiCheck } from "react-icons/fi";
import useAuthStore from "../../store/authStore";
import useUIStore, { formatNotificationTime } from "../../store/uiStore";
import { useAuthStore, useProfileStore, useUIStore } from "../../store";
import { formatNotificationTime } from "../../store/uiStore";

function DashboardHeader({ title = "Dashboard", subtitle }) {
const { user } = useAuthStore();
const { user: authUser } = useAuthStore();
const { user: profileUser, fetchProfile } = useProfileStore();
const { notifications = [], markAllAsRead, markAsRead } = useUIStore();
const navigate = useNavigate();

useEffect(() => {
if (!profileUser) {
fetchProfile();
}
}, [profileUser, fetchProfile]);

const user = profileUser || authUser;
const avatarSrc = user?.avatar || user?.photo || user?.profileImage || user?.imageUrl || "/images/chef-avatar.png";

const [showDropdown, setShowDropdown] = useState(false);
const dropdownRef = useRef(null);
Expand All @@ -20,11 +30,22 @@ function DashboardHeader({ title = "Dashboard", subtitle }) {

const unreadCount = notifications.filter((n) => !n.read).length;

const safeName = typeof user?.name === 'string' ? user.name : '';
const safeRole = typeof user?.role === 'string' ? user.role : 'Staff';

const firstName = safeName ? safeName.split(" ")[0] : "";
const fullName = safeName || "Loading...";
const rawName =
profileUser?.name ||
profileUser?.fullName ||
(profileUser?.firstName || profileUser?.lastName ? `${profileUser?.firstName || ""} ${profileUser?.lastName || ""}`.trim() : "") ||
authUser?.name ||
authUser?.fullName ||
(authUser?.firstName || authUser?.lastName ? `${authUser?.firstName || ""} ${authUser?.lastName || ""}`.trim() : "") ||
authUser?.username ||
authUser?.email?.split("@")[0] ||
"Chef Admin";

const safeName = typeof rawName === 'string' && rawName.trim() ? rawName.trim() : 'Chef Admin';
const safeRole = typeof user?.role === 'string' && user.role ? user.role : 'Staff';

const firstName = safeName.split(" ")[0];
const fullName = safeName;
const roleName = safeRole;

const initials = safeName
Expand Down Expand Up @@ -169,26 +190,16 @@ function DashboardHeader({ title = "Dashboard", subtitle }) {
<p className="text-[13px] font-bold text-[#1a1a1a] m-0">{fullName}</p>
</div>

{user?.avatar ? (
<img
src={user.avatar}
alt="Profile"
className="w-[42px] h-[42px] rounded-xl object-cover bg-white shadow-sm"
onError={(e) => {
e.currentTarget.style.display = "none";
e.currentTarget.nextSibling.style.display = "flex";
}}
/>
) : null}

{/* Fallback avatar */}
<div
className={`${user?.avatar ? "hidden" : "flex"} w-[42px] h-[42px] rounded-xl bg-gray-800 items-center justify-center text-white font-bold text-[14px] shadow-sm tracking-widest`}
>
{user?.name ? initials : (
<div className="w-full h-full rounded-xl bg-gray-200 animate-pulse" />
)}
</div>
<img
src={avatarSrc}
alt="Profile"
className="w-[42px] h-[42px] rounded-xl object-cover bg-white shadow-sm border border-gray-100"
onError={(e) => {
if (!e.currentTarget.src.endsWith("/images/chef-avatar.png")) {
e.currentTarget.src = "/images/chef-avatar.png";
}
}}
/>
</div>
</div>
</div>
Expand Down
5 changes: 2 additions & 3 deletions src/components/Dashboard/DashboardView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function DashboardView() {
{loadingCats ? <ChartSkeleton height={320} /> : <TopCategories data={safeCategories} />}
</div>

<div className="grid grid-cols-1 lg:grid-cols-[1.5fr_1fr] gap-6">
<div className="grid grid-cols-1 lg:grid-cols-[2fr_1fr] gap-6">
{loadingOrdOv ? <ChartSkeleton height={280} /> : <OrdersOverviewChart data={safeOrdersOverview} />}
{loadingTypes ? <ChartSkeleton height={280} /> : <OrderTypes data={safeOrderTypes} />}
</div>
Expand All @@ -83,8 +83,7 @@ function DashboardView() {
</div>
</div>

{/* Bottom Row (Full Width) */}
{loadingRevw ? <ChartSkeleton height={180} /> : <CustomerReviews data={safeReviews} />}
{loadingRevw ? <ChartSkeleton height={200} /> : <CustomerReviews data={safeReviews} />}
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/LiveKitchenView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function LiveKitchenView() {
message={`Are you sure you want to move ticket #${ticketConfirm?.ticketId} to ${ticketConfirm?.status}?`}
confirmLabel={ticketConfirm?.label || "Confirm"}
confirmClassName={
ticketConfirm?.status === "READY"
ticketConfirm?.status?.toUpperCase() === "READY" || ticketConfirm?.status?.toUpperCase() === "PREPARING"
? "bg-[#F97316] hover:bg-orange-600 shadow-lg shadow-orange-500/30"
: "bg-[#16A34A] hover:bg-green-700 shadow-lg shadow-green-500/30"
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/MetricCards.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const labels = {
};

function formatValue(key, value) {
if (key === "totalRevenue") return `$${value.toLocaleString()}`;
if (key === "totalRevenue") return `${value.toLocaleString()} EGP`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use formatCurrency instead of inline EGP formatting.

formatValue bypasses the shared formatCurrency utility and uses toLocaleString() which doesn't guarantee 2 decimal places (e.g., "1,234 EGP" vs "1,234.00 EGP"). This creates inconsistency across the app's price displays.

♻️ Proposed fix
-  if (key === "totalRevenue") return `${value.toLocaleString()} EGP`;
+  if (key === "totalRevenue") return formatCurrency(value);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (key === "totalRevenue") return `${value.toLocaleString()} EGP`;
if (key === "totalRevenue") return formatCurrency(value);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard/MetricCards.jsx` at line 16, The `formatValue` logic
in `MetricCards` is formatting `totalRevenue` inline with `toLocaleString()`,
which bypasses the shared currency formatter and can produce inconsistent
precision. Update the `formatValue` branch for `totalRevenue` to use the
existing `formatCurrency` utility instead of constructing the EGP string
manually, so the display matches the rest of the app’s price formatting.

return value.toLocaleString();
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/Dashboard/OrdersView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ function OrdersView() {
<div className="flex justify-between items-end w-full mt-auto">
<p className="text-[11px] font-bold text-[#1a1a1a] m-0">Today Sales</p>
<p className="text-[11px] font-semibold text-gray-400 m-0">
(${metrics.dailyGoal.salesCurrent.toLocaleString()} / ${metrics.dailyGoal.salesTarget.toLocaleString()})
({metrics.dailyGoal.salesCurrent.toLocaleString()} / {metrics.dailyGoal.salesTarget.toLocaleString()} EGP)
</p>
</div>
</div>
Expand Down Expand Up @@ -275,7 +275,7 @@ function OrdersView() {
<td className="px-5 py-4 text-[13px] text-[#1a1a1a] font-medium">{order.time.replace(/ (AM|PM)/, "")}</td>
<td className="px-5 py-4 text-[13px] font-medium text-[#1a1a1a] max-w-[180px] truncate">{order.name}</td>
<td className="px-5 py-4 text-[13px] text-[#1a1a1a] font-medium">{order.items}</td>
<td className="px-5 py-4 text-[13px] font-bold text-orange-500">${order.total.toFixed(0)}</td>
<td className="px-5 py-4 text-[13px] font-bold text-orange-500">{order.total.toFixed(0)} EGP</td>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Inconsistent decimal precision for order totals.

The table renders order.total.toFixed(0) while OrderDetailsModal (line 25 of the same file's companion) renders the same order.total with toFixed(2). A value like 150.99 shows as "151 EGP" in the table but "150.99 EGP" in the modal, which could confuse users.

Proposed fix: align decimal precision
-<td className="px-5 py-4 text-[13px] font-bold text-orange-500">{order.total.toFixed(0)} EGP</td>
+<td className="px-5 py-4 text-[13px] font-bold text-orange-500">{Number(order.total).toFixed(2)} EGP</td>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<td className="px-5 py-4 text-[13px] font-bold text-orange-500">{order.total.toFixed(0)} EGP</td>
<td className="px-5 py-4 text-[13px] font-bold text-orange-500">{Number(order.total).toFixed(2)} EGP</td>
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 278-278: A list component should have a key to prevent re-rendering
Context: {order.customer}
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(list-component-needs-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard/OrdersView.jsx` at line 278, The order total
formatting is inconsistent between the table row in OrdersView and the
OrderDetailsModal, which can show different values for the same order. Update
the total display in the table so it uses the same decimal precision as the
modal’s order total formatting, and make sure both places rely on the same
formatting approach for the order.total value.

<td className="px-5 py-4 text-[13px] text-[#1a1a1a] font-medium">{order.customer}</td>
<td className="px-5 py-4">
<StatusBadge status={order.status} />
Expand Down
60 changes: 41 additions & 19 deletions src/components/Dashboard/RevenueChart.jsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,75 @@
import {
LineChart, Line, XAxis, YAxis, CartesianGrid,
Tooltip, Legend, ResponsiveContainer,
AreaChart, Area, XAxis, YAxis, CartesianGrid,
Tooltip, ResponsiveContainer,
} from "recharts";
import TimeFilter from "./shared/TimeFilter";

const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
const val = Number(payload[0].value || 0);
return (
<div className="bg-[#1a1a1a] rounded-xl px-3.5 py-2.5 text-xs text-white shadow-lg">
<p className="mb-1.5 font-semibold text-gray-400">{label}</p>
{payload.map((entry) => (
<p key={entry.dataKey} className="my-0.5" style={{ color: entry.color }}>
{entry.name}: <strong>${entry.value}k</strong>
</p>
))}
<p className="mb-1 font-semibold text-gray-400">{label}</p>
<p className="my-0" style={{ color: "#F97316" }}>
Revenue: <strong>{val.toLocaleString()} EGP</strong>
</p>
</div>
);
}
return null;
};

function RevenueChart({ data, totalRevenue = 0 }) {
const formattedTotal = `$${totalRevenue.toLocaleString()}`;
const formattedTotal = `${Number(totalRevenue || 0).toLocaleString()} EGP`;

return (
<div className="bg-white rounded-3xl px-6 py-6 shadow-sm">
<div className="flex items-start justify-between mb-2">
<div className="flex items-start justify-between mb-4">
<div className="flex flex-col gap-1">
<p className="text-[13px] text-gray-500 font-medium m-0">Total Revenue</p>
<h3 className="text-[24px] font-bold text-[#1a1a1a] m-0">{formattedTotal}</h3>
</div>
<TimeFilter defaultValue="This Month" />
</div>


<ResponsiveContainer width="100%" height={220}>
<LineChart data={data} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
<AreaChart data={data} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
<defs>
<linearGradient id="revenueGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#F97316" stopOpacity={0.18} />
<stop offset="95%" stopColor="#F97316" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="#F3F4F6" vertical={false} />
<XAxis dataKey="month" axisLine={false} tickLine={false} tick={{ fontSize: 11, fill: "#9CA3AF" }} dy={10} />
<YAxis axisLine={false} tickLine={false} tick={{ fontSize: 11, fill: "#9CA3AF" }} />
<XAxis
dataKey="month"
axisLine={false}
tickLine={false}
tick={{ fontSize: 11, fill: "#9CA3AF" }}
dy={10}
/>
<YAxis
axisLine={false}
tickLine={false}
tick={{ fontSize: 11, fill: "#9CA3AF" }}
tickFormatter={(v) => v >= 1000 ? `${(v / 1000).toFixed(v % 1000 !== 0 ? 1 : 0)}k` : v}
/>
<Tooltip content={<CustomTooltip />} />
<Legend verticalAlign="top" height={36} wrapperStyle={{ fontSize: "11px", color: "#6B7280" }} iconType="circle" iconSize={6} />
<Line type="monotone" dataKey="income" name="Income" stroke="#F97316" strokeWidth={2.5} dot={false} activeDot={{ r: 5, fill: "#F97316" }} />
<Line type="monotone" dataKey="revenue" name="Revenue" stroke="#10B981" strokeWidth={2.5} dot={false} activeDot={{ r: 5, fill: "#10B981" }} />
<Line type="monotone" dataKey="expense" name="Expense" stroke="#111827" strokeWidth={2.5} dot={false} activeDot={{ r: 5, fill: "#111827" }} />
</LineChart>
<Area
type="monotone"
dataKey="revenue"
name="Revenue"
stroke="#F97316"
strokeWidth={2.5}
fill="url(#revenueGradient)"
dot={false}
activeDot={{ r: 5, fill: "#F97316", strokeWidth: 2, stroke: "#fff" }}
/>
</AreaChart>
</ResponsiveContainer>
</div>
);
}

export default RevenueChart;

2 changes: 1 addition & 1 deletion src/components/Dashboard/TrendingMenus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function TrendingMenus({ data }) {
<div className="flex items-center gap-1">
<MdAttachMoney size={15} className="text-[#F97316]" />
<span className="text-[10px] text-[#1a1a1a] font-medium">Revenue</span>
<span className="text-[11px] font-bold text-[#F97316] ml-1">${(item.revenue / 1000).toFixed(3)}</span>
<span className="text-[11px] font-bold text-[#F97316] ml-1">{(item.revenue / 1000).toFixed(1)}k EGP</span>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/shared/DishDetailsModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function DishDetailsModal({ isOpen, onClose, dish }) {
</p>
</div>
<div className="text-right shrink-0">
<span className="block text-[22px] font-black text-[#38761d]">${dish.price}</span>
<span className="block text-[22px] font-black text-[#38761d]">{dish.price} EGP</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Apply numeric formatting to dish.price.

dish.price is rendered raw without Number().toFixed(). If the value is a float like 150.5 or a string, the display may be inconsistent with other price displays in the app that use toFixed(2) or toFixed(0).

Proposed fix
-<span className="block text-[22px] font-black text-[`#38761d`]">{dish.price} EGP</span>
+<span className="block text-[22px] font-black text-[`#38761d`]">{Number(dish.price).toFixed(2)} EGP</span>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<span className="block text-[22px] font-black text-[#38761d]">{dish.price} EGP</span>
<span className="block text-[22px] font-black text-[`#38761d`]">{Number(dish.price).toFixed(2)} EGP</span>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard/shared/DishDetailsModal.jsx` at line 42, The price
display in DishDetailsModal is using dish.price directly, so it can render
inconsistent values for floats or string inputs. Update the price rendering in
the DishDetailsModal component to format dish.price numerically before display,
matching the app’s other price formatting patterns (for example using
Number(...).toFixed(...) as appropriate), and keep the existing label and
styling intact.

</div>
</div>

Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/shared/InactiveMenuModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default function InactiveMenuModal({ isOpen, onClose, inactiveItems }) {
<div className="flex items-center gap-2 text-[12px] font-medium text-gray-500">
<span>{item.category}</span>
<span className="w-1 h-1 bg-gray-300 rounded-full"></span>
<span className="text-orange-500 font-bold">${item.price}</span>
<span className="text-orange-500 font-bold">{item.price} EGP</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Apply numeric formatting to item.price.

Same as DishDetailsModal — item.price is rendered without Number().toFixed(), risking inconsistent display for float or string values.

Proposed fix
-<span className="text-orange-500 font-bold">{item.price} EGP</span>
+<span className="text-orange-500 font-bold">{Number(item.price).toFixed(2)} EGP</span>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<span className="text-orange-500 font-bold">{item.price} EGP</span>
<span className="text-orange-500 font-bold">{Number(item.price).toFixed(2)} EGP</span>
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 110-114: A list component should have a key to prevent re-rendering
Context:


{item.category}

{item.price} EGP

Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(list-component-needs-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/Dashboard/shared/InactiveMenuModal.jsx` at line 114, The price
display in InactiveMenuModal is rendering item.price directly, which can lead to
inconsistent formatting for float or string values. Update the price rendering
in InactiveMenuModal to format item.price the same way as DishDetailsModal by
converting it to a number and applying toFixed before display, so the price
output is consistent across menus.

</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/shared/OrderDetailsModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function OrderDetailsModal({ isOpen, onClose, order, showCustomer
const customerAddress = order.address || "123 Main Street, Food District, Cityville";

// Parse total price safely
const totalPrice = order.total !== undefined ? `$${Number(order.total).toFixed(2)}` : "Paid / N/A";
const totalPrice = order.total !== undefined ? `${Number(order.total).toFixed(2)} EGP` : "Paid / N/A";

return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4">
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/PopularMenuCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const PopularMenuCard = ({ name, imageUrl, price }) => {
<span className="text-sm sm:text-base font-medium text-gray-600">
Starting
</span>
<span className="text-lg sm:text-xl font-bold text-(--color-orange)">
{Number(price || 0).toFixed(2)}$
<span className="text-lg sm:text-xl font-bold text-orange">
{Number(price || 0).toFixed(2)} EGP
</span>
</div>
</div>
Expand Down
16 changes: 8 additions & 8 deletions src/components/ui/RegularFoodCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,28 @@ const RegularFoodCard = ({ meal }) => {
{/* Fat */}
<div className="flex items-center gap-0.5 sm:gap-1">
<span className="font-semibold text-gray-700">Fat</span>
<span className="text-(--color-green) font-semibold ml-auto">
<span className="text-green font-semibold ml-auto">
{fat}g
</span>
</div>
{/* Pro */}
<div className="flex items-center gap-0.5 sm:gap-1">
<span className="font-semibold text-gray-700">Pro</span>
<span className="text-(--color-green) font-semibold ml-auto">
<span className="text-green font-semibold ml-auto">
{protein}g
</span>
</div>
{/* Cal */}
<div className="flex items-center gap-0.5 sm:gap-1">
<span className="font-semibold text-gray-700">Cal</span>
<span className="text-(--color-green) font-semibold ml-auto">
<span className="text-green font-semibold ml-auto">
{calories}
</span>
</div>
{/* Sug */}
<div className="flex items-center gap-0.5 sm:gap-1">
<span className="font-semibold text-gray-700">Sug</span>
<span className="text-(--color-green) font-semibold ml-auto">
<span className="text-green font-semibold ml-auto">
{sugar}g
</span>
</div>
Expand All @@ -122,15 +122,15 @@ const RegularFoodCard = ({ meal }) => {
<div className="flex flex-col xs:flex-row items-start xs:items-baseline gap-0.5 xs:gap-1.5 shrink-0">
{hasDiscount && (
<span className="text-[10px] sm:text-xs text-gray-400 line-through">
${formatPrice(price)}
{formatPrice(price)} EGP
</span>
)}
<span
className={`text-sm sm:text-base md:text-lg lg:text-xl font-extrabold leading-none ${
hasDiscount ? "text-(--color-orange)" : "text-gray-900"
hasDiscount ? "text-orange" : "text-gray-900"
}`}
>
${formatPrice(displayPrice)}
{formatPrice(displayPrice)} EGP
</span>
</div>

Expand All @@ -144,7 +144,7 @@ const RegularFoodCard = ({ meal }) => {
imageUrl,
})
}
className="w-1/2 bg-(--color-orange) hover:bg-orange-500 active:bg-orange-600 text-white text-[10px] sm:text-xs md:text-sm font-semibold py-1.5 sm:py-2 px-1 sm:px-3 rounded-full transition-all duration-200 shadow-sm hover:shadow-md cursor-pointer text-center"
className="w-1/2 bg-orange hover:bg-orange-500 active:bg-orange-600 text-white text-[10px] sm:text-xs md:text-sm font-semibold py-1.5 sm:py-2 px-1 sm:px-3 rounded-full transition-all duration-200 shadow-sm hover:shadow-md cursor-pointer text-center"
>
Add to cart
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const DEFAULT_COUNTRY = "Egypt";

// --- Currency Configuration ---
/** @type {string} Symbol used for price displays */
export const CURRENCY_SYMBOL = "$";
export const CURRENCY_SYMBOL = "EGP";

/**
* Determines where the currency symbol is placed.
Expand Down
9 changes: 8 additions & 1 deletion src/hooks/dashboard/useOrders.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { toast } from "../../utils/toastUtils";
import { getOrdersMetrics, getOrders, updateOrderStatus, getTrendingMenus } from "../../services/dashboardService";
import { pushActivity } from "../../utils/activityLog";
import useUIStore from "../../store/uiStore";

export const orderKeys = {
Expand Down Expand Up @@ -73,11 +74,17 @@ export function useUpdateOrderStatus() {
pending: "warning",
};
useUIStore.getState().addNotification({
title: `Order #${orderId} Updated`,
title: `Order ${orderId} Updated`,
message: `Order status has been updated to "${String(status).toUpperCase()}".`,
type: typeMap[String(status).toLowerCase()] || "info",
category: "Orders",
});
// Push to localStorage activity log so RecentActivity widget shows real events
pushActivity({
user: "Admin",
role: "Kitchen Admin",
action: `Order ${orderId} marked as ${String(status).toUpperCase()}`,
});
},
onSettled: () => qc.invalidateQueries({ queryKey: orderKeys.all }),
});
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Profile/components/OrderCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const OrderCard = ({ order }) => {
className="text-sm font-bold whitespace-nowrap"
style={{ color: "#2e7d32" }}
>
{order.totalPrice}$
{order.totalPrice} EGP

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Apply number formatting to order.totalPrice.

{order.totalPrice} EGP renders the raw value without decimal formatting. If totalPrice is 12.5, the user sees "12.5 EGP" instead of "12.50 EGP", inconsistent with other price displays across the app.

💚 Proposed fix
-            {order.totalPrice} EGP
+            {Number(order.totalPrice || 0).toFixed(2)} EGP
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{order.totalPrice} EGP
{Number(order.totalPrice || 0).toFixed(2)} EGP
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Profile/components/OrderCard.jsx` at line 67, The OrderCard price
display is rendering order.totalPrice as a raw value, so it may show
inconsistent decimals. Update the total price render in OrderCard.jsx to use the
same number formatting approach used elsewhere in the app, ensuring values like
12.5 display as 12.50 while keeping the EGP label.

</span>
</div>

Expand Down
Loading