419 lines
11 KiB
JavaScript
419 lines
11 KiB
JavaScript
import moment from "jalali-moment";
|
|
import { toast } from "react-toastify";
|
|
import specialties from "@/data/specialties.json";
|
|
import Cookies from "js-cookie";
|
|
|
|
export const numberToArStyle = (num) => num?.toLocaleString("ar-AE") || "";
|
|
|
|
export const isActiveURL = (link, name) => link === name;
|
|
|
|
export const convertToJalali = (date) => {
|
|
const currentDate = date;
|
|
|
|
const jalaliDate = moment(currentDate).format("jYYYY/jM/jD");
|
|
const jalaliYear = moment(jalaliDate, "jYYYY/jM/jD").jYear();
|
|
const jalaliMonth = moment(jalaliDate, "jYYYY/jM/jD").jMonth() + 1;
|
|
const jalaliDay = moment(jalaliDate, "jYYYY/jM/jD").jDate();
|
|
|
|
return `${jalaliYear}/${jalaliMonth}/${jalaliDay}`;
|
|
};
|
|
|
|
export const handleTwoLength = (value) =>
|
|
String(value).length === 1 ? `0${value}` : value;
|
|
|
|
export const checkAllValues = (data) => {
|
|
for (let key in data) {
|
|
if (typeof data[key] === "object" && data[key] !== null) {
|
|
if ("value" in data[key]) {
|
|
if (!data[key].value) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (!checkAllValues(data[key])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
export const checkTimes = (arr) => {
|
|
return arr.map((day) => {
|
|
const hasMorningTime = day.morning_time.some((time) => time !== "");
|
|
const hasEveningTime = day.evening_time.some((time) => time !== "");
|
|
return hasMorningTime && hasEveningTime;
|
|
});
|
|
};
|
|
|
|
export const uploadImage = async (event) => {
|
|
let obj = {
|
|
file: "",
|
|
blob: "",
|
|
};
|
|
|
|
const file = event.target.files[0];
|
|
if (file) {
|
|
obj.file = file;
|
|
const readFileAsDataURL = (file) => {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
|
|
reader.onload = () => resolve(reader.result);
|
|
|
|
reader.onerror = (error) => reject(error);
|
|
|
|
reader.readAsDataURL(file);
|
|
});
|
|
};
|
|
try {
|
|
obj.blob = await readFileAsDataURL(file);
|
|
return obj;
|
|
} catch (error) {
|
|
console.error("Error reading file: ", error);
|
|
throw error;
|
|
}
|
|
} else {
|
|
throw new Error("No file selected");
|
|
}
|
|
};
|
|
|
|
export const alert = (type, text, prop) => {
|
|
toast[type](
|
|
<div className="h-full w-full flex flex-col items-start justify-center gap-[13px]">
|
|
<p className="text-[14px] font-medium">
|
|
پیغام{" "}
|
|
{type === "error"
|
|
? "خطا"
|
|
: type === "warning"
|
|
? "هشدار"
|
|
: type === "info"
|
|
? "اعلام"
|
|
: "موفقیت"}
|
|
</p>
|
|
<p className="text-[14px] font-normal">{text}</p>
|
|
</div>,
|
|
{ prop }
|
|
);
|
|
};
|
|
|
|
export const addLabelToList = (list) =>
|
|
list.map((item) => {
|
|
return {
|
|
...item,
|
|
label: item.name,
|
|
};
|
|
});
|
|
|
|
export const formatPhoneNumber = (input) => {
|
|
if (typeof input !== "string") input = String(input);
|
|
|
|
const normalized = input
|
|
.replace(/[\u06F0-\u06F9]/g, (d) => String(d.charCodeAt(0) - 0x06f0))
|
|
.replace(/[\u0660-\u0669]/g, (d) => String(d.charCodeAt(0) - 0x0660));
|
|
|
|
const digits = normalized.replace(/\D/g, "");
|
|
|
|
const trimmed = digits.substring(0, 9);
|
|
|
|
const match = trimmed.match(/^(\d{0,2})(\d{0,3})(\d{0,4})$/);
|
|
if (!match) return trimmed;
|
|
|
|
return [match[1], match[2], match[3]].filter(Boolean).join(" ");
|
|
};
|
|
|
|
export function validatePhoneNumber(input) {
|
|
if (!input) {
|
|
return { valid: false, text: "شماره موبایل نمیتواند خالی باشد." };
|
|
}
|
|
|
|
if (input.length !== 11) {
|
|
return { valid: false, text: "شماره موبایل باید دقیقا 11 رقم باشد." };
|
|
}
|
|
|
|
const isValid = /^09\d{9}$/.test(input);
|
|
if (!isValid) {
|
|
return { valid: false, text: "شماره موبایل نامعتبر است." };
|
|
}
|
|
|
|
return { valid: true, text: null };
|
|
}
|
|
|
|
export const searchOnList = (list, value, name) => {
|
|
let newList = list;
|
|
newList = list.filter((item) => item[name]?.toLowerCase()?.includes(value));
|
|
return newList;
|
|
};
|
|
|
|
export function clearFilterParams(router, listRemove) {
|
|
const currentParams = new URLSearchParams(window.location.search);
|
|
const keysToRemove = listRemove;
|
|
keysToRemove.forEach((key) => currentParams.delete(key));
|
|
const queryString = currentParams.toString();
|
|
const newUrl = queryString ? `/doctors?${queryString}` : "/doctors";
|
|
|
|
router.push(newUrl);
|
|
}
|
|
|
|
export const filterList = (data) => {
|
|
const parentList = specialties.filter((item) => !item.parent);
|
|
const childrenList = specialties.filter((item) => item.parent);
|
|
|
|
const filteredChildrenList =
|
|
data && data.category
|
|
? childrenList.filter((item) => item.parent === data.category.id)
|
|
: [];
|
|
|
|
return {
|
|
parentList: parentList,
|
|
childrenList: filteredChildrenList,
|
|
};
|
|
};
|
|
|
|
export function getCleanNumberValue(value, defaultValue = 0) {
|
|
if (typeof value !== "string") value = String(value);
|
|
|
|
const persianArabicToEnglish = value
|
|
.replace(/[\u06F0-\u06F9]/g, (d) => String(d.charCodeAt(0) - 0x06f0))
|
|
.replace(/[\u0660-\u0669]/g, (d) => String(d.charCodeAt(0) - 0x0660));
|
|
|
|
const cleaned = persianArabicToEnglish.replace(/[^0-9.]/g, "");
|
|
|
|
const number = parseFloat(cleaned);
|
|
return isNaN(number) ? defaultValue : number;
|
|
}
|
|
|
|
export function hasDataChanged(previousData, newData) {
|
|
const oldDataString = JSON.stringify(
|
|
previousData,
|
|
Object.keys(previousData).sort()
|
|
);
|
|
const newDataString = JSON.stringify(newData, Object.keys(newData).sort());
|
|
return oldDataString !== newDataString;
|
|
}
|
|
|
|
export const getParsedUserInfo = () => {
|
|
const user = Cookies.get("userInfo");
|
|
const parsedUserInfo = user && JSON.parse(user);
|
|
return parsedUserInfo;
|
|
};
|
|
|
|
export const handleTimeExpiresToken = (expires_in) => {
|
|
const accessTokenExpires = new Date();
|
|
accessTokenExpires.setSeconds(accessTokenExpires.getSeconds() + expires_in);
|
|
const refreshTokenExpires = new Date();
|
|
refreshTokenExpires.setDate(refreshTokenExpires.getDate() + 30);
|
|
|
|
return {
|
|
accessTokenExpires,
|
|
refreshTokenExpires,
|
|
};
|
|
};
|
|
|
|
export const removeAdditionalKeysDashboard = (information) => {
|
|
const {
|
|
national_code,
|
|
changed,
|
|
created,
|
|
id,
|
|
status,
|
|
prev_data,
|
|
uuid,
|
|
...usedKays
|
|
} = information;
|
|
|
|
return usedKays;
|
|
};
|
|
|
|
// handle TimeStamp
|
|
|
|
function div(a, b) {
|
|
return Math.floor(a / b);
|
|
}
|
|
|
|
function isLeapGregorian(year) {
|
|
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
}
|
|
|
|
function dayOfYearToGregorian(year, dayOfYear) {
|
|
const monthDays = [
|
|
31,
|
|
isLeapGregorian(year) ? 29 : 28,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
];
|
|
let month = 1;
|
|
while (dayOfYear > monthDays[month - 1]) {
|
|
dayOfYear -= monthDays[month - 1];
|
|
month++;
|
|
}
|
|
return { month, day: dayOfYear };
|
|
}
|
|
|
|
function jalaliToGregorian(jy, jm, jd) {
|
|
jy = parseInt(jy);
|
|
jm = parseInt(jm);
|
|
jd = parseInt(jd);
|
|
|
|
const breaks = [
|
|
-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097,
|
|
2192, 2262, 2324, 2394, 2456, 3178,
|
|
];
|
|
|
|
let gy = jy + 621;
|
|
let leapJ = -14;
|
|
let jp = breaks[0];
|
|
let jump, i;
|
|
|
|
for (i = 1; i < breaks.length; i++) {
|
|
jump = breaks[i] - jp;
|
|
if (jy < breaks[i]) break;
|
|
leapJ += div(jump, 33) * 8 + div(jump % 33, 4);
|
|
jp = breaks[i];
|
|
}
|
|
|
|
let nYear = jy - jp;
|
|
leapJ += div(nYear, 33) * 8 + div((nYear % 33) + 3, 4);
|
|
if (jump % 33 === 4 && jump - nYear === 4) leapJ += 1;
|
|
|
|
let leapG = div(gy, 4) - div((div(gy, 100) + 1) * 3, 4) - 150;
|
|
let march = 20 + leapJ - leapG;
|
|
|
|
let gregorianYear = gy;
|
|
let gregorianMonth, gregorianDay;
|
|
|
|
let jalaliDayOfYear = jm <= 7 ? (jm - 1) * 31 + jd : (jm - 7) * 30 + 186 + jd;
|
|
|
|
if (jalaliDayOfYear <= march) {
|
|
gregorianYear -= 1;
|
|
const daysInPrevYear = isLeapGregorian(gregorianYear) ? 366 : 365;
|
|
const dayOfYear = daysInPrevYear - (march - jalaliDayOfYear);
|
|
const gDate = dayOfYearToGregorian(gregorianYear, dayOfYear);
|
|
gregorianMonth = gDate.month;
|
|
gregorianDay = gDate.day;
|
|
} else {
|
|
const dayOfYear = jalaliDayOfYear - march;
|
|
const gDate = dayOfYearToGregorian(gregorianYear, dayOfYear);
|
|
gregorianMonth = gDate.month;
|
|
gregorianDay = gDate.day;
|
|
}
|
|
|
|
return { gy: gregorianYear, gm: gregorianMonth, gd: gregorianDay };
|
|
}
|
|
|
|
function gregorianToJalali(gy, gm, gd) {
|
|
gy = parseInt(gy);
|
|
gm = parseInt(gm);
|
|
gd = parseInt(gd);
|
|
|
|
const breaks = [
|
|
-61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097,
|
|
2192, 2262, 2324, 2394, 2456, 3178,
|
|
];
|
|
|
|
let jy = 0;
|
|
let leapJ = -14;
|
|
let jp = breaks[0];
|
|
let jump, i;
|
|
|
|
for (i = 1; i < breaks.length; i++) {
|
|
jump = breaks[i] - jp;
|
|
if (gy < breaks[i]) break;
|
|
leapJ += div(jump, 33) * 8 + div(jump % 33, 4);
|
|
jp = breaks[i];
|
|
}
|
|
|
|
let nYear = gy - jp;
|
|
leapJ += div(nYear, 33) * 8 + div((nYear % 33) + 3, 4);
|
|
if (jump % 33 === 4 && jump - nYear === 4) leapJ += 1;
|
|
|
|
let leapG = div(gy, 4) - div((div(gy, 100) + 1) * 3, 4) - 150;
|
|
let march = 20 + leapJ - leapG;
|
|
|
|
let gregorianDayOfYear = dayOfYear(gy, gm, gd);
|
|
let jalaliDayOfYear, jyNew;
|
|
|
|
if (gregorianDayOfYear > march) {
|
|
jalaliDayOfYear = gregorianDayOfYear - march;
|
|
jyNew = gy - 621;
|
|
} else {
|
|
let daysInPrevYear = isLeapGregorian(gy - 1) ? 366 : 365;
|
|
jalaliDayOfYear = gregorianDayOfYear + daysInPrevYear - march;
|
|
jyNew = gy - 622;
|
|
}
|
|
|
|
let jmNew, jdNew;
|
|
if (jalaliDayOfYear <= 186) {
|
|
jmNew = Math.ceil(jalaliDayOfYear / 31);
|
|
jdNew = jalaliDayOfYear % 31;
|
|
if (jdNew === 0) jdNew = 31;
|
|
} else {
|
|
jalaliDayOfYear -= 186;
|
|
jmNew = Math.ceil(jalaliDayOfYear / 30) + 6;
|
|
jdNew = jalaliDayOfYear % 30;
|
|
if (jdNew === 0) jdNew = 30;
|
|
}
|
|
|
|
return { jy: jyNew, jm: jmNew, jd: jdNew };
|
|
}
|
|
|
|
function dayOfYear(year, month, day) {
|
|
const monthDays = [
|
|
31,
|
|
isLeapGregorian(year) ? 29 : 28,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
];
|
|
let doy = 0;
|
|
for (let i = 1; i < month; i++) {
|
|
doy += monthDays[i - 1];
|
|
}
|
|
doy += day;
|
|
return doy;
|
|
}
|
|
|
|
export function convertJalaliTimestamp(input, convertToTimestamp) {
|
|
if (convertToTimestamp) {
|
|
// input = { jy, jm, jd, hour?, minute?, second? }
|
|
const { jy, jm, jd, hour = 0, minute = 0, second = 0 } = input;
|
|
const { gy, gm, gd } = jalaliToGregorian(jy, jm, jd);
|
|
const date = new Date(gy, gm - 1, gd, hour, minute, second);
|
|
return Math.floor(date.getTime() / 1000);
|
|
} else {
|
|
const date = new Date(input * 1000);
|
|
const gy = date.getFullYear();
|
|
const gm = date.getMonth() + 1;
|
|
const gd = date.getDate();
|
|
const hour = date.getHours();
|
|
const minute = date.getMinutes();
|
|
const second = date.getSeconds();
|
|
const { jy, jm, jd } = gregorianToJalali(gy, gm, gd);
|
|
return { jy, jm, jd, hour, minute, second };
|
|
}
|
|
}
|
|
|
|
const timestamp = convertJalaliTimestamp(
|
|
{ jy: 1404, jm: 4, jd: 3, hour: 22, minute: 36, second: 10 },
|
|
true
|
|
);
|
|
console.log(timestamp);
|
|
|
|
const jalaliDate = convertJalaliTimestamp(1750791970, false);
|
|
console.log(jalaliDate);
|