Redesign for initial setup wizard
This commit is contained in:
parent
029a5678a6
commit
de685f28f5
|
@ -1,13 +1,15 @@
|
|||
import React, { useState } from 'react'
|
||||
import React from 'react'
|
||||
import { gql, useQuery, useMutation } from '@apollo/client'
|
||||
import { Redirect } from 'react-router-dom'
|
||||
import { Button, Form, Message, Header } from 'semantic-ui-react'
|
||||
import { Container } from './loginUtilities'
|
||||
|
||||
import { checkInitialSetupQuery, login } from './loginUtilities'
|
||||
import { authToken } from '../../helpers/authentication'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { CheckInitialSetup } from './__generated__/CheckInitialSetup'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { Submit, TextField } from '../../primitives/form/Input'
|
||||
import MessageBox from '../../primitives/form/MessageBox'
|
||||
|
||||
const initialSetupMutation = gql`
|
||||
mutation InitialSetup(
|
||||
|
@ -27,14 +29,26 @@ const initialSetupMutation = gql`
|
|||
}
|
||||
`
|
||||
|
||||
type InitialSetupFormData = {
|
||||
username: string
|
||||
password: string
|
||||
rootPath: string
|
||||
}
|
||||
|
||||
const InitialSetupPage = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [state, setState] = useState({
|
||||
username: '',
|
||||
password: '',
|
||||
rootPath: '',
|
||||
})
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors: formErrors },
|
||||
} = useForm<InitialSetupFormData>()
|
||||
|
||||
// const [state, setState] = useState({
|
||||
// username: '',
|
||||
// password: '',
|
||||
// rootPath: '',
|
||||
// })
|
||||
|
||||
if (authToken()) {
|
||||
return <Redirect to="/" />
|
||||
|
@ -48,41 +62,37 @@ const InitialSetupPage = () => {
|
|||
<Redirect to="/" />
|
||||
)
|
||||
|
||||
const [
|
||||
authorize,
|
||||
{ loading: authorizeLoading, data: authorizationData },
|
||||
] = useMutation(initialSetupMutation, {
|
||||
onCompleted: data => {
|
||||
const { success, token } = data.initialSetupWizard
|
||||
const [authorize, { loading: authorizeLoading, data: authorizationData }] =
|
||||
useMutation(initialSetupMutation, {
|
||||
onCompleted: data => {
|
||||
const { success, token } = data.initialSetupWizard
|
||||
|
||||
if (success) {
|
||||
login(token)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const handleChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>,
|
||||
key: string
|
||||
) => {
|
||||
const value = event.target.value
|
||||
setState(prevState => ({
|
||||
...prevState,
|
||||
[key]: value,
|
||||
}))
|
||||
}
|
||||
|
||||
const signIn = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
|
||||
authorize({
|
||||
variables: {
|
||||
username: state.username,
|
||||
password: state.password,
|
||||
rootPath: state.rootPath,
|
||||
if (success) {
|
||||
login(token)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// const handleChange = (
|
||||
// event: React.ChangeEvent<HTMLInputElement>,
|
||||
// key: string
|
||||
// ) => {
|
||||
// const value = event.target.value
|
||||
// setState(prevState => ({
|
||||
// ...prevState,
|
||||
// [key]: value,
|
||||
// }))
|
||||
// }
|
||||
|
||||
const signIn = handleSubmit(data => {
|
||||
authorize({
|
||||
variables: {
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
rootPath: data.rootPath,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
let errorMessage = null
|
||||
if (authorizationData && !authorizationData.initialSetupWizard.success) {
|
||||
|
@ -93,49 +103,59 @@ const InitialSetupPage = () => {
|
|||
<div>
|
||||
{initialSetupRedirect}
|
||||
<Container>
|
||||
<Header as="h1" textAlign="center">
|
||||
<h1 className="text-center text-xl">
|
||||
{t('login_page.initial_setup.title', 'Initial Setup')}
|
||||
</Header>
|
||||
<Form
|
||||
style={{ width: 500, margin: 'auto' }}
|
||||
error={!!errorMessage}
|
||||
onSubmit={signIn}
|
||||
loading={
|
||||
authorizeLoading || authorizationData?.initialSetupWizard?.success
|
||||
}
|
||||
>
|
||||
<Form.Field>
|
||||
<label>{t('login_page.field.username', 'Username')}</label>
|
||||
<input onChange={e => handleChange(e, 'username')} />
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>{t('login_page.field.password', 'Password')}</label>
|
||||
<input
|
||||
type="password"
|
||||
onChange={e => handleChange(e, 'password')}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Field>
|
||||
<label>
|
||||
{t(
|
||||
'login_page.initial_setup.field.photo_path.label',
|
||||
'Photo path'
|
||||
)}
|
||||
</label>
|
||||
<input
|
||||
placeholder={t(
|
||||
'login_page.initial_setup.field.photo_path.placeholder',
|
||||
'/path/to/photos'
|
||||
)}
|
||||
type="text"
|
||||
onChange={e => handleChange(e, 'rootPath')}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Message error content={errorMessage} />
|
||||
<Button type="submit">
|
||||
</h1>
|
||||
<form onSubmit={signIn} className="max-w-[500px] mx-auto">
|
||||
<TextField
|
||||
wrapperClassName="my-4"
|
||||
fullWidth
|
||||
{...register('username', { required: true })}
|
||||
label={t('login_page.field.username', 'Username')}
|
||||
error={
|
||||
formErrors.username?.type == 'required'
|
||||
? 'Please enter a username'
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
wrapperClassName="my-4"
|
||||
fullWidth
|
||||
{...register('password', { required: true })}
|
||||
label={t('login_page.field.password', 'Password')}
|
||||
error={
|
||||
formErrors.password?.type == 'required'
|
||||
? 'Please enter a password'
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
wrapperClassName="my-4"
|
||||
fullWidth
|
||||
{...register('rootPath', { required: true })}
|
||||
label={t(
|
||||
'login_page.initial_setup.field.photo_path.label',
|
||||
'Photo path'
|
||||
)}
|
||||
placeholder={t(
|
||||
'login_page.initial_setup.field.photo_path.placeholder',
|
||||
'/path/to/photos'
|
||||
)}
|
||||
error={
|
||||
formErrors.password?.type == 'required'
|
||||
? 'Please enter a photo path'
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<MessageBox
|
||||
type="negative"
|
||||
message={errorMessage}
|
||||
show={errorMessage}
|
||||
/>
|
||||
<Submit className="mt-2" disabled={authorizeLoading}>
|
||||
{t('login_page.initial_setup.field.submit', 'Setup Photoview')}
|
||||
</Button>
|
||||
</Form>
|
||||
</Submit>
|
||||
</form>
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ const LogoHeader = () => {
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex justify-center flex-col pb-20 pt-12">
|
||||
<div className="flex justify-center flex-col mb-14 mt-20">
|
||||
<img className="h-24" src={logoPath} alt="photoview logo" />
|
||||
<h1 className="text-3xl text-center mt-4">
|
||||
{t('login_page.welcome', 'Welcome to Photoview')}
|
||||
|
@ -73,13 +73,13 @@ const LoginForm = () => {
|
|||
|
||||
return (
|
||||
<form
|
||||
className="mx-auto max-w-[450px] px-4"
|
||||
className="mx-auto max-w-[500px] px-4"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
// loading={loading || (data && data.authorizeUser.success)}
|
||||
>
|
||||
<TextField
|
||||
sizeVariant="big"
|
||||
wrapperClassName="my-4"
|
||||
wrapperClassName="my-6"
|
||||
className="w-full"
|
||||
label={t('login_page.field.username', 'Username')}
|
||||
{...register('username', { required: true })}
|
||||
|
@ -91,7 +91,7 @@ const LoginForm = () => {
|
|||
/>
|
||||
<TextField
|
||||
sizeVariant="big"
|
||||
wrapperClassName="my-4"
|
||||
wrapperClassName="my-6"
|
||||
className="w-full"
|
||||
type="password"
|
||||
label={t('login_page.field.password', 'Password')}
|
||||
|
@ -106,7 +106,7 @@ const LoginForm = () => {
|
|||
type="submit"
|
||||
disabled={loading}
|
||||
value={t('login_page.field.submit', 'Sign in') as string}
|
||||
className="rounded-md px-8 py-2 mt-1 focus:outline-none cursor-pointer bg-gradient-to-bl from-[#FF8246] to-[#D6264D] text-white font-semibold focus:ring-2 focus:ring-red-200 disabled:cursor-default disabled:opacity-80"
|
||||
className="rounded-md px-8 py-2 mt-2 focus:outline-none cursor-pointer bg-gradient-to-bl from-[#FF8246] to-[#D6264D] text-white font-semibold focus:ring-2 focus:ring-red-200 disabled:cursor-default disabled:opacity-80"
|
||||
/>
|
||||
<MessageBox
|
||||
message={errorMessage}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { gql } from '@apollo/client'
|
||||
import { saveTokenCookie } from '../../helpers/authentication'
|
||||
import styled from 'styled-components'
|
||||
import { Container as SemanticContainer } from 'semantic-ui-react'
|
||||
// import { Container as SemanticContainer } from 'semantic-ui-react'
|
||||
|
||||
export const checkInitialSetupQuery = gql`
|
||||
query CheckInitialSetup {
|
||||
|
@ -16,6 +16,4 @@ export function login(token: string) {
|
|||
window.location.href = '/'
|
||||
}
|
||||
|
||||
export const Container = styled(SemanticContainer)`
|
||||
margin-top: 80px;
|
||||
`
|
||||
export const Container = styled.div.attrs({ className: 'mt-20' })``
|
||||
|
|
|
@ -37,7 +37,7 @@ export const TextField = forwardRef(
|
|||
let variant = 'bg-white border-gray-200 focus:border-blue-400'
|
||||
if (error)
|
||||
variant =
|
||||
'bg-red-50 border-red-200 focus:border-red-400 focus:ring-red-100'
|
||||
'bg-red-50 border-red-200 focus:border-red-400 focus:ring-red-100 placeholder-red-300'
|
||||
|
||||
if (disabled) variant = 'bg-gray-100'
|
||||
|
||||
|
@ -148,15 +148,21 @@ const buttonStyles = ({ variant, background }: ButtonProps) =>
|
|||
background == 'white' ? 'bg-white' : 'bg-gray-50'
|
||||
)
|
||||
|
||||
type SubmitProps = ButtonProps & {
|
||||
children: string
|
||||
}
|
||||
|
||||
export const Submit = ({
|
||||
className,
|
||||
variant,
|
||||
background,
|
||||
children,
|
||||
...props
|
||||
}: ButtonProps & React.ButtonHTMLAttributes<HTMLInputElement>) => (
|
||||
}: SubmitProps & React.ButtonHTMLAttributes<HTMLInputElement>) => (
|
||||
<input
|
||||
className={classNames(buttonStyles({ variant, background }), className)}
|
||||
type="submit"
|
||||
value={children}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue