Spaces:
Build error
Build error
File size: 6,699 Bytes
a8b3f00 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
'use client'
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import type { SubmitHandler } from 'react-hook-form'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'
import Loading from '../components/base/loading'
import classNames from '@/utils/classnames'
import Button from '@/app/components/base/button'
import { fetchInitValidateStatus, fetchSetupStatus, setup } from '@/service/common'
import type { InitValidateStatusResponse, SetupStatusResponse } from '@/models/common'
const validPassword = /^(?=.*[a-zA-Z])(?=.*\d).{8,}$/
const accountFormSchema = z.object({
email: z
.string()
.min(1, { message: 'login.error.emailInValid' })
.email('login.error.emailInValid'),
name: z.string().min(1, { message: 'login.error.nameEmpty' }),
password: z.string().min(8, {
message: 'login.error.passwordLengthInValid',
}).regex(validPassword, 'login.error.passwordInvalid'),
})
type AccountFormValues = z.infer<typeof accountFormSchema>
const InstallForm = () => {
const { t } = useTranslation()
const router = useRouter()
const [showPassword, setShowPassword] = React.useState(false)
const [loading, setLoading] = React.useState(true)
const {
register,
handleSubmit,
formState: { errors },
} = useForm<AccountFormValues>({
resolver: zodResolver(accountFormSchema),
defaultValues: {
name: '',
password: '',
email: '',
},
})
const onSubmit: SubmitHandler<AccountFormValues> = async (data) => {
await setup({
body: {
...data,
},
})
router.push('/signin')
}
const handleSetting = async () => {
handleSubmit(onSubmit)()
}
useEffect(() => {
fetchSetupStatus().then((res: SetupStatusResponse) => {
if (res.step === 'finished') {
localStorage.setItem('setup_status', 'finished')
window.location.href = '/signin'
}
else {
fetchInitValidateStatus().then((res: InitValidateStatusResponse) => {
if (res.status === 'not_started')
window.location.href = '/init'
})
}
setLoading(false)
})
}, [])
return (
loading
? <Loading />
: <>
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="text-[32px] font-bold text-gray-900">{t('login.setAdminAccount')}</h2>
<p className='
mt-1 text-sm text-gray-600
'>{t('login.setAdminAccountDesc')}</p>
</div>
<div className="grow mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white ">
<form onSubmit={handleSubmit(onSubmit)}>
<div className='mb-5'>
<label htmlFor="email" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.email')}
</label>
<div className="mt-1">
<input
{...register('email')}
placeholder={t('login.emailPlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm'}
/>
{errors.email && <span className='text-red-400 text-sm'>{t(`${errors.email?.message}`)}</span>}
</div>
</div>
<div className='mb-5'>
<label htmlFor="name" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.name')}
</label>
<div className="mt-1 relative rounded-md shadow-sm">
<input
{...register('name')}
placeholder={t('login.namePlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm pr-10'}
/>
</div>
{errors.name && <span className='text-red-400 text-sm'>{t(`${errors.name.message}`)}</span>}
</div>
<div className='mb-5'>
<label htmlFor="password" className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
{t('login.password')}
</label>
<div className="mt-1 relative rounded-md shadow-sm">
<input
{...register('password')}
type={showPassword ? 'text' : 'password'}
placeholder={t('login.passwordPlaceholder') || ''}
className={'appearance-none block w-full rounded-lg pl-[14px] px-3 py-2 border border-gray-200 hover:border-gray-300 hover:shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 placeholder-gray-400 caret-primary-600 sm:text-sm pr-10'}
/>
<div className="absolute inset-y-0 right-0 flex items-center pr-3">
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="text-gray-400 hover:text-gray-500 focus:outline-none focus:text-gray-500"
>
{showPassword ? '👀' : '😝'}
</button>
</div>
</div>
<div className={classNames('mt-1 text-xs text-gray-500', {
'text-red-400 !text-sm': errors.password,
})}>{t('login.error.passwordInvalid')}</div>
</div>
<div>
<Button variant='primary' className='w-full' onClick={handleSetting}>
{t('login.installBtn')}
</Button>
</div>
</form>
<div className="block w-full mt-2 text-xs text-gray-600">
{t('login.license.tip')}
<Link
className='text-primary-600'
target='_blank' rel='noopener noreferrer'
href={'https://docs.dify.ai/user-agreement/open-source'}
>{t('login.license.link')}</Link>
</div>
</div>
</div>
</>
)
}
export default InstallForm
|