Perf improvements and billing updates
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
import { GlobalLoader } from '@kit/ui/global-loader';
|
import { GlobalLoader } from '@kit/ui/global-loader';
|
||||||
|
|
||||||
export default GlobalLoader;
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export default withI18n(GlobalLoader);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export function TeamAccountCheckoutForm(params: { accountId: string }) {
|
|||||||
if (checkoutToken) {
|
if (checkoutToken) {
|
||||||
return (
|
return (
|
||||||
<EmbeddedCheckout
|
<EmbeddedCheckout
|
||||||
|
load
|
||||||
checkoutToken={checkoutToken}
|
checkoutToken={checkoutToken}
|
||||||
provider={billingConfig.provider}
|
provider={billingConfig.provider}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,11 +16,18 @@ interface SessionPageProps {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const LazyEmbeddedCheckout = dynamic(async () => {
|
const LazyEmbeddedCheckout = dynamic(
|
||||||
const { EmbeddedCheckout } = await import('@kit/billing-gateway/components');
|
async () => {
|
||||||
|
const { EmbeddedCheckout } = await import(
|
||||||
|
'@kit/billing-gateway/components'
|
||||||
|
);
|
||||||
|
|
||||||
return EmbeddedCheckout;
|
return EmbeddedCheckout;
|
||||||
});
|
},
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
async function ReturnStripeSessionPage({ searchParams }: SessionPageProps) {
|
async function ReturnStripeSessionPage({ searchParams }: SessionPageProps) {
|
||||||
const { customerEmail, checkoutToken } = await loadCheckoutSession(
|
const { customerEmail, checkoutToken } = await loadCheckoutSession(
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
import { GlobalLoader } from '@kit/ui/global-loader';
|
import { GlobalLoader } from '@kit/ui/global-loader';
|
||||||
|
|
||||||
export default GlobalLoader;
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export default withI18n(GlobalLoader);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
import { GlobalLoader } from '@kit/ui/global-loader';
|
import { GlobalLoader } from '@kit/ui/global-loader';
|
||||||
|
|
||||||
export default GlobalLoader;
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export default withI18n(GlobalLoader);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function SiteNavigation() {
|
|||||||
<>
|
<>
|
||||||
<div className={'hidden items-center lg:flex'}>
|
<div className={'hidden items-center lg:flex'}>
|
||||||
<NavigationMenu>
|
<NavigationMenu>
|
||||||
<NavigationMenuList className={'space-x-2.5'}>
|
<NavigationMenuList className={'space-x-3'}>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
<Link className={className} href={links.Blog.path}>
|
<Link className={className} href={links.Blog.path}>
|
||||||
{links.Blog.label}
|
{links.Blog.label}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Post from '~/(marketing)/blog/_components/post';
|
|||||||
import appConfig from '~/config/app.config';
|
import appConfig from '~/config/app.config';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
export async function generateMetadata({
|
export function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: { slug: string };
|
params: { slug: string };
|
||||||
@@ -49,7 +49,7 @@ export async function generateMetadata({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function BlogPost({ params }: { params: { slug: string } }) {
|
function BlogPost({ params }: { params: { slug: string } }) {
|
||||||
const post = allPosts.find((post) => post.slug === params.slug);
|
const post = allPosts.find((post) => post.slug === params.slug);
|
||||||
|
|
||||||
if (!post) {
|
if (!post) {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import React from 'react';
|
import dynamic from 'next/dynamic';
|
||||||
|
|
||||||
import type { Post as PostType } from 'contentlayer/generated';
|
import type { Post as PostType } from 'contentlayer/generated';
|
||||||
|
|
||||||
import { Mdx } from '@kit/ui/mdx';
|
|
||||||
|
|
||||||
import { PostHeader } from './post-header';
|
import { PostHeader } from './post-header';
|
||||||
|
|
||||||
|
const Mdx = dynamic(() =>
|
||||||
|
import('@kit/ui/mdx').then((mod) => ({ default: mod.Mdx })),
|
||||||
|
);
|
||||||
|
|
||||||
export const Post: React.FC<{
|
export const Post: React.FC<{
|
||||||
post: PostType;
|
post: PostType;
|
||||||
content: string;
|
content: string;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
import { GlobalLoader } from '@kit/ui/global-loader';
|
import { GlobalLoader } from '@kit/ui/global-loader';
|
||||||
|
|
||||||
export default GlobalLoader;
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export default withI18n(GlobalLoader);
|
||||||
|
|||||||
5
apps/web/app/loading.tsx
Normal file
5
apps/web/app/loading.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { GlobalLoader } from '@kit/ui/global-loader';
|
||||||
|
|
||||||
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export default withI18n(GlobalLoader);
|
||||||
@@ -2,6 +2,7 @@ import Link from 'next/link';
|
|||||||
|
|
||||||
import { ArrowLeft } from 'lucide-react';
|
import { ArrowLeft } from 'lucide-react';
|
||||||
|
|
||||||
|
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
|
||||||
import { Button } from '@kit/ui/button';
|
import { Button } from '@kit/ui/button';
|
||||||
import { Heading } from '@kit/ui/heading';
|
import { Heading } from '@kit/ui/heading';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
@@ -14,10 +15,16 @@ export const metadata = {
|
|||||||
title: `Page not found - ${appConfig.name}`,
|
title: `Page not found - ${appConfig.name}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotFoundPage = () => {
|
const NotFoundPage = async () => {
|
||||||
|
const client = getSupabaseServerComponentClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { session },
|
||||||
|
} = await client.auth.getSession();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'flex h-screen flex-1 flex-col'}>
|
<div className={'flex h-screen flex-1 flex-col'}>
|
||||||
<SiteHeader session={null} />
|
<SiteHeader session={session} />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
|
|||||||
@@ -143,12 +143,14 @@ function getPatterns() {
|
|||||||
const supabase = createMiddlewareClient(req, res);
|
const supabase = createMiddlewareClient(req, res);
|
||||||
const { data, error } = await supabase.auth.getSession();
|
const { data, error } = await supabase.auth.getSession();
|
||||||
const origin = req.nextUrl.origin;
|
const origin = req.nextUrl.origin;
|
||||||
|
const next = req.nextUrl.pathname;
|
||||||
|
|
||||||
// If user is not logged in, redirect to sign in page.
|
// If user is not logged in, redirect to sign in page.
|
||||||
if (!data.session || error) {
|
if (!data.session || error) {
|
||||||
return NextResponse.redirect(
|
const signIn = pathsConfig.auth.signIn;
|
||||||
new URL(pathsConfig.auth.signIn, origin).href,
|
const redirectPath = `${signIn}?next=${next}`;
|
||||||
);
|
|
||||||
|
return NextResponse.redirect(new URL(redirectPath, origin).href);
|
||||||
}
|
}
|
||||||
|
|
||||||
const requiresMultiFactorAuthentication =
|
const requiresMultiFactorAuthentication =
|
||||||
|
|||||||
@@ -3,35 +3,49 @@ import withBundleAnalyzer from '@next/bundle-analyzer';
|
|||||||
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
|
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
|
||||||
const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
||||||
|
|
||||||
|
const INTERNAL_PACKAGES = [
|
||||||
|
'@kit/ui',
|
||||||
|
'@kit/auth',
|
||||||
|
'@kit/accounts',
|
||||||
|
'@kit/team-accounts',
|
||||||
|
'@kit/shared',
|
||||||
|
'@kit/supabase',
|
||||||
|
'@kit/i18n',
|
||||||
|
'@kit/mailers',
|
||||||
|
'@kit/billing',
|
||||||
|
'@kit/billing-gateway',
|
||||||
|
'@kit/stripe',
|
||||||
|
];
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
swcMinify: true,
|
||||||
/** Enables hot reloading for local packages without a build step */
|
/** Enables hot reloading for local packages without a build step */
|
||||||
transpilePackages: [
|
transpilePackages: INTERNAL_PACKAGES,
|
||||||
'@kit/ui',
|
|
||||||
'@kit/auth',
|
|
||||||
'@kit/accounts',
|
|
||||||
'@kit/team-accounts',
|
|
||||||
'@kit/shared',
|
|
||||||
'@kit/supabase',
|
|
||||||
'@kit/i18n',
|
|
||||||
'@kit/mailers',
|
|
||||||
'@kit/billing',
|
|
||||||
'@kit/billing-gateway',
|
|
||||||
'@kit/stripe',
|
|
||||||
],
|
|
||||||
pageExtensions: ['ts', 'tsx'],
|
pageExtensions: ['ts', 'tsx'],
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: getRemotePatterns(),
|
remotePatterns: getRemotePatterns(),
|
||||||
},
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
mdxRs: true,
|
mdxRs: true,
|
||||||
optimizePackageImports: []
|
optimizePackageImports: [
|
||||||
|
'recharts',
|
||||||
|
'lucide-react',
|
||||||
|
'@radix-ui/react-icons',
|
||||||
|
'@radix-ui/react-avatar',
|
||||||
|
'@radix-ui/react-select',
|
||||||
|
'date-fns',
|
||||||
|
...INTERNAL_PACKAGES,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
modularizeImports: {
|
modularizeImports: {
|
||||||
"lucide-react": {
|
'lucide-react': {
|
||||||
transform: "lucide-react/dist/esm/icons/{{ kebabCase member }}",
|
transform: 'lucide-react/dist/esm/icons/{{ kebabCase member }}',
|
||||||
}
|
},
|
||||||
|
lodash: {
|
||||||
|
transform: 'lodash/{{member}}',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
/** We already do linting and typechecking as separate tasks in CI */
|
/** We already do linting and typechecking as separate tasks in CI */
|
||||||
eslint: { ignoreDuringBuilds: true },
|
eslint: { ignoreDuringBuilds: true },
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
"name": "web",
|
"name": "web",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "ANALYZE=true pnpm run build",
|
"analyze": "ANALYZE=true pnpm run build",
|
||||||
"build": "pnpm with-env next build",
|
"build": "pnpm with-env next build",
|
||||||
"clean": "git clean -xdf .next .turbo node_modules",
|
"clean": "git clean -xdf .next .turbo node_modules",
|
||||||
"dev": "pnpm with-env next dev",
|
"dev": "pnpm with-env next dev --turbo",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"format": "prettier --check \"**/*.{js,cjs,mjs,ts,tsx,md,json}\"",
|
"format": "prettier --check \"**/*.{js,cjs,mjs,ts,tsx,md,json}\"",
|
||||||
"start": "pnpm with-env next start",
|
"start": "pnpm with-env next start",
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
"next-contentlayer": "0.3.4",
|
"next-contentlayer": "0.3.4",
|
||||||
"react-i18next": "^14.1.0",
|
"react-i18next": "^14.1.0",
|
||||||
"date-fns": "^3.2.0",
|
"date-fns": "^3.2.0",
|
||||||
"next": "^14.2.0-canary.41",
|
"next": "canary",
|
||||||
"next-sitemap": "^4.2.3",
|
"next-sitemap": "^4.2.3",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
@@ -60,7 +61,7 @@
|
|||||||
"@kit/prettier-config": "^0.1.0",
|
"@kit/prettier-config": "^0.1.0",
|
||||||
"@kit/tailwind-config": "^0.1.0",
|
"@kit/tailwind-config": "^0.1.0",
|
||||||
"@kit/tsconfig": "^0.1.0",
|
"@kit/tsconfig": "^0.1.0",
|
||||||
"@next/bundle-analyzer": "^14.2.0-canary.41",
|
"@next/bundle-analyzer": "canary",
|
||||||
"@types/mdx": "^2.0.10",
|
"@types/mdx": "^2.0.10",
|
||||||
"@types/node": "^20.11.5",
|
"@types/node": "^20.11.5",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
@@ -81,4 +82,4 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"prettier": "@kit/prettier-config"
|
"prettier": "@kit/prettier-config"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ArrowRightIcon } from '@radix-ui/react-icons';
|
import { ArrowUpRight } from 'lucide-react';
|
||||||
|
|
||||||
import { Button } from '@kit/ui/button';
|
import { Button } from '@kit/ui/button';
|
||||||
import {
|
import {
|
||||||
@@ -15,7 +15,7 @@ export function BillingPortalCard() {
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Manage your Subscription</CardTitle>
|
<CardTitle>Manage your Billing Details</CardTitle>
|
||||||
|
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
You can change your plan or cancel your subscription at any time.
|
You can change your plan or cancel your subscription at any time.
|
||||||
@@ -23,15 +23,13 @@ export function BillingPortalCard() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className={'space-y-2'}>
|
<CardContent className={'space-y-2'}>
|
||||||
<Button className={'w-full'}>
|
<div>
|
||||||
<span>Manage your Billing Settings</span>
|
<Button>
|
||||||
<ArrowRightIcon className={'ml-2 h-4'} />
|
<span>Visit the billing portal</span>
|
||||||
</Button>
|
|
||||||
|
|
||||||
<p className={'text-sm'}>
|
<ArrowUpRight className={'h-4'} />
|
||||||
Visit the billing portal to manage your subscription (update payment
|
</Button>
|
||||||
method, cancel subscription, etc.)
|
</div>
|
||||||
</p>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { Database } from '@kit/supabase/database';
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||||
|
|
||||||
|
export function CurrentPlanAlert(
|
||||||
|
props: React.PropsWithoutRef<{
|
||||||
|
status: Database['public']['Enums']['subscription_status'];
|
||||||
|
}>,
|
||||||
|
) {
|
||||||
|
let variant: 'success' | 'warning' | 'destructive';
|
||||||
|
let text: string;
|
||||||
|
let title: string;
|
||||||
|
|
||||||
|
switch (props.status) {
|
||||||
|
case 'active':
|
||||||
|
variant = 'success';
|
||||||
|
title = 'Active';
|
||||||
|
text = 'Your subscription is active';
|
||||||
|
break;
|
||||||
|
case 'trialing':
|
||||||
|
variant = 'success';
|
||||||
|
title = 'Trial';
|
||||||
|
text = 'You are currently on a trial';
|
||||||
|
break;
|
||||||
|
case 'past_due':
|
||||||
|
variant = 'destructive';
|
||||||
|
title = 'Past Due';
|
||||||
|
text = 'Your subscription payment is past due';
|
||||||
|
break;
|
||||||
|
case 'canceled':
|
||||||
|
variant = 'destructive';
|
||||||
|
title = 'Canceled';
|
||||||
|
text = 'You have canceled your subscription';
|
||||||
|
break;
|
||||||
|
case 'unpaid':
|
||||||
|
variant = 'destructive';
|
||||||
|
title = 'Unpaid';
|
||||||
|
text = 'Your subscription payment is unpaid';
|
||||||
|
break;
|
||||||
|
case 'incomplete':
|
||||||
|
variant = 'warning';
|
||||||
|
title = 'Incomplete';
|
||||||
|
text = 'We are processing your subscription payment';
|
||||||
|
break;
|
||||||
|
case 'incomplete_expired':
|
||||||
|
variant = 'destructive';
|
||||||
|
title = 'Incomplete Expired';
|
||||||
|
text = 'Your subscription payment has expired';
|
||||||
|
break;
|
||||||
|
case 'paused':
|
||||||
|
variant = 'warning';
|
||||||
|
title = 'Paused';
|
||||||
|
text = 'Your subscription is paused';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert variant={variant}>
|
||||||
|
<AlertTitle>{title}</AlertTitle>
|
||||||
|
|
||||||
|
<AlertDescription>{text}</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { Database } from '@kit/supabase/database';
|
||||||
|
import { Badge } from '@kit/ui/badge';
|
||||||
|
|
||||||
|
export function CurrentPlanBadge(
|
||||||
|
props: React.PropsWithoutRef<{
|
||||||
|
status: Database['public']['Enums']['subscription_status'];
|
||||||
|
}>,
|
||||||
|
) {
|
||||||
|
let variant: 'success' | 'warning' | 'destructive';
|
||||||
|
let text: string;
|
||||||
|
|
||||||
|
switch (props.status) {
|
||||||
|
case 'active':
|
||||||
|
variant = 'success';
|
||||||
|
text = 'Active';
|
||||||
|
break;
|
||||||
|
case 'trialing':
|
||||||
|
variant = 'success';
|
||||||
|
text = 'Trialing';
|
||||||
|
break;
|
||||||
|
case 'past_due':
|
||||||
|
variant = 'destructive';
|
||||||
|
text = 'Past due';
|
||||||
|
break;
|
||||||
|
case 'canceled':
|
||||||
|
variant = 'destructive';
|
||||||
|
text = 'Canceled';
|
||||||
|
break;
|
||||||
|
case 'unpaid':
|
||||||
|
variant = 'destructive';
|
||||||
|
text = 'Unpaid';
|
||||||
|
break;
|
||||||
|
case 'incomplete':
|
||||||
|
variant = 'warning';
|
||||||
|
text = 'Incomplete';
|
||||||
|
break;
|
||||||
|
case 'incomplete_expired':
|
||||||
|
variant = 'destructive';
|
||||||
|
text = 'Incomplete expired';
|
||||||
|
break;
|
||||||
|
case 'paused':
|
||||||
|
variant = 'warning';
|
||||||
|
text = 'Paused';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Badge variant={variant}>{text}</Badge>;
|
||||||
|
}
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
import { formatDate } from 'date-fns';
|
import { formatDate } from 'date-fns';
|
||||||
|
import { BadgeCheck, CheckCircle2 } from 'lucide-react';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { BillingSchema, getProductPlanPairFromId } from '@kit/billing';
|
import { BillingSchema, getProductPlanPairFromId } from '@kit/billing';
|
||||||
import { Database } from '@kit/supabase/database';
|
import { Database } from '@kit/supabase/database';
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from '@kit/ui/accordion';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
@@ -11,6 +18,10 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from '@kit/ui/card';
|
} from '@kit/ui/card';
|
||||||
import { If } from '@kit/ui/if';
|
import { If } from '@kit/ui/if';
|
||||||
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
|
import { CurrentPlanAlert } from './current-plan-alert';
|
||||||
|
import { CurrentPlanBadge } from './current-plan-badge';
|
||||||
|
|
||||||
export function CurrentPlanCard({
|
export function CurrentPlanCard({
|
||||||
subscription,
|
subscription,
|
||||||
@@ -27,41 +38,103 @@ export function CurrentPlanCard({
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{product.name}</CardTitle>
|
<CardTitle>Your Plan</CardTitle>
|
||||||
|
|
||||||
<CardDescription>{product.description}</CardDescription>
|
<CardDescription>
|
||||||
|
You can change your plan or cancel your subscription at any time.
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className={'space-y-4 text-sm'}>
|
<CardContent className={'space-y-2.5 text-sm'}>
|
||||||
<div>
|
<div className={'flex flex-col space-y-1'}>
|
||||||
<div className={'font-semibold'}>
|
<div className={'flex items-center space-x-2 text-lg font-semibold'}>
|
||||||
Your Current Plan: <span>{plan.name}</span>
|
<BadgeCheck
|
||||||
|
className={
|
||||||
|
's-6 fill-green-500 text-white dark:fill-white dark:text-black'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span>{product.name}</span>
|
||||||
|
<CurrentPlanBadge status={subscription.status} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'text-muted-foreground'}>
|
||||||
|
Renews every {subscription.interval} at{' '}
|
||||||
|
<span>{product.currency}</span> <span>{plan.price}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className={'font-semibold'}>
|
<CurrentPlanAlert status={subscription.status} />
|
||||||
Your Subscription is currently <span>{subscription.status}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<If condition={subscription.cancel_at_period_end}>
|
<div>
|
||||||
<div>
|
<Accordion type="single" collapsible>
|
||||||
<div className={'font-semibold'}>
|
<AccordionItem value="features">
|
||||||
Cancellation Date:{' '}
|
<AccordionTrigger>Plan details</AccordionTrigger>
|
||||||
<span>{formatDate(subscription.period_ends_at, 'P')}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</If>
|
|
||||||
|
|
||||||
<If condition={!subscription.cancel_at_period_end}>
|
<AccordionContent className="space-y-2.5">
|
||||||
<div>
|
<If condition={subscription.status === 'trialing'}>
|
||||||
<div className={'font-semibold'}>
|
<div className="flex flex-col">
|
||||||
Next Billing Date:{' '}
|
<span className="font-medium">Your trial ends on</span>
|
||||||
<span>{formatDate(subscription.period_ends_at, 'P')}</span>{' '}
|
|
||||||
</div>
|
<div className={'text-muted-foreground'}>
|
||||||
</div>
|
<span>
|
||||||
</If>
|
{subscription.trial_ends_at
|
||||||
|
? formatDate(subscription.trial_ends_at, 'P')
|
||||||
|
: ''}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<If condition={subscription.cancel_at_period_end}>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span className="font-medium">
|
||||||
|
Your subscription will be cancelled at the end of the
|
||||||
|
period
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div className={'text-muted-foreground'}>
|
||||||
|
<span>
|
||||||
|
{formatDate(subscription.period_ends_at ?? '', 'P')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<If condition={!subscription.cancel_at_period_end}>
|
||||||
|
<div className="flex flex-col space-y-1">
|
||||||
|
<span className="font-medium">Your next bill</span>
|
||||||
|
|
||||||
|
<div className={'text-muted-foreground'}>
|
||||||
|
Your next bill is for {product.currency} {plan.price} on{' '}
|
||||||
|
<span>
|
||||||
|
{formatDate(subscription.period_ends_at ?? '', 'P')}
|
||||||
|
</span>{' '}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<div className="flex flex-col space-y-1">
|
||||||
|
<span className="font-medium">Features</span>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{product.features.map((item) => {
|
||||||
|
return (
|
||||||
|
<li key={item} className="flex items-center space-x-0.5">
|
||||||
|
<CheckCircle2 className="h-4 text-green-500" />
|
||||||
|
<span>
|
||||||
|
<Trans i18nKey={item} defaults={item} />
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,10 +15,22 @@ export function EmbeddedCheckout(
|
|||||||
provider: BillingProvider;
|
provider: BillingProvider;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}>,
|
}>,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<LazyCheckout onClose={props.onClose} checkoutToken={props.checkoutToken} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function LazyCheckout(
|
||||||
|
props: React.PropsWithChildren<{
|
||||||
|
checkoutToken: string;
|
||||||
|
provider: BillingProvider;
|
||||||
|
onClose?: () => void;
|
||||||
|
}>,
|
||||||
) {
|
) {
|
||||||
const CheckoutComponent = useMemo(
|
const CheckoutComponent = useMemo(
|
||||||
() => memo(loadCheckoutComponent(props.provider)),
|
() => memo(loadCheckoutComponent(props.provider)),
|
||||||
[],
|
[props.provider],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -69,7 +81,7 @@ function buildLazyComponent<
|
|||||||
) {
|
) {
|
||||||
let LoadedComponent: ReturnType<typeof lazy> | null = null;
|
let LoadedComponent: ReturnType<typeof lazy> | null = null;
|
||||||
|
|
||||||
const LazyComponent = forwardRef((props, ref) => {
|
const LazyComponent = forwardRef(function LazyDynamicComponent(props, ref) {
|
||||||
if (!LoadedComponent) {
|
if (!LoadedComponent) {
|
||||||
LoadedComponent = lazy(load);
|
LoadedComponent = lazy(load);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,5 +105,5 @@ export function getProductPlanPairFromId(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
throw new Error(`Plan with ID ${planId} not found`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
|
||||||
import type { Provider } from '@supabase/supabase-js';
|
import type { Provider } from '@supabase/supabase-js';
|
||||||
|
|
||||||
@@ -27,13 +27,17 @@ export function SignInMethodsContainer(props: {
|
|||||||
oAuth: Provider[];
|
oAuth: Provider[];
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
|
const nextPath = useSearchParams().get('next') ?? props.paths.home;
|
||||||
|
|
||||||
const redirectUrl = new URL(
|
const redirectUrl = new URL(
|
||||||
props.paths.callback,
|
props.paths.callback,
|
||||||
isBrowser() ? window?.location.origin : '',
|
isBrowser() ? window?.location.origin : '',
|
||||||
).toString();
|
).toString();
|
||||||
|
|
||||||
const router = useRouter();
|
const onSignIn = () => {
|
||||||
const onSignIn = () => router.replace(props.paths.home);
|
router.replace(nextPath);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function initializeI18nClient(
|
|||||||
.use(
|
.use(
|
||||||
resourcesToBackend(async (language, namespace, callback) => {
|
resourcesToBackend(async (language, namespace, callback) => {
|
||||||
const data = await i18nResolver(language, namespace);
|
const data = await i18nResolver(language, namespace);
|
||||||
console.log(data);
|
|
||||||
return callback(null, data);
|
return callback(null, data);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class StripeWebhookHandlerService
|
|||||||
async verifyWebhookSignature(request: Request) {
|
async verifyWebhookSignature(request: Request) {
|
||||||
const body = await request.clone().text();
|
const body = await request.clone().text();
|
||||||
const signatureKey = `stripe-signature`;
|
const signatureKey = `stripe-signature`;
|
||||||
const signature = request.headers.get(signatureKey) as string;
|
const signature = request.headers.get(signatureKey)!;
|
||||||
|
|
||||||
const { STRIPE_WEBHOOK_SECRET } = StripeServerEnvSchema.parse({
|
const { STRIPE_WEBHOOK_SECRET } = StripeServerEnvSchema.parse({
|
||||||
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ function AuthRedirectListener({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// keep this running for the whole session unless the component was unmounted
|
// keep this running for the whole session unless the component was unmounted
|
||||||
const listener = client.auth.onAuthStateChange((_, user) => {
|
const listener = client.auth.onAuthStateChange((_, user) => {
|
||||||
|
console.log(_, user);
|
||||||
// log user out if user is falsy
|
// log user out if user is falsy
|
||||||
// and if the current path is a private route
|
// and if the current path is a private route
|
||||||
const shouldRedirectUser = !user && isPrivateRoute(pathName);
|
const shouldRedirectUser = !user && isPrivateRoute(pathName);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-accordion": "1.1.2",
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
@@ -44,7 +45,6 @@
|
|||||||
"@kit/prettier-config": "0.1.0",
|
"@kit/prettier-config": "0.1.0",
|
||||||
"@kit/tailwind-config": "0.1.0",
|
"@kit/tailwind-config": "0.1.0",
|
||||||
"@kit/tsconfig": "0.1.0",
|
"@kit/tsconfig": "0.1.0",
|
||||||
"@tanstack/react-table": "^8.11.3",
|
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"date-fns": "^3.2.0",
|
"date-fns": "^3.2.0",
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
},
|
},
|
||||||
"prettier": "@kit/prettier-config",
|
"prettier": "@kit/prettier-config",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
"./accordion": "./src/shadcn/accordion.tsx",
|
||||||
"./avatar": "./src/shadcn/avatar.tsx",
|
"./avatar": "./src/shadcn/avatar.tsx",
|
||||||
"./button": "./src/shadcn/button.tsx",
|
"./button": "./src/shadcn/button.tsx",
|
||||||
"./calendar": "./src/shadcn/calendar.tsx",
|
"./calendar": "./src/shadcn/calendar.tsx",
|
||||||
@@ -117,4 +118,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import { cn } from './utils';
|
|
||||||
|
|
||||||
const NavigationContainer: React.FC<{
|
|
||||||
className?: string;
|
|
||||||
}> = ({ children, className }) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={cn(`dark:border-dark-800 border-b border-gray-50`, className)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NavigationContainer;
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useContext } from 'react';
|
|
||||||
|
|
||||||
import Link from 'next/link';
|
|
||||||
import { usePathname } from 'next/navigation';
|
|
||||||
|
|
||||||
import Trans from '@/components/app/Trans';
|
|
||||||
import { cva } from 'class-variance-authority';
|
|
||||||
|
|
||||||
import isRouteActive from '@kit/generic/is-route-active';
|
|
||||||
|
|
||||||
import { NavigationMenuContext } from './navigation-menu-context';
|
|
||||||
import { cn } from './utils';
|
|
||||||
|
|
||||||
interface Link {
|
|
||||||
path: string;
|
|
||||||
label?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const NavigationMenuItem: React.FC<{
|
|
||||||
link: Link;
|
|
||||||
depth?: number;
|
|
||||||
disabled?: boolean;
|
|
||||||
shallow?: boolean;
|
|
||||||
className?: string;
|
|
||||||
}> = ({ link, disabled, shallow, depth, ...props }) => {
|
|
||||||
const pathName = usePathname() ?? '';
|
|
||||||
const active = isRouteActive(link.path, pathName, depth ?? 3);
|
|
||||||
const menuProps = useContext(NavigationMenuContext);
|
|
||||||
const label = link.label;
|
|
||||||
|
|
||||||
const itemClassName = getNavigationMenuItemClassBuilder()({
|
|
||||||
active,
|
|
||||||
...menuProps,
|
|
||||||
});
|
|
||||||
|
|
||||||
const className = cn(itemClassName, props.className ?? ``);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li className={className}>
|
|
||||||
<Link
|
|
||||||
className={
|
|
||||||
'justify-center transition-transform duration-500 lg:justify-start'
|
|
||||||
}
|
|
||||||
aria-disabled={disabled}
|
|
||||||
href={disabled ? '' : link.path}
|
|
||||||
shallow={shallow ?? active}
|
|
||||||
>
|
|
||||||
<Trans i18nKey={label} defaults={label} />
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NavigationMenuItem;
|
|
||||||
|
|
||||||
function getNavigationMenuItemClassBuilder() {
|
|
||||||
return cva(
|
|
||||||
[
|
|
||||||
`flex items-center justify-center font-medium lg:justify-start rounded-md text-sm transition colors transform *:active:translate-y-[2px]`,
|
|
||||||
'*:p-1 *:lg:px-2.5 *:s-full *:flex *:items-center',
|
|
||||||
'aria-disabled:cursor-not-allowed aria-disabled:opacity-50',
|
|
||||||
],
|
|
||||||
{
|
|
||||||
compoundVariants: [
|
|
||||||
// not active - shared
|
|
||||||
{
|
|
||||||
active: false,
|
|
||||||
className: `font-medium hover:underline`,
|
|
||||||
},
|
|
||||||
// active - shared
|
|
||||||
{
|
|
||||||
active: true,
|
|
||||||
className: `font-semibold`,
|
|
||||||
},
|
|
||||||
// active - pill
|
|
||||||
{
|
|
||||||
active: true,
|
|
||||||
pill: true,
|
|
||||||
className: `bg-gray-50 text-gray-800 dark:bg-primary-300/10`,
|
|
||||||
},
|
|
||||||
// not active - pill
|
|
||||||
{
|
|
||||||
active: false,
|
|
||||||
pill: true,
|
|
||||||
className: `hover:bg-gray-50 active:bg-gray-100 text-gray-500 dark:text-gray-300 dark:hover:bg-background dark:active:bg-dark-900/90`,
|
|
||||||
},
|
|
||||||
// not active - bordered
|
|
||||||
{
|
|
||||||
active: false,
|
|
||||||
bordered: true,
|
|
||||||
className: `hover:bg-gray-50 active:bg-gray-100 dark:active:bg-dark-800 dark:hover:bg-dark/90 transition-colors rounded-lg border-transparent`,
|
|
||||||
},
|
|
||||||
// active - bordered
|
|
||||||
{
|
|
||||||
active: true,
|
|
||||||
bordered: true,
|
|
||||||
className: `top-[0.4rem] border-b-[0.25rem] rounded-none border-primary bg-transparent pb-[0.55rem] text-primary-700 dark:text-white`,
|
|
||||||
},
|
|
||||||
// active - secondary
|
|
||||||
{
|
|
||||||
active: true,
|
|
||||||
secondary: true,
|
|
||||||
className: `bg-transparent font-semibold`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
variants: {
|
|
||||||
active: {
|
|
||||||
true: ``,
|
|
||||||
},
|
|
||||||
pill: {
|
|
||||||
true: `[&>*]:py-2`,
|
|
||||||
},
|
|
||||||
bordered: {
|
|
||||||
true: `relative h-10`,
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
true: ``,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { createContext } from 'react';
|
|
||||||
|
|
||||||
import type { NavigationMenuProps } from './navigation-menu';
|
|
||||||
|
|
||||||
export const NavigationMenuContext = createContext<NavigationMenuProps>({});
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import type { PropsWithChildren } from 'react';
|
|
||||||
|
|
||||||
import { cva } from 'class-variance-authority';
|
|
||||||
|
|
||||||
import { NavigationMenuContext } from './navigation-menu-context';
|
|
||||||
|
|
||||||
type Vertical = {
|
|
||||||
vertical?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Bordered = {
|
|
||||||
bordered?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Pill = {
|
|
||||||
pill?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type NavigationMenuProps = Vertical & (Bordered | Pill);
|
|
||||||
|
|
||||||
function NavigationMenu(props: PropsWithChildren<NavigationMenuProps>) {
|
|
||||||
const className = getNavigationMenuClassBuilder()(props);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ul className={className}>
|
|
||||||
<NavigationMenuContext.Provider value={props}>
|
|
||||||
{props.children}
|
|
||||||
</NavigationMenuContext.Provider>
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NavigationMenu;
|
|
||||||
|
|
||||||
function getNavigationMenuClassBuilder() {
|
|
||||||
return cva(['w-full dark:text-gray-300 items-center flex-wrap flex'], {
|
|
||||||
variants: {
|
|
||||||
vertical: {
|
|
||||||
true: `flex items-start justify-between space-x-2
|
|
||||||
lg:flex-col lg:justify-start lg:space-x-0 lg:space-y-1.5 [&>li>a]:w-full`,
|
|
||||||
},
|
|
||||||
bordered: {
|
|
||||||
true: `lg:space-x-3 border-b border-gray-100 dark:border-dark-800 pb-1.5`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,6 @@ function Spinner(
|
|||||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<path
|
<path
|
||||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||||
fill="currentFill"
|
fill="currentFill"
|
||||||
|
|||||||
58
packages/ui/src/shadcn/accordion.tsx
Normal file
58
packages/ui/src/shadcn/accordion.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
||||||
|
import { ChevronDownIcon } from '@radix-ui/react-icons';
|
||||||
|
|
||||||
|
import { cn } from '../utils';
|
||||||
|
|
||||||
|
const Accordion = AccordionPrimitive.Root;
|
||||||
|
|
||||||
|
const AccordionItem = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Item
|
||||||
|
ref={ref}
|
||||||
|
className={cn('border-b', className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
AccordionItem.displayName = 'AccordionItem';
|
||||||
|
|
||||||
|
const AccordionTrigger = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Header className="flex">
|
||||||
|
<AccordionPrimitive.Trigger
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
|
||||||
|
</AccordionPrimitive.Trigger>
|
||||||
|
</AccordionPrimitive.Header>
|
||||||
|
));
|
||||||
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
||||||
|
|
||||||
|
const AccordionContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof AccordionPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
||||||
|
>(({ className, children, ...props }, ref) => (
|
||||||
|
<AccordionPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className="overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className={cn('pb-4 pt-0', className)}>{children}</div>
|
||||||
|
</AccordionPrimitive.Content>
|
||||||
|
));
|
||||||
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
||||||
@@ -17,7 +17,7 @@ const badgeVariants = cva(
|
|||||||
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
|
'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
|
||||||
outline: 'text-foreground',
|
outline: 'text-foreground',
|
||||||
success:
|
success:
|
||||||
'border-transparent bg-green-50 text-green-500 dark:bg-transparent',
|
'border-transparent bg-green-50 text-green-500 dark:bg-green-500/20',
|
||||||
warning:
|
warning:
|
||||||
'border-transparent bg-orange-50 text-orange-500 dark:bg-transparent',
|
'border-transparent bg-orange-50 text-orange-500 dark:bg-transparent',
|
||||||
info: 'border-transparent bg-blue-50 text-blue-500 dark:bg-transparent',
|
info: 'border-transparent bg-blue-50 text-blue-500 dark:bg-transparent',
|
||||||
|
|||||||
153
pnpm-lock.yaml
generated
153
pnpm-lock.yaml
generated
@@ -88,7 +88,7 @@ importers:
|
|||||||
version: 5.28.6(react@18.2.0)
|
version: 5.28.6(react@18.2.0)
|
||||||
'@tanstack/react-query-next-experimental':
|
'@tanstack/react-query-next-experimental':
|
||||||
specifier: ^5.28.6
|
specifier: ^5.28.6
|
||||||
version: 5.28.6(@tanstack/react-query@5.28.6)(next@14.2.0-canary.41)(react@18.2.0)
|
version: 5.28.6(@tanstack/react-query@5.28.6)(next@14.2.0-canary.43)(react@18.2.0)
|
||||||
'@tanstack/react-table':
|
'@tanstack/react-table':
|
||||||
specifier: ^8.11.3
|
specifier: ^8.11.3
|
||||||
version: 8.14.0(react-dom@18.2.0)(react@18.2.0)
|
version: 8.14.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
@@ -100,7 +100,7 @@ importers:
|
|||||||
version: 3.6.0
|
version: 3.6.0
|
||||||
edge-csrf:
|
edge-csrf:
|
||||||
specifier: ^1.0.9
|
specifier: ^1.0.9
|
||||||
version: 1.0.9(next@14.2.0-canary.41)
|
version: 1.0.9(next@14.2.0-canary.43)
|
||||||
i18next:
|
i18next:
|
||||||
specifier: ^23.10.1
|
specifier: ^23.10.1
|
||||||
version: 23.10.1
|
version: 23.10.1
|
||||||
@@ -108,17 +108,17 @@ importers:
|
|||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
next:
|
next:
|
||||||
specifier: ^14.2.0-canary.41
|
specifier: canary
|
||||||
version: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
version: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
next-contentlayer:
|
next-contentlayer:
|
||||||
specifier: 0.3.4
|
specifier: 0.3.4
|
||||||
version: 0.3.4(contentlayer@0.3.4)(esbuild@0.19.11)(next@14.2.0-canary.41)(react-dom@18.2.0)(react@18.2.0)
|
version: 0.3.4(contentlayer@0.3.4)(esbuild@0.19.11)(next@14.2.0-canary.43)(react-dom@18.2.0)(react@18.2.0)
|
||||||
next-sitemap:
|
next-sitemap:
|
||||||
specifier: ^4.2.3
|
specifier: ^4.2.3
|
||||||
version: 4.2.3(next@14.2.0-canary.41)
|
version: 4.2.3(next@14.2.0-canary.43)
|
||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.2.1
|
specifier: ^0.2.1
|
||||||
version: 0.2.1(next@14.2.0-canary.41)(react-dom@18.2.0)(react@18.2.0)
|
version: 0.2.1(next@14.2.0-canary.43)(react-dom@18.2.0)(react@18.2.0)
|
||||||
react:
|
react:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
@@ -163,8 +163,8 @@ importers:
|
|||||||
specifier: ^0.1.0
|
specifier: ^0.1.0
|
||||||
version: link:../../tooling/typescript
|
version: link:../../tooling/typescript
|
||||||
'@next/bundle-analyzer':
|
'@next/bundle-analyzer':
|
||||||
specifier: ^14.2.0-canary.41
|
specifier: canary
|
||||||
version: 14.2.0-canary.41
|
version: 14.2.0-canary.43
|
||||||
'@types/mdx':
|
'@types/mdx':
|
||||||
specifier: ^2.0.10
|
specifier: ^2.0.10
|
||||||
version: 2.0.11
|
version: 2.0.11
|
||||||
@@ -333,6 +333,10 @@ importers:
|
|||||||
version: link:../../../tooling/typescript
|
version: link:../../../tooling/typescript
|
||||||
|
|
||||||
packages/features/admin:
|
packages/features/admin:
|
||||||
|
dependencies:
|
||||||
|
'@kit/ui':
|
||||||
|
specifier: 0.1.0
|
||||||
|
version: link:../../ui
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@kit/eslint-config':
|
'@kit/eslint-config':
|
||||||
specifier: 0.2.0
|
specifier: 0.2.0
|
||||||
@@ -568,6 +572,9 @@ importers:
|
|||||||
|
|
||||||
packages/ui:
|
packages/ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@radix-ui/react-accordion':
|
||||||
|
specifier: 1.1.2
|
||||||
|
version: 1.1.2(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-alert-dialog':
|
'@radix-ui/react-alert-dialog':
|
||||||
specifier: ^1.0.5
|
specifier: ^1.0.5
|
||||||
version: 1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
@@ -619,6 +626,9 @@ importers:
|
|||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: 1.0.7
|
specifier: 1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@tanstack/react-table':
|
||||||
|
specifier: ^8.10.7
|
||||||
|
version: 8.14.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
class-variance-authority:
|
class-variance-authority:
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
@@ -659,9 +669,6 @@ importers:
|
|||||||
'@kit/tsconfig':
|
'@kit/tsconfig':
|
||||||
specifier: 0.1.0
|
specifier: 0.1.0
|
||||||
version: link:../../tooling/typescript
|
version: link:../../tooling/typescript
|
||||||
'@tanstack/react-table':
|
|
||||||
specifier: ^8.11.3
|
|
||||||
version: 8.14.0(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^18.2.48
|
specifier: ^18.2.48
|
||||||
version: 18.2.67
|
version: 18.2.67
|
||||||
@@ -1770,8 +1777,8 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/bundle-analyzer@14.2.0-canary.41:
|
/@next/bundle-analyzer@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-1+PP3XaC3lz0oE49D0jxGsiEJZOmwlDgqV3yantl64vXRNX8Ae3Gsk1KcDhp7JHKKPvFx4AF13/LF48sbH0zkw==}
|
resolution: {integrity: sha512-5GYBb99OLnmg5xZDrUUD0ILB/gJDN4MxJTG5fU5JQXIDc6Ew+jJgMzjdqptJduvlExorAWNNpQnjdnRlnZCQfg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
webpack-bundle-analyzer: 4.10.1
|
webpack-bundle-analyzer: 4.10.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -1791,8 +1798,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==}
|
resolution: {integrity: sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/env@14.2.0-canary.41:
|
/@next/env@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-6bd8zNDEferyJ9qkJrCB0pTgGFaJ9XttMI+uj5jrSeQ88kxsgPcoOFqBEMDtDOEzWqi+17B29alThei0Cmw0dA==}
|
resolution: {integrity: sha512-jBjfC5J053shwv+g4kplFG+iH1TqWwMtLCIpDSplOmRDLdGeai6s3oKmWIxd+MbG5ETSZOl1vCN5A3nMgGkXfg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/eslint-plugin-next@14.1.4:
|
/@next/eslint-plugin-next@14.1.4:
|
||||||
@@ -1833,8 +1840,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-darwin-arm64@14.2.0-canary.41:
|
/@next/swc-darwin-arm64@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-cplMeo/uQcfSHwZH2naB87IWzJouOSPXFQqRk1/nwuQNPxLFT2xO2v7zP4L4W98qukvLylFxWQhqpIQqZnohIA==}
|
resolution: {integrity: sha512-M9Asj8J6GMVNdMRnDnR+hELiyjgaHSUYAZz4M7ro5Vd1X8wpg3jygd/RnkTv+hhHn3rqwV9jWyZ4xdyG3SORrg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@@ -1860,8 +1867,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-darwin-x64@14.2.0-canary.41:
|
/@next/swc-darwin-x64@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-mnqPeUMFUg73DXEsNOxrKXy09ikcErLeFEzYVqn5XwaewVyqny9xwf8f02BYBcLEBrmk565xkocnTs7su45qqA==}
|
resolution: {integrity: sha512-3BQ5FirbYZgXAFOCUynDr/Sl0fcFfEiLiDVdGMaJO7754fuWJShcj5tODiFC2B7MgLsVkri/84prBzsjkg76jA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@@ -1887,8 +1894,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-arm64-gnu@14.2.0-canary.41:
|
/@next/swc-linux-arm64-gnu@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-ns0/YS9yqqS71h4xZNGn+IDZC7q3fLrF9mIaZ3aXhkHpXfeyjACOAEC6/0l0E49w4VkPv0XK64aRvsxsZfFr9g==}
|
resolution: {integrity: sha512-VoCLYDTD2bkLsUkT0bACplrdpTw+IBKdFr5ih85atePrujCz6dMPUxeNMwH9aYL7r3PgzH6dR30r0Y5TFwUUSg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1914,8 +1921,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-arm64-musl@14.2.0-canary.41:
|
/@next/swc-linux-arm64-musl@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-22nsQMLgJH3ZbxbgQmiwGbFtW8KtDRQJU8OSyWcO8MFTgPdL3IcRd/lTsR5r9qliosoGgHzFSYDAq/7M5I/w0Q==}
|
resolution: {integrity: sha512-8c35oylAS4Ggu155txTpOv7VG4BzG8BTluVbUZuaneZwsZi6VTbjVKMVnLYmmdcdRkkvRgPc83oUr2HGxwxFBw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1941,8 +1948,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-x64-gnu@14.2.0-canary.41:
|
/@next/swc-linux-x64-gnu@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-ZkcPQk+SV+i06i0k/UVmXKk+k70yKIwtTPrWl7JpeJ/Wc7sWoRqNCdpFqP227oOsy6dM0NKqJTEOATBYAefQLg==}
|
resolution: {integrity: sha512-PHy7clJ+ChZzNJ3c9A2IrWJN4aNa+FZ+v39XNdcjdkdhPvwu1QSvtirWSbxqKpAqgA/3sMhAGCvwOx6yeBs4Ug==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1968,8 +1975,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-x64-musl@14.2.0-canary.41:
|
/@next/swc-linux-x64-musl@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-1Uofz0Bkec63oN7Xj9lHGevCqxZJrr6pruPx5JUb613CYqUVCVj6JA8H2JutYYwgcbwstjdA+9He37HlW1FGTw==}
|
resolution: {integrity: sha512-pvma+GKwkDEzhQRrwl9P4oGu9A9NGJH/Za+SG/XwWph2i78+4OMDCKrmKEJ1T5BE6Bgo+Emfhdy8TmfqHPQQCg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1995,8 +2002,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-arm64-msvc@14.2.0-canary.41:
|
/@next/swc-win32-arm64-msvc@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-gMzwgq1ZnKwxYx2I4qhuRtaGZ/6WZD8XV0cObnaWXiu8O7NCK1kEKa6+IWy+Manax5qwamHKzWND5uKbeddToQ==}
|
resolution: {integrity: sha512-b1npBheIu7/BgMZTCFkuNYv0Q/N9u6+7MYY5xjZDVIutW8ut2V93JZqeC2SYWFm03I+LNdYjplRhn3TVerz9Xg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -2022,8 +2029,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-ia32-msvc@14.2.0-canary.41:
|
/@next/swc-win32-ia32-msvc@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-U72bjcHUUoRToFTAouUqK9y/PaiKVo4rDX5/RwzIZThPghfHf5ALG6DYiw64sKWSRXSfFOv9DzhofjK1+CIgSA==}
|
resolution: {integrity: sha512-1bZDCGyQzvdRNxVUUhsjBZOzBEEoQlh1r91ifjUz9nhcFYOlmP6IplPMjaLmG+GJMUiI36j5svdPYO3LP08b8g==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -2049,8 +2056,8 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-x64-msvc@14.2.0-canary.41:
|
/@next/swc-win32-x64-msvc@14.2.0-canary.43:
|
||||||
resolution: {integrity: sha512-cBgEDwdxfyv9bBoo5dKBtfxd7S7Dv3dTRKYx7agprJ3BdGc8gXs2zdi08lR/fBU0kjpsC4gw/tg5p+IDkuZUaw==}
|
resolution: {integrity: sha512-pU9gjLmp4yjYzBqCGa5bQ0iyJ5D73IRITEUFKrjZPi0XHUbFLrhcaaCsnVgMO4xfOQJgS7ODuQB7N0iPk7/EMw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -2386,6 +2393,35 @@ packages:
|
|||||||
'@babel/runtime': 7.24.1
|
'@babel/runtime': 7.24.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-accordion@1.1.2(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '*'
|
||||||
|
'@types/react-dom': '*'
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0
|
||||||
|
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
'@types/react-dom':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.24.1
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.67)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.67)(react@18.2.0)
|
||||||
|
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.67)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.67)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.67)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.67
|
||||||
|
'@types/react-dom': 18.2.22
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==}
|
resolution: {integrity: sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4187,7 +4223,7 @@ packages:
|
|||||||
/@tanstack/query-core@5.28.6:
|
/@tanstack/query-core@5.28.6:
|
||||||
resolution: {integrity: sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==}
|
resolution: {integrity: sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==}
|
||||||
|
|
||||||
/@tanstack/react-query-next-experimental@5.28.6(@tanstack/react-query@5.28.6)(next@14.2.0-canary.41)(react@18.2.0):
|
/@tanstack/react-query-next-experimental@5.28.6(@tanstack/react-query@5.28.6)(next@14.2.0-canary.43)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-KHTR1nGChTXk/kELit2gaqF3cQuN68F5UJv0377Gz5DnllPnBegja6if2W9KtKxm3Z1xP0j8LQXplqlqny2SYw==}
|
resolution: {integrity: sha512-KHTR1nGChTXk/kELit2gaqF3cQuN68F5UJv0377Gz5DnllPnBegja6if2W9KtKxm3Z1xP0j8LQXplqlqny2SYw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-query': ^5.28.6
|
'@tanstack/react-query': ^5.28.6
|
||||||
@@ -4195,7 +4231,7 @@ packages:
|
|||||||
react: ^18.0.0
|
react: ^18.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/react-query': 5.28.6(react@18.2.0)
|
'@tanstack/react-query': 5.28.6(react@18.2.0)
|
||||||
next: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
next: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@@ -4217,10 +4253,12 @@ packages:
|
|||||||
'@tanstack/table-core': 8.14.0
|
'@tanstack/table-core': 8.14.0
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@tanstack/table-core@8.14.0:
|
/@tanstack/table-core@8.14.0:
|
||||||
resolution: {integrity: sha512-wDhpKJahGHWhmRt4RxtV3pES63CoeadljGWS/xeS9OJr1HBl2NB+OO44ht3sxDH5j5TRDAbQzC0NvSlsUfn7lQ==}
|
resolution: {integrity: sha512-wDhpKJahGHWhmRt4RxtV3pES63CoeadljGWS/xeS9OJr1HBl2NB+OO44ht3sxDH5j5TRDAbQzC0NvSlsUfn7lQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@tootallnate/quickjs-emscripten@0.23.0:
|
/@tootallnate/quickjs-emscripten@0.23.0:
|
||||||
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
|
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
|
||||||
@@ -6033,12 +6071,12 @@ packages:
|
|||||||
/eastasianwidth@0.2.0:
|
/eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
|
|
||||||
/edge-csrf@1.0.9(next@14.2.0-canary.41):
|
/edge-csrf@1.0.9(next@14.2.0-canary.43):
|
||||||
resolution: {integrity: sha512-3F89YTh42UDdISr3s9AEcgJDLi4ysgjGfnybzF0LuZGaG2W31h1ZwgWwEQBLMj04lAklcP4XHZYi7vk9o8zcbg==}
|
resolution: {integrity: sha512-3F89YTh42UDdISr3s9AEcgJDLi4ysgjGfnybzF0LuZGaG2W31h1ZwgWwEQBLMj04lAklcP4XHZYi7vk9o8zcbg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: ^13.0.0 || ^14.0.0
|
next: ^13.0.0 || ^14.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
next: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
next: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/editorconfig@1.0.4:
|
/editorconfig@1.0.4:
|
||||||
@@ -8784,7 +8822,7 @@ packages:
|
|||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/next-contentlayer@0.3.4(contentlayer@0.3.4)(esbuild@0.19.11)(next@14.2.0-canary.41)(react-dom@18.2.0)(react@18.2.0):
|
/next-contentlayer@0.3.4(contentlayer@0.3.4)(esbuild@0.19.11)(next@14.2.0-canary.43)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-UtUCwgAl159KwfhNaOwyiI7Lg6sdioyKMeh+E7jxx0CJ29JuXGxBEYmCI6+72NxFGIFZKx8lvttbbQhbnYWYSw==}
|
resolution: {integrity: sha512-UtUCwgAl159KwfhNaOwyiI7Lg6sdioyKMeh+E7jxx0CJ29JuXGxBEYmCI6+72NxFGIFZKx8lvttbbQhbnYWYSw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
contentlayer: 0.3.4
|
contentlayer: 0.3.4
|
||||||
@@ -8795,7 +8833,7 @@ packages:
|
|||||||
'@contentlayer/core': 0.3.4(esbuild@0.19.11)
|
'@contentlayer/core': 0.3.4(esbuild@0.19.11)
|
||||||
'@contentlayer/utils': 0.3.4
|
'@contentlayer/utils': 0.3.4
|
||||||
contentlayer: 0.3.4(esbuild@0.19.11)
|
contentlayer: 0.3.4(esbuild@0.19.11)
|
||||||
next: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
next: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -8805,7 +8843,7 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/next-sitemap@4.2.3(next@14.2.0-canary.41):
|
/next-sitemap@4.2.3(next@14.2.0-canary.43):
|
||||||
resolution: {integrity: sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==}
|
resolution: {integrity: sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==}
|
||||||
engines: {node: '>=14.18'}
|
engines: {node: '>=14.18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -8816,17 +8854,17 @@ packages:
|
|||||||
'@next/env': 13.5.6
|
'@next/env': 13.5.6
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
next: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
next: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/next-themes@0.2.1(next@14.2.0-canary.41)(react-dom@18.2.0)(react@18.2.0):
|
/next-themes@0.2.1(next@14.2.0-canary.43)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
|
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: '*'
|
next: '*'
|
||||||
react: '*'
|
react: '*'
|
||||||
react-dom: '*'
|
react-dom: '*'
|
||||||
dependencies:
|
dependencies:
|
||||||
next: 14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
next: 14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
@@ -8909,22 +8947,25 @@ packages:
|
|||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/next@14.2.0-canary.41(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0):
|
/next@14.2.0-canary.43(@opentelemetry/api@1.8.0)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-jqNSTq1COP04WXpj88Bzt8kkCLXFNpCU4tHzQrICAMVWeNtHTZpK2WPR8560SWBw614bW2qHYY85k0tez3YLiA==}
|
resolution: {integrity: sha512-tL5fxsleOuRS7Momx5wRwkCOPLybQKwgJnpzgMGVReQs+kA9lkQiBANvlYdAsrvZ3vjzx2H+9mSqKDcKaC8UXQ==}
|
||||||
engines: {node: '>=18.17.0'}
|
engines: {node: '>=18.17.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@opentelemetry/api': ^1.1.0
|
'@opentelemetry/api': ^1.1.0
|
||||||
|
'@playwright/test': ^1.41.2
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
react-dom: ^18.2.0
|
react-dom: ^18.2.0
|
||||||
sass: ^1.3.0
|
sass: ^1.3.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@opentelemetry/api':
|
'@opentelemetry/api':
|
||||||
optional: true
|
optional: true
|
||||||
|
'@playwright/test':
|
||||||
|
optional: true
|
||||||
sass:
|
sass:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 14.2.0-canary.41
|
'@next/env': 14.2.0-canary.43
|
||||||
'@opentelemetry/api': 1.8.0
|
'@opentelemetry/api': 1.8.0
|
||||||
'@swc/helpers': 0.5.5
|
'@swc/helpers': 0.5.5
|
||||||
busboy: 1.6.0
|
busboy: 1.6.0
|
||||||
@@ -8935,15 +8976,15 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
styled-jsx: 5.1.1(react@18.2.0)
|
styled-jsx: 5.1.1(react@18.2.0)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 14.2.0-canary.41
|
'@next/swc-darwin-arm64': 14.2.0-canary.43
|
||||||
'@next/swc-darwin-x64': 14.2.0-canary.41
|
'@next/swc-darwin-x64': 14.2.0-canary.43
|
||||||
'@next/swc-linux-arm64-gnu': 14.2.0-canary.41
|
'@next/swc-linux-arm64-gnu': 14.2.0-canary.43
|
||||||
'@next/swc-linux-arm64-musl': 14.2.0-canary.41
|
'@next/swc-linux-arm64-musl': 14.2.0-canary.43
|
||||||
'@next/swc-linux-x64-gnu': 14.2.0-canary.41
|
'@next/swc-linux-x64-gnu': 14.2.0-canary.43
|
||||||
'@next/swc-linux-x64-musl': 14.2.0-canary.41
|
'@next/swc-linux-x64-musl': 14.2.0-canary.43
|
||||||
'@next/swc-win32-arm64-msvc': 14.2.0-canary.41
|
'@next/swc-win32-arm64-msvc': 14.2.0-canary.43
|
||||||
'@next/swc-win32-ia32-msvc': 14.2.0-canary.41
|
'@next/swc-win32-ia32-msvc': 14.2.0-canary.43
|
||||||
'@next/swc-win32-x64-msvc': 14.2.0-canary.41
|
'@next/swc-win32-x64-msvc': 14.2.0-canary.43
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ const config = {
|
|||||||
'^@supabase/supabase-js$',
|
'^@supabase/supabase-js$',
|
||||||
'^@supabase/gotrue-js$',
|
'^@supabase/gotrue-js$',
|
||||||
'<THIRD_PARTY_MODULES>',
|
'<THIRD_PARTY_MODULES>',
|
||||||
'^@packages/(.*)$',
|
|
||||||
'^@kit/(.*)$',
|
'^@kit/(.*)$',
|
||||||
'^~/(.*)$', // app-specific imports
|
'^~/(.*)$', // app-specific imports
|
||||||
'^[./]', // relative imports
|
'^[./]', // relative imports
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { fontFamily } from 'tailwindcss/defaultTheme';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
darkMode: ['class'],
|
darkMode: ['class'],
|
||||||
content: ['../../packages/**/*.{ts,tsx}', '../../apps/**/*.{ts,tsx}'],
|
content: ['../../packages/**/*.tsx', '../../apps/**/*.tsx'],
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
|
|||||||
@@ -16,5 +16,6 @@
|
|||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"noUncheckedIndexedAccess": true
|
"noUncheckedIndexedAccess": true
|
||||||
}
|
},
|
||||||
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
44
turbo.json
44
turbo.json
@@ -1,31 +1,49 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://turborepo.org/schema.json",
|
"$schema": "https://turborepo.org/schema.json",
|
||||||
"globalDependencies": ["**/.env"],
|
"globalDependencies": [
|
||||||
|
"**/.env"
|
||||||
|
],
|
||||||
"pipeline": {
|
"pipeline": {
|
||||||
"topo": {
|
"topo": {
|
||||||
"dependsOn": ["^topo"]
|
"dependsOn": [
|
||||||
|
"^topo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": [
|
||||||
"outputs": [".next/**", "!.next/cache/**", "next-env.d.ts"],
|
"^build"
|
||||||
"dotEnv": [".env.production.local", ".env.local", ".env.production", ".env"]
|
],
|
||||||
|
"outputs": [
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**",
|
||||||
|
"next-env.d.ts"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"cache": false,
|
"cache": false
|
||||||
"dotEnv": [".env.development.local", ".env.local", ".env.development", ".env"]
|
|
||||||
},
|
},
|
||||||
"format": {
|
"format": {
|
||||||
"outputs": ["node_modules/.cache/.prettiercache"],
|
"outputs": [
|
||||||
|
"node_modules/.cache/.prettiercache"
|
||||||
|
],
|
||||||
"outputMode": "new-only"
|
"outputMode": "new-only"
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"dependsOn": ["^topo"],
|
"dependsOn": [
|
||||||
"outputs": ["node_modules/.cache/.eslintcache"]
|
"^topo"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"node_modules/.cache/.eslintcache"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"typecheck": {
|
"typecheck": {
|
||||||
"dependsOn": ["^topo"],
|
"dependsOn": [
|
||||||
"outputs": ["node_modules/.cache/tsbuildinfo.json"]
|
"^topo"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"node_modules/.cache/tsbuildinfo.json"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"clean": {
|
"clean": {
|
||||||
"cache": false
|
"cache": false
|
||||||
@@ -39,4 +57,4 @@
|
|||||||
"STRIPE_SECRET_KEY",
|
"STRIPE_SECRET_KEY",
|
||||||
"STRIPE_WEBHOOK_SECRET"
|
"STRIPE_WEBHOOK_SECRET"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user