Files
lti-web-client/src/lib/helper.ts
T
2025-12-06 17:13:27 +07:00

137 lines
3.4 KiB
TypeScript

import moment from 'moment';
import 'moment/locale/id';
import { twMerge } from 'tailwind-merge';
import clsx, { ClassValue } from 'clsx';
// set locale globally
moment.locale('id');
export const sleep = (ms: number = 1000) =>
new Promise((resolve) => setTimeout(resolve, ms));
export const formatDate = (date: moment.MomentInput, format?: string) => {
if (!date) return '-';
return moment(date).format(format);
};
export const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
};
export const formatNumber = (
value: number | bigint | Intl.StringNumericLiteral,
locale = 'id-ID',
minimumFractionDigits = 0,
maximumFractionDigits = 2
) => {
return new Intl.NumberFormat(locale, {
minimumFractionDigits,
maximumFractionDigits,
}).format(value);
};
export function formatVechicleNumber(value: string): string {
let result = '';
for (let i = 0; i < (value?.length ?? 0); i++) {
const curr = value[i];
const prev = value[i - 1];
// Cek apakah terjadi perpindahan dari huruf ke angka atau angka ke huruf
if (i > 0) {
const isCurrDigit = /\d/.test(curr);
const isPrevDigit = /\d/.test(prev);
if (isCurrDigit !== isPrevDigit) {
result += ' ';
}
}
result += curr;
}
return result.trim().replace(/\s+/g, ' ');
}
export const formatCurrency = (
value: number | bigint | Intl.StringNumericLiteral,
currency = 'IDR',
locale = 'id-ID',
minimumFractionDigits = 0,
maximumFractionDigits = 2
) => {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency,
minimumFractionDigits,
maximumFractionDigits,
}).format(value);
};
/**
* Retrieves a nested value from an object using a dot-delimited key path.
* Supports array indexes (e.g., "users.0.name") and returns a default value
* if the path does not exist.
*
* @param obj - The source object to search.
* @param path - Dot-delimited key string (e.g., "user.address.city").
* @param defaultValue - Optional value to return if the key path is not found.
* @returns The value found at the specified path, or the default value.
*/
export function getByPath<T, D = undefined>(
obj: T,
path: string,
defaultValue?: D
): D {
if (obj == null) return defaultValue as D;
if (!path) return obj as D;
const segments = path.split('.').filter(Boolean);
let cur: { [key: string]: unknown } = obj;
for (const seg of segments) {
if (cur == null) return defaultValue as D;
const key: string | number =
Array.isArray(cur) && /^\d+$/.test(seg) ? Number(seg) : seg;
if (Object(cur) !== cur || !(key in cur)) {
return defaultValue as D;
}
cur = cur[key] as { [key: string]: unknown };
}
return cur as D;
}
export const convertRowSelectionArrToObj = (
rowSelectionArr: string[] | number[]
) => {
const result: Record<string | number, boolean> = {};
rowSelectionArr.forEach((item) => {
result[item] = true;
});
return result;
};
export const convertRowSelectionObjToArr = (
rowSelection: string[] | number[]
) => {
const result = Object.keys(rowSelection).map(Number);
return result;
};
export const isPathActive = (pathname: string, link?: string) => {
if (!link) return false;
const splittedPathname = pathname.split('/');
const splittedLink = link.split('/');
const isActiveLinkValid = splittedLink.every((linkChunk, idx) => {
return linkChunk === splittedPathname[idx];
});
return pathname.startsWith(link) && isActiveLinkValid;
};