265 lines
7.0 KiB
JavaScript
265 lines
7.0 KiB
JavaScript
import { useEffect, useState } from "react";
|
|
import { parseISO, formatISO } from "date-fns";
|
|
export const formatFileSize = (bytes) => {
|
|
if (bytes < 1024) return bytes + " B";
|
|
else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB";
|
|
else return (bytes / (1024 * 1024)).toFixed(2) + " MB";
|
|
};
|
|
export const AppColorconfig = {
|
|
colors: {
|
|
primary: "#696cff",
|
|
secondary: "#8592a3",
|
|
success: "#71dd37",
|
|
info: "#03c3ec",
|
|
warning: "#ffab00",
|
|
danger: "#ff3e1d",
|
|
dark: "#233446",
|
|
black: "#000",
|
|
white: "#fff",
|
|
cardColor: "#fff",
|
|
bodyBg: "#f5f5f9",
|
|
bodyColor: "#697a8d",
|
|
headingColor: "#566a7f",
|
|
textMuted: "#a1acb8",
|
|
borderColor: "#eceef1",
|
|
},
|
|
};
|
|
export const getColorNameFromHex = (hex) => {
|
|
const normalizedHex = hex?.replace(/'/g, "").toLowerCase();
|
|
const colors = AppColorconfig.colors;
|
|
|
|
for (const [name, value] of Object.entries(colors)) {
|
|
if (value.toLowerCase() === normalizedHex) {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
export const getJobStatusBadge = (statusId) => {
|
|
if (!statusId) return "bg-label-secondary";
|
|
|
|
const map = {
|
|
"32d76a02-8f44-4aa0-9b66-c3716c45a918": "bg-label-primary", // New
|
|
"cfa1886d-055f-4ded-84c6-42a2a8a14a66": "bg-label-info", // Assigned
|
|
"5a6873a5-fed7-4745-a52f-8f61bf3bd72d": "bg-label-warning", // In Progress
|
|
"aab71020-2fb8-44d9-9430-c9a7e9bf33b0": "bg-label-dark", // Review
|
|
"ed10ab57-dbaa-4ca5-8ecd-56745dcbdbd7": "bg-label-success", // Done
|
|
"3ddeefb5-ae3c-4e10-a922-35e0a452bb69": "bg-label-secondary", // Closed
|
|
"75a0c8b8-9c6a-41af-80bf-b35bab722eb2": "bg-label-danger", // On Hold
|
|
};
|
|
|
|
return map[statusId] || "bg-label-secondary";
|
|
};
|
|
|
|
|
|
export const useDebounce = (value, delay = 500) => {
|
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
|
return () => clearTimeout(timer);
|
|
}, [value, delay]);
|
|
|
|
return debouncedValue;
|
|
};
|
|
|
|
export const getIconByFileType = (type = "") => {
|
|
const lower = type.toLowerCase();
|
|
|
|
if (lower === "application/pdf") return "bxs-file-pdf text-danger";
|
|
if (lower.includes("word")) return "bxs-file-doc text-primary text-primry";
|
|
if (lower.includes("excel") || lower.includes("spreadsheet"))
|
|
return "bxs-file-xls text-primry";
|
|
if (lower === "image/png") return "bxs-file-png";
|
|
if (lower === "image/jpeg" || lower === "image/jpg")
|
|
return "bxs-file-jpg text-primry";
|
|
if (lower.includes("zip") || lower.includes("rar"))
|
|
return "bxs-file-archive text-secondary";
|
|
|
|
return "bx bx-file";
|
|
};
|
|
|
|
export const normalizeAllowedContentTypes = (allowedContentType) => {
|
|
if (!allowedContentType) return [];
|
|
if (Array.isArray(allowedContentType)) return allowedContentType;
|
|
if (typeof allowedContentType === "string")
|
|
return allowedContentType.split(",");
|
|
return [];
|
|
};
|
|
export function localToUtc(dateString) {
|
|
if (!dateString || typeof dateString !== "string") return null;
|
|
|
|
const parts = dateString.trim().split("-");
|
|
if (parts.length !== 3) return null;
|
|
|
|
let day, month, year;
|
|
|
|
if (parts[0].length === 4) {
|
|
// Format: yyyy-mm-dd
|
|
[year, month, day] = parts;
|
|
} else {
|
|
// Format: dd-mm-yyyy
|
|
[day, month, year] = parts;
|
|
}
|
|
|
|
if (!day || !month || !year) return null;
|
|
|
|
const date = new Date(
|
|
Date.UTC(Number(year), Number(month) - 1, Number(day), 0, 0, 0)
|
|
);
|
|
return isNaN(date.getTime()) ? null : date.toISOString();
|
|
}
|
|
|
|
export const formatCurrency = (amount, currency = "INR", locale = "en-US") => {
|
|
return new Intl.NumberFormat(locale, {
|
|
style: "currency",
|
|
notation: "compact",
|
|
compactDisplay: "short",
|
|
currency: currency,
|
|
minimumFractionDigits: 0,
|
|
maximumFractionDigits: 2,
|
|
}).format(amount);
|
|
};
|
|
|
|
export const countDigit = (num) => {
|
|
return Math.abs(num).toString().length;
|
|
};
|
|
export const formatFigure = (
|
|
amount,
|
|
{
|
|
type = "number",
|
|
currency = "INR",
|
|
locale = "en-US",
|
|
notation = "standard", // standard or 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);
|
|
};
|
|
|
|
export const frequencyLabel = (
|
|
freq,
|
|
isLong = false,
|
|
isMonthRequired = false
|
|
) => {
|
|
const frequency = parseInt(freq, 10);
|
|
switch (frequency) {
|
|
case 0:
|
|
if (isLong && isMonthRequired) {
|
|
return { planDurationInString: "1 Month", planDurationInInt: 1 };
|
|
}
|
|
if (isLong) {
|
|
return "1 Month";
|
|
} else {
|
|
return "1 mon";
|
|
}
|
|
case 1:
|
|
if (isLong && isMonthRequired) {
|
|
return {
|
|
planDurationInString: "Quarterly (3 Months)",
|
|
planDurationInInt: 3,
|
|
};
|
|
}
|
|
if (isLong) {
|
|
return "Quarterly (3 Months)";
|
|
} else {
|
|
return "3 mon";
|
|
}
|
|
case 2:
|
|
if (isLong && isMonthRequired) {
|
|
return { planDurationInString: "6 Month", planDurationInInt: 6 };
|
|
}
|
|
if (isLong) {
|
|
return "6 Month";
|
|
} else {
|
|
return "6 mon";
|
|
}
|
|
case 3:
|
|
if (isLong && isMonthRequired) {
|
|
return { planDurationInString: "1 Year", planDurationInInt: 12 };
|
|
}
|
|
if (isLong) {
|
|
return "1 Year";
|
|
} else {
|
|
return "1 yr";
|
|
}
|
|
default:
|
|
return isLong ? "Unknown" : "N/A";
|
|
}
|
|
};
|
|
|
|
const badgeColors = ["primary", "secondary", "success", "warning", "info"];
|
|
|
|
let colorIndex = 0;
|
|
|
|
export function getNextBadgeColor(type = "label") {
|
|
const color = badgeColors[colorIndex];
|
|
colorIndex = (colorIndex + 1) % badgeColors.length;
|
|
return `rounded-pill text-bg-${color}`;
|
|
}
|
|
|
|
export function daysLeft(startDate, dueDate) {
|
|
if (!startDate || !dueDate) {
|
|
return { days: null, color: "label-secondary" };
|
|
}
|
|
|
|
const start = new Date(startDate);
|
|
const due = new Date(dueDate);
|
|
|
|
const today = new Date();
|
|
const diffTime = due.getTime() - today.getTime();
|
|
const days = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
let color = "label-primary"; // default
|
|
|
|
if (days < 0) {
|
|
color = "label-danger"; // overdue → red
|
|
} else if (days <= 15) {
|
|
color = "label-warning"; // near due → yellow
|
|
} else {
|
|
color = "label-primary"; // safe range
|
|
}
|
|
|
|
return { days, color };
|
|
}
|
|
|
|
export function calculateTDSPercentage(baseAmount = 0, taxAmount = 0, tdsPercentage = 0) {
|
|
baseAmount = Number(baseAmount) || 0;
|
|
taxAmount = Number(taxAmount) || 0;
|
|
tdsPercentage = Number(tdsPercentage) || 0;
|
|
|
|
const grossAmount = baseAmount + taxAmount;
|
|
const tdsAmount = (baseAmount * tdsPercentage) / 100;
|
|
const netPayable = grossAmount - tdsAmount;
|
|
|
|
return {
|
|
grossAmount,
|
|
tdsAmount,
|
|
netPayable,
|
|
};
|
|
}
|
|
|
|
|