improve signup container
This commit is contained in:
@@ -57,10 +57,9 @@ async function SignUpPage({ searchParams }: Props) {
|
||||
</div>
|
||||
|
||||
<SignUpMethodsContainer
|
||||
providers={authConfig.providers}
|
||||
authConfig={authConfig}
|
||||
inviteToken={inviteToken}
|
||||
paths={paths}
|
||||
displayTermsCheckbox={authConfig.displayTermsCheckbox}
|
||||
/>
|
||||
|
||||
<div className={'flex justify-center'}>
|
||||
|
||||
@@ -59,10 +59,10 @@ export function UpdateAccountForm({
|
||||
const loading = toast.loading(t('updateAccount.updateAccountLoading'));
|
||||
try {
|
||||
const response = await onUpdateAccount({
|
||||
firstName: hasFirstName ? firstName : values.firstName,
|
||||
lastName: hasLastName ? lastName : values.lastName,
|
||||
personalCode: hasPersonalCode ? personalCode : values.personalCode,
|
||||
email: hasEmail ? email : values.email,
|
||||
firstName: values.firstName || firstName,
|
||||
lastName: values.lastName || lastName,
|
||||
personalCode: values.personalCode || personalCode,
|
||||
email: values.email || email,
|
||||
phone: values.phone,
|
||||
weight: ((("weight" in values && values.weight) ?? defaultValues_weight) || null) as number,
|
||||
height: ((("height" in values && values.height) ?? defaultValues_height) || null) as number,
|
||||
|
||||
@@ -7,9 +7,8 @@ export function AuthLayoutShell({
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'sm:py-auto flex flex-col items-center justify-center py-6' +
|
||||
' bg-background lg:bg-muted/30 gap-y-10 lg:gap-y-8' +
|
||||
' animate-in fade-in slide-in-from-top-16 zoom-in-95 duration-1000'
|
||||
'sm:py-auto flex flex-col items-center justify-center py-6 h-screen' +
|
||||
' bg-background lg:bg-muted/30 gap-y-10 lg:gap-y-8'
|
||||
}
|
||||
>
|
||||
{Logo ? <Logo /> : null}
|
||||
|
||||
@@ -113,12 +113,16 @@ export const OauthProviders: React.FC<{
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Trans
|
||||
i18nKey={'auth:signInWithProvider'}
|
||||
values={{
|
||||
provider: getProviderName(provider),
|
||||
}}
|
||||
/>
|
||||
{provider === 'keycloak' ? (
|
||||
<Trans i18nKey={'auth:signInWithKeycloak'} />
|
||||
) : (
|
||||
<Trans
|
||||
i18nKey={'auth:signInWithProvider'}
|
||||
values={{
|
||||
provider: getProviderName(provider),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</AuthProviderButton>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -10,9 +10,18 @@ import { useCaptchaToken } from '../captcha/client';
|
||||
import { usePasswordSignUpFlow } from '../hooks/use-sign-up-flow';
|
||||
import { AuthErrorAlert } from './auth-error-alert';
|
||||
import { PasswordSignUpForm } from './password-sign-up-form';
|
||||
import { Spinner } from '@kit/ui/makerkit/spinner';
|
||||
|
||||
interface EmailPasswordSignUpContainerProps {
|
||||
displayTermsCheckbox?: boolean;
|
||||
authConfig: {
|
||||
providers: {
|
||||
password: boolean;
|
||||
magicLink: boolean;
|
||||
oAuth: string[];
|
||||
};
|
||||
displayTermsCheckbox: boolean | undefined;
|
||||
isMailerAutoconfirmEnabled: boolean;
|
||||
};
|
||||
defaultValues?: {
|
||||
email: string;
|
||||
};
|
||||
@@ -21,10 +30,10 @@ interface EmailPasswordSignUpContainerProps {
|
||||
}
|
||||
|
||||
export function EmailPasswordSignUpContainer({
|
||||
authConfig,
|
||||
defaultValues,
|
||||
onSignUp,
|
||||
emailRedirectTo,
|
||||
displayTermsCheckbox,
|
||||
}: EmailPasswordSignUpContainerProps) {
|
||||
const { captchaToken, resetCaptchaToken } = useCaptchaToken();
|
||||
|
||||
@@ -43,7 +52,12 @@ export function EmailPasswordSignUpContainer({
|
||||
return (
|
||||
<>
|
||||
<If condition={showVerifyEmailAlert}>
|
||||
<SuccessAlert />
|
||||
{authConfig.isMailerAutoconfirmEnabled ? (
|
||||
<div className="flex justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : <SuccessAlert />
|
||||
}
|
||||
</If>
|
||||
|
||||
<If condition={!showVerifyEmailAlert}>
|
||||
@@ -53,7 +67,7 @@ export function EmailPasswordSignUpContainer({
|
||||
onSubmit={onSignupRequested}
|
||||
loading={loading}
|
||||
defaultValues={defaultValues}
|
||||
displayTermsCheckbox={displayTermsCheckbox}
|
||||
displayTermsCheckbox={authConfig.displayTermsCheckbox}
|
||||
/>
|
||||
</If>
|
||||
</>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import type { Provider } from '@supabase/supabase-js';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { isBrowser } from '@kit/shared/utils';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||
@@ -19,15 +20,20 @@ export function SignUpMethodsContainer(props: {
|
||||
updateAccount: string;
|
||||
};
|
||||
|
||||
providers: {
|
||||
password: boolean;
|
||||
magicLink: boolean;
|
||||
oAuth: Provider[];
|
||||
authConfig: {
|
||||
providers: {
|
||||
password: boolean;
|
||||
magicLink: boolean;
|
||||
oAuth: Provider[];
|
||||
};
|
||||
displayTermsCheckbox: boolean | undefined;
|
||||
isMailerAutoconfirmEnabled: boolean;
|
||||
};
|
||||
|
||||
displayTermsCheckbox?: boolean;
|
||||
inviteToken?: string;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
const redirectUrl = getCallbackUrl(props);
|
||||
const defaultValues = getDefaultValues();
|
||||
|
||||
@@ -37,26 +43,33 @@ export function SignUpMethodsContainer(props: {
|
||||
<InviteAlert />
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.password}>
|
||||
<If condition={props.authConfig.providers.password}>
|
||||
<EmailPasswordSignUpContainer
|
||||
emailRedirectTo={props.paths.callback}
|
||||
defaultValues={defaultValues}
|
||||
displayTermsCheckbox={props.displayTermsCheckbox}
|
||||
//onSignUp={() => redirect(redirectUrl)}
|
||||
authConfig={props.authConfig}
|
||||
onSignUp={() => {
|
||||
if (!props.authConfig.isMailerAutoconfirmEnabled) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
router.replace(props.paths.updateAccount)
|
||||
}, 2_500);
|
||||
}}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.magicLink}>
|
||||
<If condition={props.authConfig.providers.magicLink}>
|
||||
<MagicLinkAuthContainer
|
||||
inviteToken={props.inviteToken}
|
||||
redirectUrl={redirectUrl}
|
||||
shouldCreateUser={true}
|
||||
defaultValues={defaultValues}
|
||||
displayTermsCheckbox={props.displayTermsCheckbox}
|
||||
displayTermsCheckbox={props.authConfig.displayTermsCheckbox}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.oAuth.length}>
|
||||
<If condition={props.authConfig.providers.oAuth.length}>
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<Separator />
|
||||
@@ -70,7 +83,7 @@ export function SignUpMethodsContainer(props: {
|
||||
</div>
|
||||
|
||||
<OauthProviders
|
||||
enabledProviders={props.providers.oAuth}
|
||||
enabledProviders={props.authConfig.providers.oAuth}
|
||||
inviteToken={props.inviteToken}
|
||||
shouldCreateUser={true}
|
||||
paths={{
|
||||
|
||||
@@ -23,7 +23,7 @@ export function InfoTooltip({
|
||||
<TooltipTrigger>
|
||||
{icon || <Info className="size-4 cursor-pointer" />}
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className='sm:max-w-[400px]'>{content}</TooltipContent>
|
||||
<TooltipContent className='max-w-[90vw] sm:max-w-[400px]'>{content}</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ type SupabaseExternalProvider = Provider | 'email';
|
||||
interface SupabaseAuthSettings {
|
||||
external: Record<SupabaseExternalProvider, boolean>;
|
||||
disable_signup: boolean;
|
||||
mailer_autoconfirm: boolean;
|
||||
}
|
||||
|
||||
export class AuthProvidersService {
|
||||
@@ -61,6 +62,10 @@ export class AuthProvidersService {
|
||||
return process.env.NEXT_PUBLIC_AUTH_PASSWORD === 'true';
|
||||
}
|
||||
|
||||
isMailerAutoconfirmEnabled({ settings }: { settings: SupabaseAuthSettings | null }): boolean {
|
||||
return settings?.mailer_autoconfirm === true;
|
||||
}
|
||||
|
||||
isMagicLinkEnabled(): boolean {
|
||||
return process.env.NEXT_PUBLIC_AUTH_MAGIC_LINK === 'true';
|
||||
}
|
||||
@@ -105,10 +110,11 @@ export class AuthProvidersService {
|
||||
|
||||
async getAuthConfig() {
|
||||
const settings = await this.fetchAuthSettings();
|
||||
const [passwordEnabled, magicLinkEnabled, oAuthProviders] = await Promise.all([
|
||||
const [passwordEnabled, magicLinkEnabled, oAuthProviders, isMailerAutoconfirmEnabled] = await Promise.all([
|
||||
this.isPasswordEnabled({ settings }),
|
||||
this.isMagicLinkEnabled(),
|
||||
this.getEnabledOAuthProviders({ settings }),
|
||||
this.isMailerAutoconfirmEnabled({ settings }),
|
||||
]);
|
||||
|
||||
return {
|
||||
@@ -118,6 +124,7 @@ export class AuthProvidersService {
|
||||
oAuth: oAuthProviders,
|
||||
},
|
||||
displayTermsCheckbox: authConfig.displayTermsCheckbox,
|
||||
isMailerAutoconfirmEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,19 @@ const DynamicAuthConfigSchema = z.object({
|
||||
oAuth: providers.array(),
|
||||
}),
|
||||
displayTermsCheckbox: z.boolean().describe('Whether to display the terms checkbox during sign-up.'),
|
||||
isMailerAutoconfirmEnabled: z.boolean().describe('Whether Supabase sends confirmation email automatically.'),
|
||||
});
|
||||
|
||||
export type DynamicAuthConfig = {
|
||||
providers: {
|
||||
password: boolean;
|
||||
magicLink: boolean;
|
||||
oAuth: Provider[];
|
||||
};
|
||||
displayTermsCheckbox: boolean | undefined;
|
||||
isMailerAutoconfirmEnabled: boolean;
|
||||
}
|
||||
|
||||
export async function getDynamicAuthConfig() {
|
||||
const authService = createAuthProvidersService();
|
||||
const dynamicProviders = await authService.getAuthConfig();
|
||||
@@ -20,6 +31,7 @@ export async function getDynamicAuthConfig() {
|
||||
const config = {
|
||||
providers: dynamicProviders.providers,
|
||||
displayTermsCheckbox: dynamicProviders.displayTermsCheckbox,
|
||||
isMailerAutoconfirmEnabled: dynamicProviders.isMailerAutoconfirmEnabled,
|
||||
};
|
||||
|
||||
return DynamicAuthConfigSchema.parse(config);
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
createPath,
|
||||
getTeamAccountSidebarConfig,
|
||||
} from './team-account-navigation.config';
|
||||
import { getCachedAuthConfig, getServerAuthConfig } from './dynamic-auth.config';
|
||||
import { DynamicAuthConfig, getCachedAuthConfig, getServerAuthConfig } from './dynamic-auth.config';
|
||||
|
||||
export {
|
||||
appConfig,
|
||||
@@ -21,4 +21,5 @@ export {
|
||||
personalAccountNavigationConfig,
|
||||
getCachedAuthConfig,
|
||||
getServerAuthConfig,
|
||||
type DynamicAuthConfig,
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ function PageWithSidebar(props: PageProps) {
|
||||
>
|
||||
{MobileNavigation}
|
||||
|
||||
<div className={'bg-background flex flex-1 flex-col px-4 pb-8 lg:px-0'}>
|
||||
<div className={'bg-background flex flex-1 flex-col px-2 pb-8 lg:px-0'}>
|
||||
{Children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,7 @@ const CardHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
|
||||
<div className={cn('flex flex-col space-y-1.5 p-4 sm:p-6', className)} {...props} />
|
||||
);
|
||||
CardHeader.displayName = 'CardHeader';
|
||||
|
||||
@@ -60,14 +60,14 @@ CardDescription.displayName = 'CardDescription';
|
||||
const CardContent: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({
|
||||
className,
|
||||
...props
|
||||
}) => <div className={cn('p-6 pt-0', className)} {...props} />;
|
||||
}) => <div className={cn('p-4 sm:p-6 pt-0', className)} {...props} />;
|
||||
CardContent.displayName = 'CardContent';
|
||||
|
||||
const CardFooter: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div className={cn('flex items-center p-6 pt-0', className)} {...props} />
|
||||
<div className={cn('flex items-center p-4 sm:p-6 pt-0', className)} {...props} />
|
||||
);
|
||||
CardFooter.displayName = 'CardFooter';
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"alreadyHaveAccountStatement": "I already have an account, I want to sign in instead",
|
||||
"doNotHaveAccountStatement": "I do not have an account, I want to sign up instead",
|
||||
"signInWithProvider": "Sign in with {{provider}}",
|
||||
"signInWithKeycloak": "Smart-ID/Mobile-ID/ID-card",
|
||||
"signInWithPhoneNumber": "Sign in with Phone Number",
|
||||
"signInWithEmail": "Sign in with Email",
|
||||
"signUpWithEmail": "Sign up with Email",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"signUpHeading": "Loo konto",
|
||||
"signUp": "Loo konto",
|
||||
"signUpSubheading": "Täida allolev vorm, et luua konto.",
|
||||
"signInHeading": "Logi oma kontole sisse",
|
||||
"signInHeading": "Logi sisse",
|
||||
"signInSubheading": "Tere tulemast tagasi! Palun sisesta oma andmed",
|
||||
"signIn": "Logi sisse",
|
||||
"getStarted": "Alusta",
|
||||
@@ -22,6 +22,7 @@
|
||||
"alreadyHaveAccountStatement": "Mul on juba konto, ma tahan sisse logida",
|
||||
"doNotHaveAccountStatement": "Mul pole kontot, ma tahan registreeruda",
|
||||
"signInWithProvider": "Logi sisse teenusega {{provider}}",
|
||||
"signInWithKeycloak": "Smart-ID/Mobiil-ID/ID-kaart",
|
||||
"signInWithPhoneNumber": "Logi sisse telefoninumbriga",
|
||||
"signInWithEmail": "Logi sisse e-posti aadressiga",
|
||||
"signUpWithEmail": "Registreeru e-posti aadressiga",
|
||||
@@ -68,7 +69,7 @@
|
||||
"acceptTermsAndConditions": "Ma nõustun <TermsOfServiceLink /> ja <PrivacyPolicyLink />",
|
||||
"termsOfService": "Kasutustingimused",
|
||||
"privacyPolicy": "Privaatsuspoliitika",
|
||||
"orContinueWith": "Või jätka koos",
|
||||
"orContinueWith": "Või",
|
||||
"redirecting": "Oled sees! Palun oota...",
|
||||
"errors": {
|
||||
"Invalid login credentials": "Sisestatud andmed on valed",
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"alreadyHaveAccountStatement": "У меня уже есть аккаунт, я хочу войти",
|
||||
"doNotHaveAccountStatement": "У меня нет аккаунта, я хочу зарегистрироваться",
|
||||
"signInWithProvider": "Войти через {{provider}}",
|
||||
"signInWithKeycloak": "Smart-ID/Mobiil-ID/ID-kaart",
|
||||
"signInWithPhoneNumber": "Войти по номеру телефона",
|
||||
"signInWithEmail": "Войти по Email",
|
||||
"signUpWithEmail": "Зарегистрироваться по Email",
|
||||
|
||||
Reference in New Issue
Block a user