added tooling (eslint, typescript and prettier)
This commit is contained in:
@@ -4,16 +4,15 @@
|
||||
*
|
||||
* We also create a few inference helpers for input and output types.
|
||||
*/
|
||||
import { type TRPCClientErrorBase, httpLink, loggerLink } from "@trpc/client";
|
||||
import { createTRPCNext } from "@trpc/next";
|
||||
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
|
||||
import superjson from "superjson";
|
||||
|
||||
import { type AppRouter } from "@/server/api/root";
|
||||
import { toast } from "@/components/ui/use-toast";
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
import { type AppRouter } from '@/server/api/root';
|
||||
import { httpLink, loggerLink, type TRPCClientErrorBase } from '@trpc/client';
|
||||
import { createTRPCNext } from '@trpc/next';
|
||||
import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server';
|
||||
import superjson from 'superjson';
|
||||
|
||||
const getBaseUrl = () => {
|
||||
if (typeof window !== "undefined") return ""; // browser should use relative url
|
||||
if (typeof window !== 'undefined') return ''; // browser should use relative url
|
||||
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
|
||||
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
|
||||
};
|
||||
@@ -28,9 +27,9 @@ export const api = createTRPCNext<AppRouter>({
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
enabled: typeof window !== "undefined",
|
||||
enabled: typeof window !== 'undefined',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Transformer used for data de-serialization from the server.
|
||||
@@ -47,8 +46,8 @@ export const api = createTRPCNext<AppRouter>({
|
||||
links: [
|
||||
loggerLink({
|
||||
enabled: (opts) =>
|
||||
process.env.NODE_ENV === "development" ||
|
||||
(opts.direction === "down" && opts.result instanceof Error),
|
||||
process.env.NODE_ENV === 'development' ||
|
||||
(opts.direction === 'down' && opts.result instanceof Error),
|
||||
}),
|
||||
httpLink({
|
||||
url: `${getBaseUrl()}/api/trpc`,
|
||||
@@ -78,10 +77,9 @@ export type RouterInputs = inferRouterInputs<AppRouter>;
|
||||
*/
|
||||
export type RouterOutputs = inferRouterOutputs<AppRouter>;
|
||||
|
||||
|
||||
export function handleError(error: TRPCClientErrorBase<any>) {
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: error.message,
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { toast } from "@/components/ui/use-toast"
|
||||
import { toast } from '@/components/ui/use-toast';
|
||||
|
||||
export function clipboard(value: string | number) {
|
||||
navigator.clipboard.writeText(value.toString())
|
||||
navigator.clipboard.writeText(value.toString());
|
||||
toast({
|
||||
title: "Copied to clipboard",
|
||||
title: 'Copied to clipboard',
|
||||
description: value.toString(),
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { clsx, type ClassValue } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
export const operators = {
|
||||
is: "Is",
|
||||
isNot: "Is not",
|
||||
contains: "Contains",
|
||||
doesNotContain: "Not contains",
|
||||
is: 'Is',
|
||||
isNot: 'Is not',
|
||||
contains: 'Contains',
|
||||
doesNotContain: 'Not contains',
|
||||
};
|
||||
|
||||
export const chartTypes = {
|
||||
linear: "Linear",
|
||||
bar: "Bar",
|
||||
pie: "Pie",
|
||||
metric: "Metric",
|
||||
area: "Area",
|
||||
linear: 'Linear',
|
||||
bar: 'Bar',
|
||||
pie: 'Pie',
|
||||
metric: 'Metric',
|
||||
area: 'Area',
|
||||
};
|
||||
|
||||
export const intervals = {
|
||||
minute: "Minute",
|
||||
day: "Day",
|
||||
hour: "Hour",
|
||||
month: "Month",
|
||||
minute: 'Minute',
|
||||
day: 'Day',
|
||||
hour: 'Hour',
|
||||
month: 'Month',
|
||||
};
|
||||
|
||||
export const alphabetIds = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
] as const;
|
||||
|
||||
export const timeRanges = [
|
||||
{ range: 0.3, title: "30m" },
|
||||
{ range: 0.6, title: "1h" },
|
||||
{ range: 0, title: "Today" },
|
||||
{ range: 1, title: "24h" },
|
||||
{ range: 7, title: "7d" },
|
||||
{ range: 14, title: "14d" },
|
||||
{ range: 30, title: "30d" },
|
||||
{ range: 90, title: "3mo" },
|
||||
{ range: 180, title: "6mo" },
|
||||
{ range: 365, title: "1y" },
|
||||
{ range: 0.3, title: '30m' },
|
||||
{ range: 0.6, title: '1h' },
|
||||
{ range: 0, title: 'Today' },
|
||||
{ range: 1, title: '24h' },
|
||||
{ range: 7, title: '7d' },
|
||||
{ range: 14, title: '14d' },
|
||||
{ range: 30, title: '30d' },
|
||||
{ range: 90, title: '3mo' },
|
||||
{ range: 180, title: '6mo' },
|
||||
{ range: 365, title: '1y' },
|
||||
] as const;
|
||||
|
||||
@@ -10,11 +10,11 @@ export function dateDifferanceInDays(date1: Date, date2: Date) {
|
||||
}
|
||||
|
||||
export function getLocale() {
|
||||
if (typeof navigator === "undefined") {
|
||||
return "en-US";
|
||||
if (typeof navigator === 'undefined') {
|
||||
return 'en-US';
|
||||
}
|
||||
|
||||
return navigator.language ?? "en-US";
|
||||
return navigator.language ?? 'en-US';
|
||||
}
|
||||
|
||||
export function formatDate(date: Date) {
|
||||
@@ -23,10 +23,10 @@ export function formatDate(date: Date) {
|
||||
|
||||
export function formatDateTime(date: Date) {
|
||||
return new Intl.DateTimeFormat(getLocale(), {
|
||||
day: "numeric",
|
||||
month: "numeric",
|
||||
year: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
day: 'numeric',
|
||||
month: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { type IChartRange } from "@/types";
|
||||
import { timeRanges } from "./constants";
|
||||
import { type IChartRange } from '@/types';
|
||||
|
||||
import { timeRanges } from './constants';
|
||||
|
||||
export function getRangeLabel(range: IChartRange) {
|
||||
return timeRanges.find(
|
||||
(item) => item.range === range,
|
||||
)?.title ?? null
|
||||
}
|
||||
return timeRanges.find((item) => item.range === range)?.title ?? null;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
export function toDots(
|
||||
obj: Record<string, unknown>,
|
||||
path = "",
|
||||
path = ''
|
||||
): Record<string, number | string | boolean> {
|
||||
return Object.entries(obj).reduce((acc, [key, value]) => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
return {
|
||||
...acc,
|
||||
...toDots(value as Record<string, unknown>, `${path}${key}.`),
|
||||
@@ -15,4 +15,4 @@ export function toDots(
|
||||
[`${path}${key}`]: value,
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import _slugify from 'slugify'
|
||||
import _slugify from 'slugify';
|
||||
|
||||
const slugify = (str: string) => {
|
||||
return _slugify(
|
||||
@@ -9,10 +9,10 @@ const slugify = (str: string) => {
|
||||
.replace('Å', 'A')
|
||||
.replace('Ä', 'A')
|
||||
.replace('Ö', 'O'),
|
||||
{ lower: true, strict: true, trim: true },
|
||||
)
|
||||
}
|
||||
{ lower: true, strict: true, trim: true }
|
||||
);
|
||||
};
|
||||
|
||||
export function slug(str: string): string {
|
||||
return slugify(str)
|
||||
return slugify(str);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import resolveConfig from "tailwindcss/resolveConfig";
|
||||
import tailwinConfig from "../../tailwind.config";
|
||||
import resolveConfig from 'tailwindcss/resolveConfig';
|
||||
|
||||
import tailwinConfig from '../../tailwind.config';
|
||||
|
||||
// @ts-expect-error
|
||||
const config = resolveConfig(tailwinConfig);
|
||||
|
||||
@@ -7,7 +9,7 @@ export const theme = config.theme as any;
|
||||
|
||||
export function getChartColor(index: number): string {
|
||||
const chartColors: string[] = Object.keys(theme?.colors ?? {})
|
||||
.filter((key) => key.startsWith("chart-"))
|
||||
.filter((key) => key.startsWith('chart-'))
|
||||
.map((key) => theme.colors[key] as string);
|
||||
|
||||
return chartColors[index % chartColors.length]!;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
import { operators, chartTypes, intervals } from "./constants";
|
||||
import { z } from 'zod';
|
||||
|
||||
import { chartTypes, intervals, operators } from './constants';
|
||||
|
||||
function objectToZodEnums<K extends string>(obj: Record<K, any>): [K, ...K[]] {
|
||||
const [firstKey, ...otherKeys] = Object.keys(obj) as K[];
|
||||
@@ -9,14 +10,14 @@ function objectToZodEnums<K extends string>(obj: Record<K, any>): [K, ...K[]] {
|
||||
export const zChartEvent = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
segment: z.enum(["event", "user"]),
|
||||
segment: z.enum(['event', 'user']),
|
||||
filters: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
operator: z.enum(objectToZodEnums(operators)),
|
||||
value: z.array(z.string().or(z.number()).or(z.boolean()).or(z.null())),
|
||||
}),
|
||||
})
|
||||
),
|
||||
});
|
||||
export const zChartBreakdown = z.object({
|
||||
|
||||
Reference in New Issue
Block a user