mirror of
https://github.com/IT4Change/ohmyform-ui.git
synced 2025-12-13 09:45:50 +00:00
add form submissions in admin
update fields during on next
This commit is contained in:
parent
37f9d0b62d
commit
98bb74ea0f
@ -33,7 +33,6 @@ export const FieldCard: React.FC<Props> = props => {
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
console.log('update fields')
|
||||
onChangeFields(fields.map((field, i) => {
|
||||
if (i === index) {
|
||||
return {
|
||||
@ -102,7 +101,10 @@ export const FieldCard: React.FC<Props> = props => {
|
||||
<Checkbox />
|
||||
</Form.Item>
|
||||
|
||||
<TypeComponent field={field} />
|
||||
<TypeComponent
|
||||
field={field}
|
||||
form={form}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,28 +1,37 @@
|
||||
import {DatePicker, Form} from 'antd'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
import {AdminFieldTypeProps} from './type.props'
|
||||
|
||||
export const DateType: React.FC<AdminFieldTypeProps> = props => {
|
||||
export const DateType: React.FC<AdminFieldTypeProps> = ({field, form}) => {
|
||||
return (
|
||||
<div>
|
||||
<Form.Item
|
||||
label={'Default Date'}
|
||||
name={[props.field.name, 'value']}
|
||||
name={[field.name, 'value']}
|
||||
labelCol={{ span: 6 }}
|
||||
getValueFromEvent={e => e ? e.format('YYYY-MM-DD') : undefined}
|
||||
getValueProps={e => ({value: e ? moment(e) : undefined})}
|
||||
>
|
||||
<DatePicker />
|
||||
<DatePicker
|
||||
format={'YYYY-MM-DD'}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={'Min Date'}
|
||||
name={[props.field.name, 'min']}
|
||||
name={[field.name, 'min']}
|
||||
labelCol={{ span: 6 }}
|
||||
getValueFromEvent={e => e.format('YYYY-MM-DD')}
|
||||
getValueProps={e => ({value: e ? moment(e) : undefined})}
|
||||
>
|
||||
<DatePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={'Max Date'}
|
||||
name={[props.field.name, 'max']}
|
||||
name={[field.name, 'max']}
|
||||
labelCol={{ span: 6 }}
|
||||
getValueFromEvent={e => e.format('YYYY-MM-DD')}
|
||||
getValueProps={e => ({value: e ? moment(e) : undefined})}
|
||||
>
|
||||
<DatePicker />
|
||||
</Form.Item>
|
||||
|
||||
@ -4,14 +4,12 @@ import {AdminFieldTypeProps} from './type.props'
|
||||
|
||||
export const TextType: React.FC<AdminFieldTypeProps> = props => {
|
||||
return (
|
||||
<div>
|
||||
<Form.Item
|
||||
label={'Default Value'}
|
||||
name={[props.field.name, 'value']}
|
||||
labelCol={{ span: 6 }}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
label={'Default Value'}
|
||||
name={[props.field.name, 'value']}
|
||||
labelCol={{ span: 6 }}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import {FormInstance} from 'antd/lib/form'
|
||||
|
||||
export interface AdminFieldTypeProps {
|
||||
form: FormInstance
|
||||
field: any
|
||||
}
|
||||
|
||||
@ -13,18 +13,19 @@ interface Props {
|
||||
field: FormFieldFragment
|
||||
design: FormDesignFragment
|
||||
|
||||
save: (data: any) => any
|
||||
next: () => any
|
||||
prev: () => any
|
||||
}
|
||||
|
||||
export const Field: React.FC<Props> = ({field, design, children, next, prev, ...props}) => {
|
||||
export const Field: React.FC<Props> = ({field, save, design, children, next, prev, ...props}) => {
|
||||
const [form] = useForm()
|
||||
|
||||
const FieldInput: React.FC<FieldTypeProps> = fieldTypes[field.type] || TextType
|
||||
|
||||
const finish = (data) => {
|
||||
console.log('received field data', data)
|
||||
|
||||
save(data)
|
||||
next()
|
||||
}
|
||||
|
||||
|
||||
@ -4,8 +4,9 @@ import React from 'react'
|
||||
import {StyledDateInput} from '../../styled/date.input'
|
||||
import {FieldTypeProps} from './type.props'
|
||||
|
||||
export const DateType: React.FC<FieldTypeProps> = ({field, design}) => {
|
||||
export const DateType: React.FC<FieldTypeProps> = ({ field, design}) => {
|
||||
// TODO check min and max
|
||||
// TODO if default is passed, then the changing should not be required
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -14,6 +15,8 @@ export const DateType: React.FC<FieldTypeProps> = ({field, design}) => {
|
||||
rules={[
|
||||
{ required: field.required, message: 'Please provide Information' },
|
||||
]}
|
||||
getValueFromEvent={e => e.format('YYYY-MM-DD')}
|
||||
getValueProps={e => ({value: e ? moment(e) : undefined})}
|
||||
>
|
||||
<StyledDateInput
|
||||
size={'large'}
|
||||
|
||||
@ -1,20 +1,23 @@
|
||||
import {Form, InputNumber} from 'antd'
|
||||
import {Form} from 'antd'
|
||||
import React from 'react'
|
||||
import {StyledNumberInput} from '../../styled/number.input'
|
||||
import {FieldTypeProps} from './type.props'
|
||||
|
||||
export const NumberType: React.FC<FieldTypeProps> = ({field}) => {
|
||||
export const NumberType: React.FC<FieldTypeProps> = ({field, design}) => {
|
||||
return (
|
||||
<div>
|
||||
<Form.Item
|
||||
label={'Default Number'}
|
||||
name={[field.id, 'value']}
|
||||
rules={[
|
||||
{ type: 'number', message: 'Must be a valid URL' },
|
||||
{ required: field.required, message: 'Please provide Information' },
|
||||
]}
|
||||
labelCol={{ span: 6 }}
|
||||
>
|
||||
<InputNumber />
|
||||
<StyledNumberInput
|
||||
design={design}
|
||||
size={'large'}
|
||||
defaultValue={parseFloat(field.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)
|
||||
|
||||
63
components/styled/number.input.tsx
Normal file
63
components/styled/number.input.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import {InputNumber} from 'antd'
|
||||
import {InputNumberProps} from 'antd/lib/input-number'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import styled from 'styled-components'
|
||||
import {FormDesignFragment} from '../../graphql/fragment/form.fragment'
|
||||
import {transparentize} from './color.change'
|
||||
|
||||
interface Props extends InputNumberProps {
|
||||
design: FormDesignFragment
|
||||
}
|
||||
|
||||
export const StyledNumberInput: React.FC<Props> = ({design, children, ...props}) => {
|
||||
const [Field, setField] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
setField(
|
||||
styled(InputNumber)`
|
||||
color: ${design.colors.answerColor};
|
||||
border-color: ${design.colors.answerColor};
|
||||
background: none !important;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
|
||||
:focus {
|
||||
outline: ${design.colors.answerColor} auto 5px
|
||||
}
|
||||
|
||||
:hover,
|
||||
:active {
|
||||
border-color: ${design.colors.answerColor};
|
||||
}
|
||||
|
||||
&.ant-input-number {
|
||||
box-shadow: none
|
||||
}
|
||||
|
||||
input {
|
||||
background: none !important;
|
||||
color: ${design.colors.answerColor};
|
||||
|
||||
::placeholder {
|
||||
color: ${transparentize(design.colors.answerColor, 60)}
|
||||
}
|
||||
}
|
||||
|
||||
.anticon {
|
||||
color: ${design.colors.answerColor};
|
||||
}
|
||||
`
|
||||
)
|
||||
}, [design])
|
||||
|
||||
if (!Field) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Field {...props}>{children}</Field>
|
||||
)
|
||||
}
|
||||
68
components/use.submission.ts
Normal file
68
components/use.submission.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {useMutation} from '@apollo/react-hooks'
|
||||
import {useCallback, useEffect, useState} from 'react'
|
||||
import {
|
||||
SUBMISSION_SET_FIELD_MUTATION,
|
||||
SubmissionSetFieldMutationData,
|
||||
SubmissionSetFieldMutationVariables
|
||||
} from '../graphql/mutation/submission.set.field.mutation'
|
||||
import {
|
||||
SUBMISSION_START_MUTATION,
|
||||
SubmissionStartMutationData,
|
||||
SubmissionStartMutationVariables
|
||||
} from '../graphql/mutation/submission.start.mutation'
|
||||
|
||||
export const useSubmission = (formId: string) => {
|
||||
const [submission, setSubmission] = useState<{ id: string, token: string }>()
|
||||
|
||||
const [start] = useMutation<SubmissionStartMutationData, SubmissionStartMutationVariables>(SUBMISSION_START_MUTATION)
|
||||
const [save] = useMutation<SubmissionSetFieldMutationData, SubmissionSetFieldMutationVariables>(SUBMISSION_SET_FIELD_MUTATION)
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const token = '123' // TODO generate secure token
|
||||
|
||||
const {data} = await start({
|
||||
variables: {
|
||||
form: formId,
|
||||
submission: {
|
||||
token,
|
||||
device: {
|
||||
name: '',
|
||||
type: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
setSubmission({
|
||||
id: data.submission.id,
|
||||
token,
|
||||
})
|
||||
})()
|
||||
}, [formId])
|
||||
|
||||
const setField = useCallback(async (fieldId: string, data: any) => {
|
||||
console.log('just save', fieldId, data)
|
||||
await save({
|
||||
variables: {
|
||||
submission: submission.id,
|
||||
field: {
|
||||
token: submission.token,
|
||||
field: fieldId,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [submission])
|
||||
|
||||
const finish = useCallback(() => {
|
||||
console.log('finish submission!!', formId)
|
||||
}, [submission])
|
||||
|
||||
console.log('submission saver :D', formId)
|
||||
|
||||
return {
|
||||
setField,
|
||||
finish,
|
||||
}
|
||||
}
|
||||
16
graphql/fragment/submission.fragment.ts
Normal file
16
graphql/fragment/submission.fragment.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {gql} from 'apollo-boost'
|
||||
|
||||
export interface SubmissionFragment {
|
||||
id?: string
|
||||
title: string
|
||||
created: string
|
||||
}
|
||||
|
||||
export const FORM_FRAGMENT = gql`
|
||||
fragment Submission on Submission {
|
||||
id
|
||||
title
|
||||
language
|
||||
showFooter
|
||||
}
|
||||
`
|
||||
0
graphql/mutation/submission.finish.mutation.ts
Normal file
0
graphql/mutation/submission.finish.mutation.ts
Normal file
26
graphql/mutation/submission.set.field.mutation.ts
Normal file
26
graphql/mutation/submission.set.field.mutation.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import {gql} from 'apollo-boost'
|
||||
|
||||
export interface SubmissionSetFieldMutationData {
|
||||
submission: {
|
||||
id: string
|
||||
percentageComplete: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface SubmissionSetFieldMutationVariables {
|
||||
submission: string
|
||||
field: {
|
||||
token: string
|
||||
field: string
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export const SUBMISSION_SET_FIELD_MUTATION = gql`
|
||||
mutation start($submission: ID!,$field: SubmissionSetFieldInput!) {
|
||||
submission: submissionSetField(submission: $submission, field: $field) {
|
||||
id
|
||||
percentageComplete
|
||||
}
|
||||
}
|
||||
`
|
||||
28
graphql/mutation/submission.start.mutation.ts
Normal file
28
graphql/mutation/submission.start.mutation.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import {gql} from 'apollo-boost'
|
||||
|
||||
export interface SubmissionStartMutationData {
|
||||
submission: {
|
||||
id: string
|
||||
percentageComplete: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface SubmissionStartMutationVariables {
|
||||
form: string
|
||||
submission: {
|
||||
token: string
|
||||
device: {
|
||||
type: string
|
||||
name: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const SUBMISSION_START_MUTATION = gql`
|
||||
mutation start($form: ID!,$submission: SubmissionStartInput!) {
|
||||
submission: submissionStart(form: $form, submission: $submission) {
|
||||
id
|
||||
percentageComplete
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -1,6 +1,6 @@
|
||||
import {gql} from 'apollo-boost'
|
||||
|
||||
export interface PagerFormEntryQueryData {
|
||||
export interface AdminPagerFormEntryQueryData {
|
||||
id: string
|
||||
created: string
|
||||
lastModified?: string
|
||||
@ -14,9 +14,9 @@ export interface PagerFormEntryQueryData {
|
||||
}
|
||||
}
|
||||
|
||||
export interface PagerFormQueryData {
|
||||
export interface AdminPagerFormQueryData {
|
||||
pager: {
|
||||
entries: PagerFormEntryQueryData[]
|
||||
entries: AdminPagerFormEntryQueryData[]
|
||||
|
||||
total: number
|
||||
limit: number
|
||||
@ -24,12 +24,12 @@ export interface PagerFormQueryData {
|
||||
}
|
||||
}
|
||||
|
||||
export interface PagerFormQueryVariables {
|
||||
export interface AdminPagerFormQueryVariables {
|
||||
start?: number
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export const PAGER_FORM_QUERY = gql`
|
||||
export const ADMIN_PAGER_FORM_QUERY = gql`
|
||||
query pager($start: Int, $limit: Int){
|
||||
pager: listForms(start: $start, limit: $limit) {
|
||||
entries {
|
||||
68
graphql/query/admin.pager.submission.query.ts
Normal file
68
graphql/query/admin.pager.submission.query.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import {gql} from 'apollo-boost'
|
||||
|
||||
export interface AdminPagerSubmissionFormQueryData {
|
||||
id: string
|
||||
title: string
|
||||
isLive: boolean
|
||||
}
|
||||
|
||||
export interface AdminPagerSubmissionEntryQueryData {
|
||||
id: string
|
||||
created: string
|
||||
lastModified?: string
|
||||
percentageComplete: number
|
||||
timeElapsed: number
|
||||
geoLocation: {
|
||||
country: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface AdminPagerSubmissionQueryData {
|
||||
pager: {
|
||||
entries: AdminPagerSubmissionEntryQueryData[]
|
||||
|
||||
total: number
|
||||
limit: number
|
||||
start: number
|
||||
}
|
||||
|
||||
form: AdminPagerSubmissionFormQueryData
|
||||
}
|
||||
|
||||
export interface AdminPagerSubmissionQueryVariables {
|
||||
form: string
|
||||
start?: number
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export const ADMIN_PAGER_SUBMISSION_QUERY = gql`
|
||||
query pager($form: ID!, $start: Int, $limit: Int){
|
||||
form: getFormById(id: $form) {
|
||||
id
|
||||
title
|
||||
isLive
|
||||
}
|
||||
|
||||
pager: listSubmissions(form: $form, start: $start, limit: $limit) {
|
||||
entries {
|
||||
id
|
||||
created
|
||||
lastModified
|
||||
percentageComplete
|
||||
timeElapsed
|
||||
geoLocation {
|
||||
country
|
||||
}
|
||||
|
||||
fields {
|
||||
id
|
||||
value
|
||||
type
|
||||
}
|
||||
}
|
||||
total
|
||||
limit
|
||||
start
|
||||
}
|
||||
}
|
||||
`
|
||||
121
pages/admin/forms/[id]/submissions.tsx
Normal file
121
pages/admin/forms/[id]/submissions.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
import {EditOutlined} from '@ant-design/icons/lib'
|
||||
import {useQuery} from '@apollo/react-hooks'
|
||||
import {Button, Space, Table} from 'antd'
|
||||
import {PaginationProps} from 'antd/es/pagination'
|
||||
import {DateTime} from 'components/date.time'
|
||||
import Structure from 'components/structure'
|
||||
import {TimeAgo} from 'components/time.ago'
|
||||
import {withAuth} from 'components/with.auth'
|
||||
import {NextPage} from 'next'
|
||||
import Link from 'next/link'
|
||||
import {useRouter} from 'next/router'
|
||||
import React, {useState} from 'react'
|
||||
import {
|
||||
ADMIN_PAGER_SUBMISSION_QUERY,
|
||||
AdminPagerSubmissionEntryQueryData,
|
||||
AdminPagerSubmissionFormQueryData,
|
||||
AdminPagerSubmissionQueryData,
|
||||
AdminPagerSubmissionQueryVariables
|
||||
} from '../../../../graphql/query/admin.pager.submission.query'
|
||||
|
||||
const Submissions: NextPage = () => {
|
||||
const router = useRouter()
|
||||
const [pagination, setPagination] = useState<PaginationProps>({
|
||||
pageSize: 25,
|
||||
})
|
||||
const [form, setForm] = useState<AdminPagerSubmissionFormQueryData>()
|
||||
const [entries, setEntries] = useState<AdminPagerSubmissionEntryQueryData[]>()
|
||||
const {loading, refetch} = useQuery<AdminPagerSubmissionQueryData, AdminPagerSubmissionQueryVariables>(ADMIN_PAGER_SUBMISSION_QUERY, {
|
||||
variables: {
|
||||
form: router.query.id as string,
|
||||
limit: pagination.pageSize,
|
||||
start: pagination.current * pagination.pageSize || 0
|
||||
},
|
||||
onCompleted: ({pager, form}) => {
|
||||
setPagination({
|
||||
...pagination,
|
||||
total: pager.total,
|
||||
})
|
||||
setForm(form)
|
||||
setEntries(pager.entries)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Values',
|
||||
dataIndex: 'fields',
|
||||
render: fields => <pre>{JSON.stringify(fields, null, 2)}</pre>
|
||||
},
|
||||
{
|
||||
title: 'Created',
|
||||
dataIndex: 'created',
|
||||
render: date => <DateTime date={date} />
|
||||
},
|
||||
{
|
||||
title: 'Last Change',
|
||||
dataIndex: 'lastModified',
|
||||
render: date => <TimeAgo date={date} />
|
||||
},
|
||||
{
|
||||
render: row => {
|
||||
return (
|
||||
<Space>
|
||||
<Link
|
||||
href={'/admin/forms/[id]'}
|
||||
as={`/admin/forms/${row.id}`}
|
||||
>
|
||||
<Button type={'primary'}><EditOutlined /></Button>
|
||||
</Link>
|
||||
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<Structure
|
||||
title={loading ? 'Loading Submissions' : 'Submissions'}
|
||||
selected={'forms'}
|
||||
loading={loading}
|
||||
breadcrumbs={[
|
||||
{ href: '/admin', name: 'Home' },
|
||||
{ href: '/admin/forms', name: 'Form' },
|
||||
{ href: '/admin/forms/[id]', name: loading || !form ? 'Loading Form' : `Edit Form "${form.title}"`, as: `/admin/forms/${router.query.id}` },
|
||||
]}
|
||||
padded={false}
|
||||
extra={[
|
||||
<Link
|
||||
key={'edit'}
|
||||
href={'/admin/forms/[id]'}
|
||||
as={`/admin/forms/${router.query.id}`}
|
||||
>
|
||||
<Button>
|
||||
Edit
|
||||
</Button>
|
||||
</Link>,
|
||||
<Button
|
||||
key={'web'}
|
||||
href={`/forms/${router.query.id}`}
|
||||
target={'_blank'}
|
||||
type={'primary'}
|
||||
>
|
||||
Open Form
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={entries}
|
||||
rowKey={'id'}
|
||||
pagination={pagination}
|
||||
onChange={next => {
|
||||
setPagination(pagination)
|
||||
}}
|
||||
/>
|
||||
</Structure>
|
||||
)
|
||||
}
|
||||
|
||||
export default withAuth(Submissions, ['admin'])
|
||||
@ -1,4 +1,4 @@
|
||||
import {DeleteOutlined, EditOutlined, GlobalOutlined} from '@ant-design/icons/lib'
|
||||
import {DeleteOutlined, EditOutlined, GlobalOutlined, UnorderedListOutlined} from '@ant-design/icons/lib'
|
||||
import {useQuery} from '@apollo/react-hooks'
|
||||
import {Button, Popconfirm, Space, Table, Tooltip} from 'antd'
|
||||
import {PaginationProps} from 'antd/es/pagination'
|
||||
@ -8,11 +8,11 @@ import Structure from 'components/structure'
|
||||
import {TimeAgo} from 'components/time.ago'
|
||||
import {withAuth} from 'components/with.auth'
|
||||
import {
|
||||
PAGER_FORM_QUERY,
|
||||
PagerFormEntryQueryData,
|
||||
PagerFormQueryData,
|
||||
PagerFormQueryVariables
|
||||
} from 'graphql/query/pager.form.query'
|
||||
ADMIN_PAGER_FORM_QUERY,
|
||||
AdminPagerFormEntryQueryData,
|
||||
AdminPagerFormQueryData,
|
||||
AdminPagerFormQueryVariables
|
||||
} from 'graphql/query/admin.pager.form.query'
|
||||
import {NextPage} from 'next'
|
||||
import Link from 'next/link'
|
||||
import React, {useState} from 'react'
|
||||
@ -21,9 +21,8 @@ const Index: NextPage = () => {
|
||||
const [pagination, setPagination] = useState<PaginationProps>({
|
||||
pageSize: 25,
|
||||
})
|
||||
const [entries, setEntries] = useState<PagerFormEntryQueryData[]>()
|
||||
// TODO limit forms if user is only admin!
|
||||
const {loading, refetch} = useQuery<PagerFormQueryData, PagerFormQueryVariables>(PAGER_FORM_QUERY, {
|
||||
const [entries, setEntries] = useState<AdminPagerFormEntryQueryData[]>()
|
||||
const {loading, refetch} = useQuery<AdminPagerFormQueryData, AdminPagerFormQueryVariables>(ADMIN_PAGER_FORM_QUERY, {
|
||||
variables: {
|
||||
limit: pagination.pageSize,
|
||||
start: pagination.current * pagination.pageSize || 0
|
||||
@ -80,6 +79,15 @@ const Index: NextPage = () => {
|
||||
render: row => {
|
||||
return (
|
||||
<Space>
|
||||
<Link
|
||||
href={'/admin/forms/[id]/submissions'}
|
||||
as={`/admin/forms/${row.id}/submissions`}
|
||||
>
|
||||
<Tooltip title={'Show Submissions'}>
|
||||
<Button><UnorderedListOutlined /></Button>
|
||||
</Tooltip>
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href={'/admin/forms/[id]'}
|
||||
as={`/admin/forms/${row.id}`}
|
||||
|
||||
@ -10,6 +10,7 @@ import React, {useState} from 'react'
|
||||
import Swiper from 'react-id-swiper'
|
||||
import {ReactIdSwiperProps} from 'react-id-swiper/lib/types'
|
||||
import * as OriginalSwiper from 'swiper'
|
||||
import {useSubmission} from '../../../components/use.submission'
|
||||
|
||||
interface Props {
|
||||
id: string
|
||||
@ -18,6 +19,7 @@ interface Props {
|
||||
const Index: NextPage<Props> = ({id}) => {
|
||||
const windowSize = useWindowSize()
|
||||
const [swiper, setSwiper] = useState<OriginalSwiper.default>(null)
|
||||
const submission = useSubmission(id)
|
||||
|
||||
const {loading, data, error} = useQuery<FormQueryData, FormQueryVariables>(FORM_QUERY, {
|
||||
variables: {
|
||||
@ -70,11 +72,18 @@ const Index: NextPage<Props> = ({id}) => {
|
||||
next={goNext}
|
||||
prev={goPrev}
|
||||
/> : undefined,
|
||||
...data.form.fields.map(field => (
|
||||
...data.form.fields.map((field, i) => (
|
||||
<Field
|
||||
key={field.id}
|
||||
field={field}
|
||||
design={design}
|
||||
save={values => {
|
||||
submission.setField(field.id, values[field.id])
|
||||
|
||||
if (data.form.fields.length === i - 1) {
|
||||
submission.finish()
|
||||
}
|
||||
}}
|
||||
next={goNext}
|
||||
prev={goPrev}
|
||||
/>
|
||||
@ -84,7 +93,7 @@ const Index: NextPage<Props> = ({id}) => {
|
||||
type={'end'}
|
||||
page={data.form.endPage}
|
||||
design={design}
|
||||
next={goNext}
|
||||
next={submission.finish}
|
||||
prev={goPrev}
|
||||
/> : undefined
|
||||
].filter(e => !!e)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user