chore: bump version to 2.20.1 in package.json and refactor layout and… (#404)
* chore: bump version to 2.20.1 in package.json and refactor layout and form components - Incremented application version from 2.20.0 to 2.20.1 in package.json. - Refactored RootLayout to optimize asynchronous calls and introduced getRootClassName function for better class management. - Updated font handling in getFontsClassName function to streamline class generation. - Enhanced various authentication form components by replacing Input with EmailInput and PasswordInput for improved consistency and usability. - Adjusted layout styles in AuthLayoutShell and other components for better responsiveness. * fix: improve content rendering fallback logic in ContentRenderer component - Enhanced the ContentRenderer function to explicitly check for the presence of a renderer before returning content. - Added a fallback mechanism to return raw content as React nodes when no renderer is found, improving robustness and user experience.
This commit is contained in:
committed by
GitHub
parent
116d41a284
commit
ac12c9355c
@@ -1,6 +1,7 @@
|
|||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
|
|
||||||
import { Toaster } from '@kit/ui/sonner';
|
import { Toaster } from '@kit/ui/sonner';
|
||||||
|
import { cn } from '@kit/ui/utils';
|
||||||
|
|
||||||
import { RootProviders } from '~/components/root-providers';
|
import { RootProviders } from '~/components/root-providers';
|
||||||
import { getFontsClassName } from '~/lib/fonts';
|
import { getFontsClassName } from '~/lib/fonts';
|
||||||
@@ -19,13 +20,17 @@ export default async function RootLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const { language } = await createI18nServerInstance();
|
const [theme, nonce, i18n] = await Promise.all([
|
||||||
const theme = await getRootTheme();
|
getRootTheme(),
|
||||||
const className = getFontsClassName(theme);
|
getCspNonce(),
|
||||||
const nonce = await getCspNonce();
|
createI18nServerInstance(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const className = getRootClassName(theme);
|
||||||
|
const language = i18n.language;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={language} className={`${className} overscroll-y-none`}>
|
<html lang={language} className={className}>
|
||||||
<body>
|
<body>
|
||||||
<RootProviders theme={theme} lang={language} nonce={nonce}>
|
<RootProviders theme={theme} lang={language} nonce={nonce}>
|
||||||
{children}
|
{children}
|
||||||
@@ -37,6 +42,15 @@ export default async function RootLayout({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRootClassName(theme: string) {
|
||||||
|
const fontsClassName = getFontsClassName(theme);
|
||||||
|
|
||||||
|
return cn(
|
||||||
|
'bg-background min-h-screen overscroll-y-none antialiased',
|
||||||
|
fontsClassName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function getCspNonce() {
|
async function getCspNonce() {
|
||||||
const headersStore = await headers();
|
const headersStore = await headers();
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export function getFontsClassName(theme?: string) {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
return cn('bg-background min-h-screen antialiased', ...font, {
|
return cn(...font, {
|
||||||
dark,
|
dark,
|
||||||
light,
|
light,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-supabase-saas-kit-turbo",
|
"name": "next-supabase-saas-kit-turbo",
|
||||||
"version": "2.20.0",
|
"version": "2.20.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { CmsType } from '@kit/cms-types';
|
import { CmsType } from '@kit/cms-types';
|
||||||
|
import { createRegistry } from '@kit/shared/registry';
|
||||||
|
|
||||||
const CMS_CLIENT = process.env.CMS_CLIENT as CmsType;
|
const CMS_CLIENT = process.env.CMS_CLIENT as CmsType;
|
||||||
|
|
||||||
@@ -7,42 +8,34 @@ interface ContentRendererProps {
|
|||||||
type?: CmsType;
|
type?: CmsType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a registry for CMS client implementations
|
||||||
|
const cmsContentRendererRegistry = createRegistry<
|
||||||
|
React.ComponentType<ContentRendererProps>,
|
||||||
|
CmsType
|
||||||
|
>();
|
||||||
|
|
||||||
export async function ContentRenderer({
|
export async function ContentRenderer({
|
||||||
content,
|
content,
|
||||||
type = CMS_CLIENT,
|
type = CMS_CLIENT,
|
||||||
}: ContentRendererProps) {
|
}: ContentRendererProps) {
|
||||||
const Renderer = await getContentRenderer(type);
|
const Renderer = await cmsContentRendererRegistry.get(type);
|
||||||
|
|
||||||
return Renderer ? <Renderer content={content} /> : null;
|
if (Renderer) {
|
||||||
}
|
return <Renderer content={content} />;
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the content renderer for the specified CMS client.
|
|
||||||
*
|
|
||||||
* @param {CmsType} type - The type of CMS client.
|
|
||||||
*/
|
|
||||||
async function getContentRenderer(type: CmsType) {
|
|
||||||
switch (type) {
|
|
||||||
case 'keystatic': {
|
|
||||||
const { KeystaticContentRenderer } = await import(
|
|
||||||
'@kit/keystatic/renderer'
|
|
||||||
);
|
|
||||||
|
|
||||||
return KeystaticContentRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'wordpress': {
|
|
||||||
const { WordpressContentRenderer } = await import(
|
|
||||||
'@kit/wordpress/renderer'
|
|
||||||
);
|
|
||||||
|
|
||||||
return WordpressContentRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
console.error(`Unknown CMS client: ${type as string}`);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fallback to the raw content if no renderer is found
|
||||||
|
return content as React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmsContentRendererRegistry.register('keystatic', async () => {
|
||||||
|
const { KeystaticContentRenderer } = await import('@kit/keystatic/renderer');
|
||||||
|
|
||||||
|
return KeystaticContentRenderer;
|
||||||
|
});
|
||||||
|
|
||||||
|
cmsContentRendererRegistry.register('wordpress', async () => {
|
||||||
|
const { WordpressContentRenderer } = await import('@kit/wordpress/renderer');
|
||||||
|
|
||||||
|
return WordpressContentRenderer;
|
||||||
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function AuthLayoutShell({
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background flex w-full max-w-[23rem] flex-col gap-y-6 rounded-lg px-6 md:w-8/12 md:px-8 md:py-6 lg:w-5/12 lg:px-8 xl:w-4/12 xl:py-8',
|
'bg-background flex w-full max-w-[22rem] flex-col gap-y-6 rounded-lg px-6 md:w-8/12 md:px-8 md:py-6 lg:w-5/12 lg:px-8 xl:w-4/12 xl:py-8',
|
||||||
contentClassName,
|
contentClassName,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
30
packages/features/auth/src/components/email-input.tsx
Normal file
30
packages/features/auth/src/components/email-input.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Mail } from 'lucide-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupInput,
|
||||||
|
} from '@kit/ui/input-group';
|
||||||
|
|
||||||
|
export function EmailInput(props: React.ComponentProps<'input'>) {
|
||||||
|
const { t } = useTranslation('auth');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InputGroup className="dark:bg-background">
|
||||||
|
<InputGroupAddon>
|
||||||
|
<Mail className="h-4 w-4" />
|
||||||
|
</InputGroupAddon>
|
||||||
|
|
||||||
|
<InputGroupInput
|
||||||
|
data-test={'email-input'}
|
||||||
|
required
|
||||||
|
type="email"
|
||||||
|
placeholder={t('emailPlaceholder')}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -70,11 +70,7 @@ export function ExistingAccountHintImpl({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<If condition={Boolean(methodDescription)}>
|
<If condition={Boolean(methodDescription)}>
|
||||||
<Alert
|
<Alert data-test={'existing-account-hint'} className={className}>
|
||||||
data-test={'existing-account-hint'}
|
|
||||||
variant="info"
|
|
||||||
className={className}
|
|
||||||
>
|
|
||||||
<UserCheck className="h-4 w-4" />
|
<UserCheck className="h-4 w-4" />
|
||||||
|
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
@@ -84,10 +80,7 @@ export function ExistingAccountHintImpl({
|
|||||||
components={{
|
components={{
|
||||||
method: <span className="font-medium" />,
|
method: <span className="font-medium" />,
|
||||||
signInLink: (
|
signInLink: (
|
||||||
<Link
|
<Link href={signInPath} className="font-medium underline" />
|
||||||
href={signInPath}
|
|
||||||
className="font-medium underline hover:no-underline"
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { If } from '@kit/ui/if';
|
import { If } from '@kit/ui/if';
|
||||||
import { Input } from '@kit/ui/input';
|
|
||||||
import { toast } from '@kit/ui/sonner';
|
import { toast } from '@kit/ui/sonner';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { useCaptcha } from '../captcha/client';
|
import { useCaptcha } from '../captcha/client';
|
||||||
import { useLastAuthMethod } from '../hooks/use-last-auth-method';
|
import { useLastAuthMethod } from '../hooks/use-last-auth-method';
|
||||||
|
import { EmailInput } from './email-input';
|
||||||
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
|
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
|
||||||
|
|
||||||
export function MagicLinkAuthContainer({
|
export function MagicLinkAuthContainer({
|
||||||
@@ -118,13 +118,7 @@ export function MagicLinkAuthContainer({
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<EmailInput data-test="email-input" {...field} />
|
||||||
data-test={'email-input'}
|
|
||||||
required
|
|
||||||
type="email"
|
|
||||||
placeholder={t('auth:emailPlaceholder')}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
FormItem,
|
FormItem,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { Input } from '@kit/ui/input';
|
|
||||||
import {
|
import {
|
||||||
InputOTP,
|
InputOTP,
|
||||||
InputOTPGroup,
|
InputOTPGroup,
|
||||||
@@ -30,6 +29,7 @@ import { Trans } from '@kit/ui/trans';
|
|||||||
import { useCaptcha } from '../captcha/client';
|
import { useCaptcha } from '../captcha/client';
|
||||||
import { useLastAuthMethod } from '../hooks/use-last-auth-method';
|
import { useLastAuthMethod } from '../hooks/use-last-auth-method';
|
||||||
import { AuthErrorAlert } from './auth-error-alert';
|
import { AuthErrorAlert } from './auth-error-alert';
|
||||||
|
import { EmailInput } from './email-input';
|
||||||
|
|
||||||
const EmailSchema = z.object({ email: z.string().email() });
|
const EmailSchema = z.object({ email: z.string().email() });
|
||||||
const OtpSchema = z.object({ token: z.string().min(6).max(6) });
|
const OtpSchema = z.object({ token: z.string().min(6).max(6) });
|
||||||
@@ -216,13 +216,7 @@ function OtpEmailForm({
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<EmailInput data-test="otp-email-input" {...field} />
|
||||||
required
|
|
||||||
type="email"
|
|
||||||
placeholder="email@example.com"
|
|
||||||
data-test="otp-email-input"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
46
packages/features/auth/src/components/password-input.tsx
Normal file
46
packages/features/auth/src/components/password-input.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { Eye, EyeOff, Lock } from 'lucide-react';
|
||||||
|
|
||||||
|
import { Button } from '@kit/ui/button';
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupInput,
|
||||||
|
} from '@kit/ui/input-group';
|
||||||
|
|
||||||
|
export function PasswordInput(props: React.ComponentProps<'input'>) {
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InputGroup className="dark:bg-background">
|
||||||
|
<InputGroupAddon>
|
||||||
|
<Lock className="h-4 w-4" />
|
||||||
|
</InputGroupAddon>
|
||||||
|
|
||||||
|
<InputGroupInput
|
||||||
|
data-test="password-input"
|
||||||
|
type={showPassword ? 'text' : 'password'}
|
||||||
|
placeholder={'************'}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputGroupAddon align="inline-end">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<EyeOff className="h-4 w-4" />
|
||||||
|
) : (
|
||||||
|
<Eye className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</InputGroupAddon>
|
||||||
|
</InputGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { ArrowRight } from 'lucide-react';
|
import { ArrowRight, Mail } from 'lucide-react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { z } from 'zod';
|
import type { z } from 'zod';
|
||||||
@@ -14,14 +14,18 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { If } from '@kit/ui/if';
|
import { If } from '@kit/ui/if';
|
||||||
import { Input } from '@kit/ui/input';
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupInput,
|
||||||
|
} from '@kit/ui/input-group';
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { PasswordSignInSchema } from '../schemas/password-sign-in.schema';
|
import { PasswordSignInSchema } from '../schemas/password-sign-in.schema';
|
||||||
|
import { PasswordInput } from './password-input';
|
||||||
|
|
||||||
export function PasswordSignInForm({
|
export function PasswordSignInForm({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
@@ -48,67 +52,61 @@ export function PasswordSignInForm({
|
|||||||
className={'flex w-full flex-col gap-y-4'}
|
className={'flex w-full flex-col gap-y-4'}
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
>
|
>
|
||||||
<FormField
|
<div className={'flex flex-col space-y-2.5'}>
|
||||||
control={form.control}
|
<FormField
|
||||||
name={'email'}
|
control={form.control}
|
||||||
render={({ field }) => (
|
name={'email'}
|
||||||
<FormItem>
|
render={({ field }) => (
|
||||||
<FormLabel>
|
<FormItem>
|
||||||
<Trans i18nKey={'common:emailAddress'} />
|
<FormControl>
|
||||||
</FormLabel>
|
<InputGroup className="dark:bg-background">
|
||||||
|
<InputGroupAddon>
|
||||||
|
<Mail className="h-4 w-4" />
|
||||||
|
</InputGroupAddon>
|
||||||
|
|
||||||
<FormControl>
|
<InputGroupInput
|
||||||
<Input
|
data-test={'email-input'}
|
||||||
data-test={'email-input'}
|
required
|
||||||
required
|
type="email"
|
||||||
type="email"
|
placeholder={t('emailPlaceholder')}
|
||||||
placeholder={t('emailPlaceholder')}
|
{...field}
|
||||||
{...field}
|
/>
|
||||||
/>
|
</InputGroup>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={'password'}
|
name={'password'}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormControl>
|
||||||
<Trans i18nKey={'common:password'} />
|
<PasswordInput {...field} />
|
||||||
</FormLabel>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl>
|
<FormMessage />
|
||||||
<Input
|
|
||||||
required
|
|
||||||
data-test={'password-input'}
|
|
||||||
type="password"
|
|
||||||
placeholder={''}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormMessage />
|
<div>
|
||||||
|
<Button
|
||||||
<div>
|
asChild
|
||||||
<Button
|
type={'button'}
|
||||||
asChild
|
size={'sm'}
|
||||||
type={'button'}
|
variant={'link'}
|
||||||
size={'sm'}
|
className={'text-xs'}
|
||||||
variant={'link'}
|
>
|
||||||
className={'text-xs'}
|
<Link href={'/auth/password-reset'}>
|
||||||
>
|
<Trans i18nKey={'auth:passwordForgottenQuestion'} />
|
||||||
<Link href={'/auth/password-reset'}>
|
</Link>
|
||||||
<Trans i18nKey={'auth:passwordForgottenQuestion'} />
|
</Button>
|
||||||
</Link>
|
</div>
|
||||||
</Button>
|
</FormItem>
|
||||||
</div>
|
)}
|
||||||
</FormItem>
|
/>
|
||||||
)}
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
data-test="auth-submit-button"
|
data-test="auth-submit-button"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { ArrowRight } from 'lucide-react';
|
import { ArrowRight } from 'lucide-react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import { Button } from '@kit/ui/button';
|
import { Button } from '@kit/ui/button';
|
||||||
import {
|
import {
|
||||||
@@ -12,14 +11,14 @@ import {
|
|||||||
FormDescription,
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { If } from '@kit/ui/if';
|
import { If } from '@kit/ui/if';
|
||||||
import { Input } from '@kit/ui/input';
|
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { PasswordSignUpSchema } from '../schemas/password-sign-up.schema';
|
import { PasswordSignUpSchema } from '../schemas/password-sign-up.schema';
|
||||||
|
import { EmailInput } from './email-input';
|
||||||
|
import { PasswordInput } from './password-input';
|
||||||
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
|
import { TermsAndConditionsFormField } from './terms-and-conditions-form-field';
|
||||||
|
|
||||||
interface PasswordSignUpFormProps {
|
interface PasswordSignUpFormProps {
|
||||||
@@ -43,8 +42,6 @@ export function PasswordSignUpForm({
|
|||||||
onSubmit,
|
onSubmit,
|
||||||
loading,
|
loading,
|
||||||
}: PasswordSignUpFormProps) {
|
}: PasswordSignUpFormProps) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
resolver: zodResolver(PasswordSignUpSchema),
|
resolver: zodResolver(PasswordSignUpSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -60,82 +57,56 @@ export function PasswordSignUpForm({
|
|||||||
className={'flex w-full flex-col gap-y-4'}
|
className={'flex w-full flex-col gap-y-4'}
|
||||||
onSubmit={form.handleSubmit(onSubmit)}
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
>
|
>
|
||||||
<FormField
|
<div className={'flex flex-col space-y-2.5'}>
|
||||||
control={form.control}
|
<FormField
|
||||||
name={'email'}
|
control={form.control}
|
||||||
render={({ field }) => (
|
name={'email'}
|
||||||
<FormItem>
|
render={({ field }) => (
|
||||||
<FormLabel>
|
<FormItem>
|
||||||
<Trans i18nKey={'common:emailAddress'} />
|
<FormControl>
|
||||||
</FormLabel>
|
<EmailInput data-test={'email-input'} {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<FormControl>
|
<FormMessage />
|
||||||
<Input
|
</FormItem>
|
||||||
data-test={'email-input'}
|
)}
|
||||||
required
|
/>
|
||||||
type="email"
|
|
||||||
placeholder={t('emailPlaceholder')}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormMessage />
|
<FormField
|
||||||
</FormItem>
|
control={form.control}
|
||||||
)}
|
name={'password'}
|
||||||
/>
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<PasswordInput {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<FormField
|
<FormMessage />
|
||||||
control={form.control}
|
</FormItem>
|
||||||
name={'password'}
|
)}
|
||||||
render={({ field }) => (
|
/>
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
<Trans i18nKey={'common:password'} />
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
<FormField
|
||||||
<Input
|
control={form.control}
|
||||||
required
|
name={'repeatPassword'}
|
||||||
data-test={'password-input'}
|
render={({ field }) => (
|
||||||
type="password"
|
<FormItem>
|
||||||
autoComplete="new-password"
|
<FormControl>
|
||||||
placeholder={''}
|
<PasswordInput
|
||||||
{...field}
|
data-test={'repeat-password-input'}
|
||||||
/>
|
{...field}
|
||||||
</FormControl>
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormDescription>
|
||||||
</FormItem>
|
<Trans i18nKey={'auth:repeatPasswordDescription'} />
|
||||||
)}
|
</FormDescription>
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
<FormMessage />
|
||||||
control={form.control}
|
</FormItem>
|
||||||
name={'repeatPassword'}
|
)}
|
||||||
render={({ field }) => (
|
/>
|
||||||
<FormItem>
|
</div>
|
||||||
<FormLabel>
|
|
||||||
<Trans i18nKey={'auth:repeatPassword'} />
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
required
|
|
||||||
data-test={'repeat-password-input'}
|
|
||||||
type="password"
|
|
||||||
placeholder={''}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
|
|
||||||
<FormDescription className={'pb-2 text-xs'}>
|
|
||||||
<Trans i18nKey={'auth:repeatPasswordHint'} />
|
|
||||||
</FormDescription>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<If condition={displayTermsCheckbox}>
|
<If condition={displayTermsCheckbox}>
|
||||||
<TermsAndConditionsFormField />
|
<TermsAndConditionsFormField />
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { Input } from '@kit/ui/input';
|
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { useCaptcha } from '../captcha/client';
|
import { useCaptcha } from '../captcha/client';
|
||||||
|
import { EmailInput } from './email-input';
|
||||||
|
|
||||||
export function ResendAuthLinkForm(props: {
|
export function ResendAuthLinkForm(props: {
|
||||||
redirectPath?: string;
|
redirectPath?: string;
|
||||||
@@ -71,20 +71,18 @@ export function ResendAuthLinkForm(props: {
|
|||||||
{captcha.field}
|
{captcha.field}
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
|
name={'email'}
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
|
||||||
<Trans i18nKey={'common:emailAddress'} />
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="email" required {...field} />
|
<EmailInput data-test="email-input" {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
name={'email'}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button disabled={resendLink.isPending}>
|
<Button disabled={resendLink.isPending}>
|
||||||
|
|||||||
@@ -15,16 +15,16 @@ import { Button } from '@kit/ui/button';
|
|||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
FormField,
|
FormField,
|
||||||
FormItem,
|
FormItem,
|
||||||
FormLabel,
|
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@kit/ui/form';
|
} from '@kit/ui/form';
|
||||||
import { Heading } from '@kit/ui/heading';
|
import { Heading } from '@kit/ui/heading';
|
||||||
import { Input } from '@kit/ui/input';
|
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { PasswordResetSchema } from '../schemas/password-reset.schema';
|
import { PasswordResetSchema } from '../schemas/password-reset.schema';
|
||||||
|
import { PasswordInput } from './password-input';
|
||||||
|
|
||||||
export function UpdatePasswordForm(params: {
|
export function UpdatePasswordForm(params: {
|
||||||
redirectTo: string;
|
redirectTo: string;
|
||||||
@@ -72,22 +72,13 @@ export function UpdatePasswordForm(params: {
|
|||||||
toast.success(t('account:updatePasswordSuccessMessage'));
|
toast.success(t('account:updatePasswordSuccessMessage'));
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className={'flex-col space-y-4'}>
|
<div className={'flex-col space-y-2.5'}>
|
||||||
<FormField
|
<FormField
|
||||||
name={'password'}
|
name={'password'}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
|
||||||
<Trans i18nKey={'common:password'} />
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<PasswordInput autoComplete={'new-password'} {...field} />
|
||||||
required
|
|
||||||
type="password"
|
|
||||||
autoComplete={'new-password'}
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -99,14 +90,14 @@ export function UpdatePasswordForm(params: {
|
|||||||
name={'repeatPassword'}
|
name={'repeatPassword'}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
|
||||||
<Trans i18nKey={'common:repeatPassword'} />
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input required type="password" {...field} />
|
<PasswordInput autoComplete={'new-password'} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
<FormDescription>
|
||||||
|
<Trans i18nKey={'common:repeatPassword'} />
|
||||||
|
</FormDescription>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user