feat: revenue tracking

* wip

* wip

* wip

* wip

* show revenue better on overview

* align realtime and overview counters

* update revenue docs

* always return device id

* add project settings, improve projects charts,

* fix: comments

* fixes

* fix migration

* ignore sql files

* fix comments
This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-19 14:27:34 +01:00
committed by GitHub
parent d61cbf6f2c
commit 790801b728
58 changed files with 2191 additions and 23691 deletions

View File

@@ -1,9 +1,20 @@
import type { IInterval } from '@openpanel/validation';
export function formatDateInterval(interval: IInterval, date: Date): string {
export function formatDateInterval(options: {
interval: IInterval;
date: Date;
short: boolean;
}): string {
const { interval, date, short } = options;
try {
if (interval === 'hour' || interval === 'minute') {
return new Intl.DateTimeFormat('en-GB', {
...(!short
? {
month: '2-digit',
day: '2-digit',
}
: {}),
hour: '2-digit',
minute: '2-digit',
}).format(date);
@@ -35,10 +46,13 @@ export function formatDateInterval(interval: IInterval, date: Date): string {
}
}
export function useFormatDateInterval(interval: IInterval) {
export function useFormatDateInterval(options: {
interval: IInterval;
short: boolean;
}) {
return (date: Date | string) =>
formatDateInterval(
interval,
typeof date === 'string' ? new Date(date) : date,
);
formatDateInterval({
...options,
date: typeof date === 'string' ? new Date(date) : date,
});
}

View File

@@ -33,7 +33,35 @@ export const shortNumber =
export const formatCurrency =
(locale: string) =>
(amount: number, currency = 'USD') => {
(
amount: number,
options?: {
currency?: string;
short?: boolean;
},
) => {
const short = options?.short ?? false;
const currency = options?.currency ?? 'USD';
if (short) {
// Use compact notation for short format (e.g., "73K $")
const formatter = new Intl.NumberFormat(locale, {
notation: 'compact',
minimumFractionDigits: 0,
maximumFractionDigits: 1,
});
const formatted = formatter.format(amount);
// Get currency symbol
const currencyFormatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
const parts = currencyFormatter.formatToParts(0);
const symbol =
parts.find((part) => part.type === 'currency')?.value || '$';
return `${formatted} ${symbol}`;
}
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,