import {Prisma} from '@prisma/client' import bcrypt from 'bcryptjs' import {type ClassValue, clsx} from 'clsx' import {getLocale} from 'next-intl/server' import slugify from 'slugify' import {twMerge} from 'tailwind-merge' import {i18nDefaultLocale} from '@/i18n-config' /** * Just output dump using pretty output * * @param variable */ export function dump(variable: any): [string, string] { return [ (new Error().stack?.split('\n')[2]?.trim().split(' ')[1] as string) + ' ', JSON.stringify(variable, null, 2) ] } export const toPrice = (price: any) => parseFloat(price).toFixed(2) /** * Create fallback avatar for showing during login process or in case if empty * * @param name */ export const avatarFallback = (name: string): string => name ? name .split(' ') .slice(0, 2) .map(w => w[0]) .join('') .toUpperCase() : 'U' export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } /** * Slugify the string based on locale using kebab case * * @param string * @param locale */ export function slug(string: string, locale: string = 'uk'): string { return slugify(string, { lower: true, strict: true, locale }) } export const formatNumberWithDecimal = (num: number): string => { const [int, decimal] = num.toString().split('.') return decimal ? `$(num).${decimal.padEnd(2, '0')}` : int } export const toInt = (input: unknown): number | null => { let output = NaN if (typeof input === 'string' || typeof input === 'number') { output = parseInt(input as string, 10) } if (isNaN(output)) { console.log('input invalid type: ', typeof input) return null } return output } export const hashPassword = async (value: string): Promise => { return bcrypt.hash(value, 10) } export const verifyHashedPassword = async ( value: string, hashPassword: string ): Promise => { return await bcrypt.compare(value, hashPassword) } /** * Remove empty properties from the object * * @param queryParams */ export const cleanEmptyParams = (queryParams: any) => { return Object.keys(queryParams) .filter(key => queryParams[key] != '') .reduce((acc, key) => Object.assign(acc, {[key]: queryParams[key]}), {}) } /** * Replace null value with empty string for the object and array of them as well * * @param data */ export const toEmptyParams = (data: object | object[]) => { const result = [] const isArray = Array.isArray(data) const toProcess: object[] = isArray ? data : [data] for (let x in toProcess) { const norm = Object.keys(toProcess[x]).reduce( (obj: {}, key: string) => Object.assign(obj, { // @ts-ignore [key]: toProcess[x][key] === null ? '' : toProcess[x][key] }), {} ) if (!isArray) return norm result.push(norm) } return result } export const thisLocales = async (locales: any) => { const loc = await getLocale() return locales.filter((locale: any) => locale.lang === loc) } export const thisLocale = async (locales: any) => { const loc = await getLocale() return locales.find((locale: any) => locale.lang === loc) } export const dbErrorHandling = (e: unknown, message?: string | null) => { if (e instanceof Prisma.PrismaClientKnownRequestError) { return {error: `${e.code}: ${e.message}`} } else if ((e as {code: string}).code === 'ETIMEDOUT') { return { error: 'Неможливо підключитися до бази даних. Будь ласка, спробуйте згодом.' } } else if ((e as {code: string}).code === '503') { return { error: 'Сервіс тимчасово недоступний. Будь ласка, спробуйте згодом.' } } else { return {error: 'Сталася несподівана помилка. Будь ласка, спробуйте згодом.'} } } /** * Check if the object is empty * * @param obj */ export const isEmptyObj = (obj: object): boolean => Object.keys(obj).length === 0