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

Tuloselvityksen saavutettavuus- ja UI-parannuksia #6384

Merged
merged 3 commits into from
Feb 17, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
AttachmentId,
IncomeStatementId
} from 'lib-common/generated/api-types/shared'
import { IncomeStatementAttachments } from 'lib-common/income-statements'
import { IncomeStatementAttachments } from 'lib-common/income-statements/attachments'
import { FixedSpaceColumn } from 'lib-components/layout/flex-helpers'
import FileUpload from 'lib-components/molecules/FileUpload'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
IncomeStatementId
} from 'lib-common/generated/api-types/shared'
import { fromUuid } from 'lib-common/id-type'
import { fromBody } from 'lib-common/income-statements/body'
import * as Form from 'lib-common/income-statements/form'
import { emptyIncomeStatementForm } from 'lib-common/income-statements/form'
import LocalDate from 'lib-common/local-date'
import {
constantQuery,
Expand All @@ -31,9 +34,6 @@ import {
incomeStatementQuery,
updateIncomeStatementMutation
} from './queries'
import { fromBody } from './types/body'
import * as Form from './types/form'
import { emptyIncomeStatementForm } from './types/form'

interface EditorState {
id: string | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import styled from 'styled-components'
import { Result } from 'lib-common/api'
import { IncomeStatementStatus } from 'lib-common/generated/api-types/incomestatement'
import { IncomeStatementId } from 'lib-common/generated/api-types/shared'
import { numAttachments } from 'lib-common/income-statements'
import { numAttachments } from 'lib-common/income-statements/attachments'
import * as Form from 'lib-common/income-statements/form'
import LocalDate from 'lib-common/local-date'
import { scrollToRef } from 'lib-common/utils/scrolling'
import { AsyncButton } from 'lib-components/atoms/buttons/AsyncButton'
Expand All @@ -31,7 +32,7 @@ import { useLang, useTranslation } from '../localization'
import ChildIncomeStatementAttachments from './ChildIncomeStatementAttachments'
import {
AttachmentSection,
makeAttachmentHandler
useAttachmentHandler
} from './IncomeStatementAttachments'
import {
ActionContainer,
Expand All @@ -42,7 +43,6 @@ import {
useFieldDispatch,
useFieldSetState
} from './IncomeStatementComponents'
import * as Form from './types/form'

const OtherInfoContainer = styled.div`
max-width: 716px;
Expand All @@ -62,14 +62,10 @@ const ChildIncome = React.memo(function ChildIncome({
const t = useTranslation()

const onAttachmentChange = useFieldSetState(onChange, 'attachments')
const attachmentHandler = useMemo(
() =>
makeAttachmentHandler(
incomeStatementId,
formData.attachments,
onAttachmentChange
),
[formData.attachments, incomeStatementId, onAttachmentChange]
const attachmentHandler = useAttachmentHandler(
incomeStatementId,
formData.attachments,
onAttachmentChange
)

const onOtherInfoChanged = useFieldDispatch(onChange, 'otherInfo')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { IncomeStatementId } from 'lib-common/generated/api-types/shared'
import {
collectAttachmentIds,
toIncomeStatementAttachments
} from 'lib-common/income-statements'
} from 'lib-common/income-statements/attachments'
import {
computeRequiredAttachments,
fromIncomeStatement
} from 'lib-common/income-statements/form'
import { useQueryResult } from 'lib-common/query'
import { useIdRouteParam } from 'lib-common/useRouteParams'
import HorizontalLine from 'lib-components/atoms/HorizontalLine'
Expand All @@ -36,7 +40,6 @@ import {
incomeStatementQuery,
updateSentIncomeStatementMutation
} from './queries'
import { computeRequiredAttachments, fromIncomeStatement } from './types/form'

export default React.memo(function ChildIncomeStatementView() {
const incomeStatementId =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: LGPL-2.1-or-later

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React, { useCallback, useMemo } from 'react'
import React, { useCallback, useMemo, useRef } from 'react'
import styled from 'styled-components'

import { Attachment } from 'lib-common/generated/api-types/attachment'
Expand All @@ -18,8 +18,7 @@ import {
import {
IncomeStatementAttachments,
numAttachments
} from 'lib-common/income-statements'
import { scrollToElement } from 'lib-common/utils/scrolling'
} from 'lib-common/income-statements/attachments'
import UnorderedList from 'lib-components/atoms/UnorderedList'
import { Button } from 'lib-components/atoms/buttons/Button'
import { ContentArea } from 'lib-components/layout/Container'
Expand All @@ -45,7 +44,7 @@ import {
SetStateCallback
} from './IncomeStatementComponents'

function attachmentSectionId(type: IncomeStatementAttachmentType): string {
function attachmentSectionDataQa(type: IncomeStatementAttachmentType): string {
return `attachment-section-${type}`
}

Expand All @@ -58,80 +57,104 @@ export interface AttachmentHandler {
onDeleted: (id: AttachmentId) => void
getDownloadUrl: (id: AttachmentId) => string
}
setElement: (
attachmentType: IncomeStatementAttachmentType,
el: HTMLElement | null
) => void
focus: (attachmentType: IncomeStatementAttachmentType) => void
}

/** Returns `undefined` if the income statement contains old untyped attachments */
export function makeAttachmentHandler(
export function useAttachmentHandler(
id: IncomeStatementId | undefined,
attachments: IncomeStatementAttachments,
onChange: SetStateCallback<IncomeStatementAttachments>
): AttachmentHandler | undefined {
if (!attachments.typed) {
// Has untyped attachments
return undefined
}
const { attachmentsByType } = attachments
return {
hasAttachment: (attachmentType: IncomeStatementAttachmentType) =>
!!attachmentsByType[attachmentType]?.length,
fileUploadProps: (attachmentType: IncomeStatementAttachmentType) => {
const files = attachmentsByType[attachmentType] ?? []
return {
files,
uploadHandler: incomeStatementAttachment(id, attachmentType),
onUploaded: (attachment: Attachment) => {
onChange((prev) => {
// Should not happen
if (!prev.typed) return prev
const refs = useRef<
Partial<Record<IncomeStatementAttachmentType, HTMLElement>>
>({})
return useMemo(() => {
if (!attachments.typed) {
// Has untyped attachments
return undefined
}
const { attachmentsByType } = attachments
return {
hasAttachment: (attachmentType: IncomeStatementAttachmentType) =>
!!attachmentsByType[attachmentType]?.length,
fileUploadProps: (attachmentType: IncomeStatementAttachmentType) => {
const files = attachmentsByType[attachmentType] ?? []
return {
files,
uploadHandler: incomeStatementAttachment(id, attachmentType),
onUploaded: (attachment: Attachment) => {
onChange((prev) => {
// Should not happen
if (!prev.typed) return prev

const { attachmentsByType } = prev
if (attachmentsByType[attachmentType]) {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: [
...attachmentsByType[attachmentType],
attachment
]
const { attachmentsByType } = prev
if (attachmentsByType[attachmentType]) {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: [
...attachmentsByType[attachmentType],
attachment
]
}
}
}
} else {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: [attachment]
} else {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: [attachment]
}
}
}
}
})
},
onDeleted: (id: AttachmentId) => {
onChange((prev) => {
// Should not happen
if (!prev.typed) return prev
})
},
onDeleted: (id: AttachmentId) => {
onChange((prev) => {
// Should not happen
if (!prev.typed) return prev

const { attachmentsByType } = prev
if (attachmentsByType[attachmentType]) {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: attachmentsByType[attachmentType].filter(
(a) => a.id !== id
)
const { attachmentsByType } = prev
if (attachmentsByType[attachmentType]) {
return {
...prev,
attachmentsByType: {
...attachmentsByType,
[attachmentType]: attachmentsByType[attachmentType].filter(
(a) => a.id !== id
)
}
}
} else {
return prev
}
} else {
return prev
}
})
},
getDownloadUrl: () => ''
})
},
getDownloadUrl: () => ''
}
},
setElement: (
attachmentType: IncomeStatementAttachmentType,
el: HTMLElement | null
) => {
if (el) {
refs.current[attachmentType] = el
} else {
delete refs.current[attachmentType]
}
},
focus: (attachmentType: IncomeStatementAttachmentType) => {
const element = refs.current[attachmentType]
if (element) element.focus()
}
}
}
}, [attachments, id, onChange])
}

export const AttachmentSection = React.memo(function AttachmentSection({
Expand Down Expand Up @@ -176,7 +199,8 @@ export const AttachmentSection = React.memo(function AttachmentSection({
{labelAndInfo}
{!dense && <Gap size="xs" />}
<FileUpload
id={attachmentSectionId(attachmentType)}
ref={(el) => attachmentHandler.setElement(attachmentType, el)}
data-qa={attachmentSectionDataQa(attachmentType)}
{...fileUploadProps(attachmentType)}
/>
</>
Expand Down Expand Up @@ -209,12 +233,7 @@ export const IncomeStatementMissingAttachments = React.memo(
<Button
appearance="link"
onClick={() => {
const element = document.getElementById(
attachmentSectionId(attachmentType)
)
if (element) {
scrollToElement(element, 0, 'center')
}
attachmentHandler.focus(attachmentType)
}}
text={t.income.attachments.attachmentNames[attachmentType]}
/>
Expand Down Expand Up @@ -373,14 +392,10 @@ export const CitizenAttachmentsWithUpload = React.memo(
onChange: SetStateCallback<IncomeStatementAttachments>
}) {
const t = useTranslation()
const attachmentHandler = useMemo(
() =>
makeAttachmentHandler(
incomeStatementId,
incomeStatementAttachments,
onChange
),
[incomeStatementAttachments, incomeStatementId, onChange]
const attachmentHandler = useAttachmentHandler(
incomeStatementId,
incomeStatementAttachments,
onChange
)

if (!incomeStatementAttachments.typed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { combine, Loading, Result } from 'lib-common/api'
import { IncomeStatementStatus } from 'lib-common/generated/api-types/incomestatement'
import { IncomeStatementId } from 'lib-common/generated/api-types/shared'
import { fromUuid } from 'lib-common/id-type'
import { fromBody } from 'lib-common/income-statements/body'
import * as Form from 'lib-common/income-statements/form'
import { emptyIncomeStatementForm } from 'lib-common/income-statements/form'
import LocalDate from 'lib-common/local-date'
import {
constantQuery,
Expand All @@ -28,9 +31,6 @@ import {
incomeStatementStartDatesQuery,
updateIncomeStatementMutation
} from './queries'
import { fromBody } from './types/body'
import * as Form from './types/form'
import { emptyIncomeStatementForm } from './types/form'

interface EditorState {
id: string | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
otherIncomes
} from 'lib-common/generated/api-types/incomestatement'
import { IncomeStatementId } from 'lib-common/generated/api-types/shared'
import * as Form from 'lib-common/income-statements/form'
import LocalDate from 'lib-common/local-date'
import { scrollToRef } from 'lib-common/utils/scrolling'
import UnorderedList from 'lib-components/atoms/UnorderedList'
Expand Down Expand Up @@ -56,9 +57,9 @@ import { useLang, useTranslation } from '../localization'
import {
IncomeStatementUntypedAttachments,
IncomeStatementMissingAttachments,
makeAttachmentHandler,
AttachmentHandler,
AttachmentSection
AttachmentSection,
useAttachmentHandler
} from './IncomeStatementAttachments'
import {
ActionContainer,
Expand All @@ -71,7 +72,6 @@ import {
useFieldDispatch,
useFieldSetState
} from './IncomeStatementComponents'
import * as Form from './types/form'

interface Props {
incomeStatementId: IncomeStatementId | undefined
Expand Down Expand Up @@ -180,14 +180,10 @@ export default React.memo(
)

const onAttachmentChange = useFieldSetState(onChange, 'attachments')
const attachmentHandler = useMemo(
() =>
makeAttachmentHandler(
incomeStatementId,
formData.attachments,
onAttachmentChange
),
[formData.attachments, incomeStatementId, onAttachmentChange]
const attachmentHandler = useAttachmentHandler(
incomeStatementId,
formData.attachments,
onAttachmentChange
)

const sendButtonEnabled = useMemo(
Expand Down
Loading
Loading