Skip to content

Commit

Permalink
feat: start using suspense in EventFormWizard and add Exit modal
Browse files Browse the repository at this point in the history
  • Loading branch information
naftis committed Dec 3, 2024
1 parent 2bbd6d0 commit 9edad33
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 59 deletions.
46 changes: 28 additions & 18 deletions packages/client/src/v2-events/features/events/EventFormWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,58 @@ import {
Button,
Icon,
Content,
FormWizard
FormWizard,
Spinner
} from '@opencrvs/components'
import React from 'react'
import { useEventConfiguration } from './useEventConfiguration'
import { useParams } from 'react-router-dom'
import { useEventForm } from './useEventForm'
import { EventConfig } from '@opencrvs/commons/client'
import {
TextField,
Paragraph,
DateField,
RadioGroup
} from './registered-fields'
import { usePagination } from '@client/v2-events/hooks/usePagination'
import { useEventFormNavigation } from './useEventFormNavigation'
import { useIntl } from 'react-intl'
import { useParams } from 'react-router-dom'

export function EventFormWizardIndex() {
const { eventType } = useParams<{ eventType: string }>()

const { event, isLoading } = useEventConfiguration(eventType)

if (isLoading) {
return <div>Loading...</div>
}
const { event } = useEventConfiguration(eventType)

if (!event) {
throw new Error('Event not found')
}

return <EventFormWizard event={event} />
return (
<React.Suspense fallback={<Spinner id="event-form-spinner" />}>
<EventFormWizard event={event} />
</React.Suspense>
)
}

export function EventFormWizard({ event }: { event: EventConfig }) {
const { title, pages, exit, saveAndExit, previous, next, currentPageIndex } =
useEventForm(event)
const intl = useIntl()
const { page, next, previous } = usePagination(
event.actions[0].forms[0].pages.length
)
const { modal, exit } = useEventFormNavigation()

return (
<Frame
skipToContentText="Skip to form"
header={
<AppBar
mobileLeft={title}
desktopLeft={title}
mobileLeft={intl.formatMessage(event.label)}
desktopLeft={intl.formatMessage(event.label)}
desktopRight={
<Stack direction="row">
<Button type="primary" onClick={saveAndExit}>
<Button
type="primary"
onClick={() => alert('Whoops... Not implemented.')}
>
<Icon name="DownloadSimple" />
Save and exit
</Button>
Expand All @@ -72,6 +80,8 @@ export function EventFormWizard({ event }: { event: EventConfig }) {
/>
}
>
{modal}

<Frame.LayoutForm>
<Frame.SectionFormBackAction>
{previous && (
Expand All @@ -83,10 +93,10 @@ export function EventFormWizard({ event }: { event: EventConfig }) {
</Frame.SectionFormBackAction>

<Frame.Section>
<Content title={title}>
<Content title={intl.formatMessage(event.label)}>
<FormWizard
currentPage={currentPageIndex}
pages={pages}
currentPage={page}
pages={event.actions[0].forms[0].pages}
components={{
TEXT: TextField,
PARAGRAPH: Paragraph,
Expand Down
41 changes: 0 additions & 41 deletions packages/client/src/v2-events/features/events/useEventForm.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* OpenCRVS is also distributed under the terms of the Civil Registration
* & Healthcare Disclaimer located at http://opencrvs.org/license.
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import React from 'react'
import { Button, ResponsiveModal, Stack, Text } from '@opencrvs/components'
import { defineMessages, useIntl } from 'react-intl'
import { useModal } from '@client/v2-events/hooks/useModal'
import { V2_ROOT_ROUTE } from '@client/v2-events/routes'
import { useHistory } from 'react-router-dom'

const modalMessages = defineMessages({
cancel: {
id: 'exitModal.cancel',
defaultMessage: 'Cancel'
},
confirm: {
id: 'buttons.confirm',
defaultMessage: 'Confirm'
},
exitWithoutSavingTitle: {
id: 'exitModal.exitWithoutSaving',
defaultMessage: 'Exit without saving changes?'
},
exitWithoutSavingDescription: {
id: 'exitModal.exitWithoutSavingDescription',
defaultMessage:
'You have unsaved changes on your declaration form. Are you sure you want to exit without saving?'
}
})

export const useEventFormNavigation = () => {
const intl = useIntl()
const [modal, openModal] = useModal()
const history = useHistory()

const goToHome = () => {
history.push(V2_ROOT_ROUTE)
}

const exit = async () => {
const exitConfirm = await openModal<boolean | null>((close) => (
<ResponsiveModal
autoHeight
responsive={false}
title={intl.formatMessage(modalMessages.exitWithoutSavingTitle)}
actions={[
<Button
type="tertiary"
id="cancel_save_without_exit"
key="cancel_save_without_exit"
onClick={() => {
close(null)
}}
>
{intl.formatMessage(modalMessages.cancel)}
</Button>,
<Button
type="primary"
key="confirm_save_without_exit"
id="confirm_save_without_exit"
onClick={() => {
close(true)
}}
>
{intl.formatMessage(modalMessages.confirm)}
</Button>
]}
show={true}
handleClose={() => close(null)}
>
<Stack>
<Text variant="reg16" element="p" color="grey500">
{intl.formatMessage(modalMessages.exitWithoutSavingDescription)}
</Text>
</Stack>
</ResponsiveModal>
))

if (exitConfirm) {
goToHome()
}
}

return { exit, modal }
}
32 changes: 32 additions & 0 deletions packages/client/src/v2-events/hooks/useModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* OpenCRVS is also distributed under the terms of the Civil Registration
* & Healthcare Disclaimer located at http://opencrvs.org/license.
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import { ReactNode, useState } from 'react'

type CloseModal<ResultType> = (result: ResultType) => void

type ModalFactory<ResultType> = (close: CloseModal<ResultType>) => ReactNode

export function useModal() {
const [modalNode, setModalNode] = useState<ReactNode>(null)

function openModal<ModalResult>(modalFactory: ModalFactory<ModalResult>) {
return new Promise<ModalResult>((resolve) => {
function close(value: ModalResult) {
resolve(value)
setModalNode(null)
}

setModalNode(modalFactory(close))
})
}

return [modalNode, openModal] as const
}

0 comments on commit 9edad33

Please sign in to comment.