Skip to content

Commit

Permalink
Merge branch 'master' into Nekku_meal_integration
Browse files Browse the repository at this point in the history
  • Loading branch information
tahtee committed Feb 13, 2025
2 parents a1b1429 + d642bed commit 305ed01
Show file tree
Hide file tree
Showing 71 changed files with 2,490 additions and 1,473 deletions.
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"concurrently": "^9.1.0",
"css-loader": "^7.1.1",
"csstype": "^3.1.2",
"esbuild": "^0.24.0",
"esbuild": "^0.25.0",
"eslint": "^9.20.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-import": "^2.31.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import LocalDate from 'lib-common/local-date'
import { useIdRouteParam } from 'lib-common/useRouteParams'
import { useUniqueId } from 'lib-common/utils/useUniqueId'
import Checkbox from 'lib-components/atoms/form/Checkbox'
import AdaptiveFlex from 'lib-components/layout/AdaptiveFlex'
import ExpandingInfo from 'lib-components/molecules/ExpandingInfo'
import FileUpload from 'lib-components/molecules/FileUpload'
import { AlertBox } from 'lib-components/molecules/MessageBoxes'
Expand Down Expand Up @@ -127,12 +128,25 @@ export default React.memo(function PreferredStartSubSection({
<>
<Gap size="s" />

<strong>
{
t.applications.editor.serviceNeed.urgent.attachmentsMessage
.subtitle
}
</strong>
<AdaptiveFlex>
<strong>
{
t.applications.editor.serviceNeed.urgent
.attachmentsMessage.subtitle
}
</strong>
{verificationRequested &&
errors.urgencyAttachments?.arrayErrors && (
<AlertBox
message={
t.validationErrors[
errors.urgencyAttachments.arrayErrors
]
}
thin
/>
)}
</AdaptiveFlex>

<Gap size="s" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useIdRouteParam } from 'lib-common/useRouteParams'
import Checkbox from 'lib-components/atoms/form/Checkbox'
import Radio from 'lib-components/atoms/form/Radio'
import TimeInput from 'lib-components/atoms/form/TimeInput'
import AdaptiveFlex from 'lib-components/layout/AdaptiveFlex'
import {
FixedSpaceColumn,
FixedSpaceRow
Expand Down Expand Up @@ -296,9 +297,20 @@ export default React.memo(function ServiceTimeSubSectionDaycare({

<Gap size="s" />

<strong>
{t.applications.editor.serviceNeed.shiftCare.attachmentsSubtitle}
</strong>
<AdaptiveFlex>
<strong>
{t.applications.editor.serviceNeed.shiftCare.attachmentsSubtitle}
</strong>
{verificationRequested &&
errors.shiftCareAttachments?.arrayErrors && (
<AlertBox
message={
t.validationErrors[errors.shiftCareAttachments.arrayErrors]
}
thin
/>
)}
</AdaptiveFlex>

<Gap size="s" />

Expand Down
56 changes: 54 additions & 2 deletions frontend/src/citizen-frontend/applications/editor/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
TIME_REGEXP,
validate
} from 'lib-common/form-validation'
import { ApplicationDetails as ApplicationDetailsGen } from 'lib-common/generated/api-types/application'
import {
ApplicationAttachment,
ApplicationDetails as ApplicationDetailsGen
} from 'lib-common/generated/api-types/application'
import LocalDate from 'lib-common/local-date'
import { featureFlags } from 'lib-customizations/citizen'

Expand Down Expand Up @@ -67,6 +70,26 @@ const preferredStartDateValidator =
? undefined
: err

export const getUrgencyAttachmentValidStatus = (
urgent: boolean,
urgencyAttachments: ApplicationAttachment[]
) =>
urgent && urgencyAttachments.length === 0 && featureFlags.urgencyAttachments
? featureFlags.requireAttachments
? 'require'
: 'notify'
: undefined

export const getShiftCareAttachmentsValidStatus = (
shiftCare: boolean,
shiftCareAttachments: ApplicationAttachment[]
) =>
shiftCare && shiftCareAttachments.length === 0
? featureFlags.requireAttachments
? 'require'
: 'notify'
: undefined

export const validateApplication = (
apiData: ApplicationDetailsGen,
form: ApplicationFormData,
Expand Down Expand Up @@ -125,7 +148,36 @@ export const validateApplication = (
: undefined,
assistanceDescription: form.serviceNeed.assistanceNeeded
? required(form.serviceNeed.assistanceDescription)
: undefined
: undefined,
urgencyAttachments:
getUrgencyAttachmentValidStatus(
form.serviceNeed.urgent,
form.serviceNeed.urgencyAttachments
) === 'require'
? {
arrayErrors: 'required',
itemErrors: form.serviceNeed.urgencyAttachments.map(() => ({
id: undefined,
name: undefined
}))
}
: undefined,
shiftCareAttachments:
getShiftCareAttachmentsValidStatus(
form.serviceNeed.shiftCare,
form.serviceNeed.shiftCareAttachments
) === 'require'
? {
arrayErrors:
form.serviceNeed.shiftCareAttachments.length === 0
? 'required'
: undefined,
itemErrors: form.serviceNeed.shiftCareAttachments.map(() => ({
id: undefined,
name: undefined
}))
}
: undefined
},
unitPreference: {
siblingName:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ import RoundIcon from 'lib-components/atoms/RoundIcon'
import Container, { ContentArea } from 'lib-components/layout/Container'
import { H1, P } from 'lib-components/typography'
import { defaultMargins, Gap } from 'lib-components/white-space'
import { featureFlags } from 'lib-customizations/citizen'
import colors from 'lib-customizations/common'
import { faInfo } from 'lib-icons'

import BasicsSection from '../../../applications/editor/verification/BasicsSection'
import UnitPreferenceSection from '../../../applications/editor/verification/UnitPreferenceSection'
import { useTranslation } from '../../../localization'
import {
getShiftCareAttachmentsValidStatus,
getUrgencyAttachmentValidStatus
} from '../validations'

import AdditionalDetailsSection from './AdditionalDetailsSection'
import ContactInfoSection from './ContactInfoSection'
Expand Down Expand Up @@ -52,14 +55,18 @@ export default React.memo(function ApplicationVerificationViewDaycare({
}: DaycareApplicationVerificationViewProps) {
const t = useTranslation()
const missingUrgencyAttachments =
formData.serviceNeed.urgent &&
formData.serviceNeed.urgencyAttachments.length === 0 &&
featureFlags.urgencyAttachments
getUrgencyAttachmentValidStatus(
formData.serviceNeed.urgent,
formData.serviceNeed.urgencyAttachments
) === 'notify'
const missingShiftCareAttachments =
getShiftCareAttachmentsValidStatus(
formData.serviceNeed.shiftCare,
formData.serviceNeed.shiftCareAttachments
) === 'notify'

const missingAttachments =
missingUrgencyAttachments ||
(formData.serviceNeed.shiftCare &&
formData.serviceNeed.shiftCareAttachments.length === 0)
missingUrgencyAttachments || missingShiftCareAttachments
return (
<Container>
<ContentArea opaque>
Expand All @@ -83,15 +90,11 @@ export default React.memo(function ApplicationVerificationViewDaycare({
{t.applications.editor.verification.attachmentBox.urgency}
</li>
)}
{formData.serviceNeed.shiftCare &&
formData.serviceNeed.shiftCareAttachments.length === 0 && (
<li>
{
t.applications.editor.verification.attachmentBox
.shiftCare
}
</li>
)}
{missingShiftCareAttachments && (
<li>
{t.applications.editor.verification.attachmentBox.shiftCare}
</li>
)}
</ul>
<P>
<a href="#" onClick={closeVerification} role="button">
Expand Down
55 changes: 34 additions & 21 deletions frontend/src/citizen-frontend/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
// SPDX-License-Identifier: LGPL-2.1-or-later

import { Failure, Success, wrapResult } from 'lib-common/api'
import { AttachmentType } from 'lib-common/generated/api-types/attachment'
import { ApplicationAttachmentType } from 'lib-common/generated/api-types/application'
import { IncomeStatementAttachmentType } from 'lib-common/generated/api-types/incomestatement'
import {
ApplicationId,
AttachmentId,
Expand All @@ -14,22 +15,30 @@ import { UploadHandler } from 'lib-components/molecules/FileUpload'
import { API_URL, client } from './api-client'
import { deleteAttachment } from './generated/api-clients/attachment'

function uploadHandler(url: string): UploadHandler {
function uploadHandler(config: {
path: string
params?: unknown
}): UploadHandler {
return {
upload: async (file, onUploadProgress) => {
const formData = new FormData()
formData.append('file', file)

try {
const { data } = await client.post<AttachmentId>(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: ({ loaded, total }) =>
onUploadProgress(
total !== undefined && total !== 0
? Math.round((loaded / total) * 100)
: 0
)
})
const { data } = await client.post<AttachmentId>(
config.path,
formData,
{
headers: { 'Content-Type': 'multipart/form-data' },
params: config.params,
onUploadProgress: ({ loaded, total }) =>
onUploadProgress(
total !== undefined && total !== 0
? Math.round((loaded * 100) / total)
: 0
)
}
)
return Success.of(data)
} catch (e) {
return Failure.fromError(e)
Expand All @@ -42,24 +51,28 @@ function uploadHandler(url: string): UploadHandler {
const deleteAttachmentResult = wrapResult(deleteAttachment)

export function incomeStatementAttachment(
incomeStatementId: IncomeStatementId | undefined
incomeStatementId: IncomeStatementId | undefined,
attachmentType: IncomeStatementAttachmentType | null
): UploadHandler {
return uploadHandler(
incomeStatementId
return uploadHandler({
path: incomeStatementId
? `/citizen/attachments/income-statements/${incomeStatementId}`
: '/citizen/attachments/income-statements'
)
: '/citizen/attachments/income-statements',
params: { attachmentType }
})
}

export const messageAttachment = uploadHandler('/citizen/attachments/messages')
export const messageAttachment = uploadHandler({
path: '/citizen/attachments/messages'
})

export function applicationAttachment(
applicationId: ApplicationId,
attachmentType: AttachmentType
attachmentType: ApplicationAttachmentType
): UploadHandler {
return uploadHandler(
`/citizen/attachments/applications/${applicationId}?type=${attachmentType}`
)
return uploadHandler({
path: `/citizen/attachments/applications/${applicationId}?type=${attachmentType}`
})
}

export function getAttachmentUrl(
Expand Down
Loading

0 comments on commit 305ed01

Please sign in to comment.