mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-17 10:11:31 +10:00
feat(i18n): implement localization using LinguiJS
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { GithubLogo, GoogleLogo } from "@phosphor-icons/react";
|
||||
import { Button } from "@reactive-resume/ui";
|
||||
|
||||
@ -5,15 +6,15 @@ export const SocialAuth = () => (
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Button asChild size="lg" className="w-full !bg-[#222] !text-white hover:!bg-[#222]/80">
|
||||
<a href="/api/auth/github">
|
||||
<GoogleLogo className="mr-3 h-4 w-4" />
|
||||
GitHub
|
||||
<GithubLogo className="mr-3 h-4 w-4" />
|
||||
{t`GitHub`}
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
<Button asChild size="lg" className="w-full !bg-[#4285F4] !text-white hover:!bg-[#4285F4]/80">
|
||||
<a href="/api/auth/google">
|
||||
<GithubLogo className="mr-3 h-4 w-4" />
|
||||
Google
|
||||
<GoogleLogo className="mr-3 h-4 w-4" />
|
||||
{t`Google`}
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t } from "@lingui/macro";
|
||||
import { Warning } from "@phosphor-icons/react";
|
||||
import { twoFactorBackupSchema } from "@reactive-resume/dto";
|
||||
import { usePasswordToggle } from "@reactive-resume/hooks";
|
||||
@ -49,7 +50,7 @@ export const BackupOtpPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to sign in",
|
||||
title: t`An error occurred while trying to sign in to your account.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -59,9 +60,9 @@ export const BackupOtpPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Use your backup code</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Use your backup code`}</h2>
|
||||
<h6 className="leading-relaxed opacity-60">
|
||||
Enter one of the 10 backup codes you saved when you enabled two-factor authentication.
|
||||
{t`Enter one of the 10 backup codes you saved when you enabled two-factor authentication.`}
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
@ -77,12 +78,12 @@ export const BackupOtpPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Backup Code</FormLabel>
|
||||
<FormLabel>{t`Backup Code`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
pattern="[a-z0-9]{10}"
|
||||
placeholder="a1b2c3d4e5"
|
||||
title="may contain lowercase letters or numbers, and must be exactly 10 characters."
|
||||
title={t`Backup Codes may contain only lowercase letters or numbers, and must be exactly 10 characters.`}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
@ -92,7 +93,7 @@ export const BackupOtpPage = () => {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={loading} className="mt-4 w-full">
|
||||
Sign in
|
||||
{t`Sign in`}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t } from "@lingui/macro";
|
||||
import { Warning } from "@phosphor-icons/react";
|
||||
import { forgotPasswordSchema } from "@reactive-resume/dto";
|
||||
import {
|
||||
@ -44,7 +45,7 @@ export const ForgotPasswordPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to send your password recovery email",
|
||||
title: t`An error occurred while trying to send your password recovery email.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -55,11 +56,10 @@ export const ForgotPasswordPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">You've got mail!</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`You've got mail!`}</h2>
|
||||
<Alert variant="success">
|
||||
<AlertDescription className="pt-0">
|
||||
A password reset link should have been sent to your inbox, if an account existed with
|
||||
the email you provided.
|
||||
{t`A password reset link should have been sent to your inbox, if an account existed with the email you provided.`}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
@ -70,10 +70,9 @@ export const ForgotPasswordPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Forgot your password?</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Forgot your password?`}</h2>
|
||||
<h6 className="leading-relaxed opacity-75">
|
||||
Enter your email address and we will send you a link to reset your password if the account
|
||||
exists.
|
||||
{t`Enter your email address and we will send you a link to reset your password if the account exists.`}
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
@ -85,7 +84,7 @@ export const ForgotPasswordPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormLabel>{t`Email`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="john.doe@example.com" {...field} />
|
||||
</FormControl>
|
||||
@ -95,7 +94,7 @@ export const ForgotPasswordPage = () => {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={loading} className="mt-4 w-full">
|
||||
Send Email
|
||||
{t`Send Email`}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import { useMemo } from "react";
|
||||
import { Link, matchRoutes, Outlet, useLocation } from "react-router-dom";
|
||||
|
||||
@ -25,7 +26,13 @@ export const AuthLayout = () => {
|
||||
<>
|
||||
<div className="flex items-center gap-x-4">
|
||||
<hr className="flex-1" />
|
||||
<span className="text-xs font-medium">or continue with</span>
|
||||
<span className="text-xs font-medium">
|
||||
{t({
|
||||
message: "or continue with",
|
||||
context:
|
||||
"The user can either login with email/password, or continue with GitHub or Google.",
|
||||
})}
|
||||
</span>
|
||||
<hr className="flex-1" />
|
||||
</div>
|
||||
|
||||
@ -38,18 +45,18 @@ export const AuthLayout = () => {
|
||||
<img
|
||||
width={1920}
|
||||
height={1080}
|
||||
alt="Open books on a table"
|
||||
alt={t`Open books on a table`}
|
||||
className="h-screen w-full object-cover object-center"
|
||||
src="/backgrounds/patrick-tomasso-Oaqk7qqNh_c-unsplash.jpg"
|
||||
/>
|
||||
|
||||
<div className="absolute bottom-5 right-5 z-10 bg-primary/30 px-4 py-2 text-xs font-medium text-primary-foreground backdrop-blur-sm">
|
||||
<a
|
||||
href="https://unsplash.com/photos/Oaqk7qqNh_c"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
href="https://unsplash.com/photos/Oaqk7qqNh_c"
|
||||
>
|
||||
Photograph by Patrick Tomasso
|
||||
{t`Photograph by Patrick Tomasso`}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { ArrowRight, Warning } from "@phosphor-icons/react";
|
||||
import { loginSchema } from "@reactive-resume/dto";
|
||||
import { usePasswordToggle } from "@reactive-resume/hooks";
|
||||
@ -48,7 +49,7 @@ export const LoginPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to sign in",
|
||||
title: t`An error occurred while trying to sign in to your account.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -58,12 +59,13 @@ export const LoginPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Sign in to your account</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Sign in to your account`}</h2>
|
||||
<h6>
|
||||
<span className="opacity-75">Don't have an account?</span>
|
||||
<span className="opacity-75">{t`Don't have an account?`}</span>
|
||||
<Button asChild variant="link" className="px-1.5">
|
||||
<Link to="/auth/register">
|
||||
Create one now <ArrowRight className="ml-1" />
|
||||
{t({ message: "Create one now", context: "This is a link to create a new account" })}{" "}
|
||||
<ArrowRight className="ml-1" />
|
||||
</Link>
|
||||
</Button>
|
||||
</h6>
|
||||
@ -81,11 +83,11 @@ export const LoginPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormLabel>{t`Email`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="john.doe@example.com" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>You can also enter your username.</FormDescription>
|
||||
<FormDescription>{t`You can also enter your username.`}</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@ -96,13 +98,15 @@ export const LoginPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormLabel>{t`Password`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
<Trans>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -111,11 +115,11 @@ export const LoginPage = () => {
|
||||
|
||||
<div className="mt-4 flex items-center gap-x-4">
|
||||
<Button type="submit" disabled={loading} className="flex-1">
|
||||
Sign in
|
||||
{t`Sign in`}
|
||||
</Button>
|
||||
|
||||
<Button asChild variant="link" className="px-4">
|
||||
<Link to="/auth/forgot-password">Forgot Password?</Link>
|
||||
<Link to="/auth/forgot-password">{t`Forgot Password?`}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { ArrowRight, Warning } from "@phosphor-icons/react";
|
||||
import { registerSchema } from "@reactive-resume/dto";
|
||||
import { usePasswordToggle } from "@reactive-resume/hooks";
|
||||
@ -38,7 +39,7 @@ export const RegisterPage = () => {
|
||||
username: "",
|
||||
email: "",
|
||||
password: "",
|
||||
language: "en",
|
||||
locale: "en",
|
||||
},
|
||||
});
|
||||
|
||||
@ -56,7 +57,7 @@ export const RegisterPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to sign up",
|
||||
title: t`An error occurred while trying to create a new account.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -66,12 +67,12 @@ export const RegisterPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Create a new account</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Create a new account`}</h2>
|
||||
<h6>
|
||||
<span className="opacity-75">Already have an account?</span>
|
||||
<span className="opacity-75">{t`Already have an account?`}</span>
|
||||
<Button asChild variant="link" className="px-1.5">
|
||||
<Link to="/auth/login">
|
||||
Sign in now <ArrowRight className="ml-1" />
|
||||
{t`Sign in now`} <ArrowRight className="ml-1" />
|
||||
</Link>
|
||||
</Button>
|
||||
</h6>
|
||||
@ -89,9 +90,16 @@ export const RegisterPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormLabel>{t`Name`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="John Doe" {...field} />
|
||||
<Input
|
||||
placeholder={t({
|
||||
message: "John Doe",
|
||||
context:
|
||||
"Localized version of a placeholder name. For example, Max Mustermann in German or Jan Kowalski in Polish.",
|
||||
})}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -103,9 +111,16 @@ export const RegisterPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormLabel>{t`Username`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="john.doe" {...field} />
|
||||
<Input
|
||||
placeholder={t({
|
||||
message: "john.doe",
|
||||
context:
|
||||
"Localized version of a placeholder username. For example, max.mustermann in German or jan.kowalski in Polish.",
|
||||
})}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -117,9 +132,16 @@ export const RegisterPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Email</FormLabel>
|
||||
<FormLabel>{t`Email`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="john.doe@example.com" {...field} />
|
||||
<Input
|
||||
placeholder={t({
|
||||
message: "john.doe@example.com",
|
||||
context:
|
||||
"Localized version of a placeholder email. For example, max.mustermann@example.de in German or jan.kowalski@example.pl in Polish.",
|
||||
})}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -131,13 +153,15 @@ export const RegisterPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormLabel>{t`Password`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
<Trans>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -145,7 +169,7 @@ export const RegisterPage = () => {
|
||||
/>
|
||||
|
||||
<Button disabled={loading} className="mt-4 w-full">
|
||||
Sign up
|
||||
{t`Sign up`}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { Warning } from "@phosphor-icons/react";
|
||||
import { resetPasswordSchema } from "@reactive-resume/dto";
|
||||
import { usePasswordToggle } from "@reactive-resume/hooks";
|
||||
@ -53,7 +54,7 @@ export const ResetPasswordPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to reset your password",
|
||||
title: t`An error occurred while trying to reset your password.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -68,9 +69,9 @@ export const ResetPasswordPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Reset your password</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Reset your password`}</h2>
|
||||
<h6 className="leading-relaxed opacity-75">
|
||||
Enter a new password below, and make sure it's secure.
|
||||
{t`Enter a new password below, and make sure it's secure.`}
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
@ -86,13 +87,15 @@ export const ResetPasswordPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormLabel>{t`Password`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" {...field} />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
<Trans>
|
||||
Hold <code className="text-xs font-bold">Ctrl</code> to display your password
|
||||
temporarily.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -100,7 +103,7 @@ export const ResetPasswordPage = () => {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={loading} className="mt-4 w-full">
|
||||
Update Password
|
||||
{t`Change Password`}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { ArrowRight, Info, SealCheck, Warning } from "@phosphor-icons/react";
|
||||
import { Alert, AlertDescription, AlertTitle, Button } from "@reactive-resume/ui";
|
||||
import { AxiosError } from "axios";
|
||||
@ -25,7 +26,7 @@ export const VerifyEmailPage = () => {
|
||||
toast({
|
||||
variant: "success",
|
||||
icon: <SealCheck size={16} weight="bold" />,
|
||||
title: "Your email address has been verified successfully.",
|
||||
title: t`Your email address has been verified successfully.`,
|
||||
});
|
||||
|
||||
navigate("/dashboard/resumes", { replace: true });
|
||||
@ -36,7 +37,7 @@ export const VerifyEmailPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to verify your email address",
|
||||
title: t`An error occurred while trying to verify your email address.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -51,27 +52,26 @@ export const VerifyEmailPage = () => {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Verify your email address</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Verify your email address`}</h2>
|
||||
<p className="leading-relaxed opacity-75">
|
||||
You should have received an email from <strong>Reactive Resume</strong> with a link to
|
||||
verify your account.
|
||||
<Trans>
|
||||
You should have received an email from <strong>Reactive Resume</strong> with a link to
|
||||
verify your account.
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Alert variant="info">
|
||||
<Info size={18} />
|
||||
|
||||
<AlertTitle>Please note that this step is completely optional.</AlertTitle>
|
||||
|
||||
<AlertTitle>{t`Please note that this step is completely optional.`}</AlertTitle>
|
||||
<AlertDescription>
|
||||
We verify your email address only to ensure that we can send you a password reset link in
|
||||
case you forget your password.
|
||||
{t`We verify your email address only to ensure that we can send you a password reset link in case you forget your password.`}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<Button asChild disabled={loading}>
|
||||
<Link to="/dashboard">
|
||||
Continue to Dashboard
|
||||
{t`Go to Dashboard`}
|
||||
<ArrowRight className="ml-2" />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { t } from "@lingui/macro";
|
||||
import { ArrowRight, Warning } from "@phosphor-icons/react";
|
||||
import { twoFactorSchema } from "@reactive-resume/dto";
|
||||
import { usePasswordToggle } from "@reactive-resume/hooks";
|
||||
@ -49,7 +50,7 @@ export const VerifyOtpPage = () => {
|
||||
toast({
|
||||
variant: "error",
|
||||
icon: <Warning size={16} weight="bold" />,
|
||||
title: "An error occurred while trying to sign in",
|
||||
title: t`An error occurred while trying to sign in to your account.`,
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
@ -59,14 +60,14 @@ export const VerifyOtpPage = () => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-1.5">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Two Step Verification</h2>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">{t`Two-Factor Authentication`}</h2>
|
||||
<h6>
|
||||
<span className="opacity-75">
|
||||
Enter the one-time password provided by your authenticator app below.
|
||||
{t`Enter the one-time password provided by your authenticator app below.`}
|
||||
</span>
|
||||
<Button asChild variant="link" className="px-1.5">
|
||||
<Link to="/auth/backup-otp">
|
||||
Lost your device? <ArrowRight className="ml-1" />
|
||||
{t`Lost your device?`} <ArrowRight className="ml-1" />
|
||||
</Link>
|
||||
</Button>
|
||||
</h6>
|
||||
@ -84,7 +85,7 @@ export const VerifyOtpPage = () => {
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>One-Time Password</FormLabel>
|
||||
<FormLabel>{t`One-Time Password`}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="123456" {...field} />
|
||||
</FormControl>
|
||||
@ -94,7 +95,7 @@ export const VerifyOtpPage = () => {
|
||||
/>
|
||||
|
||||
<Button type="submit" disabled={loading} className="mt-4 w-full">
|
||||
Sign in
|
||||
{t`Sign in`}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
Reference in New Issue
Block a user