Skip to content

Commit

Permalink
events v2 collect certificate workflow boilerplate code
Browse files Browse the repository at this point in the history
  • Loading branch information
tareq89 committed Jan 10, 2025
1 parent 0c24f14 commit f5083b4
Show file tree
Hide file tree
Showing 12 changed files with 371 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* 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, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import {
useTypedParams,
useTypedSearchParams
} from 'react-router-typesafe-routes/dom'
import { v4 as uuid } from 'uuid'
import { ActionType, getCurrentEventState } from '@opencrvs/commons/client'
import { useEvents } from '@client/v2-events//features/events/useEvents/useEvents'
import { Pages as PagesComponent } from '@client/v2-events/features/events/components/Pages'
import { useEventConfiguration } from '@client/v2-events/features/events/useEventConfiguration'
import { useEventFormNavigation } from '@client/v2-events/features/events/useEventFormNavigation'
import { ROUTES } from '@client/v2-events/routes'
import { useEventFormData } from '@client/v2-events/features/events/useEventFormData'
import { FormLayout } from '@client/v2-events/layouts/form'

export function Pages() {
const { eventId, pageId } = useTypedParams(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES
)
const [searchParams] = useTypedSearchParams(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES
)
const setFormValues = useEventFormData((state) => state.setFormValues)
const formEventId = useEventFormData((state) => state.eventId)
const form = useEventFormData((state) => state.formValues)
const navigate = useNavigate()
const events = useEvents()
const { modal, goToHome } = useEventFormNavigation()

const [event] = events.getEvent.useSuspenseQuery(eventId)
const currentState = getCurrentEventState(event)

useEffect(() => {
if (formEventId !== event.id) {
setFormValues(event.id, currentState.data)
}
}, [currentState.data, event.id, formEventId, setFormValues])

const { eventConfiguration: configuration } = useEventConfiguration(
event.type
)
const formPages = configuration.actions
.find((action) => action.type === ActionType.COLLECT_CERTIFICATE)
?.forms.find((form) => form.active)?.pages

if (!formPages) {
throw new Error('Form configuration not found for type: ' + event.type)
}

const currentPageId =
formPages.find((p) => p.id === pageId)?.id || formPages[0]?.id

if (!currentPageId) {
throw new Error('Form does not have any pages')
}

useEffect(() => {
if (pageId !== currentPageId) {
navigate(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES.buildPath({
eventId,
pageId: currentPageId
}),
{ replace: true }
)
}
}, [pageId, currentPageId, navigate, eventId])

return (
<FormLayout
route={ROUTES.V2.EVENTS.COLLECT_CERTIFICATE}
onSaveAndExit={() => {
events.actions.collectCertificate.mutate({
eventId: event.id,
data: form,
transactionId: uuid(),
draft: true
})
goToHome()
}}
>
{modal}
<PagesComponent
eventId={eventId}
formPages={formPages}
pageId={currentPageId}
showReviewButton={searchParams.from === 'review'}
onFormPageChange={(nextPageId: string) =>
navigate(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES.buildPath({
eventId,
pageId: nextPageId
})
)
}
onSubmit={() =>
navigate(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.REVIEW.buildPath({ eventId })
)
}
/>
</FormLayout>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* 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, { useEffect } from 'react'
import { defineMessages } from 'react-intl'
import { useNavigate } from 'react-router-dom'
import { v4 as uuid } from 'uuid'
import { useTypedParams } from 'react-router-typesafe-routes/dom'
import { getCurrentEventState, ActionType } from '@opencrvs/commons/client'
import { ROUTES } from '@client/v2-events/routes'
import { useEvents } from '@client/v2-events/features/events/useEvents/useEvents'
import { Review as ReviewComponent } from '@client/v2-events/features/events/components/Review'
import { useModal } from '@client/v2-events/hooks/useModal'
import { useEventFormNavigation } from '@client/v2-events/features/events/useEventFormNavigation'
import { useEventConfiguration } from '@client/v2-events/features/events/useEventConfiguration'
import { useEventFormData } from '@client/v2-events/features/events/useEventFormData'
import { FormLayout } from '@client/v2-events/layouts/form'

const messages = defineMessages({
registerActionTitle: {
id: 'registerAction.title',
defaultMessage: 'Register member',
description: 'The title for register action'
},
registerActionDescription: {
id: 'registerAction.description',
defaultMessage:
'By clicking register, you confirm that the information entered is correct and the member can be registered.',
description: 'The description for register action'
},
registerActionDeclare: {
id: 'registerAction.Declare',
defaultMessage: 'Register',
description: 'The label for declare button of register action'
}
})

/**
*
* Preview of event to be registered.
*/
export function Review() {
const { eventId } = useTypedParams(ROUTES.V2.EVENTS.COLLECT_CERTIFICATE)
const events = useEvents()
const [modal, openModal] = useModal()
const navigate = useNavigate()
const { goToHome } = useEventFormNavigation()
const collectCertificateMutation = events.actions.collectCertificate

const [event] = events.getEvent.useSuspenseQuery(eventId)

const { eventConfiguration: config } = useEventConfiguration(event.type)

if (!config) {
throw new Error('Event configuration not found with type: ' + event.type)
}

const { forms: formConfigs } = config.actions.filter(
(action) => action.type === ActionType.COLLECT_CERTIFICATE
)[0]

const setFormValues = useEventFormData((state) => state.setFormValues)
const getFormValues = useEventFormData((state) => state.getFormValues)

useEffect(() => {
setFormValues(eventId, getCurrentEventState(event).data)
}, [event, eventId, setFormValues])

const form = getFormValues(eventId)

async function handleEdit({
pageId,
fieldId
}: {
pageId: string
fieldId?: string
}) {
const confirmedEdit = await openModal<boolean | null>((close) => (
<ReviewComponent.EditModal close={close} />
))

if (confirmedEdit) {
navigate(
ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES.buildPath(
{ pageId, eventId },
{
from: 'review'
},
fieldId
)
)
}
return
}

async function handleRegistration() {
const confirmedRegistration = await openModal<boolean | null>((close) => (
<ReviewComponent.ActionModal action="Collect Certificate" close={close} />
))
if (confirmedRegistration) {
collectCertificateMutation.mutate({
eventId: event.id,
data: form,
transactionId: uuid()
})

goToHome()
}
}

return (
<FormLayout
route={ROUTES.V2.EVENTS.COLLECT_CERTIFICATE}
onSaveAndExit={() => {
events.actions.collectCertificate.mutate({
eventId: event.id,
data: form,
transactionId: uuid(),
draft: true
})
goToHome()
}}
>
<ReviewComponent.Body
eventConfig={config}
form={form}
formConfig={formConfigs[0]}
title=""
onEdit={handleEdit}
>
<ReviewComponent.Actions
messages={{
title: messages.registerActionTitle,
description: messages.registerActionDescription,
onConfirm: messages.registerActionDeclare
}}
onConfirm={handleRegistration}
/>
{modal}
</ReviewComponent.Body>
</FormLayout>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* 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 { Review } from './Review'
import { Pages } from './Pages'

export { Review, Pages }
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ type Mutation =
| typeof api.event.actions.notify
| typeof api.event.actions.register
| typeof api.event.actions.validate
| typeof api.event.actions.collectCertificate

type Procedure =
| typeof utils.event.actions.declare
| typeof utils.event.actions.notify
| typeof utils.event.actions.register
| typeof utils.event.actions.validate
| typeof utils.event.actions.collectCertificate

/*
* This makes sure that if you are offline and do
Expand Down Expand Up @@ -164,6 +166,15 @@ utils.event.actions.validate.setMutationDefaults(({ canonicalMutationFn }) => ({
onSuccess: updateLocalEvent
}))

utils.event.actions.collectCertificate.setMutationDefaults(
({ canonicalMutationFn }) => ({
retry: true,
retryDelay: 10000,
mutationFn: waitUntilEventIsCreated(canonicalMutationFn),
onSuccess: updateLocalEvent
})
)

export function useEventAction<P extends Procedure, M extends Mutation>(
procedure: P,
mutation: M
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ export function useEvents() {
register: useEventAction(
utils.event.actions.register,
api.event.actions.register
),
collectCertificate: useEventAction(
utils.event.actions.collectCertificate,
api.event.actions.collectCertificate
)
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/v2-events/layouts/form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FormHeader } from './FormHeader'
type AllowedRoute =
| typeof ROUTES.V2.EVENTS.REGISTER
| typeof ROUTES.V2.EVENTS.DECLARE
| typeof ROUTES.V2.EVENTS.COLLECT_CERTIFICATE

/**
* Layout for form and review pages.
Expand Down
19 changes: 19 additions & 0 deletions packages/client/src/v2-events/routes/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Debug } from '@client/v2-events/features/debug/debug'
import * as Declare from '@client/v2-events/features/events/actions/declare'
import { DeleteEvent } from '@client/v2-events/features/events/actions/delete'
import * as Register from '@client/v2-events/features/events/actions/register'
import * as CollectCertificate from '@client/v2-events/features/events/actions/collect-certificate'
import { ValidateEvent } from '@client/v2-events/features/events/actions/validate'
import { EventSelection } from '@client/v2-events/features/events/EventSelection'
import { EventOverviewIndex } from '@client/v2-events/features/workqueues/EventOverview/EventOverview'
Expand Down Expand Up @@ -108,6 +109,24 @@ export const routesConfig = {
element: <Register.Review />
}
]
},
{
path: ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.path,
element: <Outlet />,
children: [
{
index: true,
element: <CollectCertificate.Pages />
},
{
path: ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.PAGES.path,
element: <CollectCertificate.Pages />
},
{
path: ROUTES.V2.EVENTS.COLLECT_CERTIFICATE.REVIEW.path,
element: <CollectCertificate.Review />
}
]
}
]
}
18 changes: 17 additions & 1 deletion packages/client/src/v2-events/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,23 @@ export const ROUTES = {
),
VALIDATE: route('validate/:eventId', {
params: { eventId: string().defined() }
})
}),
COLLECT_CERTIFICATE: route(
'collect-certificates/:eventId',
{
params: { eventId: string().defined() }
},
{
REVIEW: route('review'),
PAGES: route('pages/:pageId', {
params: { pageId: string() },
searchParams: {
from: string()
},
hash: hashValues()
})
}
)
}
),
WORKQUEUE: route('workqueue', {
Expand Down
Loading

0 comments on commit f5083b4

Please sign in to comment.