feat: migrate auth from supabase to better auth (#596)
* feat: add README for @cio/db package and remove existingAccounts.json * load session, load profile and organization, add create profile hook * chore: cache session request The trick was passing all the cookies to the backend. Previously I was only passing the better-auth.session_token and not better-auth.session_data. Read about the difference here https://www.better-auth.com/docs/concepts/cookies#custom-cookies * feat: login, logout, onboarding, verify email, reset password. * feat: complete change email and email verification * feat: standardise how we make rpc calls and create org endpoints * fix ui errors * fix: handle potential undefined customerId and standardize avatar URL property * refactor: standardize custom domain handling and update telegram chat ID references * chore: add tailwind prefix to @cio/ui this fixed the media query issues because @cio/ui classes were overriding this dashboard tailwind build * chore: clean up org sidebar * chore: persist mode state * feat: implement order breadcrumbs * chore: upgrade to better auth 1.4 * chore: address common auth flow bugs and setup app for others to setup locally.
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
data-chart={chartId}
|
||||
data-slot="chart"
|
||||
class={cn(
|
||||
'flex aspect-video justify-center overflow-visible text-xs',
|
||||
'ui:flex ui:justify-center ui:overflow-visible ui:text-xs aspect-video',
|
||||
// Overrides
|
||||
//
|
||||
// Stroke around dots/marks when hovering
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { THEMES, type ChartConfig } from "./chart-utils.js";
|
||||
import { THEMES, type ChartConfig } from './chart-utils.js';
|
||||
|
||||
let { id, config }: { id: string; config: ChartConfig } = $props();
|
||||
let { id, config }: { id: string; config: ChartConfig } = $props();
|
||||
|
||||
const colorConfig = $derived(
|
||||
config ? Object.entries(config).filter(([, config]) => config.theme || config.color) : null
|
||||
);
|
||||
const colorConfig = $derived(
|
||||
config ? Object.entries(config).filter(([, config]) => config.theme || config.color) : null
|
||||
);
|
||||
|
||||
const themeContents = $derived.by(() => {
|
||||
if (!colorConfig || !colorConfig.length) return;
|
||||
const themeContents = $derived.by(() => {
|
||||
if (!colorConfig || !colorConfig.length) return;
|
||||
|
||||
const themeContents = [];
|
||||
for (let [_theme, prefix] of Object.entries(THEMES)) {
|
||||
let content = `${prefix} [data-chart=${id}] {\n`;
|
||||
const color = colorConfig.map(([key, itemConfig]) => {
|
||||
const theme = _theme as keyof typeof itemConfig.theme;
|
||||
const color = itemConfig.theme?.[theme] || itemConfig.color;
|
||||
return color ? `\t--color-${key}: ${color};` : null;
|
||||
});
|
||||
const themeContents = [];
|
||||
for (let [_theme, prefix] of Object.entries(THEMES)) {
|
||||
let content = `${prefix} [data-chart=${id}] {\n`;
|
||||
const color = colorConfig.map(([key, itemConfig]) => {
|
||||
const theme = _theme as keyof typeof itemConfig.theme;
|
||||
const color = itemConfig.theme?.[theme] || itemConfig.color;
|
||||
return color ? `\t--color-${key}: ${color};` : null;
|
||||
});
|
||||
|
||||
content += color.join("\n") + "\n}";
|
||||
content += color.join('\n') + '\n}';
|
||||
|
||||
themeContents.push(content);
|
||||
}
|
||||
themeContents.push(content);
|
||||
}
|
||||
|
||||
return themeContents.join("\n");
|
||||
});
|
||||
return themeContents.join('\n');
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if themeContents}
|
||||
{#key id}
|
||||
<svelte:element this={"style"}>
|
||||
{themeContents}
|
||||
</svelte:element>
|
||||
{/key}
|
||||
{#key id}
|
||||
<svelte:element this={'style'}>
|
||||
{themeContents}
|
||||
</svelte:element>
|
||||
{/key}
|
||||
{/if}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
{#snippet TooltipLabel()}
|
||||
{#if formattedLabel}
|
||||
<div class={cn('font-medium', labelClassName)}>
|
||||
<div class={cn('ui:font-medium', labelClassName)}>
|
||||
{#if typeof formattedLabel === 'function'}
|
||||
{@render formattedLabel()}
|
||||
{:else}
|
||||
@@ -86,7 +86,7 @@
|
||||
<TooltipPrimitive.Root variant="none">
|
||||
<div
|
||||
class={cn(
|
||||
'border-border/50 bg-background grid min-w-[9rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl',
|
||||
'ui:border-border/50 ui:bg-background ui:grid ui:min-w-[9rem] ui:items-start ui:gap-1.5 ui:rounded-lg ui:border ui:px-2.5 ui:py-1.5 ui:text-xs ui:shadow-xl',
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
@@ -94,14 +94,14 @@
|
||||
{#if !nestLabel}
|
||||
{@render TooltipLabel()}
|
||||
{/if}
|
||||
<div class="grid gap-1.5">
|
||||
<div class="ui:grid ui:gap-1.5">
|
||||
{#each tooltipCtx.payload as item, i (item.key + i)}
|
||||
{@const key = `${nameKey || item.key || item.name || 'value'}`}
|
||||
{@const itemConfig = getPayloadConfigFromPayload(chart.config, item, key)}
|
||||
{@const indicatorColor = color || item.payload?.color || item.color}
|
||||
<div
|
||||
class={cn(
|
||||
'[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5',
|
||||
'ui:[&>svg]:text-muted-foreground ui:flex ui:w-full ui:flex-wrap ui:items-stretch ui:gap-2 ui:[&>svg]:size-2.5',
|
||||
indicator === 'dot' && 'items-center'
|
||||
)}
|
||||
>
|
||||
@@ -119,27 +119,30 @@
|
||||
{:else if !hideIndicator}
|
||||
<div
|
||||
style="--color-bg: {indicatorColor}; --color-border: {indicatorColor};"
|
||||
class={cn('border-(--color-border) bg-(--color-bg) shrink-0 rounded-[2px]', {
|
||||
'size-2.5': indicator === 'dot',
|
||||
'h-full w-1': indicator === 'line',
|
||||
'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',
|
||||
'my-0.5': nestLabel && indicator === 'dashed'
|
||||
class={cn('ui:border-(--color-border) ui:bg-(--color-bg) ui:shrink-0 ui:rounded-[2px]', {
|
||||
'ui:size-2.5': indicator === 'dot',
|
||||
'ui:h-full ui:w-1': indicator === 'line',
|
||||
'ui:w-0 ui:border-[1.5px] ui:border-dashed ui:bg-transparent': indicator === 'dashed',
|
||||
'ui:my-0.5': nestLabel && indicator === 'dashed'
|
||||
})}
|
||||
></div>
|
||||
{/if}
|
||||
<div
|
||||
class={cn('flex flex-1 shrink-0 justify-between leading-none', nestLabel ? 'items-end' : 'items-center')}
|
||||
class={cn(
|
||||
'ui:flex ui:flex-1 ui:shrink-0 ui:justify-between ui:leading-none',
|
||||
nestLabel ? 'ui:items-end' : 'ui:items-center'
|
||||
)}
|
||||
>
|
||||
<div class="grid gap-1.5">
|
||||
<div class="ui:grid ui:gap-1.5">
|
||||
{#if nestLabel}
|
||||
{@render TooltipLabel()}
|
||||
{/if}
|
||||
<span class="text-muted-foreground">
|
||||
<span class="ui:text-muted-foreground">
|
||||
{itemConfig?.label || item.name}
|
||||
</span>
|
||||
</div>
|
||||
{#if item.value !== undefined}
|
||||
<span class="text-foreground font-mono font-medium tabular-nums">
|
||||
<span class="ui:text-foreground ui:font-mono ui:font-medium tabular-nums">
|
||||
{item.value.toLocaleString()}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
@@ -1,66 +1,57 @@
|
||||
import type { Tooltip } from "layerchart";
|
||||
import { getContext, setContext, type Component, type ComponentProps, type Snippet } from "svelte";
|
||||
import type { Tooltip } from 'layerchart';
|
||||
import { getContext, setContext, type Component, type ComponentProps, type Snippet } from 'svelte';
|
||||
|
||||
export const THEMES = { light: "", dark: ".dark" } as const;
|
||||
export const THEMES = { light: '', dark: '.dark' } as const;
|
||||
|
||||
export type ChartConfig = {
|
||||
[k in string]: {
|
||||
label?: string;
|
||||
icon?: Component;
|
||||
} & (
|
||||
| { color?: string; theme?: never }
|
||||
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
||||
);
|
||||
[k in string]: {
|
||||
label?: string;
|
||||
icon?: Component;
|
||||
} & ({ color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> });
|
||||
};
|
||||
|
||||
export type ExtractSnippetParams<T> = T extends Snippet<[infer P]> ? P : never;
|
||||
|
||||
export type TooltipPayload = ExtractSnippetParams<
|
||||
ComponentProps<typeof Tooltip.Root>["children"]
|
||||
>["payload"][number];
|
||||
export type TooltipPayload = ExtractSnippetParams<ComponentProps<typeof Tooltip.Root>['children']>['payload'][number];
|
||||
|
||||
// Helper to extract item config from a payload.
|
||||
export function getPayloadConfigFromPayload(
|
||||
config: ChartConfig,
|
||||
payload: TooltipPayload,
|
||||
key: string
|
||||
) {
|
||||
if (typeof payload !== "object" || payload === null) return undefined;
|
||||
export function getPayloadConfigFromPayload(config: ChartConfig, payload: TooltipPayload, key: string) {
|
||||
if (typeof payload !== 'object' || payload === null) return undefined;
|
||||
|
||||
const payloadPayload =
|
||||
"payload" in payload && typeof payload.payload === "object" && payload.payload !== null
|
||||
? payload.payload
|
||||
: undefined;
|
||||
const payloadPayload =
|
||||
'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null
|
||||
? payload.payload
|
||||
: undefined;
|
||||
|
||||
let configLabelKey: string = key;
|
||||
let configLabelKey: string = key;
|
||||
|
||||
if (payload.key === key) {
|
||||
configLabelKey = payload.key;
|
||||
} else if (payload.name === key) {
|
||||
configLabelKey = payload.name;
|
||||
} else if (key in payload && typeof payload[key as keyof typeof payload] === "string") {
|
||||
configLabelKey = payload[key as keyof typeof payload] as string;
|
||||
} else if (
|
||||
payloadPayload !== undefined &&
|
||||
key in payloadPayload &&
|
||||
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
|
||||
) {
|
||||
configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;
|
||||
}
|
||||
if (payload.key === key) {
|
||||
configLabelKey = payload.key;
|
||||
} else if (payload.name === key) {
|
||||
configLabelKey = payload.name;
|
||||
} else if (key in payload && typeof payload[key as keyof typeof payload] === 'string') {
|
||||
configLabelKey = payload[key as keyof typeof payload] as string;
|
||||
} else if (
|
||||
payloadPayload !== undefined &&
|
||||
key in payloadPayload &&
|
||||
typeof payloadPayload[key as keyof typeof payloadPayload] === 'string'
|
||||
) {
|
||||
configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;
|
||||
}
|
||||
|
||||
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
|
||||
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
|
||||
}
|
||||
|
||||
type ChartContextValue = {
|
||||
config: ChartConfig;
|
||||
config: ChartConfig;
|
||||
};
|
||||
|
||||
const chartContextKey = Symbol("chart-context");
|
||||
const chartContextKey = Symbol('chart-context');
|
||||
|
||||
export function setChartContext(value: ChartContextValue) {
|
||||
return setContext(chartContextKey, value);
|
||||
return setContext(chartContextKey, value);
|
||||
}
|
||||
|
||||
export function useChart() {
|
||||
return getContext<ChartContextValue>(chartContextKey);
|
||||
return getContext<ChartContextValue>(chartContextKey);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user