Skip to content

Commit

Permalink
feat: add pin fields to the reset password page
Browse files Browse the repository at this point in the history
  • Loading branch information
theozebua committed Oct 10, 2024
1 parent 9d4a740 commit 5d486b3
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Input } from '@nextui-org/react'
import { Eye, EyeOff } from 'lucide-react'
import { usePinVisibilityState } from '../_stores/pin-visibility'
import { useFormSubmissionState } from '@/stores/form-submission'
import { useErrorMessageState } from '@/stores/input-error-message'
import { FormEvent } from 'react'

export default function ConfirmPinField() {
// Stores
const { isSubmitting } = useFormSubmissionState()
const { isVisible, toggleVisibility } = usePinVisibilityState(
state => state.confirmPin,
)
const { fields } = useErrorMessageState()

const errorMessage = fields.find(
field => field.identifier === 'confirm_pin',
)?.message

const handleInput = (event: FormEvent<HTMLInputElement>) => {
const element = event.target as HTMLInputElement
const value = element.value

if (!/^\d*$/.test(value)) {
element.value = value.replace(/[^\d]/g, '')
}

if (element.value.length > 6) {
element.value = element.value.slice(0, 6)
}
}

return (
<Input
label="Konfirmasi PIN Baru"
name="confirm_pin"
isRequired
isDisabled={isSubmitting}
isInvalid={!!errorMessage}
errorMessage={errorMessage}
inputMode="numeric"
pattern="\d{6}"
onInput={handleInput}
endContent={
<button
tabIndex={-1}
className="focus:outline-none"
type="button"
onClick={() => toggleVisibility()}
aria-label="toggle confirm-pin visibility">
{isVisible ? (
<EyeOff className="pointer-events-none text-2xl text-default-400" />
) : (
<Eye className="pointer-events-none text-2xl text-default-400" />
)}
</button>
}
type={isVisible ? 'text' : 'password'}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Input } from '@nextui-org/react'
import { Eye, EyeOff } from 'lucide-react'
import { usePinVisibilityState } from '../_stores/pin-visibility'
import { useFormSubmissionState } from '@/stores/form-submission'
import { useErrorMessageState } from '@/stores/input-error-message'
import { FormEvent } from 'react'

export default function PinField() {
// Stores
const { isSubmitting } = useFormSubmissionState()
const { isVisible, toggleVisibility } = usePinVisibilityState(
state => state.pin,
)
const { fields } = useErrorMessageState()

const errorMessage = fields.find(field => field.identifier === 'pin')?.message

const handleInput = (event: FormEvent<HTMLInputElement>) => {
const element = event.target as HTMLInputElement
const value = element.value

if (!/^\d*$/.test(value)) {
element.value = value.replace(/[^\d]/g, '')
}

if (element.value.length > 6) {
element.value = element.value.slice(0, 6)
}
}

return (
<Input
label="PIN Baru"
name="pin"
isRequired
isDisabled={isSubmitting}
isInvalid={!!errorMessage}
errorMessage={errorMessage}
inputMode="numeric"
onInput={handleInput}
endContent={
<button
tabIndex={-1}
className="focus:outline-none"
type="button"
onClick={() => toggleVisibility()}
aria-label="toggle pin visibility">
{isVisible ? (
<EyeOff className="pointer-events-none text-2xl text-default-400" />
) : (
<Eye className="pointer-events-none text-2xl text-default-400" />
)}
</button>
}
type={isVisible ? 'text' : 'password'}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { FormEvent, useState } from 'react'
import PasswordField from './_components/password-field'
import ConfirmPasswordField from './_components/confirm-password-field'
import { useErrorMessageState } from '@/stores/input-error-message'
import PinField from './_components/pin-field'
import ConfirmPinField from './_components/confirm-pin-field'

export default function ResetPasswordForm() {
// States
Expand All @@ -19,8 +21,10 @@ export default function ResetPasswordForm() {
const formData = new FormData(event.currentTarget)
const password = formData.get('password') as string
const confirmPassword = formData.get('confirm_password') as string
const pin = formData.get('pin') as string
const confirmPin = formData.get('confirm_pin') as string

if (!validateInputFields(password, confirmPassword)) {
if (!validateInputFields(password, confirmPassword, pin, confirmPin)) {
return
}

Expand All @@ -31,7 +35,12 @@ export default function ResetPasswordForm() {
}, 2000)
}

const validateInputFields = (password: string, confirmPassword: string) => {
const validateInputFields = (
password: string,
confirmPassword: string,
pin: string,
confirmPin: string,
) => {
let passed = true

if (password.length < 1) {
Expand Down Expand Up @@ -72,13 +81,45 @@ export default function ResetPasswordForm() {
passed = false
}

if (pin.length < 1) {
setErrorMessage('pin', 'PIN tidak boleh kosong')

passed = false
}

if (pin.length > 0 && pin.length < 6) {
setErrorMessage('pin', 'Panjang PIN minimal 6 digit')

passed = false
}

if (confirmPin.length < 1) {
setErrorMessage('confirm_pin', 'Konfirmasi PIN tidak boleh kosong')

passed = false
}

if (confirmPin.length > 0 && confirmPin.length < 6) {
setErrorMessage('confirm_pin', 'Panjang konfirmasi PIN minimal 6 digit')

passed = false
}

if (pin.length > 0 && confirmPin.length > 0 && pin !== confirmPin) {
setErrorMessage('confirm_pin', 'PIN tidak cocok')

passed = false
}

return passed
}

return (
<form className="space-y-4" onSubmit={handleResetPassword}>
<PasswordField />
<ConfirmPasswordField />
<PinField />
<ConfirmPinField />

<Button
color="primary"
Expand Down

0 comments on commit 5d486b3

Please sign in to comment.