diff --git a/apps/judicial-system/backend/src/app/modules/event/event.service.ts b/apps/judicial-system/backend/src/app/modules/event/event.service.ts index 9ab7679e86ae..d3b9c0848136 100644 --- a/apps/judicial-system/backend/src/app/modules/event/event.service.ts +++ b/apps/judicial-system/backend/src/app/modules/event/event.service.ts @@ -43,7 +43,7 @@ const caseEvent: Record = { [CaseTransition.ACCEPT]: ':white_check_mark: Samþykkt', [CaseTransition.APPEAL]: ':judge: Kæra', ARCHIVE: ':file_cabinet: Sett í geymslu', - [CaseTransition.ASK_FOR_CANCELLATION]: ':interrobang: Beðið um aftuköllun', + [CaseTransition.ASK_FOR_CANCELLATION]: ':interrobang: Beðið um afturköllun', [CaseTransition.ASK_FOR_CONFIRMATION]: ':question: Beðið um staðfestingu', [CaseTransition.COMPLETE]: ':white_check_mark: Lokið', [CaseTransition.COMPLETE_APPEAL]: ':white_check_mark: Kæru lokið', diff --git a/apps/judicial-system/web/src/components/CaseFile/CaseFile.tsx b/apps/judicial-system/web/src/components/CaseFile/CaseFile.tsx index f6447323b82d..31ea2167c494 100644 --- a/apps/judicial-system/web/src/components/CaseFile/CaseFile.tsx +++ b/apps/judicial-system/web/src/components/CaseFile/CaseFile.tsx @@ -5,7 +5,7 @@ import { IconMapIcon } from '@island.is/island-ui/core' import { Box, Icon, StatusColor, Text } from '@island.is/island-ui/core' import { Colors } from '@island.is/island-ui/theme' -import { fileSize } from '../../utils/stepHelper' +import { fileSize } from '../../utils/utils' import IconButton from '../IconButton/IconButton' import * as styles from './CaseFile.css' diff --git a/apps/judicial-system/web/src/components/CourtArrangements/CourtArrangements.tsx b/apps/judicial-system/web/src/components/CourtArrangements/CourtArrangements.tsx index 9e8ee4794428..528dc8c62c7e 100644 --- a/apps/judicial-system/web/src/components/CourtArrangements/CourtArrangements.tsx +++ b/apps/judicial-system/web/src/components/CourtArrangements/CourtArrangements.tsx @@ -17,7 +17,7 @@ import { UpdateCase, useCase, } from '@island.is/judicial-system-web/src/utils/hooks' -import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/utils' import { strings } from './CourtArrangements.string' diff --git a/apps/judicial-system/web/src/components/RestrictionTags/RestrictionTags.tsx b/apps/judicial-system/web/src/components/RestrictionTags/RestrictionTags.tsx index 244e40b50256..af0f5754f87f 100644 --- a/apps/judicial-system/web/src/components/RestrictionTags/RestrictionTags.tsx +++ b/apps/judicial-system/web/src/components/RestrictionTags/RestrictionTags.tsx @@ -8,7 +8,7 @@ import { CaseType, } from '@island.is/judicial-system-web/src/graphql/schema' import { TempCase as Case } from '@island.is/judicial-system-web/src/types' -import { getRestrictionTagVariant } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { getRestrictionTagVariant } from '@island.is/judicial-system-web/src/utils/utils' interface Props { workingCase: Case diff --git a/apps/judicial-system/web/src/routes/Court/InvestigationCase/HearingArrangements/HearingArrangements.tsx b/apps/judicial-system/web/src/routes/Court/InvestigationCase/HearingArrangements/HearingArrangements.tsx index fe6b8e5775b3..a5c6736832c5 100644 --- a/apps/judicial-system/web/src/routes/Court/InvestigationCase/HearingArrangements/HearingArrangements.tsx +++ b/apps/judicial-system/web/src/routes/Court/InvestigationCase/HearingArrangements/HearingArrangements.tsx @@ -28,7 +28,7 @@ import { useCase, useOnceOn, } from '@island.is/judicial-system-web/src/utils/hooks' -import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/utils' import { isCourtHearingArrangementsStepValidIC } from '@island.is/judicial-system-web/src/utils/validate' import { icHearingArrangements as m } from './HearingArrangements.strings' diff --git a/apps/judicial-system/web/src/routes/Court/RestrictionCase/HearingArrangements/HearingArrangements.tsx b/apps/judicial-system/web/src/routes/Court/RestrictionCase/HearingArrangements/HearingArrangements.tsx index 29c8ac9ab0d6..0a47f7681314 100644 --- a/apps/judicial-system/web/src/routes/Court/RestrictionCase/HearingArrangements/HearingArrangements.tsx +++ b/apps/judicial-system/web/src/routes/Court/RestrictionCase/HearingArrangements/HearingArrangements.tsx @@ -28,7 +28,7 @@ import { useCase, useOnceOn, } from '@island.is/judicial-system-web/src/utils/hooks' -import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/utils' import { isCourtHearingArrangemenstStepValidRC } from '@island.is/judicial-system-web/src/utils/validate' import { rcHearingArrangements as m } from './HearingArrangements.strings' diff --git a/apps/judicial-system/web/src/routes/Court/components/ReceptionAndAssignment/ReceptionAndAssignment.tsx b/apps/judicial-system/web/src/routes/Court/components/ReceptionAndAssignment/ReceptionAndAssignment.tsx index 9e84c4ee1299..b23499449778 100644 --- a/apps/judicial-system/web/src/routes/Court/components/ReceptionAndAssignment/ReceptionAndAssignment.tsx +++ b/apps/judicial-system/web/src/routes/Court/components/ReceptionAndAssignment/ReceptionAndAssignment.tsx @@ -20,7 +20,7 @@ import { PageTitle, } from '@island.is/judicial-system-web/src/components' import { Gender } from '@island.is/judicial-system-web/src/graphql/schema' -import { getDefendantPleaText } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { getDefendantPleaText } from '@island.is/judicial-system-web/src/utils/utils' import { isReceptionAndAssignmentStepValid } from '@island.is/judicial-system-web/src/utils/validate' import CourtCaseNumber from '../CourtCaseNumber/CourtCaseNumber' diff --git a/apps/judicial-system/web/src/routes/CourtOfAppeal/AppealCase/AppealCase.tsx b/apps/judicial-system/web/src/routes/CourtOfAppeal/AppealCase/AppealCase.tsx index 034a368283de..174518642b1e 100644 --- a/apps/judicial-system/web/src/routes/CourtOfAppeal/AppealCase/AppealCase.tsx +++ b/apps/judicial-system/web/src/routes/CourtOfAppeal/AppealCase/AppealCase.tsx @@ -28,7 +28,7 @@ import { useCase } from '@island.is/judicial-system-web/src/utils/hooks' import { hasSentNotification, isReopenedCOACase, -} from '@island.is/judicial-system-web/src/utils/stepHelper' +} from '@island.is/judicial-system-web/src/utils/utils' import { isCourtOfAppealCaseStepValid } from '@island.is/judicial-system-web/src/utils/validate' import CaseNumberInput from '../components/CaseNumberInput/CaseNumberInput' diff --git a/apps/judicial-system/web/src/routes/CourtOfAppeal/Overview/Overview.tsx b/apps/judicial-system/web/src/routes/CourtOfAppeal/Overview/Overview.tsx index ee4b2b49bd93..97581a5ecf69 100644 --- a/apps/judicial-system/web/src/routes/CourtOfAppeal/Overview/Overview.tsx +++ b/apps/judicial-system/web/src/routes/CourtOfAppeal/Overview/Overview.tsx @@ -20,8 +20,8 @@ import { } from '@island.is/judicial-system-web/src/components' import useInfoCardItems from '@island.is/judicial-system-web/src/components/InfoCard/useInfoCardItems' import { useAppealAlertBanner } from '@island.is/judicial-system-web/src/utils/hooks' -import { shouldUseAppealWithdrawnRoutes } from '@island.is/judicial-system-web/src/utils/stepHelper' import { titleForCase } from '@island.is/judicial-system-web/src/utils/titleForCase/titleForCase' +import { shouldUseAppealWithdrawnRoutes } from '@island.is/judicial-system-web/src/utils/utils' import CaseFilesOverview from '../components/CaseFilesOverview/CaseFilesOverview' import CaseOverviewHeader from '../components/CaseOverviewHeader/CaseOverviewHeader' diff --git a/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.spec.tsx b/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.spec.tsx index 75066f7860ae..f24308e2417e 100644 --- a/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.spec.tsx +++ b/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.spec.tsx @@ -9,11 +9,11 @@ import { CaseType, } from '@island.is/judicial-system-web/src/graphql/schema' import { mockTransitonCaseMutation } from '@island.is/judicial-system-web/src/utils/mocks' -import * as stepHelper from '@island.is/judicial-system-web/src/utils/stepHelper' import { FormContextWrapper, IntlProviderWrapper, } from '@island.is/judicial-system-web/src/utils/testHelpers' +import * as utils from '@island.is/judicial-system-web/src/utils/utils' import Summary from './Summary' @@ -70,7 +70,7 @@ describe('Summary', () => { it('should show a modal window when the appeal ruling is modified', async () => { const caseId = faker.datatype.uuid() jest - .spyOn(stepHelper, 'hasSentNotification') + .spyOn(utils, 'hasSentNotification') .mockReturnValue({ hasSent: true, date: null }) render( diff --git a/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.tsx b/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.tsx index 4d77a326cd87..3d34ee158612 100644 --- a/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.tsx +++ b/apps/judicial-system/web/src/routes/CourtOfAppeal/Summary/Summary.tsx @@ -31,7 +31,7 @@ import { import { hasSentNotification, shouldUseAppealWithdrawnRoutes, -} from '@island.is/judicial-system-web/src/utils/stepHelper' +} from '@island.is/judicial-system-web/src/utils/utils' import CaseNumbers from '../components/CaseNumbers/CaseNumbers' import RulingModifiedModal from './RulingModifiedModal/RulingModifiedModal' diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx index 5f5e15f5b14a..5214cd58e3ac 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/Defendant.tsx @@ -30,7 +30,6 @@ import { } from '@island.is/judicial-system-web/src/graphql/schema' import { TempCase as Case } from '@island.is/judicial-system-web/src/types' import { - UpdateIndictmentCount, useCase, useDefendants, useIndictmentCounts, @@ -115,7 +114,7 @@ const Defendant = () => { } = useDefendants() const router = useRouter() - const { updateIndictmentCount } = useIndictmentCounts() + const { updateIndictmentCount, deleteIndictmentCount } = useIndictmentCounts() const [policeCases, setPoliceCases] = useState([]) @@ -249,6 +248,12 @@ const Defendant = () => { workingCase, setWorkingCase, ) + + const indictmentCountId = workingCase.indictmentCounts?.[index]?.id + + if (indictmentCountId) { + deleteIndictmentCount(workingCase.id, indictmentCountId) + } } const handleUpdatePoliceCase = ( @@ -279,20 +284,28 @@ const Defendant = () => { const handleUpdateIndictmentCount = ( policeCaseNumber: string, crimeScene: CrimeScene, + subtypes?: Record, ) => { if (workingCase.indictmentCounts) { workingCase.indictmentCounts - .filter((ic) => ic.policeCaseNumber === policeCaseNumber) - .forEach((ic) => { + .filter( + (indictmentCount) => + indictmentCount.policeCaseNumber === policeCaseNumber, + ) + .forEach((indictmentCount) => { const incidentDescription = getIncidentDescription( - ic, + indictmentCount, formatMessage, crimeScene, + subtypes, ) - updateIndictmentCount(workingCase.id, ic.id, { + updateIndictmentCount(workingCase.id, indictmentCount.id, { incidentDescription, - } as UpdateIndictmentCount) + ...(subtypes && { + indictmentCountSubtypes: subtypes[policeCaseNumber], + }), + }) }) } } @@ -506,6 +519,11 @@ const Defendant = () => { workingCase.origin === CaseOrigin.LOKE && index === 0 } updateIndictmentCount={handleUpdateIndictmentCount} + indictmentCount={workingCase.indictmentCounts?.find( + (indictmentCount) => + indictmentCount.policeCaseNumber === + workingCase.policeCaseNumbers?.[index], + )} /> )} diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/PoliceCaseInfo/PoliceCaseInfo.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/PoliceCaseInfo/PoliceCaseInfo.tsx index 8ebfb8969f63..8a61889ca3dd 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/PoliceCaseInfo/PoliceCaseInfo.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Defendant/PoliceCaseInfo/PoliceCaseInfo.tsx @@ -20,6 +20,7 @@ import { DateTime, UserContext, } from '@island.is/judicial-system-web/src/components' +import { TempIndictmentCount } from '@island.is/judicial-system-web/src/types' import { removeErrorMessageIfValid, validateAndSetErrorMessage, @@ -53,8 +54,10 @@ interface Props { updateIndictmentCount: ( policeCaseNumber: string, crimeScene: CrimeScene, + subtypes?: Record, ) => void policeCaseNumberImmutable: boolean + indictmentCount?: TempIndictmentCount } export const PoliceCaseInfo: FC = ({ @@ -68,6 +71,7 @@ export const PoliceCaseInfo: FC = ({ updatePoliceCase, policeCaseNumberImmutable = false, updateIndictmentCount, + indictmentCount, }) => { const { formatMessage } = useIntl() @@ -82,6 +86,8 @@ export const PoliceCaseInfo: FC = ({ const [policeCaseNumberErrorMessage, setPoliceCaseNumberErrorMessage] = useState('') + const subtypesArray = subtypes || [] + useEffect(() => { if (policeCaseNumbers[index] !== originalPoliceCaseNumber) { // This component is now handling a new police case number @@ -208,10 +214,15 @@ export const PoliceCaseInfo: FC = ({ label={formatMessage(policeCaseInfo.indictmentTypeLabel)} placeholder={formatMessage(policeCaseInfo.indictmentTypePlaceholder)} onChange={(selectedOption) => { - const indictmentSubtype = selectedOption?.value as IndictmentSubtype - updatePoliceCase(index, { - subtypes: [...(subtypes || []), indictmentSubtype], - }) + const indictmentSubtype = selectedOption?.value + + if (!indictmentSubtype) { + return + } + + const subtypes = [...subtypesArray, indictmentSubtype] + + updatePoliceCase(index, { subtypes }) }} value={null} required @@ -231,8 +242,21 @@ export const PoliceCaseInfo: FC = ({ variant="darkerBlue" onClick={() => { updatePoliceCase(index, { + policeCaseNumber: policeCaseNumbers[index], subtypes: subtypes.filter((s) => s !== subtype), }) + + updateIndictmentCount( + policeCaseNumbers[index], + crimeScene || {}, + { + [policeCaseNumbers[index]]: subtypes.filter( + (s) => + s !== subtype && + indictmentCount?.indictmentCountSubtypes?.includes(s), + ), + }, + ) }} aria-label={formatMessage(policeCaseInfo.removeSubtype, { subtype: indictmentSubtypes[subtypes[0]], @@ -261,10 +285,11 @@ export const PoliceCaseInfo: FC = ({ }} onBlur={(event) => { updatePoliceCase() - updateIndictmentCount(policeCaseNumbers[index], { - ...crimeScene, - place: event.target.value, - }) + updateIndictmentCount( + policeCaseNumbers[index], + { ...crimeScene, place: event.target.value }, + { [policeCaseNumbers[index]]: subtypesArray }, + ) }} /> @@ -280,10 +305,11 @@ export const PoliceCaseInfo: FC = ({ crimeScene: { ...crimeScene, date: date }, }) - updateIndictmentCount(policeCaseNumbers[index], { - ...crimeScene, - date: date, - }) + updateIndictmentCount( + policeCaseNumbers[index], + { ...crimeScene, date: date }, + { [policeCaseNumbers[index]]: subtypesArray }, + ) } }} /> diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.spec.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.spec.tsx index 73ad273f1eb1..8433ed577915 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.spec.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.spec.tsx @@ -1,9 +1,13 @@ import { createIntl } from 'react-intl' import { Substance, SubstanceMap } from '@island.is/judicial-system/types' -import { IndictmentCountOffense as offense } from '@island.is/judicial-system-web/src/graphql/schema' +import { + IndictmentCountOffense as offense, + IndictmentSubtype, +} from '@island.is/judicial-system-web/src/graphql/schema' import { + getIncidentDescription, getIncidentDescriptionReason, getLegalArguments, getRelevantSubstances, @@ -192,3 +196,133 @@ describe('getIncidentDescriptionReason', () => { ) }) }) + +describe('getIncidentDescription', () => { + test('should return an empty string if there are no offenses in traffic violations', () => { + const result = getIncidentDescription( + { id: 'testId', offenses: [], policeCaseNumber: '123-123-123' }, + formatMessage, + {}, + { '123-123-123': [IndictmentSubtype.TRAFFIC_VIOLATION] }, + ) + + expect(result).toBe('') + }) + + test('should return an empty string if offenses are missing in traffic violations', () => { + const result = getIncidentDescription( + { id: 'testId', policeCaseNumber: '123-123-123' }, + formatMessage, + {}, + { '123-123-123': [IndictmentSubtype.TRAFFIC_VIOLATION] }, + ) + + expect(result).toBe('') + }) + + test('should return a description for only traffic violations', () => { + const result = getIncidentDescription( + { + id: 'testId', + offenses: [offense.DRUNK_DRIVING], + policeCaseNumber: '123-123-123', + }, + formatMessage, + {}, + { '123-123-123': [IndictmentSubtype.TRAFFIC_VIOLATION] }, + ) + + expect(result).toBe( + 'fyrir umferðarlagabrot með því að hafa, [Dagsetning], ekið bifreiðinni [Skráningarnúmer ökutækis] undir áhrifum áfengis um [Vettvangur], þar sem lögregla stöðvaði aksturinn.', + ) + }) + + test('should return a description for a single subtype that is not a traffic violation', () => { + const result = getIncidentDescription( + { + id: 'testId', + policeCaseNumber: '123-123-123', + }, + formatMessage, + {}, + { '123-123-123': [IndictmentSubtype.CUSTOMS_VIOLATION] }, + ) + + expect(result).toBe('fyrir [tollalagabrot] með því að hafa, [Dagsetning]') + }) + + test('should return a description when there are multiple subtypes but only traffic violation is selected', () => { + const result = getIncidentDescription( + { + id: 'testId', + policeCaseNumber: '123-123-123', + offenses: [offense.DRUNK_DRIVING], + indictmentCountSubtypes: [IndictmentSubtype.TRAFFIC_VIOLATION], + }, + formatMessage, + {}, + { + '123-123-123': [ + IndictmentSubtype.CUSTOMS_VIOLATION, + IndictmentSubtype.TRAFFIC_VIOLATION, + ], + }, + ) + + expect(result).toBe( + 'fyrir umferðarlagabrot með því að hafa, [Dagsetning], ekið bifreiðinni [Skráningarnúmer ökutækis] undir áhrifum áfengis um [Vettvangur], þar sem lögregla stöðvaði aksturinn.', + ) + }) + + test('should return a description when there are multiple subtypes and all are selected', () => { + const result = getIncidentDescription( + { + id: 'testId', + policeCaseNumber: '123-123-123', + offenses: [offense.DRUNK_DRIVING], + indictmentCountSubtypes: [ + IndictmentSubtype.CUSTOMS_VIOLATION, + IndictmentSubtype.THEFT, + ], + }, + formatMessage, + {}, + { + '123-123-123': [ + IndictmentSubtype.CUSTOMS_VIOLATION, + IndictmentSubtype.THEFT, + ], + }, + ) + + expect(result).toBe( + 'fyrir [tollalagabrot, þjófnaður] með því að hafa, [Dagsetning]', + ) + }) + + test('should return the traffic violation description when there are multiple subtypes, all are selected and one is a traffic violation', () => { + const result = getIncidentDescription( + { + id: 'testId', + policeCaseNumber: '123-123-123', + offenses: [offense.DRUNK_DRIVING], + indictmentCountSubtypes: [ + IndictmentSubtype.CUSTOMS_VIOLATION, + IndictmentSubtype.TRAFFIC_VIOLATION, + ], + }, + formatMessage, + {}, + { + '123-123-123': [ + IndictmentSubtype.CUSTOMS_VIOLATION, + IndictmentSubtype.TRAFFIC_VIOLATION, + ], + }, + ) + + expect(result).toBe( + 'fyrir umferðarlagabrot með því að hafa, [Dagsetning], ekið bifreiðinni [Skráningarnúmer ökutækis] undir áhrifum áfengis um [Vettvangur], þar sem lögregla stöðvaði aksturinn.', + ) + }) +}) diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.strings.ts b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.strings.ts index d6b7abe87aff..8d3428aef3df 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.strings.ts +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.strings.ts @@ -6,6 +6,11 @@ export const indictmentCount = defineMessages({ defaultMessage: 'Eyða', description: 'Notaður sem texti á Eyða hnappi á ákæruliða skrefi í ákærum.', }, + policeCaseNumberTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.police_case_number_title', + defaultMessage: 'Málsnúmer lögreglu', + description: 'Notaður sem titill fyrir "Málsnúmer lögreglu" svæði.', + }, policeCaseNumberLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.police_case_number_label', defaultMessage: 'LÖKE málsnúmer', @@ -18,6 +23,12 @@ export const indictmentCount = defineMessages({ description: 'Notaður sem skýritexti á LÖKE málsnúmers lista á ákæruliða skrefi í ákærum.', }, + vehicleRegistrationNumberTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.vehicle_registration_number_title', + defaultMessage: 'Númer ökutækis', + description: + 'Notaður sem titill á "Númer ökutækis" svæði á ákæruliða skrefi í ákærum.', + }, vehicleRegistrationNumberLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.vehicle_registration_number_label', defaultMessage: 'Skráningarnúmer ökutækis', @@ -30,6 +41,12 @@ export const indictmentCount = defineMessages({ description: 'Notaður sem skýritexti á "skráningarnúmer ökutækis" svæði á ákæruliða skrefi í ákærum.', }, + incidentTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.incident_title', + defaultMessage: 'Brot', + description: + 'Notaður sem titill á "brot" lista á ákæruliða skrefi í ákærum.', + }, incidentLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.incident_label', defaultMessage: 'Brot', @@ -42,6 +59,12 @@ export const indictmentCount = defineMessages({ description: 'Notaður sem skýritexti á "brot" lista á ákæruliða skrefi í ákærum.', }, + incidentDescriptionTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.incident_description_title', + defaultMessage: 'Atvikalýsing', + description: + 'Notaður sem titill á "atvikalýsing" svæði á ákæruliða skrefi í ákærum.', + }, incidentDescriptionLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.incident_description_label', defaultMessage: 'Atvikalýsing', @@ -54,6 +77,12 @@ export const indictmentCount = defineMessages({ description: 'Notaður sem skýritexti á "atvikalýsing" svæði á ákæruliða skrefi í ákærum.', }, + bloodAlcoholContentTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.blood_alcohol_content_title', + defaultMessage: 'Vínandamagn', + description: + 'Notaður sem titill á "vínandamagn" svæði á ákæruliða skrefi í ákærum.', + }, bloodAlcoholContentLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.blood_alcohol_content_label', defaultMessage: 'Vínandamagn (‰)', @@ -66,6 +95,12 @@ export const indictmentCount = defineMessages({ description: 'Notaður sem skýritexti á "vínandamagn" svæði á ákæruliða skrefi í ákærum.', }, + lawsBrokenTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.laws_broken_title', + defaultMessage: 'Lagaákvæði', + description: + 'Notaður sem titill á "lagaákvæði" leitarboxi á ákæruliða skrefi í ákærum.', + }, lawsBrokenLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.laws_broken_label', defaultMessage: 'Lagaákvæði', @@ -123,6 +158,18 @@ export const indictmentCount = defineMessages({ defaultMessage: 'í blóðsýni mældist', description: 'Notaður sem upphafstexti fyrir efni í blóði í atvikalýsingu.', }, + indictmentDescriptionSubtypesAutofill: { + id: 'judicial.system.core:indictments_indictment.indictment_count.indictment_description_subtypes_auto_fill', + defaultMessage: 'fyrir [{subtypes}] með því að hafa, {date}', + description: + 'Notaður sem ástæða í atvikalýsingu fyrir önnur brot en umferðalagabrot.', + }, + legalArgumentsTitle: { + id: 'judicial.system.core:indictments_indictment.indictment_count.legal_arguments_title', + defaultMessage: 'Heimfærsla', + description: + 'Notaður sem titill á "heimfærslu" svæði á ákæruliða skrefi í ákærum.', + }, legalArgumentsLabel: { id: 'judicial.system.core:indictments_indictment.indictment_count.legal_arguments_label', defaultMessage: 'Heimfærsla', diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.tsx index e1c1c97dd10a..3a7a7bf84592 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/IndictmentCount.tsx @@ -19,6 +19,7 @@ import { import { CrimeScene, IndictmentSubtype, + isTrafficViolationCase, offenseSubstances, Substance, SubstanceMap, @@ -34,6 +35,7 @@ import { TempIndictmentCount as TIndictmentCount, } from '@island.is/judicial-system-web/src/types' import { + isTrafficViolationIndictmentCount, removeErrorMessageIfValid, validateAndSetErrorMessage, } from '@island.is/judicial-system-web/src/utils/formHelper' @@ -287,41 +289,72 @@ export const getIncidentDescription = ( indictmentCount: TIndictmentCount, formatMessage: IntlShape['formatMessage'], crimeScene?: CrimeScene, + subtypesRecord?: Record, ) => { - const { offenses, substances, vehicleRegistrationNumber } = indictmentCount - - if (offenses?.length === 0) { + const { + offenses, + substances, + vehicleRegistrationNumber, + indictmentCountSubtypes, + policeCaseNumber, + } = indictmentCount + + const incidentLocation = crimeScene?.place || '[Vettvangur]' + const incidentDate = crimeScene?.date + ? formatDate(crimeScene.date, 'PPPP')?.replace('dagur,', 'daginn') || '' + : '[Dagsetning]' + + const vehicleRegistration = + vehicleRegistrationNumber || '[Skráningarnúmer ökutækis]' + + const subtypes = + (subtypesRecord && policeCaseNumber && subtypesRecord[policeCaseNumber]) || + [] + + if ( + subtypes.length > 1 && + (!indictmentCountSubtypes?.length || indictmentCountSubtypes.length === 0) + ) { return '' } - let incidentLocation = '' - let incidentDate = '' + if ( + isTrafficViolationIndictmentCount(policeCaseNumber, subtypesRecord) || + indictmentCountSubtypes?.includes(IndictmentSubtype.TRAFFIC_VIOLATION) + ) { + if (!offenses || offenses.length === 0) { + return '' + } - if (crimeScene) { - incidentLocation = crimeScene.place ?? '' - incidentDate = - formatDate(crimeScene.date, 'PPPP')?.replace('dagur,', 'daginn') ?? '' + const reason = getIncidentDescriptionReason( + offenses, + substances || {}, + formatMessage, + ) + + return formatMessage(strings.incidentDescriptionAutofill, { + incidentDate, + vehicleRegistrationNumber: vehicleRegistration, + reason, + incidentLocation, + }) } - const reason = getIncidentDescriptionReason( - offenses ?? [], - substances ?? {}, - formatMessage, - ) + if (subtypes.length === 1) { + return formatMessage(strings.indictmentDescriptionSubtypesAutofill, { + subtypes: indictmentSubtypes[subtypes[0]], + date: incidentDate, + }) + } - const incidentDescription = formatMessage( - strings.incidentDescriptionAutofill, - { - incidentDate: incidentDate ? incidentDate : '[Dagsetning]', - vehicleRegistrationNumber: vehicleRegistrationNumber - ? vehicleRegistrationNumber - : '[Skráningarnúmer ökutækis]', - reason, - incidentLocation: incidentLocation ? incidentLocation : '[Vettvangur]', - }, - ) + const allSubtypes = indictmentCountSubtypes + ?.map((subtype) => indictmentSubtypes[subtype]) + .join(', ') - return incidentDescription + return formatMessage(strings.indictmentDescriptionSubtypesAutofill, { + subtypes: allSubtypes, + date: incidentDate, + }) } export const IndictmentCount: FC = ({ @@ -346,7 +379,7 @@ export const IndictmentCount: FC = ({ const [legalArgumentsErrorMessage, setLegalArgumentsErrorMessage] = useState('') - const subtypes = indictmentCount.policeCaseNumber + const subtypes: IndictmentSubtype[] = indictmentCount.policeCaseNumber ? workingCase.indictmentSubtypes[indictmentCount.policeCaseNumber] : [] @@ -404,6 +437,7 @@ export const IndictmentCount: FC = ({ }, formatMessage, crimeScene, + workingCase.indictmentSubtypes, ) onChange(indictmentCount.id, { @@ -424,9 +458,41 @@ export const IndictmentCount: FC = ({ handleIndictmentCountChanges({ indictmentCountSubtypes: Array.from(currentSubtypes), + ...(!currentSubtypes.has(IndictmentSubtype.TRAFFIC_VIOLATION) && { + offenses: [], + substances: {}, + vehicleRegistrationNumber: null, + }), }) } + const shouldShowTrafficViolationFields = () => { + if (isTrafficViolationCase(workingCase)) { + return true + } + + const policeCaseNumber = indictmentCount.policeCaseNumber + + if ( + isTrafficViolationIndictmentCount( + policeCaseNumber, + workingCase.indictmentSubtypes, + ) + ) { + return true + } + + if ( + indictmentCount?.indictmentCountSubtypes?.includes( + IndictmentSubtype.TRAFFIC_VIOLATION, + ) + ) { + return true + } + + return false + } + return ( {onDelete && ( @@ -441,6 +507,11 @@ export const IndictmentCount: FC = ({ )} + { - removeErrorMessageIfValid( - ['empty'], - event.target.value, - vehicleRegistrationNumberErrorMessage, - setVehicleRegistrationNumberErrorMessage, - ) - - updateIndictmentCountState( - indictmentCount.id, - { - vehicleRegistrationNumber: event.target.value, - }, - setWorkingCase, - ) - }} - onBlur={async (event) => { - validateAndSetErrorMessage( - ['empty'], - event.target.value, - setVehicleRegistrationNumberErrorMessage, - ) - - handleIndictmentCountChanges({ - vehicleRegistrationNumber: event.target.value, - }) - }} - errorMessage={vehicleRegistrationNumberErrorMessage} - hasError={vehicleRegistrationNumberErrorMessage !== ''} - required - /> - - - { + removeErrorMessageIfValid( + ['empty'], + event.target.value, + vehicleRegistrationNumberErrorMessage, + setVehicleRegistrationNumberErrorMessage, + ) + + updateIndictmentCountState( + indictmentCount.id, + { + vehicleRegistrationNumber: event.target.value, + }, + setWorkingCase, + ) + }} + onBlur={async (event) => { + validateAndSetErrorMessage( + ['empty'], + event.target.value, + setVehicleRegistrationNumberErrorMessage, + ) + + handleIndictmentCountChanges({ + vehicleRegistrationNumber: event.target.value, + }) + }} + errorMessage={vehicleRegistrationNumberErrorMessage} + hasError={vehicleRegistrationNumberErrorMessage !== ''} required /> - - - )} - {indictmentCount.offenses - ?.filter( - (offenseType) => - offenseType === IndictmentCountOffense.ILLEGAL_DRUGS_DRIVING || - offenseType === IndictmentCountOffense.PRESCRIPTION_DRUGS_DRIVING, - ) - .map((offenseType) => ( - - - ))} - - { + const selectedOffense = so?.value as IndictmentCountOffense + const offenses = [ + ...(indictmentCount.offenses ?? []), + selectedOffense, + ].sort(offensesCompare) + + handleIndictmentCountChanges({ + offenses, + }) + }} + value={null} + required + /> + + {indictmentCount.offenses && indictmentCount.offenses.length > 0 && ( + + {indictmentCount.offenses.map((offense) => ( + + { + const offenses = (indictmentCount.offenses ?? []).filter( + (o) => o !== offense, + ) + + offenseSubstances[offense].forEach((e) => { + if (indictmentCount.substances) { + delete indictmentCount.substances[e] + } + }) + + handleIndictmentCountChanges({ + offenses, + substances: indictmentCount.substances, + }) + }} + > + + {formatMessage(enumStrings[offense])} + + + + + ))} + + )} + {indictmentCount.offenses?.includes( + IndictmentCountOffense.DRUNK_DRIVING, + ) && ( + + + { + removeErrorMessageIfValid( + ['empty'], + event.target.value, + bloodAlcoholContentErrorMessage, + setBloodAlcoholContentErrorMessage, + ) - handleIndictmentCountChanges({ - lawsBroken, - }) - }} - required - /> - - {indictmentCount.lawsBroken && indictmentCount.lawsBroken.length > 0 && ( - - {indictmentCount.lawsBroken.map((brokenLaw) => ( - - { - const lawsBroken = (indictmentCount.lawsBroken ?? []).filter( - (b) => lawsCompare(b, brokenLaw) !== 0, + updateIndictmentCountState( + indictmentCount.id, + { + substances: { + ...indictmentCount.substances, + ALCOHOL: event.target.value, + }, + }, + setWorkingCase, ) + }} + onBlur={(event) => { + const value = + event.target.value.length > 0 + ? `${event.target.value}${'0,00'.slice( + event.target.value.length, + )}` + : event.target.value + + validateAndSetErrorMessage( + ['empty'], + value, + setBloodAlcoholContentErrorMessage, + ) + + const substances = { + ...indictmentCount.substances, + ALCOHOL: value, + } - onChange(indictmentCount.id, { - lawsBroken: lawsBroken, - legalArguments: getLegalArguments( - lawsBroken, - formatMessage, - ), + handleIndictmentCountChanges({ + substances, }) }} - aria-label={lawTag(brokenLaw)} > - - {lawTag(brokenLaw)} - + + + + )} + {indictmentCount.offenses + ?.filter( + (offenseType) => + offenseType === IndictmentCountOffense.ILLEGAL_DRUGS_DRIVING || + offenseType === + IndictmentCountOffense.PRESCRIPTION_DRUGS_DRIVING, + ) + .map((offenseType) => ( + + + + ))} + + + = ({ /> - - - { - removeErrorMessageIfValid( - ['empty'], - event.target.value, - legalArgumentsErrorMessage, - setLegalArgumentsErrorMessage, - ) + + - updateIndictmentCountState( - indictmentCount.id, - { legalArguments: event.target.value }, - setWorkingCase, - ) - }} - onBlur={(event) => { - validateAndSetErrorMessage( - ['empty'], - event.target.value, - setLegalArgumentsErrorMessage, - ) + { + removeErrorMessageIfValid( + ['empty'], + event.target.value, + legalArgumentsErrorMessage, + setLegalArgumentsErrorMessage, + ) - onChange(indictmentCount.id, { - legalArguments: event.target.value.trim(), - }) - }} - required - rows={7} - autoExpand={{ on: true, maxHeight: 600 }} - textarea - /> - + updateIndictmentCountState( + indictmentCount.id, + { legalArguments: event.target.value }, + setWorkingCase, + ) + }} + onBlur={(event) => { + validateAndSetErrorMessage( + ['empty'], + event.target.value, + setLegalArgumentsErrorMessage, + ) + + onChange(indictmentCount.id, { + legalArguments: event.target.value.trim(), + }) + }} + required + rows={7} + autoExpand={{ on: true, maxHeight: 600 }} + textarea + /> ) diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.strings.ts b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.strings.ts index c4589002a03a..585045c28e2a 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.strings.ts +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.strings.ts @@ -1,6 +1,13 @@ import { defineMessages } from 'react-intl' export const substances = defineMessages({ + substanceTitle: { + id: 'judicial.system.core:substances.title', + defaultMessage: + '{substanceType, select, ILLEGAL_DRUGS_DRIVING {Fíkniefni} PRESCRIPTION_DRUGS_DRIVING {Lyf} other {Efni}}', + description: + 'Notaður sem titill á "veldu" lista á ákæruliða skrefi í ákærum.', + }, substanceLabel: { id: 'judicial.system.core:substances.label', defaultMessage: diff --git a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.tsx b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.tsx index 8a148721c67d..902f9d82b404 100644 --- a/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.tsx +++ b/apps/judicial-system/web/src/routes/Prosecutor/Indictments/Indictment/Substances/Substances.tsx @@ -6,6 +6,7 @@ import { offenseSubstances, Substance as SubstanceEnum, } from '@island.is/judicial-system/types' +import { SectionHeading } from '@island.is/judicial-system-web/src/components' import { IndictmentCountOffense } from '@island.is/judicial-system-web/src/graphql/schema' import { ReactSelectOption, @@ -65,6 +66,13 @@ export const Substances: FC = ({ return ( +