diff --git a/src/components/Directory/ListViewContact.jsx b/src/components/Directory/ListViewContact.jsx index 16e737a7..16fd9a14 100644 --- a/src/components/Directory/ListViewContact.jsx +++ b/src/components/Directory/ListViewContact.jsx @@ -179,7 +179,7 @@ const ListViewContact = ({ data, Pagination }) => { No contacts found diff --git a/src/components/Project/Infrastructure/WorkArea.jsx b/src/components/Project/Infrastructure/WorkArea.jsx index 71e34d0e..59f281be 100644 --- a/src/components/Project/Infrastructure/WorkArea.jsx +++ b/src/components/Project/Infrastructure/WorkArea.jsx @@ -108,7 +108,7 @@ const WorkArea = ({ workArea, floor, forBuilding }) => { diff --git a/src/components/common/ProgressBar.jsx b/src/components/common/ProgressBar.jsx index 947c6a00..cb6e7b8a 100644 --- a/src/components/common/ProgressBar.jsx +++ b/src/components/common/ProgressBar.jsx @@ -3,35 +3,65 @@ import React from "react"; const ProgressBar = ({ plannedWork = 100, completedWork = 0, - height = "8px", + height = "6px", className = "mb-4", rounded = true, + showLabel = true, }) => { const getProgress = (planned, completed) => { - if (!planned || planned === 0) return "0%"; - return `${Math.min((completed / planned) * 100, 100).toFixed(2)}%`; + if (!planned || planned === 0) return 0; + return Math.min((completed / planned) * 100, 100); }; - const progressStyle = { - width: getProgress(plannedWork, completedWork), + const percentage = getProgress(plannedWork, completedWork); + + const progressBarStyle = { + width: ` ${percentage.toFixed(2)}%`, + transition: "width 0.4s ease", + }; + + const containerStyle = { + height, + display: "flex", + alignItems: "center", + gap: "8px", }; return (
-
+
+
+
+
+
+ + {showLabel && ( + + {percentage.toFixed(2)}% + + )}
); }; export default ProgressBar; - diff --git a/src/utils/appUtils.js b/src/utils/appUtils.js index 0611d9c8..f9be1ebd 100644 --- a/src/utils/appUtils.js +++ b/src/utils/appUtils.js @@ -91,4 +91,47 @@ const date = new Date( Date.UTC(Number(year), Number(month) - 1, Number(day), 0, 0, 0) ); return isNaN(date.getTime()) ? null : date.toISOString(); -} \ No newline at end of file +} + + +/** + * Flexible number formatter for currency, numbers, or percentages. + * + * @param {number} amount - The value to format. + * @param {Object} options - Formatting options. + * @param {"currency"|"number"|"percent"} [options.type="number"] - Type of format. + * @param {string} [options.currency="INR"] - Currency code (only used when type="currency"). + * @param {string} [options.locale="en-US"] - Locale for formatting. + * @param {"short"|"long"|"standard"} [options.notation="compact"] - Display style for large numbers. + * @param {number} [options.minimumFractionDigits=0] - Minimum decimal places. + * @param {number} [options.maximumFractionDigits=2] - Maximum decimal places. + * @returns {string} Formatted number string. + */ +export const formatFigure = ( + amount, + { + type = "number", + currency = "INR", + locale = "en-US", + notation = "compact", + compactDisplay = "short", + minimumFractionDigits = 0, + maximumFractionDigits = 2, + } = {} +) => { + if (amount == null || isNaN(amount)) return "-"; + + const formatterOptions = { + style: type === "currency" ? "currency" : type === "percent" ? "percent" : "decimal", + notation: notation, + compactDisplay, + minimumFractionDigits, + maximumFractionDigits, + }; + + if (type === "currency") { + formatterOptions.currency = currency; + } + + return new Intl.NumberFormat(locale, formatterOptions).format(amount); +};