| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 | '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') {        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-hull 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
 |