Refactor authentication and internationalize metadata
This commit simplifies the authentication mechanism by directly comparing user ID and primary owner ID while refactoring the Team Account container. Simultaneously, it internationalizes the metadata of several pages by creating server I18n instances for title translations, ensuring better support for varied languages.
This commit is contained in:
@@ -12,12 +12,22 @@ import { Trans } from '@kit/ui/trans';
|
|||||||
|
|
||||||
import { createPersonalAccountBillingPortalSession } from '~/(dashboard)/home/(user)/billing/server-actions';
|
import { createPersonalAccountBillingPortalSession } from '~/(dashboard)/home/(user)/billing/server-actions';
|
||||||
import billingConfig from '~/config/billing.config';
|
import billingConfig from '~/config/billing.config';
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
import { PersonalAccountCheckoutForm } from './_components/personal-account-checkout-form';
|
import { PersonalAccountCheckoutForm } from './_components/personal-account-checkout-form';
|
||||||
|
|
||||||
type Subscription = Database['public']['Tables']['subscriptions']['Row'];
|
type Subscription = Database['public']['Tables']['subscriptions']['Row'];
|
||||||
|
|
||||||
|
export const generateMetadata = async () => {
|
||||||
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('account:billingTab');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
async function PersonalAccountBillingPage() {
|
async function PersonalAccountBillingPage() {
|
||||||
const client = getSupabaseServerComponentClient();
|
const client = getSupabaseServerComponentClient();
|
||||||
const [subscription, customerId] = await loadData(client);
|
const [subscription, customerId] = await loadData(client);
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
import { PageBody, PageHeader } from '@kit/ui/page';
|
import { PageBody, PageHeader } from '@kit/ui/page';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
export const generateMetadata = async () => {
|
||||||
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('account:homePage');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function UserHomePage() {
|
function UserHomePage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { PageBody } from '@kit/ui/page';
|
|||||||
|
|
||||||
import featureFlagsConfig from '~/config/feature-flags.config';
|
import featureFlagsConfig from '~/config/feature-flags.config';
|
||||||
import pathsConfig from '~/config/paths.config';
|
import pathsConfig from '~/config/paths.config';
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
const features = {
|
const features = {
|
||||||
@@ -13,6 +14,15 @@ const paths = {
|
|||||||
callback: pathsConfig.auth.callback + `?next=${pathsConfig.app.accountHome}`,
|
callback: pathsConfig.auth.callback + `?next=${pathsConfig.app.accountHome}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const generateMetadata = async () => {
|
||||||
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('account:settingsTab');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function PersonalAccountSettingsPage() {
|
function PersonalAccountSettingsPage() {
|
||||||
return (
|
return (
|
||||||
<PageBody>
|
<PageBody>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { Trans } from '@kit/ui/trans';
|
|||||||
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
|
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
|
||||||
import { createBillingPortalSession } from '~/(dashboard)/home/[account]/billing/server-actions';
|
import { createBillingPortalSession } from '~/(dashboard)/home/[account]/billing/server-actions';
|
||||||
import billingConfig from '~/config/billing.config';
|
import billingConfig from '~/config/billing.config';
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
import { TeamAccountCheckoutForm } from './_components/team-account-checkout-form';
|
import { TeamAccountCheckoutForm } from './_components/team-account-checkout-form';
|
||||||
@@ -21,6 +22,15 @@ interface Params {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const generateMetadata = async () => {
|
||||||
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('teams:billing.pageTitle');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
async function TeamAccountBillingPage({ params }: Params) {
|
async function TeamAccountBillingPage({ params }: Params) {
|
||||||
const workspace = await loadTeamWorkspace(params.account);
|
const workspace = await loadTeamWorkspace(params.account);
|
||||||
const accountId = workspace.account.id;
|
const accountId = workspace.account.id;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { PageBody, PageHeader } from '@kit/ui/page';
|
|||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
|
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
interface Params {
|
interface Params {
|
||||||
@@ -80,6 +81,15 @@ async function loadData(client: SupabaseClient<Database>, slug: string) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const generateMetadata = async () => {
|
||||||
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('teams:members.pageTitle');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
async function TeamAccountMembersPage({ params }: Params) {
|
async function TeamAccountMembersPage({ params }: Params) {
|
||||||
const client = getSupabaseServerComponentClient();
|
const client = getSupabaseServerComponentClient();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import Spinner from '@kit/ui/spinner';
|
|||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { AppHeader } from '~/(dashboard)/home/[account]/_components/app-header';
|
import { AppHeader } from '~/(dashboard)/home/[account]/_components/app-header';
|
||||||
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
const DashboardDemo = loadDynamic(
|
const DashboardDemo = loadDynamic(
|
||||||
@@ -31,8 +32,13 @@ const DashboardDemo = loadDynamic(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const metadata = {
|
export const generateMetadata = async () => {
|
||||||
title: 'Organization Account Home',
|
const i18n = await createI18nServerInstance();
|
||||||
|
const title = i18n.t('teams:home.pageTitle');
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function TeamAccountHomePage({
|
function TeamAccountHomePage({
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import { TeamAccountSettingsContainer } from '@kit/team-accounts/components';
|
|||||||
import { PageBody, PageHeader } from '@kit/ui/page';
|
import { PageBody, PageHeader } from '@kit/ui/page';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { loadTeamWorkspace } from '~/(dashboard)/home/[account]/_lib/load-team-account-workspace';
|
|
||||||
import pathsConfig from '~/config/paths.config';
|
import pathsConfig from '~/config/paths.config';
|
||||||
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||||
|
|
||||||
|
import { loadTeamWorkspace } from '../_lib/load-team-account-workspace';
|
||||||
|
|
||||||
export const generateMetadata = async () => {
|
export const generateMetadata = async () => {
|
||||||
const i18n = await createI18nServerInstance();
|
const i18n = await createI18nServerInstance();
|
||||||
const title = i18n.t('accounts:settings:pageTitle');
|
const title = i18n.t('teams:settings:pageTitle');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
@@ -27,6 +28,7 @@ const paths = {
|
|||||||
|
|
||||||
async function TeamAccountSettingsPage(props: Props) {
|
async function TeamAccountSettingsPage(props: Props) {
|
||||||
const data = await loadTeamWorkspace(props.params.account);
|
const data = await loadTeamWorkspace(props.params.account);
|
||||||
|
|
||||||
const account = {
|
const account = {
|
||||||
id: data.account.id,
|
id: data.account.id,
|
||||||
name: data.account.name,
|
name: data.account.name,
|
||||||
@@ -48,11 +50,7 @@ async function TeamAccountSettingsPage(props: Props) {
|
|||||||
'container mx-auto flex max-w-2xl flex-1 flex-col items-center'
|
'container mx-auto flex max-w-2xl flex-1 flex-col items-center'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<TeamAccountSettingsContainer
|
<TeamAccountSettingsContainer account={account} paths={paths} />
|
||||||
userId={data.user.id}
|
|
||||||
account={account}
|
|
||||||
paths={paths}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</PageBody>
|
</PageBody>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
"manageConnectedAccounts": "Connected Accounts",
|
"manageConnectedAccounts": "Connected Accounts",
|
||||||
"manageConnectedAccountsSubheading": "Manage your connected accounts",
|
"manageConnectedAccountsSubheading": "Manage your connected accounts",
|
||||||
"connectedAccounts": "Connected Accounts",
|
"connectedAccounts": "Connected Accounts",
|
||||||
|
"homePage": "Home",
|
||||||
|
"billingTab": "Billing",
|
||||||
|
"settingsTab": "Settings",
|
||||||
"authenticationTab": "Authentication",
|
"authenticationTab": "Authentication",
|
||||||
"multiFactorAuth": "Multi-Factor Authentication",
|
"multiFactorAuth": "Multi-Factor Authentication",
|
||||||
"multiFactorAuthDescription": "Set up Multi-Factor Authentication method to further secure your account",
|
"multiFactorAuthDescription": "Set up Multi-Factor Authentication method to further secure your account",
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"home": {
|
||||||
|
"pageTitle": "Home"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"pageTitle": "Settings",
|
"pageTitle": "Settings",
|
||||||
"pageDescription": "Manage your Team details",
|
"pageDescription": "Manage your Team details",
|
||||||
@@ -9,6 +12,12 @@
|
|||||||
"dangerZone": "Danger Zone",
|
"dangerZone": "Danger Zone",
|
||||||
"dangerZoneDescription": "This section contains actions that are irreversible"
|
"dangerZoneDescription": "This section contains actions that are irreversible"
|
||||||
},
|
},
|
||||||
|
"members": {
|
||||||
|
"pageTitle": "Members"
|
||||||
|
},
|
||||||
|
"billing": {
|
||||||
|
"pageTitle": "Billing"
|
||||||
|
},
|
||||||
"yourTeams": "Your Teams",
|
"yourTeams": "Your Teams",
|
||||||
"createTeam": "Create a Team",
|
"createTeam": "Create a Team",
|
||||||
"personalAccount": "Personal Account",
|
"personalAccount": "Personal Account",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { useUser } from '@kit/supabase/hooks/use-user';
|
||||||
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@@ -29,6 +30,7 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { Input } from '@kit/ui/input';
|
import { Input } from '@kit/ui/input';
|
||||||
|
import { LoadingOverlay } from '@kit/ui/loading-overlay';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { deleteTeamAccountAction } from '../../server/actions/delete-team-account-server-actions';
|
import { deleteTeamAccountAction } from '../../server/actions/delete-team-account-server-actions';
|
||||||
@@ -36,15 +38,23 @@ import { leaveTeamAccountAction } from '../../server/actions/leave-team-account-
|
|||||||
|
|
||||||
export function TeamAccountDangerZone({
|
export function TeamAccountDangerZone({
|
||||||
account,
|
account,
|
||||||
userIsPrimaryOwner,
|
primaryOwnerUserId,
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
account: {
|
account: {
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
userIsPrimaryOwner: boolean;
|
primaryOwnerUserId: string;
|
||||||
}>) {
|
}>) {
|
||||||
|
const { data: user, isLoading } = useUser();
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <LoadingOverlay fullPage={false} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userIsPrimaryOwner = user?.id === primaryOwnerUserId;
|
||||||
|
|
||||||
if (userIsPrimaryOwner) {
|
if (userIsPrimaryOwner) {
|
||||||
return <DeleteTeamContainer account={account} />;
|
return <DeleteTeamContainer account={account} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ export function TeamAccountSettingsContainer(props: {
|
|||||||
primaryOwnerUserId: string;
|
primaryOwnerUserId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
userId: string;
|
|
||||||
|
|
||||||
paths: {
|
paths: {
|
||||||
teamAccountSettings: string;
|
teamAccountSettings: string;
|
||||||
};
|
};
|
||||||
@@ -78,9 +76,7 @@ export function TeamAccountSettingsContainer(props: {
|
|||||||
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TeamAccountDangerZone
|
<TeamAccountDangerZone
|
||||||
userIsPrimaryOwner={
|
primaryOwnerUserId={props.account.primaryOwnerUserId}
|
||||||
props.userId === props.account.primaryOwnerUserId
|
|
||||||
}
|
|
||||||
account={props.account}
|
account={props.account}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user