mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 15:35:22 +02:00
Add loader to Button component and clean login page
This commit is contained in:
parent
10c5195930
commit
f1e0b84e60
3 changed files with 57 additions and 11 deletions
|
@ -1,6 +1,6 @@
|
||||||
import { useState, type ReactElement } from 'react'
|
import { useState, type ReactElement } from 'react'
|
||||||
import { FullPageLayout } from '@maybe-finance/client/features'
|
import { FullPageLayout } from '@maybe-finance/client/features'
|
||||||
import { Input, InputPassword, Button } from '@maybe-finance/design-system'
|
import { Input, InputPassword, Button, LoadingSpinner } from '@maybe-finance/design-system'
|
||||||
import { signIn, useSession } from 'next-auth/react'
|
import { signIn, useSession } from 'next-auth/react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
@ -10,8 +10,9 @@ import Link from 'next/link'
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [isValid, setIsValid] = useState(false)
|
const [isValid, setIsValid] = useState(true)
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const { data: session } = useSession()
|
const { data: session } = useSession()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -26,6 +27,7 @@ export default function LoginPage() {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setErrorMessage(null)
|
setErrorMessage(null)
|
||||||
setPassword('')
|
setPassword('')
|
||||||
|
setIsLoading(true)
|
||||||
|
|
||||||
const response = await signIn('credentials', {
|
const response = await signIn('credentials', {
|
||||||
email,
|
email,
|
||||||
|
@ -35,9 +37,16 @@ export default function LoginPage() {
|
||||||
|
|
||||||
if (response && response.error) {
|
if (response && response.error) {
|
||||||
setErrorMessage(response.error)
|
setErrorMessage(response.error)
|
||||||
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setErrorMessage(null)
|
||||||
|
setPassword(e.target.value)
|
||||||
|
setIsValid(e.target.value.length > 0)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Script
|
<Script
|
||||||
|
@ -68,15 +77,8 @@ export default function LoginPage() {
|
||||||
name="password"
|
name="password"
|
||||||
label="Password"
|
label="Password"
|
||||||
value={password}
|
value={password}
|
||||||
showPasswordRequirements={!isValid}
|
onChange={onPasswordChange}
|
||||||
onValidityChange={(checks) => {
|
showComplexityBar={false}
|
||||||
const passwordValid =
|
|
||||||
checks.filter((c) => !c.isValid).length === 0
|
|
||||||
setIsValid(passwordValid)
|
|
||||||
}}
|
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
setPassword(e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{errorMessage && password.length === 0 ? (
|
{errorMessage && password.length === 0 ? (
|
||||||
|
@ -89,6 +91,7 @@ export default function LoginPage() {
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isValid}
|
disabled={!isValid}
|
||||||
variant={isValid ? 'primary' : 'secondary'}
|
variant={isValid ? 'primary' : 'secondary'}
|
||||||
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
Log in
|
Log in
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default function RegisterPage() {
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [isValid, setIsValid] = useState(false)
|
const [isValid, setIsValid] = useState(false)
|
||||||
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
const [errorMessage, setErrorMessage] = useState<string | null>(null)
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const { data: session } = useSession()
|
const { data: session } = useSession()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -30,6 +31,7 @@ export default function RegisterPage() {
|
||||||
setLastName('')
|
setLastName('')
|
||||||
setEmail('')
|
setEmail('')
|
||||||
setPassword('')
|
setPassword('')
|
||||||
|
setIsLoading(true)
|
||||||
|
|
||||||
const response = await signIn('credentials', {
|
const response = await signIn('credentials', {
|
||||||
email,
|
email,
|
||||||
|
@ -41,6 +43,7 @@ export default function RegisterPage() {
|
||||||
|
|
||||||
if (response && response.error) {
|
if (response && response.error) {
|
||||||
setErrorMessage(response.error)
|
setErrorMessage(response.error)
|
||||||
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +112,7 @@ export default function RegisterPage() {
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isValid}
|
disabled={!isValid}
|
||||||
variant={isValid ? 'primary' : 'secondary'}
|
variant={isValid ? 'primary' : 'secondary'}
|
||||||
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
Register
|
Register
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -42,6 +42,9 @@ export type ButtonProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'a
|
||||||
className?: string
|
className?: string
|
||||||
|
|
||||||
leftIcon?: ReactNode
|
leftIcon?: ReactNode
|
||||||
|
|
||||||
|
/** Display spinner based on the value passed */
|
||||||
|
isLoading?: boolean
|
||||||
}>
|
}>
|
||||||
|
|
||||||
function Button(
|
function Button(
|
||||||
|
@ -53,6 +56,7 @@ function Button(
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
leftIcon,
|
leftIcon,
|
||||||
|
isLoading = false,
|
||||||
...rest
|
...rest
|
||||||
}: ButtonProps,
|
}: ButtonProps,
|
||||||
ref: React.Ref<HTMLElement>
|
ref: React.Ref<HTMLElement>
|
||||||
|
@ -81,8 +85,43 @@ function Button(
|
||||||
>
|
>
|
||||||
{leftIcon && <span className="mr-1.5">{leftIcon}</span>}
|
{leftIcon && <span className="mr-1.5">{leftIcon}</span>}
|
||||||
{children}
|
{children}
|
||||||
|
{isLoading && Tag === 'button' && (
|
||||||
|
<span className="ml-1.5">
|
||||||
|
<Spinner fill={variant === 'primary' ? '#16161A' : '#FFFFFF'} />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</Tag>
|
</Tag>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a spinner to Button component and toggle it via flag
|
||||||
|
|
||||||
|
interface SpinnerProps {
|
||||||
|
fill: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function Spinner({ fill }: SpinnerProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
||||||
|
opacity=".25"
|
||||||
|
fill={fill}
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"
|
||||||
|
fill={fill}
|
||||||
|
>
|
||||||
|
<animateTransform
|
||||||
|
attributeName="transform"
|
||||||
|
type="rotate"
|
||||||
|
dur="0.75s"
|
||||||
|
values="0 12 12;360 12 12"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default React.forwardRef(Button)
|
export default React.forwardRef(Button)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue