Cleanup
This commit is contained in:
34
apps/web/config/app.config.ts
Normal file
34
apps/web/config/app.config.ts
Normal 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;
|
||||
53
apps/web/config/auth.config.ts
Normal file
53
apps/web/config/auth.config.ts
Normal 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',
|
||||
]);
|
||||
}
|
||||
96
apps/web/config/billing.config.ts
Normal file
96
apps/web/config/billing.config.ts
Normal 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',
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
49
apps/web/config/feature-flags.config.ts
Normal file
49
apps/web/config/feature-flags.config.ts
Normal 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;
|
||||
}
|
||||
54
apps/web/config/organization-account-sidebar.config.tsx
Normal file
54
apps/web/config/organization-account-sidebar.config.tsx
Normal 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);
|
||||
}
|
||||
43
apps/web/config/paths.config.ts
Normal file
43
apps/web/config/paths.config.ts
Normal 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;
|
||||
33
apps/web/config/personal-account-sidebar.config.tsx
Normal file
33
apps/web/config/personal-account-sidebar.config.tsx
Normal 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,
|
||||
});
|
||||
Reference in New Issue
Block a user