117 lines
3.3 KiB
TypeScript
117 lines
3.3 KiB
TypeScript
import { useEffect, useRef, useState } from 'react'
|
|
|
|
import { mdiFormatTitle } from '@mdi/js'
|
|
import Icon from '@mdi/react'
|
|
import { Titles, UpdateTitlesInput } from 'types/graphql'
|
|
|
|
import { Form, Label, Submit, TextField } from '@redwoodjs/forms'
|
|
import { TypedDocumentNode, useMutation } from '@redwoodjs/web'
|
|
import { toast } from '@redwoodjs/web/toast'
|
|
|
|
const MAX_TITLES = 5
|
|
|
|
interface TitlesFormProps {
|
|
titles?: Titles
|
|
}
|
|
|
|
const UPDATE_TITLES_MUTATION: TypedDocumentNode<UpdateTitlesInput> = gql`
|
|
mutation UpdateTitlesMutation($input: UpdateTitlesInput!) {
|
|
updateTitles(input: $input) {
|
|
titles
|
|
}
|
|
}
|
|
`
|
|
|
|
const TitlesForm = ({ titles }: TitlesFormProps) => {
|
|
const title1ref = useRef<HTMLInputElement>(null)
|
|
|
|
const [preview, setPreview] = useState<boolean>(false)
|
|
|
|
const states = [
|
|
useState<string>(titles?.titles[0]),
|
|
useState<string>(titles?.titles[1]),
|
|
useState<string>(titles?.titles[2]),
|
|
useState<string>(titles?.titles[3]),
|
|
useState<string>(titles?.titles[4]),
|
|
]
|
|
|
|
useEffect(() => title1ref.current?.focus(), [])
|
|
|
|
const [updateTitles, { loading: updateLoading }] = useMutation(
|
|
UPDATE_TITLES_MUTATION,
|
|
{
|
|
onCompleted: () => toast.success('Titles saved'),
|
|
onError: (error) => toast.error(error.message),
|
|
}
|
|
)
|
|
|
|
const onSubmit = (data: Record<string, string>) =>
|
|
updateTitles({
|
|
variables: {
|
|
input: {
|
|
titles: Object.values(data).map((value) => value),
|
|
},
|
|
},
|
|
})
|
|
|
|
return (
|
|
<Form onSubmit={onSubmit} className="max-w-80 space-y-2">
|
|
<p className="text-center opacity-70">
|
|
The first one gets displayed for longer
|
|
</p>
|
|
{Array.from({ length: MAX_TITLES }).map((_, i) => (
|
|
<Label key={i} name={`title${i}`} className="form-control w-full">
|
|
<Label
|
|
name={`title${i}`}
|
|
className="input input-bordered flex items-center gap-2"
|
|
errorClassName="input input-bordered flex items-center gap-2 input-error"
|
|
>
|
|
<Label
|
|
name={`title${i}`}
|
|
className="size-4 opacity-70"
|
|
errorClassName="size-4 text-error"
|
|
>
|
|
<Icon path={mdiFormatTitle} />
|
|
</Label>
|
|
<TextField
|
|
name={`title${i}`}
|
|
ref={i === 0 ? title1ref : null}
|
|
placeholder={`Title ${i + 1}`}
|
|
defaultValue={states[i][0]}
|
|
autoComplete="off"
|
|
onChange={(e) => states[i][1](e.target.value)}
|
|
className="w-full"
|
|
/>
|
|
</Label>
|
|
{preview && (
|
|
<div className="label">
|
|
<p>
|
|
Hey 👋, I'm {`${process.env.FIRST_NAME}`},{' '}
|
|
<span className="text-primary">{states[i][0]}</span>
|
|
</p>
|
|
</div>
|
|
)}
|
|
</Label>
|
|
))}
|
|
|
|
<nav className="my-2 flex justify-center space-x-2">
|
|
<button
|
|
type="button"
|
|
className="btn btn-sm uppercase"
|
|
onClick={() => setPreview(!preview)}
|
|
>
|
|
{preview ? 'Hide' : 'Show'} Preview
|
|
</button>
|
|
<Submit
|
|
disabled={updateLoading}
|
|
className="btn btn-primary btn-sm uppercase"
|
|
>
|
|
Save
|
|
</Submit>
|
|
</nav>
|
|
</Form>
|
|
)
|
|
}
|
|
|
|
export default TitlesForm
|