refactor: clean up imports and enhance error logging in user workspace and team invitations actions

This commit is contained in:
Danel Kungla
2025-07-08 18:34:21 +03:00
parent 29ff8cb512
commit 4f36f9c037
5 changed files with 41 additions and 33 deletions

View File

@@ -1,3 +1,6 @@
import { use } from 'react';
import { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
@@ -6,9 +9,7 @@ import { withI18n } from '~/lib/i18n/with-i18n';
import Dashboard from '../_components/dashboard'; import Dashboard from '../_components/dashboard';
// local imports // local imports
import { HomeLayoutPageHeader } from '../_components/home-page-header'; import { HomeLayoutPageHeader } from '../_components/home-page-header';
import { use } from 'react';
import { loadUserWorkspace } from '../_lib/server/load-user-workspace'; import { loadUserWorkspace } from '../_lib/server/load-user-workspace';
import { PageBody } from '@kit/ui/page';
export const generateMetadata = async () => { export const generateMetadata = async () => {
const i18n = await createI18nServerInstance(); const i18n = await createI18nServerInstance();

View File

@@ -35,13 +35,13 @@ async function workspaceLoader() {
accountsPromise(), accountsPromise(),
workspacePromise, workspacePromise,
requireUserInServerComponent(), requireUserInServerComponent(),
tempAccountsPromise() tempAccountsPromise(),
]); ]);
return { return {
accounts, accounts,
workspace, workspace,
user, user,
tempVisibleAccounts tempVisibleAccounts,
}; };
} }

View File

@@ -56,6 +56,7 @@ class AccountsApi {
const { data, error: userError } = authUser; const { data, error: userError } = authUser;
if (userError) { if (userError) {
console.error('Failed to get user', userError);
throw userError; throw userError;
} }
@@ -65,25 +66,26 @@ class AccountsApi {
.from('accounts_memberships') .from('accounts_memberships')
.select( .select(
` `
account_id, account_id,
user_accounts ( accounts (
name, name,
slug, slug,
picture_url, picture_url
) )
`, `,
) )
.eq('user_id', user.id) .eq('user_id', user.id)
.eq('account_role', 'owner'); .eq('account_role', 'owner');
if (error) { if (error) {
console.error('error', error);
throw error; throw error;
} }
return accounts.map(({ user_accounts }) => ({ return accounts.map(({ accounts }) => ({
label: user_accounts.name, label: accounts.name,
value: user_accounts.slug, value: accounts.slug,
image: user_accounts.picture_url, image: accounts.picture_url,
})); }));
} }

View File

@@ -47,7 +47,7 @@ export function MultiFactorChallengeContainer({
const verifyMFAChallenge = useVerifyMFAChallenge({ const verifyMFAChallenge = useVerifyMFAChallenge({
onSuccess: () => { onSuccess: () => {
router.replace(paths.redirectPath); router.replace('/');
}, },
}); });

View File

@@ -6,6 +6,8 @@ import { redirect } from 'next/navigation';
import { z } from 'zod'; import { z } from 'zod';
import { enhanceAction } from '@kit/next/actions'; import { enhanceAction } from '@kit/next/actions';
import { createNotificationsApi } from '@kit/notifications/api';
import { getLogger } from '@kit/shared/logger';
import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client';
import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client';
@@ -16,8 +18,6 @@ import { RenewInvitationSchema } from '../../schema/renew-invitation.schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation.schema'; import { UpdateInvitationSchema } from '../../schema/update-invitation.schema';
import { createAccountInvitationsService } from '../services/account-invitations.service'; import { createAccountInvitationsService } from '../services/account-invitations.service';
import { createAccountPerSeatBillingService } from '../services/account-per-seat-billing.service'; import { createAccountPerSeatBillingService } from '../services/account-per-seat-billing.service';
import { createNotificationsApi } from '@kit/notifications/api';
import { getLogger } from '@kit/shared/logger';
/** /**
* @name createInvitationsAction * @name createInvitationsAction
@@ -32,48 +32,53 @@ export const createInvitationsAction = enhanceAction(
const service = createAccountInvitationsService(client); const service = createAccountInvitationsService(client);
const api = createNotificationsApi(serviceClient); const api = createNotificationsApi(serviceClient);
//TODO: This does not send email. It only creates invitations in the database.
await service.sendInvitations(params); await service.sendInvitations(params);
const { invitations: invitationParams, accountSlug } = params; const { invitations: invitationParams, accountSlug } = params;
const personalCodes = invitationParams.map(({ personal_code }) => personal_code); const personalCodes = invitationParams.map(
({ personal_code }) => personal_code,
);
const { data: company, error: companyError } = await client const { data: company, error: companyError } = await client
.from('accounts') .from('accounts')
.select('id') .select('id')
.eq('slug', accountSlug); .eq('slug', accountSlug);
logger.debug({ company, companyError, personalCodes }) logger.debug({ company, companyError, personalCodes });
if (companyError || !company?.length || !company[0]) { if (companyError || !company?.length || !company[0]) {
throw new Error(`Failed to fetch company id: ${companyError?.message || 'not found'}`); throw new Error(
`Failed to fetch company id: ${companyError?.message || 'not found'}`,
);
} }
const { data: invitations, error: invitationError } = await serviceClient.rpc( const { data: invitations, error: invitationError } =
'get_invitations_with_account_ids', await serviceClient.rpc('get_invitations_with_account_ids', {
{
company_id: company[0].id, company_id: company[0].id,
personal_codes: personalCodes, personal_codes: personalCodes,
} });
);
logger.debug({ invitations, invitationError }) logger.debug({ invitations, invitationError });
if (invitationError) { if (invitationError) {
throw new Error(`Failed to fetch invitations with accounts: ${invitationError.message}`); throw new Error(
`Failed to fetch invitations with accounts: ${invitationError.message}`,
);
} }
const notificationPromises = invitations const notificationPromises = invitations.map(
.map(({ invite_token, account_id }) => ({ invite_token, account_id }) =>
api.createNotification({ api.createNotification({
account_id: account_id!, account_id: account_id!,
body: `You are invited to join the company: ${accountSlug}`, body: `You are invited to join the company: ${accountSlug}`,
link: `/join?invite_token=${invite_token}`, link: `/join?invite_token=${invite_token}`,
}) }),
); );
await Promise.all(notificationPromises); await Promise.all(notificationPromises);
logger.info('All invitation notifications are sent') logger.info('All invitation notifications are sent');
revalidateMemberPage(); revalidateMemberPage();
return { return {