Skip to content

change the currency to EGP intead of $ and update the dashboard , liv… - #69

Merged
M7mednsr merged 2 commits into
devfrom
feature/update-dashboard-flow
Jul 8, 2026
Merged

change the currency to EGP intead of $ and update the dashboard , liv…#69
M7mednsr merged 2 commits into
devfrom
feature/update-dashboard-flow

Conversation

@M7mednsr

@M7mednsr M7mednsr commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

…ekitchen , orders pages with backend api

Summary by CodeRabbit

  • New Features

    • Dashboard now shows recent activity and customer reviews in a more accessible layout.
    • Order updates can now appear in a live activity feed.
  • Bug Fixes

    • Improved profile header loading so users see a cleaner name, role, and avatar fallback instead of blank or loading text.
    • Expanded status styling for kitchen confirmations to cover more ticket states.
    • Revenue, orders, and menu prices now display consistently in EGP across the app.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f17ca9ef-ff71-4e89-887b-ae5187882d36

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/update-dashboard-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/store/orderStore.js (1)

432-432: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update error message currency from $ to EGP.

The max-order-total error still says 10,000$ while the rest of the PR migrates to EGP. This is a user-facing string that should be consistent.

💚 Proposed fix
-            throw new Error("Order total exceeds limit of 10,000$.");
+            throw new Error("Order total exceeds limit of 10,000 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/store/orderStore.js` at line 432, The user-facing max-order-total error
message still uses “$” instead of “EGP”, so update the string thrown in the
order total limit check to match the new currency. Locate the error in the order
total validation logic in orderStore and change the message in the relevant
throw so it consistently says 10,000 EGP across the PR.
🧹 Nitpick comments (6)
src/components/Dashboard/DashboardHeader.jsx (2)

51-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

initials is now dead code.

The avatar rendering at lines 193-202 always uses an <img>, so initials is no longer referenced anywhere in the component. Remove it to avoid confusion.

♻️ Remove unused `initials`
-  const initials = safeName
-    ? safeName.split(" ").map(n => n[0]).join("").substring(0, 2).toUpperCase()
-    : "U";
-
   const displaySubtitle = subtitle
🤖 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/DashboardHeader.jsx` around lines 51 - 53, The
`initials` value in `DashboardHeader` is now unused because the avatar render
path always uses the `<img>` branch, so remove the dead `initials` computation
from the component. Clean up the related logic near `safeName` and ensure no
other references depend on `initials` in `DashboardHeader` or its avatar
rendering flow.

33-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

rawName derivation duplicates the same field-resolution pattern for profileUser and authUser.

The 10-line expression repeats identical name → fullName → firstName/lastName logic twice. Extracting a small helper would improve readability and make it easier to add new user sources.

♻️ Proposed helper extraction
+ const resolveName = (u) =>
+   u?.name ||
+   u?.fullName ||
+   (u?.firstName || u?.lastName
+     ? `${u?.firstName || ""} ${u?.lastName || ""}`.trim()
+     : "") ||
+   "";
+
   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";
+    resolveName(profileUser) ||
+    resolveName(authUser) ||
+    authUser?.username ||
+    authUser?.email?.split("@")[0] ||
+    "Chef Admin";
🤖 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/DashboardHeader.jsx` around lines 33 - 42, The
rawName derivation in DashboardHeader.jsx repeats the same user-name fallback
chain for profileUser and authUser, making it hard to read and maintain. Extract
the shared name-resolution logic into a small helper (for example, a function
that takes a user object and returns
name/fullName/firstName-lastName/username/email prefix) and then use that helper
for both profileUser and authUser in the rawName expression.
src/components/ui/RegularFoodCard.jsx (1)

125-133: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider using formatCurrency for price display.

Both the strike-through and main price use inline formatPrice(...) EGP instead of the shared formatCurrency utility. While formatPrice does call toFixed(2), it strips trailing zeros (parseFloat(num.toFixed(2)).toString()), so 12.00 becomes "12" — inconsistent with formatCurrency which always shows 2 decimals.

</review_comment_end -->

🤖 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/ui/RegularFoodCard.jsx` around lines 125 - 133, The price
rendering in RegularFoodCard is using formatPrice directly for both the
strike-through price and the main price, which causes inconsistent decimal
display. Update the price display logic in RegularFoodCard to use the shared
formatCurrency utility instead of formatPrice for these spans, and ensure both
the discounted and original prices render with consistent 2-decimal formatting.
Locate the affected JSX by the displayPrice/hasDiscount price block in
RegularFoodCard and replace the inline formatting there.
src/components/Dashboard/TrendingMenus.jsx (1)

62-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace MdAttachMoney with a currency-neutral icon.

The MdAttachMoney icon (a dollar sign) is still used next to the EGP-formatted revenue display, which is inconsistent with the currency migration from $ to EGP.

Proposed fix
-<MdAttachMoney size={15} className="text-[`#F97316`]" />
+<MdTrendingUp size={15} className="text-[`#F97316`]" />

Alternatively, import a more neutral icon like FiDollarSignFiTrendingUp or MdPayments depending on what's already available in the project's icon set.

🤖 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/TrendingMenus.jsx` around lines 62 - 64, Replace the
currency-specific MdAttachMoney icon in TrendingMenus with a neutral revenue
icon to match the EGP display. Update the icon used in the revenue row inside
the TrendingMenus component, keeping the existing label and formatting intact,
and swap in a neutral alternative already available in the project (for example
a payments or trend icon) so the UI no longer implies USD.
src/services/dashboardService.js (2)

165-181: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the activityLog utility instead of re-implementing storage access.

This duplicates the "revive_activity_log" key and the raw-read/try-catch already provided by getActivityRaw() in src/utils/activityLog.js. Importing the helper avoids the magic string drifting from the writer (pushActivity).

♻️ Proposed refactor
-import { formatTimeAgo } from "../utils/activityLog";
+import { formatTimeAgo, getActivityRaw } from "../utils/activityLog";
@@
 export const getRecentActivity = () => {
   try {
-    const stored = JSON.parse(localStorage.getItem("revive_activity_log") || "[]");
+    const stored = getActivityRaw();
     return Promise.resolve(
🤖 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/services/dashboardService.js` around lines 165 - 181, getRecentActivity
duplicates the revive_activity_log storage read and error handling instead of
reusing the shared activityLog helper. Update dashboardService’s
getRecentActivity to import and use getActivityRaw() from
src/utils/activityLog.js, then keep only the mapping/formatting logic there so
the storage key and try-catch stay centralized with pushActivity.

244-245: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

All dashboard metrics are derived from a hard cap of 500 orders.

Every derived value (revenue, overview, trending, adaptive daily goals, historical averages) is computed from getOrders(), which fixes size: 500. Once order volume exceeds 500, historical averages and revenue-by-month will silently undercount. Consider paginating/aggregating server-side for these computations, or documenting the cap as an intentional approximation.

🤖 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/services/dashboardService.js` around lines 244 - 245, The dashboard
metrics are all based on getOrders(), which hardcodes a size cap of 500 and
causes revenue, overview, trending, goals, and historical averages to undercount
once order volume grows beyond that limit. Update the data retrieval path used
by getOrders() and the dependent dashboard calculations to support full
pagination or server-side aggregation instead of relying on the fixed 500-order
fetch, or explicitly document the cap if it is intended as an approximation.
🤖 Prompt for all review comments with 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.

Inline comments:
In `@src/components/Dashboard/MetricCards.jsx`:
- 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.

In `@src/components/Dashboard/OrdersView.jsx`:
- 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.

In `@src/components/Dashboard/shared/DishDetailsModal.jsx`:
- 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.

In `@src/components/Dashboard/shared/InactiveMenuModal.jsx`:
- 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.

In `@src/pages/Profile/components/OrderCard.jsx`:
- 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.

In `@src/services/dashboardService.js`:
- Line 18: The dashboardService module has an unused axios import that is never
referenced because requests go through api instead. Remove the axios import from
the top of the file and keep the existing api-based calls unchanged in
dashboardService so ESLint no-unused-vars is satisfied.
- Around line 20-23: Update isOrderDone in dashboardService so it checks the
same status values produced by mapOrders/getOrders rather than raw backend
states. The current logic compares against uppercase values like CONFIRMED, but
mapOrders converts that status to the UI label Preparing, so confirmed orders
are missed in revenue/completion totals. Adjust the condition to match the
mapped label set used by getOrders/mapOrders, keeping the helper aligned with
the values it actually receives.
- Around line 41-65: The revenue aggregation in getRevenueData currently buckets
by month name only, which merges identical months across different years and can
distort the chart. Update the grouping key to include the year alongside the
month in getRevenueData, then sort the aggregated series chronologically before
calling Mappers.mapRevenueData so the revenue chart reflects true time order.

In `@src/services/mappers/dashboardMappers.js`:
- Line 129: The address fallback in the mapper currently builds a truthy ", "
when customerDetails.address and customerDetails.city are empty, which prevents
deliveryAddress from being used. Update the address composition in the dashboard
order mapper and the corresponding logic in mapKitchenOrders to only use a
customerDetails string when it contains actual non-empty parts, otherwise fall
through to item.deliveryAddress and then the empty string.

---

Outside diff comments:
In `@src/store/orderStore.js`:
- Line 432: The user-facing max-order-total error message still uses “$” instead
of “EGP”, so update the string thrown in the order total limit check to match
the new currency. Locate the error in the order total validation logic in
orderStore and change the message in the relevant throw so it consistently says
10,000 EGP across the PR.

---

Nitpick comments:
In `@src/components/Dashboard/DashboardHeader.jsx`:
- Around line 51-53: The `initials` value in `DashboardHeader` is now unused
because the avatar render path always uses the `<img>` branch, so remove the
dead `initials` computation from the component. Clean up the related logic near
`safeName` and ensure no other references depend on `initials` in
`DashboardHeader` or its avatar rendering flow.
- Around line 33-42: The rawName derivation in DashboardHeader.jsx repeats the
same user-name fallback chain for profileUser and authUser, making it hard to
read and maintain. Extract the shared name-resolution logic into a small helper
(for example, a function that takes a user object and returns
name/fullName/firstName-lastName/username/email prefix) and then use that helper
for both profileUser and authUser in the rawName expression.

In `@src/components/Dashboard/TrendingMenus.jsx`:
- Around line 62-64: Replace the currency-specific MdAttachMoney icon in
TrendingMenus with a neutral revenue icon to match the EGP display. Update the
icon used in the revenue row inside the TrendingMenus component, keeping the
existing label and formatting intact, and swap in a neutral alternative already
available in the project (for example a payments or trend icon) so the UI no
longer implies USD.

In `@src/components/ui/RegularFoodCard.jsx`:
- Around line 125-133: The price rendering in RegularFoodCard is using
formatPrice directly for both the strike-through price and the main price, which
causes inconsistent decimal display. Update the price display logic in
RegularFoodCard to use the shared formatCurrency utility instead of formatPrice
for these spans, and ensure both the discounted and original prices render with
consistent 2-decimal formatting. Locate the affected JSX by the
displayPrice/hasDiscount price block in RegularFoodCard and replace the inline
formatting there.

In `@src/services/dashboardService.js`:
- Around line 165-181: getRecentActivity duplicates the revive_activity_log
storage read and error handling instead of reusing the shared activityLog
helper. Update dashboardService’s getRecentActivity to import and use
getActivityRaw() from src/utils/activityLog.js, then keep only the
mapping/formatting logic there so the storage key and try-catch stay centralized
with pushActivity.
- Around line 244-245: The dashboard metrics are all based on getOrders(), which
hardcodes a size cap of 500 and causes revenue, overview, trending, goals, and
historical averages to undercount once order volume grows beyond that limit.
Update the data retrieval path used by getOrders() and the dependent dashboard
calculations to support full pagination or server-side aggregation instead of
relying on the fixed 500-order fetch, or explicitly document the cap if it is
intended as an approximation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: af06874d-91b1-4c2d-9415-dccd996a9c90

📥 Commits

Reviewing files that changed from the base of the PR and between 5d1d5c2 and 9b6ae1f.

📒 Files selected for processing (22)
  • src/components/Dashboard/DashboardHeader.jsx
  • src/components/Dashboard/DashboardView.jsx
  • src/components/Dashboard/LiveKitchenView.jsx
  • src/components/Dashboard/MetricCards.jsx
  • src/components/Dashboard/OrdersView.jsx
  • src/components/Dashboard/RevenueChart.jsx
  • src/components/Dashboard/TrendingMenus.jsx
  • src/components/Dashboard/shared/DishDetailsModal.jsx
  • src/components/Dashboard/shared/InactiveMenuModal.jsx
  • src/components/Dashboard/shared/OrderDetailsModal.jsx
  • src/components/ui/PopularMenuCard.jsx
  • src/components/ui/RegularFoodCard.jsx
  • src/constants.js
  • src/hooks/dashboard/useOrders.js
  • src/pages/Profile/components/OrderCard.jsx
  • src/pages/Profile/components/OrderDetailsModal.jsx
  • src/services/dashboardService.js
  • src/services/mappers/dashboardMappers.js
  • src/services/order.service.js
  • src/store/orderStore.js
  • src/utils/activityLog.js
  • src/utils/formatters.js


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.

<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.

</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.

<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 DishDetailsModalitem.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.

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.

import { useAuthStore } from "../store";
import { evaluateStock } from "../utils/stockUtils";
import { formatTimeAgo } from "../utils/activityLog";
import axios from "axios";

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 | 🟡 Minor | ⚡ Quick win

Remove the unused axios import.

axios is imported but never referenced (calls go through api). Flagged by ESLint no-unused-vars.

♻️ Proposed fix
-import { formatTimeAgo } from "../utils/activityLog";
-import axios from "axios";
+import { formatTimeAgo } from "../utils/activityLog";
📝 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
import axios from "axios";
🧰 Tools
🪛 ESLint

[error] 18-18: 'axios' is defined but never used. Allowed unused vars must match /^[A-Z_]/u.

(no-unused-vars)

🤖 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/services/dashboardService.js` at line 18, The dashboardService module has
an unused axios import that is never referenced because requests go through api
instead. Remove the axios import from the top of the file and keep the existing
api-based calls unchanged in dashboardService so ESLint no-unused-vars is
satisfied.

Source: Linters/SAST tools

Comment on lines +20 to +23
const isOrderDone = (o) => {
const st = (o?.status || "").toUpperCase();
return st === "DONE" || st === "COMPLETED" || st === "DELIVERED" || st === "CONFIRMED";
};

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm getOrders feeds mapped statuses into isOrderDone consumers
rg -nP "isOrderDone|mapOrders\b|STATUS_MAP" src/services/dashboardService.js src/services/mappers/dashboardMappers.js -C2

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 5282


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '88,106p' src/services/mappers/dashboardMappers.js
sed -n '20,24p' src/services/dashboardService.js

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 969


isOrderDone should match the mapped UI labels. getOrders() feeds it mapOrders() output, so only "Done" can match here; "CONFIRMED" becomes "Preparing", which excludes confirmed orders from revenue/completion totals.

🤖 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/services/dashboardService.js` around lines 20 - 23, Update isOrderDone in
dashboardService so it checks the same status values produced by
mapOrders/getOrders rather than raw backend states. The current logic compares
against uppercase values like CONFIRMED, but mapOrders converts that status to
the UI label Preparing, so confirmed orders are missed in revenue/completion
totals. Adjust the condition to match the mapped label set used by
getOrders/mapOrders, keeping the helper aligned with the values it actually
receives.

Comment on lines +41 to +65
export const getRevenueData = async () => {
const orders = await getOrders().catch(() => []);
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const MONTHS = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
const revenueByMonth = {};

orders.forEach(o => {
if (o.status !== 'Cancelled' && o.time) {
const date = new Date(o.time);
// Use preserved ISO createdAt from mapOrders
if (isOrderDone(o) && o.createdAt) {
const date = new Date(o.createdAt);
if (!isNaN(date.getTime())) {
const monthStr = months[date.getMonth()];
revenueByMonth[monthStr] = (revenueByMonth[monthStr] || 0) + (o.total || 0);
const key = MONTHS[date.getMonth()];
revenueByMonth[key] = (revenueByMonth[key] || 0) + (o.total || 0);
}
}
});

const result = Object.entries(revenueByMonth).map(([month, rev]) => ({
month,
revenue: Math.round(rev / 1000),
income: Math.round((rev * 0.7) / 1000),
expense: Math.round((rev * 0.3) / 1000)
revenue: Math.round(rev), // exact EGP amount
}));
return Mappers.mapRevenueData(result.length ? result : [
{ month: "Jan", income: 10, revenue: 15, expense: 5 },
{ month: "Feb", income: 12, revenue: 18, expense: 6 }
]);

// Minimal fallback only when truly no orders exist
return Mappers.mapRevenueData(
result.length ? result : [{ month: "—", income: 0, revenue: 0, expense: 0 }]
);

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

git ls-files src/services/dashboardService.js src | sed -n '1,120p'

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 5002


🏁 Script executed:

ast-grep outline src/services/dashboardService.js --view expanded

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 3286


🏁 Script executed:

sed -n '1,120p' src/services/dashboardService.js && printf '\n---\n' && sed -n '1,220p' src/components/Dashboard/RevenueChart.jsx && printf '\n---\n' && rg -n "mapRevenueData|RevenueChart|revenue" src/services src/components -g '!**/*.map'

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 9029


🏁 Script executed:

sed -n '1,120p' src/services/mappers/dashboardMappers.js && printf '\n---\n' && sed -n '1,220p' src/hooks/dashboard/useDashboard.js && printf '\n---\n' && sed -n '1,220p' src/hooks/dashboard/useDashboardRealtime.js

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 10193


🏁 Script executed:

sed -n '230,280p' src/services/dashboardService.js && printf '\n---\n' && rg -n "getRevenueData\\(" src

Repository: Revive-Graduation-Project/Revive-Front-End

Length of output: 2568


Use a year-aware key and sort the revenue series

  • MONTHS[date.getMonth()] merges the same month across different years, and useRevenueData(period) still fetches the full order history, so the chart can blend unrelated revenue into one bucket.
  • Emit the series in explicit chronological order before passing it to the chart.
🤖 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/services/dashboardService.js` around lines 41 - 65, The revenue
aggregation in getRevenueData currently buckets by month name only, which merges
identical months across different years and can distort the chart. Update the
grouping key to include the year alongside the month in getRevenueData, then
sort the aggregated series chronologically before calling Mappers.mapRevenueData
so the revenue chart reflects true time order.

total: item.totalPrice ?? item.total ?? 0,
customer: item.clientId ? `Client #${item.clientId}` : (item.customer || (item.customerDetails ? `${item.customerDetails.firstName || ""} ${item.customerDetails.lastName || ""}`.trim() : "")),
phone: item.phone || item.phoneNumber || item.customerDetails?.phone || item.customerPhone || item.user?.phone || item.customerDetails?.phoneNumber || "",
address: item.address || (item.customerDetails ? `${item.customerDetails.address || ""}, ${item.customerDetails.city || ""}` : "") || item.deliveryAddress || "",

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

Address fallback yields a stray ", " and skips deliveryAddress.

When customerDetails exists but its address/city are empty, the template produces ", ", which is truthy, so item.deliveryAddress is never reached and the UI shows a lone comma. The same pattern exists at Line 159 in mapKitchenOrders.

♻️ Proposed fix
-      address:    item.address || (item.customerDetails ? `${item.customerDetails.address || ""}, ${item.customerDetails.city || ""}` : "") || item.deliveryAddress || "",
+      address:    item.address
+        || [item.customerDetails?.address, item.customerDetails?.city].filter(Boolean).join(", ")
+        || item.deliveryAddress
+        || "",
📝 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
address: item.address || (item.customerDetails ? `${item.customerDetails.address || ""}, ${item.customerDetails.city || ""}` : "") || item.deliveryAddress || "",
address: item.address
|| [item.customerDetails?.address, item.customerDetails?.city].filter(Boolean).join(", ")
|| item.deliveryAddress
|| "",
🤖 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/services/mappers/dashboardMappers.js` at line 129, The address fallback
in the mapper currently builds a truthy ", " when customerDetails.address and
customerDetails.city are empty, which prevents deliveryAddress from being used.
Update the address composition in the dashboard order mapper and the
corresponding logic in mapKitchenOrders to only use a customerDetails string
when it contains actual non-empty parts, otherwise fall through to
item.deliveryAddress and then the empty string.

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
revive-front-end Ready Ready Preview, Comment Jul 8, 2026 3:46pm

@M7mednsr
M7mednsr merged commit 470e19b into dev Jul 8, 2026
3 checks passed
This was referenced Jul 11, 2026
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant