This commit is contained in:
giancarlo
2024-03-24 02:23:22 +08:00
parent 648d77b430
commit bce3479368
589 changed files with 37067 additions and 9596 deletions

View File

@@ -0,0 +1,34 @@
import { z } from 'zod';
const production = process.env.NODE_ENV === 'production';
enum Themes {
Light = 'light',
Dark = 'dark',
}
const AppConfigSchema = z.object({
name: z.string(),
title: z.string(),
description: z.string(),
url: z.string(),
locale: z.string().default('en'),
theme: z.nativeEnum(Themes),
production: z.boolean(),
themeColor: z.string(),
themeColorDark: z.string(),
});
const appConfig = AppConfigSchema.parse({
name: 'Awesomely',
title: 'Awesomely - Your SaaS Title',
description: 'Your SaaS Description',
url: process.env.NEXT_PUBLIC_SITE_URL,
locale: process.env.NEXT_PUBLIC_DEFAULT_LOCALE,
theme: Themes.Light,
production,
themeColor: '#ffffff',
themeColorDark: '#0a0a0a',
});
export default appConfig;

View File

@@ -0,0 +1,53 @@
import type { Provider } from '@supabase/gotrue-js';
import { z } from 'zod';
const providers: z.ZodType<Provider> = getProviders();
const AuthConfigSchema = z.object({
providers: z.object({
password: z.boolean(),
magicLink: z.boolean(),
otp: z.boolean(),
oAuth: providers.array(),
}),
});
const authConfig = AuthConfigSchema.parse({
// NB: Enable the providers below in the Supabase Console
// in your production project
providers: {
password: true,
magicLink: false,
otp: false,
oAuth: ['google'],
},
});
export default authConfig;
function getProviders() {
return z.enum([
'apple',
'azure',
'bitbucket',
'discord',
'facebook',
'figma',
'github',
'gitlab',
'google',
'kakao',
'keycloak',
'linkedin',
'linkedin_oidc',
'notion',
'slack',
'spotify',
'twitch',
'twitter',
'workos',
'zoom',
'fly',
]);
}

View File

@@ -0,0 +1,96 @@
import { createBillingSchema } from '@kit/billing';
export default createBillingSchema({
provider: 'stripe',
products: [
{
id: 'starter',
name: 'Starter',
description: 'The perfect plan to get started',
currency: 'USD',
paymentType: 'recurring',
badge: `Value`,
plans: [
{
id: 'starter-monthly',
name: 'Starter Monthly',
price: '9.99',
interval: 'month',
perSeat: false,
},
{
id: 'starter-yearly',
name: 'Starter Yearly',
price: '99.99',
interval: 'year',
perSeat: false,
},
],
features: ['Feature 1', 'Feature 2', 'Feature 3'],
},
{
id: 'pro',
name: 'Pro',
badge: `Popular`,
highlighted: true,
description: 'The perfect plan for professionals',
paymentType: 'recurring',
currency: 'USD',
plans: [
{
id: 'pro-monthly',
name: 'Pro Monthly',
price: '19.99',
interval: 'month',
perSeat: false,
},
{
id: 'pro-yearly',
name: 'Pro Yearly',
price: '199.99',
interval: 'year',
perSeat: false,
},
],
features: [
'Feature 1',
'Feature 2',
'Feature 3',
'Feature 4',
'Feature 5',
],
},
{
id: 'enterprise',
name: 'Enterprise',
description: 'The perfect plan for enterprises',
paymentType: 'recurring',
currency: 'USD',
plans: [
{
id: 'enterprise-monthly',
name: 'Enterprise Monthly',
price: '99.99',
interval: 'month',
perSeat: false,
},
{
id: 'enterprise-yearly',
name: 'Enterprise Yearly',
price: '999.99',
interval: 'year',
perSeat: false,
},
],
features: [
'Feature 1',
'Feature 2',
'Feature 3',
'Feature 4',
'Feature 5',
'Feature 6',
'Feature 7',
],
},
],
});

View File

@@ -0,0 +1,49 @@
import { z } from 'zod';
const FeatureFlagsSchema = z.object({
enableThemeSwitcher: z.boolean(),
enableAccountDeletion: z.boolean(),
enableOrganizationDeletion: z.boolean(),
enableOrganizationAccounts: z.boolean(),
enableOrganizationCreation: z.boolean(),
enablePersonalAccountBilling: z.boolean(),
enableOrganizationBilling: z.boolean(),
});
const featuresFlagConfig = FeatureFlagsSchema.parse({
enableThemeSwitcher: true,
enableAccountDeletion: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_ACCOUNT_DELETION,
false,
),
enableOrganizationDeletion: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_ORGANIZATION_DELETION,
false,
),
enableOrganizationAccounts: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_ORGANIZATION_ACCOUNTS,
true,
),
enableOrganizationCreation: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_ORGANIZATION_CREATION,
true,
),
enablePersonalAccountBilling: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING,
false,
),
enableOrganizationBilling: getBoolean(
process.env.NEXT_PUBLIC_ENABLE_ORGANIZATION_BILLING,
false,
),
});
export default featuresFlagConfig;
function getBoolean(value: unknown, defaultValue: boolean) {
if (typeof value === 'string') {
return value === 'true';
}
return defaultValue;
}

View File

@@ -0,0 +1,54 @@
import {
CreditCardIcon,
LayoutDashboardIcon,
SettingsIcon,
UsersIcon,
} from 'lucide-react';
import featureFlagsConfig from '~/config/feature-flags.config';
import pathsConfig from '~/config/paths.config';
import { SidebarConfigSchema } from '@kit/ui/sidebar-schema';
const iconClasses = 'w-4';
const routes = (account: string) => [
{
label: 'common:dashboardTabLabel',
path: pathsConfig.app.accountHome.replace('[account]', account),
Icon: <LayoutDashboardIcon className={iconClasses} />,
end: true,
},
{
label: 'common:settingsTabLabel',
collapsible: false,
children: [
{
label: 'common:settingsTabLabel',
path: createPath(pathsConfig.app.accountSettings, account),
Icon: <SettingsIcon className={iconClasses} />,
},
{
label: 'common:accountMembers',
path: createPath(pathsConfig.app.accountMembers, account),
Icon: <UsersIcon className={iconClasses} />,
},
featureFlagsConfig.enableOrganizationBilling
? {
label: 'common:billingTabLabel',
path: createPath(pathsConfig.app.accountBilling, account),
Icon: <CreditCardIcon className={iconClasses} />,
}
: undefined,
].filter(Boolean),
},
];
export function getOrganizationAccountSidebarConfig(account: string) {
return SidebarConfigSchema.parse({
routes: routes(account),
});
}
function createPath(path: string, account: string) {
return path.replace('[account]', account);
}

View File

@@ -0,0 +1,43 @@
import { z } from 'zod';
const PathsSchema = z.object({
auth: z.object({
signIn: z.string(),
signUp: z.string(),
verifyMfa: z.string(),
callback: z.string(),
passwordReset: z.string(),
passwordUpdate: z.string(),
}),
app: z.object({
home: z.string(),
personalAccountSettings: z.string(),
personalAccountBilling: z.string(),
accountHome: z.string(),
accountSettings: z.string(),
accountBilling: z.string(),
accountMembers: z.string(),
}),
});
const pathsConfig = PathsSchema.parse({
auth: {
signIn: '/auth/sign-in',
signUp: '/auth/sign-up',
verifyMfa: '/auth/verify',
callback: '/auth/callback',
passwordReset: '/auth/password-reset',
passwordUpdate: '/password-reset',
},
app: {
home: '/home',
personalAccountSettings: '/home/account',
personalAccountBilling: '/home/billing',
accountHome: '/home/[account]',
accountSettings: `/home/[account]/settings`,
accountBilling: `/home/[account]/billing`,
accountMembers: `/home/[account]/members`,
},
});
export default pathsConfig;

View File

@@ -0,0 +1,33 @@
import { CreditCardIcon, HomeIcon, UserIcon } from 'lucide-react';
import featureFlagsConfig from '~/config/feature-flags.config';
import pathsConfig from '~/config/paths.config';
import { SidebarConfigSchema } from '@kit/ui/sidebar-schema';
const iconClasses = 'w-4';
const routes = [
{
label: 'common:homeTabLabel',
path: pathsConfig.app.home,
Icon: <HomeIcon className={iconClasses} />,
end: true,
},
{
label: 'common:yourAccountTabLabel',
path: pathsConfig.app.personalAccountSettings,
Icon: <UserIcon className={iconClasses} />,
},
];
if (featureFlagsConfig.enablePersonalAccountBilling) {
routes.push({
label: 'common:billingTabLabel',
path: pathsConfig.app.personalAccountBilling,
Icon: <CreditCardIcon className={iconClasses} />,
});
}
export const personalAccountSidebarConfig = SidebarConfigSchema.parse({
routes,
});