207 lines
6.2 KiB
TypeScript

import { useMutation, useQuery } from '@apollo/client'
import React, { FormEvent, useEffect, useState } from 'react'
import { Redirect, useParams } from 'react-router-dom'
import { FORM, FORMSUBMIT } from '../../apollo'
import {
ChoiseAnswer,
ChoisesQuestion,
Form,
InputAnswer,
InputQuestion,
QueryFormArgs,
} from '../../apollo/typeDefs.gen'
import Lists from './Lists'
interface IFormQuery {
form: Form
}
const DoForm: React.FC = () => {
const { id: idString } = useParams<{ id: string }>()
const id = parseInt(idString)
const { data, error, loading } = useQuery<IFormQuery, QueryFormArgs>(FORM, {
variables: { id },
skip: isNaN(id),
})
const [
doFormSubmit,
{ error: submitError, data: submitData, loading: submitLoading },
] = useMutation(FORMSUBMIT)
const [answers, setAnswer] = useState<(InputAnswer | ChoiseAnswer)[]>([])
const getInitialState = (data: IFormQuery) => {
if (data && data.form) {
return data.form.questions.flatMap<InputAnswer | ChoiseAnswer>(
(el: InputQuestion | ChoisesQuestion) => {
if (el.__typename === 'ChoisesQuestion')
return [
{ __typename: 'ChoiseAnswer', type: 'CHOISE', userChoise: -1 },
]
if (el.__typename === 'InputQuestion')
return [{ __typename: 'InputAnswer', type: 'INPUT', userInput: '' }]
return []
}
)
}
return []
}
useEffect(() => {
if (data) {
const initialState = getInitialState(data)
setAnswer(initialState)
}
}, [data])
useEffect(() => console.log(answers), [answers])
if (isNaN(id)) return <Redirect to="/" />
if (loading) return <div>Loading...</div>
if (error) return <div>{error.message}</div>
const { form } = data!
const handleSubmit = (e: FormEvent) => {
e.preventDefault()
console.log('Submited form:', answers)
answers.forEach((el) => {
delete el.__typename
})
const submitAnswers = JSON.stringify(answers)
console.log('Filtered answers: ', submitAnswers)
doFormSubmit({
variables: {
formId: id,
answers: submitAnswers,
},
})
}
const answerChange = (num: number) => {
return (value: number | string) => {
setAnswer((prev) => {
return prev.map((el, index) => {
if (index === num) {
if (el.__typename === 'ChoiseAnswer' && typeof value === 'number')
return { ...el, userChoise: value }
if (el.__typename === 'InputAnswer' && typeof value === 'string')
return { ...el, userInput: value }
}
return el
})
})
}
}
return (
<div>
<h1>{form.title}</h1>
<p>{form.dateCreated}</p>
<h3>{form.author?.name || 'No author'}</h3>
{form.submissions ? (
<div>
<h1>Submission{form.submissions.length > 1 && 's'}:</h1>
<ul>
{form.submissions.map((submission, submissionIndex) => (
<li key={submissionIndex}>
<h2>
User:{' '}
{submission.user ? submission.user.name : 'No submitter'}
</h2>
<ul>
{submission.answers.map(
(answer: InputAnswer | ChoiseAnswer, answerIndex) => (
<li key={answerIndex}>
<h3>{form.questions[answerIndex].title}</h3>
{answer.__typename === 'ChoiseAnswer' && (
<h4>
{
(form.questions[answerIndex] as ChoisesQuestion)
.variants[answer.userChoise].text
}
</h4>
)}
{answer.__typename === 'InputAnswer' && (
<h4>{answer.userInput}</h4>
)}
</li>
)
)}
</ul>
</li>
))}
</ul>
</div>
) : (
<form onSubmit={handleSubmit}>
<ul>
{form.questions.map((el: InputQuestion | ChoisesQuestion) => {
if (el.__typename === 'InputQuestion')
return (
<li key={el.number}>
<label>
{el.title}
<input
onChange={(e) =>
answerChange(el.number)(e.currentTarget.value)
}
type="text"
/>
</label>
</li>
)
if (el.__typename === 'ChoisesQuestion')
return (
<li key={el.number}>
<label>
{el.title}
{el.type === 'SELECT' ? (
<select
onChange={(e) => {
const selectValue = el.variants.findIndex(
(val) => val.text === e.currentTarget.value
)
answerChange(el.number)(selectValue)
}}
name={el.title}
>
{el.variants.map((option, index) => (
<option key={index}>{option.text}</option>
))}
</select>
) : (
<Lists
variants={el.variants}
onChange={answerChange(el.number)}
name={el.title}
type={el.type}
/>
)}
</label>
</li>
)
return <li>Unknown question type</li>
})}
</ul>
{submitLoading ? <p>Uploading...</p> : <input type="submit" />}
</form>
)}
{submitError && <p>{submitError.message}</p>}
{submitData && submitData.formSubmit && submitData.formSubmit.success && (
<p>Successfully uploaded</p>
)}
</div>
)
}
export default DoForm