move back 😏

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-03-19 23:23:14 +01:00
parent e4643ce63e
commit ffed9bfaa5
249 changed files with 0 additions and 0 deletions

View 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(),
});
}

View 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));
}

View File

@@ -0,0 +1,26 @@
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);
}

View File

@@ -0,0 +1,35 @@
import { db } from '@openpanel/db';
import { slug } from './slug';
export async function getId(tableName: 'project' | 'dashboard', name: string) {
const newId = slug(name);
if (!db[tableName]) {
throw new Error('Table does not exists');
}
if (!('findUnique' in db[tableName])) {
throw new Error('findUnique does not exists');
}
// @ts-expect-error
const existingProject = await db[tableName].findUnique({
where: {
id: newId,
},
});
function random(str: string) {
const numbers = Math.floor(1000 + Math.random() * 9000);
if (str.match(/-\d{4}$/g)) {
return str.replace(/-\d{4}$/g, `-${numbers}`);
}
return `${str}-${numbers}`;
}
if (existingProject) {
return getId(tableName, random(name));
}
return newId;
}

View 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;

View 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,
},
],
},
};

View 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);
}

View 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]!;
}

View File

@@ -0,0 +1,6 @@
export function truncate(str: string, len: number) {
if (str.length <= len) {
return str;
}
return str.slice(0, len) + '...';
}