move sdk packages to its own folder and rename api & dashboard
This commit is contained in:
8
apps/dashboard/src/utils/clipboard.ts
Normal file
8
apps/dashboard/src/utils/clipboard.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { toast } from 'sonner';
|
||||
|
||||
export function clipboard(value: string | number) {
|
||||
navigator.clipboard.writeText(value.toString());
|
||||
toast('Copied to clipboard', {
|
||||
description: value.toString(),
|
||||
});
|
||||
}
|
||||
7
apps/dashboard/src/utils/cn.ts
Normal file
7
apps/dashboard/src/utils/cn.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { clsx } from 'clsx';
|
||||
import type { ClassValue } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
32
apps/dashboard/src/utils/date.ts
Normal file
32
apps/dashboard/src/utils/date.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export function getDaysOldDate(days: number) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() - days);
|
||||
return date;
|
||||
}
|
||||
|
||||
export function dateDifferanceInDays(date1: Date, date2: Date) {
|
||||
const diffTime = Math.abs(date2.getTime() - date1.getTime());
|
||||
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
|
||||
export function getLocale() {
|
||||
if (typeof navigator === 'undefined') {
|
||||
return 'en-US';
|
||||
}
|
||||
|
||||
return navigator.language ?? 'en-US';
|
||||
}
|
||||
|
||||
export function formatDate(date: Date) {
|
||||
return new Intl.DateTimeFormat(getLocale()).format(date);
|
||||
}
|
||||
|
||||
export function formatDateTime(date: Date) {
|
||||
return new Intl.DateTimeFormat(getLocale(), {
|
||||
day: 'numeric',
|
||||
month: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
}).format(date);
|
||||
}
|
||||
6
apps/dashboard/src/utils/getters.ts
Normal file
6
apps/dashboard/src/utils/getters.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { IServiceProfile } from '@mixan/db';
|
||||
|
||||
export function getProfileName(profile: IServiceProfile | undefined | null) {
|
||||
if (!profile) return 'No profile';
|
||||
return [profile.first_name, profile.last_name].filter(Boolean).join(' ');
|
||||
}
|
||||
26
apps/dashboard/src/utils/math.ts
Normal file
26
apps/dashboard/src/utils/math.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { isNumber } from 'mathjs';
|
||||
|
||||
export const round = (num: number, decimals = 2) => {
|
||||
const factor = Math.pow(10, decimals);
|
||||
return Math.round((num + Number.EPSILON) * factor) / factor;
|
||||
};
|
||||
|
||||
export const average = (arr: (number | null)[]) => {
|
||||
const filtered = arr.filter(
|
||||
(n): n is number =>
|
||||
isNumber(n) && !Number.isNaN(n) && Number.isFinite(n) && n !== 0
|
||||
);
|
||||
const avg = filtered.reduce((p, c) => p + c, 0) / filtered.length;
|
||||
return Number.isNaN(avg) ? 0 : avg;
|
||||
};
|
||||
|
||||
export const sum = (arr: (number | null)[]): number =>
|
||||
round(arr.filter(isNumber).reduce((acc, item) => acc + item, 0));
|
||||
|
||||
export const min = (arr: (number | null)[]): number =>
|
||||
Math.min(...arr.filter(isNumber));
|
||||
|
||||
export const max = (arr: (number | null)[]): number =>
|
||||
Math.max(...arr.filter(isNumber));
|
||||
|
||||
export const isFloat = (n: number) => n % 1 !== 0;
|
||||
21
apps/dashboard/src/utils/meta.ts
Normal file
21
apps/dashboard/src/utils/meta.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
const title = 'Openpanel.dev | An open-source alternative to Mixpanel';
|
||||
const description =
|
||||
'Unlock actionable insights effortlessly with Insightful, the open-source analytics library that combines the power of Mixpanel with the simplicity of Plausible. Enjoy a unified overview, predictable pricing, and a vibrant community. Join us in democratizing analytics today!';
|
||||
|
||||
export const defaultMeta: Metadata = {
|
||||
title,
|
||||
description,
|
||||
openGraph: {
|
||||
title,
|
||||
images: [
|
||||
{
|
||||
url: 'https://openpanel.dev/ogimage.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: title,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
18
apps/dashboard/src/utils/slug.ts
Normal file
18
apps/dashboard/src/utils/slug.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import _slugify from 'slugify';
|
||||
|
||||
const slugify = (str: string) => {
|
||||
return _slugify(
|
||||
str
|
||||
.replace('å', 'a')
|
||||
.replace('ä', 'a')
|
||||
.replace('ö', 'o')
|
||||
.replace('Å', 'A')
|
||||
.replace('Ä', 'A')
|
||||
.replace('Ö', 'O'),
|
||||
{ lower: true, strict: true, trim: true }
|
||||
);
|
||||
};
|
||||
|
||||
export function slug(str: string): string {
|
||||
return slugify(str);
|
||||
}
|
||||
17
apps/dashboard/src/utils/theme.ts
Normal file
17
apps/dashboard/src/utils/theme.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import resolveConfig from 'tailwindcss/resolveConfig';
|
||||
|
||||
import tailwinConfig from '../../tailwind.config';
|
||||
|
||||
export const resolvedTailwindConfig = resolveConfig(tailwinConfig);
|
||||
|
||||
export const theme = resolvedTailwindConfig.theme as Record<string, any>;
|
||||
|
||||
export function getChartColor(index: number): string {
|
||||
const colors = theme?.colors ?? {};
|
||||
const chartColors: string[] = Object.keys(colors)
|
||||
.filter((key) => key.startsWith('chart-'))
|
||||
.map((key) => colors[key])
|
||||
.filter((item): item is string => typeof item === 'string');
|
||||
|
||||
return chartColors[index % chartColors.length]!;
|
||||
}
|
||||
6
apps/dashboard/src/utils/truncate.ts
Normal file
6
apps/dashboard/src/utils/truncate.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export function truncate(str: string, len: number) {
|
||||
if (str.length <= len) {
|
||||
return str;
|
||||
}
|
||||
return str.slice(0, len) + '...';
|
||||
}
|
||||
Reference in New Issue
Block a user