Skip to content

Commit

Permalink
Merge pull request #6082 from espoon-voltti/finance-decision-processes
Browse files Browse the repository at this point in the history
Talouspäätösten asianhallintaprosessit
  • Loading branch information
Joosakur authored Dec 13, 2024
2 parents f6e6ea9 + 4fb9102 commit a90db8d
Show file tree
Hide file tree
Showing 29 changed files with 931 additions and 218 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017-2022 City of Espoo
// SPDX-FileCopyrightText: 2017-2024 City of Espoo
//
// SPDX-License-Identifier: LGPL-2.1-or-later

Expand All @@ -7,13 +7,16 @@ import { Navigate, useNavigate } from 'react-router'

import { Loading, Result, wrapResult } from 'lib-common/api'
import {
FeeDecisionDetailed,
FeeDecisionResponse,
FeeDecisionType
} from 'lib-common/generated/api-types/invoicing'
import { useQueryResult } from 'lib-common/query'
import { UUID } from 'lib-common/types'
import useRouteParams from 'lib-common/useRouteParams'
import ReturnButton from 'lib-components/atoms/buttons/ReturnButton'
import { Container, ContentArea } from 'lib-components/layout/Container'
import InfoModal from 'lib-components/molecules/modals/InfoModal'
import { Gap } from 'lib-components/white-space'
import { faQuestion } from 'lib-icons'

import {
Expand All @@ -22,6 +25,9 @@ import {
} from '../../generated/api-clients/invoicing'
import { useTranslation } from '../../state/i18n'
import { TitleContext, TitleState } from '../../state/title'
import MetadataSection from '../archive-metadata/MetadataSection'
import { renderResult } from '../async-rendering'
import { feeDecisionMetadataQuery } from '../fee-decisions/fee-decision-queries'
import FinanceDecisionHandlerSelectModal from '../finance-decisions/FinanceDecisionHandlerSelectModal'

import Actions from './Actions'
Expand All @@ -32,42 +38,54 @@ import Summary from './Summary'
const confirmFeeDecisionDraftsResult = wrapResult(confirmFeeDecisionDrafts)
const getFeeDecisionResult = wrapResult(getFeeDecision)

const FeeDecisionMetadataSection = React.memo(
function FeeDecisionMetadataSection({
feeDecisionId
}: {
feeDecisionId: UUID
}) {
const result = useQueryResult(feeDecisionMetadataQuery({ feeDecisionId }))
return <MetadataSection metadataResult={result} />
}
)

export default React.memo(function FeeDecisionDetailsPage() {
const [showHandlerSelectModal, setShowHandlerSelectModal] = useState(false)
const navigate = useNavigate()
const { id } = useRouteParams(['id'])
const { i18n } = useTranslation()
const { setTitle, formatTitleName } = useContext<TitleState>(TitleContext)
const [decision, setDecision] = useState<Result<FeeDecisionDetailed>>(
Loading.of()
)
const [decisionResponse, setDecisionResponse] = useState<
Result<FeeDecisionResponse>
>(Loading.of())
const [modified, setModified] = useState<boolean>(false)
const [newDecisionType, setNewDecisionType] =
useState<FeeDecisionType>('NORMAL')
const [confirmingBack, setConfirmingBack] = useState<boolean>(false)

const loadDecision = useCallback(
() => getFeeDecisionResult({ id }).then(setDecision),
() => getFeeDecisionResult({ id }).then(setDecisionResponse),
[id]
)
useEffect(() => void loadDecision(), [id]) // eslint-disable-line react-hooks/exhaustive-deps

useEffect(() => {
if (decision.isSuccess) {
if (decisionResponse.isSuccess) {
const decision = decisionResponse.value.data
const name = formatTitleName(
decision.value.headOfFamily.firstName,
decision.value.headOfFamily.lastName
decision.headOfFamily.firstName,
decision.headOfFamily.lastName
)
if (decision.value.status === 'DRAFT') {
if (decision.status === 'DRAFT') {
setTitle(`${name} | ${i18n.titles.feeDecisionDraft}`)
} else {
setTitle(`${name} | ${i18n.titles.feeDecision}`)
}
setNewDecisionType(decision.value.decisionType)
setNewDecisionType(decision.decisionType)
}
}, [decision]) // eslint-disable-line react-hooks/exhaustive-deps
}, [decisionResponse]) // eslint-disable-line react-hooks/exhaustive-deps

const decisionType = decision.map(({ decisionType }) => decisionType)
const decisionType = decisionResponse.map(({ data }) => data.decisionType)
const changeDecisionType = useCallback(
(type: FeeDecisionType) => {
if (decisionType.isSuccess) {
Expand All @@ -81,7 +99,7 @@ export default React.memo(function FeeDecisionDetailsPage() {

const goBack = useCallback(() => navigate(-1), [navigate])

if (decision.isFailure) {
if (decisionResponse.isFailure) {
return <Navigate replace to="/finance/fee-decisions" />
}

Expand All @@ -92,59 +110,69 @@ export default React.memo(function FeeDecisionDetailsPage() {
data-qa="fee-decision-details-page"
>
<ReturnButton label={i18n.common.goBack} data-qa="navigate-back" />
{decision.isSuccess && (
<>
{showHandlerSelectModal && (
<FinanceDecisionHandlerSelectModal
onResolve={async (decisionHandlerId) => {
const result = await confirmFeeDecisionDraftsResult({
decisionHandlerId,
body: [decision.value.id]
})
if (result.isSuccess) {
await loadDecision()
setShowHandlerSelectModal(false)
}
return result
}}
onReject={() => setShowHandlerSelectModal(false)}
checkedIds={[decision.value.id]}
/>
)}
<ContentArea opaque>
<Heading
{...decision.value}
changeDecisionType={changeDecisionType}
newDecisionType={newDecisionType}
/>
{decision.value.children.map(
({
child,
placementType,
placementUnit,
serviceNeedDescriptionFi
}) => (
<ChildSection
key={child.id}
child={child}
placementType={placementType}
placementUnit={placementUnit}
serviceNeedDescription={serviceNeedDescriptionFi}
/>
)
{renderResult(
decisionResponse,
({ data: decision, permittedActions }) => (
<>
{showHandlerSelectModal && (
<FinanceDecisionHandlerSelectModal
onResolve={async (decisionHandlerId) => {
const result = await confirmFeeDecisionDraftsResult({
decisionHandlerId,
body: [decision.id]
})
if (result.isSuccess) {
await loadDecision()
setShowHandlerSelectModal(false)
}
return result
}}
onReject={() => setShowHandlerSelectModal(false)}
checkedIds={[decision.id]}
/>
)}
<Summary decision={decision.value} />
<Actions
decision={decision.value}
goToDecisions={goBack}
loadDecision={loadDecision}
modified={modified}
setModified={setModified}
newDecisionType={newDecisionType}
onHandlerSelectModal={() => setShowHandlerSelectModal(true)}
/>
</ContentArea>
</>
<ContentArea opaque>
<Heading
{...decision}
changeDecisionType={changeDecisionType}
newDecisionType={newDecisionType}
/>
{decision.children.map(
({
child,
placementType,
placementUnit,
serviceNeedDescriptionFi
}) => (
<ChildSection
key={child.id}
child={child}
placementType={placementType}
placementUnit={placementUnit}
serviceNeedDescription={serviceNeedDescriptionFi}
/>
)
)}
<Summary decision={decision} />
<Actions
decision={decision}
goToDecisions={goBack}
loadDecision={loadDecision}
modified={modified}
setModified={setModified}
newDecisionType={newDecisionType}
onHandlerSelectModal={() => setShowHandlerSelectModal(true)}
/>
</ContentArea>
{decision.status !== 'DRAFT' &&
permittedActions.includes('READ_METADATA') && (
<>
<Gap />
<FeeDecisionMetadataSection feeDecisionId={id} />
</>
)}
</>
)
)}
</Container>
{confirmingBack && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: 2017-2024 City of Espoo
//
// SPDX-License-Identifier: LGPL-2.1-or-later

import { query } from 'lib-common/query'
import { Arg0 } from 'lib-common/types'

import { getFeeDecisionMetadata } from '../../generated/api-clients/process'
import { createQueryKeys } from '../../query'

const queryKeys = createQueryKeys('feeDecisions', {
feeDecisionMetadata: (args: Arg0<typeof getFeeDecisionMetadata>) => [
'feeDecisionMetadata',
args
]
})

export const feeDecisionMetadataQuery = query({
api: getFeeDecisionMetadata,
queryKey: queryKeys.feeDecisionMetadata
})
Loading

0 comments on commit a90db8d

Please sign in to comment.