Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events v2: Use the same UI components in new event selector that were used in the old one #8131

Merged
merged 8 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import {
import { Workqueues } from './v2-events/features/workqueues'
import { EventFormWizardIndex } from './v2-events/features/events/EventFormWizard'
import { TRPCProvider } from './v2-events/trcp'
import { Events } from './v2-events/features/events/EventSelection'
import { EventSelection } from './v2-events/features/events/EventSelection'

interface IAppProps {
client?: ApolloClient<NormalizedCacheObject>
Expand Down Expand Up @@ -538,7 +538,7 @@ export function App(props: IAppProps) {
<ProtectedRoute
exact
path={V2_EVENTS_ROUTE}
component={Events}
component={EventSelection}
/>
<ProtectedRoute
exact
Expand Down
3 changes: 2 additions & 1 deletion packages/client/src/v2-events/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ module.exports = {
'@client/*',
'!@client/v2-events',
'!@client/components',
'!@client/utils'
'!@client/utils',
'!@client/navigation'
]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
FormWizard
} from '@opencrvs/components'
import React from 'react'
import { useEvent } from './useEvent'
import { useEventConfiguration } from './useEventConfiguration'
import { useParams } from 'react-router-dom'
import { useEventForm } from './useEventForm'
import { EventConfig } from '@opencrvs/commons/client'
Expand All @@ -33,7 +33,7 @@ import {
export function EventFormWizardIndex() {
const { eventType } = useParams<{ eventType: string }>()

const { event, isLoading } = useEvent(eventType)
const { event, isLoading } = useEventConfiguration(eventType)

if (isLoading) {
return <div>Loading...</div>
Expand Down
208 changes: 136 additions & 72 deletions packages/client/src/v2-events/features/events/EventSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,98 +9,162 @@
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/

import React from 'react'

import { EventType } from '@client/utils/gateway'
import { AppBar } from '@opencrvs/components/lib/AppBar'
import { Button } from '@opencrvs/components/lib/Button'
import { Content, ContentSize } from '@opencrvs/components/lib/Content'
import { ErrorText } from '@opencrvs/components/lib/ErrorText'
import { Frame } from '@opencrvs/components/lib/Frame'
import { Icon } from '@opencrvs/components/lib/Icon'
import { RadioButton } from '@opencrvs/components/lib/Radio'
import { Stack } from '@opencrvs/components/lib/Stack'
import React, { useState } from 'react'
import {
Frame,
AppBar,
Button,
Icon,
Content,
ContentSize,
FormWizard,
Values,
Spinner
} from '@opencrvs/components'
import { V2_EVENT_ROUTE } from '@client/v2-events/routes'

import { trpc } from '@client/v2-events/trcp'
import { formatUrl } from './utils'
WrappedComponentProps as IntlShapeProps,
defineMessages,
injectIntl,
useIntl
} from 'react-intl'
import { connect } from 'react-redux'
import { useEventConfigurations } from './useEventConfiguration'
import { V2_EVENT_ROUTE, V2_ROOT_ROUTE } from '@client/v2-events/routes'
import { useHistory } from 'react-router-dom'
import { RadioGroup } from './registered-fields/RadioGroup'
import { formatUrl } from '@client/navigation'

const messages = defineMessages({
registerNewEventTitle: {
id: 'register.selectVitalEvent.registerNewEventTitle',
defaultMessage: 'New declaration',
description: 'The title that appears on the select vital event page'
},
registerNewEventHeading: {
id: 'register.selectVitalEvent.registerNewEventHeading',
defaultMessage: 'What type of event do you want to declare?',
description: 'The section heading on the page'
},
continueButton: {
defaultMessage: 'Continue',
description: 'Continue Button Text',
id: 'buttons.continue'
},
errorMessage: {
id: 'register.selectVitalEvent.errorMessage',
defaultMessage: 'Please select the type of event',
description: 'Error Message to show when no event is being selected'
},
exitButton: {
defaultMessage: 'EXIT',
description: 'Label for Exit button on EventTopBar',
id: 'buttons.exit'
}
})

const constantsMessages = defineMessages({
skipToMainContent: {
defaultMessage: 'Skip to main content',
description:
'Label for a keyboard accessibility link which skips to the main content',
id: 'constants.skipToMainContent'
}
})

export const Events = () => {
export const EventSelection = (props: IntlShapeProps) => {
const intl = useIntl()
const history = useHistory()
const { data, isLoading } = trpc.config.get.useQuery()
const events = useEventConfigurations()
const [eventType, setEventType] = useState('')
const [noEventSelectedError, setNoEventSelectedError] = useState(false)

const events = data ?? []
const goToHome = () => {
history.push(V2_ROOT_ROUTE)
}

const onSubmit = ({ eventType }: Values) => {
if (eventType) {
history.push(
formatUrl(V2_EVENT_ROUTE, {
eventType
})
)
const handleContinue = () => {
if (eventType === '') {
return setNoEventSelectedError(true)
}

history.push(
formatUrl(V2_EVENT_ROUTE, {
eventType
})
)
}

return (
<Frame
header={
<AppBar
title="OpenCRVS"
desktopLeft="Declaration"
desktopLeft={<Icon name="Draft" size="large" />}
desktopTitle={intl.formatMessage(messages.registerNewEventTitle)}
desktopRight={
<Button type="secondary" onClick={() => {}}>
<Button
id="goBack"
type="secondary"
size="small"
onClick={goToHome}
>
<Icon name="X" />
{intl.formatMessage(messages.exitButton)}
</Button>
}
mobileLeft={<Icon name="Draft" size="large" />}
mobileTitle={intl.formatMessage(messages.registerNewEventTitle)}
mobileRight={
<Button type="icon" size="medium" onClick={goToHome}>
<Icon name="X" />
Exit
</Button>
}
/>
}
skipToContentText="Skip to main content"
skipToContentText={intl.formatMessage(
constantsMessages.skipToMainContent
)}
>
<Frame.Layout>
<Frame.Section>
<Content size={ContentSize.SMALL} title="Event type">
{isLoading ? (
<Spinner id="event-type-spinner" />
) : (
<FormWizard
currentPage={0}
pages={[
{
fields: [
{
name: 'eventType',
type: 'RADIO_GROUP',
required: true,
label: {
defaultMessage: 'Select an event',
description: 'Select an event',
id: 'event.select.label'
},
options: events.map((event) => ({
value: event.id,
label: event.label.defaultMessage
}))
}
]
}
]}
components={{
RADIO_GROUP: RadioGroup
}}
defaultValues={{
eventType: events[0]?.id
}}
onSubmit={onSubmit}
/>
)}
</Content>
</Frame.Section>
</Frame.Layout>
<Content
size={ContentSize.SMALL}
title={intl.formatMessage(messages.registerNewEventHeading)}
bottomActionButtons={[
<Button
key="select-vital-event-continue"
id="continue"
type="primary"
size="large"
fullWidth
onClick={handleContinue}
>
{intl.formatMessage(messages.continueButton)}
</Button>
]}
>
{noEventSelectedError && (
<ErrorText id="require-error">
{intl.formatMessage(messages.errorMessage)}
</ErrorText>
)}
<Stack
id="select_vital_event_view"
direction="column"
alignItems="left"
gap={0}
>
{events.data?.map((event) => (
<RadioButton
size="large"
key={`${event.id}event`}
name={`${event.id}event`}
label={intl.formatMessage(event.label)}
value={event.id}
id="select_birth_event"
selected={eventType === event.id ? event.id : ''}
onChange={() => {
setEventType(event.id)
setNoEventSelectedError(false)
}}
/>
))}
</Stack>
</Content>
</Frame>
)
}
8 changes: 0 additions & 8 deletions packages/client/src/v2-events/features/events/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,6 @@ export const tennisClubMembershipEvent = {
defaultMessage: "Applicant's date of birth",
description: 'This is the label for the field',
id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.label'
},
options: {
notice: {
id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.notice',
defaultMessage:
'This is the notice for the date of birth field',
description: 'This is the description for the notice'
}
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { FieldProps } from '@opencrvs/commons'
import { useIntl } from 'react-intl'

export const DateField = ({ id, options }: FieldProps<'DATE'>) => {
export const DateField = ({ id, options = {} }: FieldProps<'DATE'>) => {
const intl = useIntl()
const { setValue, watch } = useFormContext()
const value = watch(id)
Expand All @@ -26,7 +26,7 @@ export const DateField = ({ id, options }: FieldProps<'DATE'>) => {
<InputField id={id} touched={false}>
<DateFieldComponent
id={id}
notice={intl.formatMessage(options.notice)}
notice={options.notice && intl.formatMessage(options.notice)}
onChange={(val) => setValue(id, val)}
value={value}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,27 @@
import { trpc } from '@client/v2-events/trcp'

/**
* Fetches configures events and finds a matching event
* Fetches configured events and finds a matching event
* @returns a list of event configurations
*/
export function useEventConfigurations() {
const res = trpc.config.get.useQuery()
const { failureReason } = res
if (failureReason) {
// eslint-disable-next-line no-console
console.error(failureReason?.data?.stack)
}

return res
}

/**
* Fetches configured events and finds a matching event
* @param eventIdentifier e.g. 'birth', 'death', 'marriage' or any configured event
* @returns event configuration
*/
export function useEvent(eventIdentifier: string) {
const hook = trpc.config.get.useQuery()
export function useEventConfiguration(eventIdentifier: string) {
const hook = useEventConfigurations()
const { error, data, isFetching } = hook

const event = data?.find((event) => event.id === eventIdentifier)
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/v2-events/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@

export const V2_ROOT_ROUTE = '/v2'
export const V2_EVENTS_ROUTE = `${V2_ROOT_ROUTE}/event`
export const V2_EVENT_ROUTE = `${V2_EVENTS_ROUTE}/event/:eventType`
export const V2_EVENT_ROUTE = `${V2_EVENTS_ROUTE}/:eventType`
10 changes: 7 additions & 3 deletions packages/commons/src/events/FieldConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ const DateField = z
id: z.string(),
required: z.boolean(),
label: TranslationConfig,
options: z.object({
notice: TranslationConfig.describe('Text to display above the date input')
})
options: z
.object({
notice: TranslationConfig.describe(
'Text to display above the date input'
).optional()
})
.optional()
})
.describe('A single date input (dd-mm-YYYY)')

Expand Down
7 changes: 0 additions & 7 deletions packages/commons/src/fixtures/tennis-club-membership-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,6 @@ export const tennisClubMembershipEvent = defineConfig({
defaultMessage: "Applicant's date of birth",
description: 'This is the label for the field',
id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.label'
},
options: {
notice: {
id: 'event.tennis-club-membership.action.declare.form.section.who.field.dob.notice',
defaultMessage: 'This is the notice for the field',
description: 'This is the description for the notice'
}
}
}
]
Expand Down
4 changes: 4 additions & 0 deletions packages/events/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"watch": ["src/**", "../commons/build/**"],
"ext": "js,ts"
}
Loading